修改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"  

相关内容