歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

修改Embedded QT鼠標驅動支持IRTOUCH觸摸屏

背景知識:
http://doc.qt.nokia.com/4.6/qt-embedded-architecture.html    Qt for Embedded Linux Architecture   
http://doc.qt.nokia.com/4.6/qt-embedded-pointer.html#available-drivers  Qt for Embedded Linux Pointer Handling  
QTSRC/src/gui/embeded/qmouselinuxinput_qws.cpp     


主要的要點是:
        1. EQT 默認只支持“pc”類型的鼠標驅動,具體來說就是如下類型:Auto、IntelliMouse、Microsoft、MouseSystems。
            要使EQT 支持Linux input子系統的鼠標驅動,在編譯QT時 configure 要添加參數: -qt-mouse-linuxinput
            (具體的configure的幫助請運行: ./configure -embedded -help .)
        2. 確保觸摸屏提交到Linux input子系統的坐標數據是正確的,我們需要通過解析/dev/event0 的數據來證明


原理說明:

1. 分辨率轉化和校准
         其實,這一款32寸的IRTOUCH產生的坐標值是絕對坐標,范圍x、y均為 0~4096。所以,我們運行的QT程序如果直接獲取
event0產生的坐標的話,鼠標位置便會超出屏幕的顯示范圍,因此,我們需要進行一下坐標值轉化,具體的函數如下:

void adjuest(int* pX,int* pY) 
{
        //* pX = 1280.0f / 1248 * (2272 - *pX); // 中間版本
        ////* pY = 720.0f / 700 * (*pY - 1030);
            
        ////* pX = (int)(1280.0f / 4062 * (*pX - 7)); // 最舊版本
        ////* pY = (int)(720.0f / 4071 * (*pY));
        *pX = (int)((*pX)*1280.0f/4050);
        *pY = (int)((*pY)*720.0f/4080);
            
        ////* pX = (int)((*pX)*1280.0f/4095); // 最新版本
        ////* pY = (int)((*pY)*720.0f/4095);
}
該函數就可以將原來4096*4096的分辨率轉換成 1280*720;至於具體的數值,我們需要根據實際的屏幕產生的數據進行修改,
重點在於四角和中間點。 
分辨率一旦設置合適,屏幕鼠標也就會校准,該函數的作用類似於void QWSLinuxInputMousePrivate::readMouseData()函數中
調用的 pos = m_handler->transform(pos)。transform()函數會根據/etc/pointercal來進行校准,如果你沒有運行過校准程序
默認會沒有該文件的。(QT自帶的例子裡面有一個校准程序:qt\examples\qws\mousecalibration。但是,由於不同的嵌入式
平台采用的芯片差異性很大,所以,這個校准程序往往無法使用,所以,才會自己編寫一個adjuest()函數來調整原始坐標值。)


2. 觸摸屏的降噪和去抖動
      由於觸摸屏本身的原因導致每次產生的數據並不是都准確和正確的,所以,我們需要對坐標進行一些處理,
主要目的在於盡量消除誤差,提高觸摸屏的准確度。由於不用硬件會有不同的情況,我們需要變通的處理。這一點也是比較
讓人頭疼的地方。下面就簡單的貼出代碼:
  1. #include "qmouselinuxinput_qws.h"   
  2. #include <QScreen>   
  3. #include <QSocketNotifier>   
  4. #include <qplatformdefs.h>   
  5. #include <private/qcore_unix_p.h> // overrides QT_OPEN   
  6. #include <errno.h>   
  7. #include <linux/input.h>   
  8.   
  9. QT_BEGIN_NAMESPACE  
  10.   
  11. class QWSLinuxInputMousePrivate : public QObject  
  12. {  
  13.     Q_OBJECT  
  14. public:  
  15.     QWSLinuxInputMousePrivate(QWSLinuxInputMouseHandler *, const QString &);  
  16.     ~QWSLinuxInputMousePrivate();  
  17.   
  18.   
  19.     void enable(bool on);  
  20.     void setButton(int num){m_buttons = num;}  
  21.   
  22.   
  23. private Q_SLOTS:  
  24.     void readMouseData();  
  25.   
  26.   
  27. private:  
  28.     QWSLinuxInputMouseHandler *m_handler;  
  29.     QSocketNotifier *          m_notify;  
  30.     int                        m_fd;  
  31.     int                        m_x, m_y;  
  32.     int                        m_buttons;  
  33. };  
  34.   
  35.   
  36. QWSLinuxInputMouseHandler::QWSLinuxInputMouseHandler(const QString &device)  
  37.     : QWSCalibratedMouseHandler(device)  
  38. {  
  39.     printf("Enter QWSLinuxInputMouseHandler \n");  
  40.     d = new QWSLinuxInputMousePrivate(this, device);  
  41. }  
  42.   
  43.   
  44. QWSLinuxInputMouseHandler::~QWSLinuxInputMouseHandler()  
  45. {  
  46.     delete d;  
  47. }  
  48.   
  49.   
  50. void QWSLinuxInputMouseHandler::suspend()  
  51. {  
  52.     d->enable(false);  
  53. }  
  54.   
  55.   
  56. void QWSLinuxInputMouseHandler::resume()  
  57. {  
  58.     d->enable(true);  
  59. }  
  60.   
  61.   
  62. QWSLinuxInputMousePrivate::QWSLinuxInputMousePrivate(QWSLinuxInputMouseHandler *h, const QString &device)  
  63.     : m_handler(h), m_notify(0), m_x(0), m_y(0), m_buttons(0)  
  64. {  
  65.     setObjectName(QLatin1String("LinuxInputSubsystem Mouse Handler"));  
  66.   
  67.   
  68.     QString dev = QLatin1String("/dev/event0");  
  69.     if (device.startsWith(QLatin1String("/dev/")))  
  70.         dev = device;  
  71.   
  72.   
  73.     m_fd = QT_OPEN(dev.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);  
  74.     if (m_fd >= 0) {  
  75.         m_notify = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);  
  76.         connect(m_notify, SIGNAL(activated(int)), this, SLOT(readMouseData()));  
  77.     } else {  
  78.         qWarning("Cannot open mouse input device '%s': %s", qPrintable(dev), strerror(errno));  
  79.         return;  
  80.     }  
  81. }  
  82.   
  83.   
  84. QWSLinuxInputMousePrivate::~QWSLinuxInputMousePrivate()  
  85. {  
  86.     if (m_fd >= 0)  
  87.         QT_CLOSE(m_fd);  
  88. }  
  89.   
  90.   
  91. void QWSLinuxInputMousePrivate::enable(bool on)  
  92. {  
  93.     if (m_notify)  
  94.         m_notify->setEnabled(on);  
  95. }  
  96. void adjuest(int* pX,int* pY)  
  97. {  
  98.         //* pX = 1280.0f / 1248 * (2272 - *pX); // 中間版本   
  99.         ////* pY = 720.0f / 700 * (*pY - 1030);   
  100.           
  101.         ////* pX = (int)(1280.0f / 4062 * (*pX - 7)); // 最舊版本   
  102.         ////* pY = (int)(720.0f / 4071 * (*pY));   
  103.         *pX = (int)((*pX)*1280.0f/4050);  
  104.         *pY = (int)((*pY)*720.0f/4080);  
  105.           
  106.         ////* pX = (int)((*pX)*1280.0f/4095); // 最新版本   
  107.         ////* pY = (int)((*pY)*720.0f/4095);   
  108. }  
  109.   
  110.   
  111. void QWSLinuxInputMousePrivate::readMouseData()  
  112. {  
  113.     if (!qt_screen)  
  114.         return;  
  115.   
  116.   
  117.     struct ::input_event buffer[32];  
  118.     int n = 0;  
  119.     static bool setXflag = 0;  
  120.     static bool setYflag = 0;  
  121.   
  122.   
  123.     forever {  
  124.         n += QT_READ(m_fd, reinterpret_cast<char *>(buffer) + n, sizeof(buffer) - n);  
  125.   
  126.   
  127.         if (n == 0) {  
  128.             qWarning("Got EOF from the input device.");  
  129.             return;  
  130.         } else if (n < 0 && (errno != EINTR && errno != EAGAIN)) {  
  131.             qWarning("Could not read from input device: %s", strerror(errno));  
  132.             return;  
  133.         } else if (n % sizeof(buffer[0]) == 0) {  
  134.             break;  
  135.         }  
  136.     }  
  137.   
  138.   
  139.     n /= sizeof(buffer[0]);  
  140.   
  141.   
  142.     for (int i = 0; i < n; ++i) {  
  143.         struct ::input_event *data = &buffer[i];  
  144.   
  145.   
  146.         bool unknown = false;  
  147.         if (data->type == EV_ABS) {  
  148.             if (data->code == ABS_X && !setXflag) {  
  149.                 m_x = data->value;  
  150.                 setXflag = 1;  
  151.             } else if (data->code == ABS_Y && !setYflag) {  
  152.                 m_y = data->value;  
  153.                 setYflag = 1;  
  154.             } else {  
  155.                 unknown = true;  
  156.             }  
  157.         } else if (data->type == EV_SYN && data->code == SYN_REPORT && setXflag && setYflag) {  
  158.             adjuest(&m_x, &m_y);  
  159.             printf("########### X=%d Y=%d\n", m_x, m_y);  
  160.             QPoint pos(m_x, m_y);  
  161.             //pos = m_handler->transform(pos);   
  162.             //m_handler->limitToScreen(pos);   
  163.             setButton(3);  
  164.             m_handler->mouseChanged(pos, m_buttons);  
  165.             setXflag = setYflag = 0;  
  166.             setButton(0);  
  167.             usleep(1000);  
  168.             m_handler->mouseChanged(pos, m_buttons);   
  169.             return;  
  170.         } else if (data->type == EV_MSC && data->code == MSC_SCAN) {  
  171.             // kernel encountered an unmapped key - just ignore it   
  172.             continue;  
  173.         } else {  
  174.             unknown = true;  
  175.         }  
  176.         if (unknown) {  
  177.             qWarning("unknown mouse event type=%x, code=%x, value=%x", data->type, data->code, data->value);  
  178.         }  
  179.     }  
  180. }  
  181.   
  182.   
  183. QT_END_NAMESPACE  
  184. #include "qmouselinuxinput_qws.moc"  
Copyright © Linux教程網 All Rights Reserved