背景知識:
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. 觸摸屏的降噪和去抖動
由於觸摸屏本身的原因導致每次產生的數據並不是都准確和正確的,所以,我們需要對坐標進行一些處理,
主要目的在於盡量消除誤差,提高觸摸屏的准確度。由於不用硬件會有不同的情況,我們需要變通的處理。這一點也是比較
讓人頭疼的地方。下面就簡單的貼出代碼:
- #include "qmouselinuxinput_qws.h"
- #include <QScreen>
- #include <QSocketNotifier>
- #include <qplatformdefs.h>
- #include <private/qcore_unix_p.h> // overrides QT_OPEN
- #include <errno.h>
- #include <linux/input.h>
-
- QT_BEGIN_NAMESPACE
-
- class QWSLinuxInputMousePrivate : public QObject
- {
- Q_OBJECT
- public:
- QWSLinuxInputMousePrivate(QWSLinuxInputMouseHandler *, const QString &);
- ~QWSLinuxInputMousePrivate();
-
-
- void enable(bool on);
- void setButton(int num){m_buttons = num;}
-
-
- private Q_SLOTS:
- void readMouseData();
-
-
- private:
- QWSLinuxInputMouseHandler *m_handler;
- QSocketNotifier * m_notify;
- int m_fd;
- int m_x, m_y;
- int m_buttons;
- };
-
-
- QWSLinuxInputMouseHandler::QWSLinuxInputMouseHandler(const QString &device)
- : QWSCalibratedMouseHandler(device)
- {
- printf("Enter QWSLinuxInputMouseHandler \n");
- d = new QWSLinuxInputMousePrivate(this, device);
- }
-
-
- QWSLinuxInputMouseHandler::~QWSLinuxInputMouseHandler()
- {
- delete d;
- }
-
-
- void QWSLinuxInputMouseHandler::suspend()
- {
- d->enable(false);
- }
-
-
- void QWSLinuxInputMouseHandler::resume()
- {
- d->enable(true);
- }
-
-
- QWSLinuxInputMousePrivate::QWSLinuxInputMousePrivate(QWSLinuxInputMouseHandler *h, const QString &device)
- : m_handler(h), m_notify(0), m_x(0), m_y(0), m_buttons(0)
- {
- setObjectName(QLatin1String("LinuxInputSubsystem Mouse Handler"));
-
-
- QString dev = QLatin1String("/dev/event0");
- if (device.startsWith(QLatin1String("/dev/")))
- dev = device;
-
-
- m_fd = QT_OPEN(dev.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);
- if (m_fd >= 0) {
- m_notify = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
- connect(m_notify, SIGNAL(activated(int)), this, SLOT(readMouseData()));
- } else {
- qWarning("Cannot open mouse input device '%s': %s", qPrintable(dev), strerror(errno));
- return;
- }
- }
-
-
- QWSLinuxInputMousePrivate::~QWSLinuxInputMousePrivate()
- {
- if (m_fd >= 0)
- QT_CLOSE(m_fd);
- }
-
-
- void QWSLinuxInputMousePrivate::enable(bool on)
- {
- if (m_notify)
- m_notify->setEnabled(on);
- }
- 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);
- }
-
-
- void QWSLinuxInputMousePrivate::readMouseData()
- {
- if (!qt_screen)
- return;
-
-
- struct ::input_event buffer[32];
- int n = 0;
- static bool setXflag = 0;
- static bool setYflag = 0;
-
-
- forever {
- n += QT_READ(m_fd, reinterpret_cast<char *>(buffer) + n, sizeof(buffer) - n);
-
-
- if (n == 0) {
- qWarning("Got EOF from the input device.");
- return;
- } else if (n < 0 && (errno != EINTR && errno != EAGAIN)) {
- qWarning("Could not read from input device: %s", strerror(errno));
- return;
- } else if (n % sizeof(buffer[0]) == 0) {
- break;
- }
- }
-
-
- n /= sizeof(buffer[0]);
-
-
- for (int i = 0; i < n; ++i) {
- struct ::input_event *data = &buffer[i];
-
-
- bool unknown = false;
- if (data->type == EV_ABS) {
- if (data->code == ABS_X && !setXflag) {
- m_x = data->value;
- setXflag = 1;
- } else if (data->code == ABS_Y && !setYflag) {
- m_y = data->value;
- setYflag = 1;
- } else {
- unknown = true;
- }
- } else if (data->type == EV_SYN && data->code == SYN_REPORT && setXflag && setYflag) {
- adjuest(&m_x, &m_y);
- printf("########### X=%d Y=%d\n", m_x, m_y);
- QPoint pos(m_x, m_y);
- //pos = m_handler->transform(pos);
- //m_handler->limitToScreen(pos);
- setButton(3);
- m_handler->mouseChanged(pos, m_buttons);
- setXflag = setYflag = 0;
- setButton(0);
- usleep(1000);
- m_handler->mouseChanged(pos, m_buttons);
- return;
- } else if (data->type == EV_MSC && data->code == MSC_SCAN) {
- // kernel encountered an unmapped key - just ignore it
- continue;
- } else {
- unknown = true;
- }
- if (unknown) {
- qWarning("unknown mouse event type=%x, code=%x, value=%x", data->type, data->code, data->value);
- }
- }
- }
-
-
- QT_END_NAMESPACE
- #include "qmouselinuxinput_qws.moc"