修改Embedded QT鼠标驱动支持IRTOUCH触摸屏
2012-04-07 18:28
183 查看
背景知识:
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. 触摸屏的降噪和去抖动
由于触摸屏本身的原因导致每次产生的数据并不是都准确和正确的,所以,我们需要对坐标进行一些处理,
主要目的在于尽量消除误差,提高触摸屏的准确度。由于不用硬件会有不同的情况,我们需要变通的处理。这一点也是比较
让人头疼的地方。下面就简单的贴出代码:
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"
相关文章推荐
- WTK2.2支持触摸屏的修改方法
- Android增加Happy Touch触摸屏支持
- Live555 的一个缺陷--例子不能支持多线程(已经修改成支持多线程)
- Light Touch:将任一平面瞬间转换成触摸屏
- 修改zepto源代码,使支持wp8的ie10
- 修改country code定制wifi支持的channel
- 支持修改主席树
- 移植uboot之修改代码支持NorFlash记录续集二
- sencha touch 扩展篇之使用sass自定义主题样式 (上)使用官方的api修改主题样式
- poi修改word文档doc/docx不支持图片
- 如何配置Git支持大小写敏感和修改文件名中大小写字母呢?(转)
- 如何修改点击触摸屏的默认声音(转)
- 数据库分库分表(sharding)系列(五) 一种支持自由规划无须数据迁移和修改路由代码的Sharding扩容方案
- Windows CE 触摸屏(TouchPanel)驱动简析(2)-DDSI函数-(基于WinCE5.0 SMDK2410 BSP的TouchPanel驱动)
- ASP.NET Core 2.0系列学习笔记-应用程序修改默认端口支持外网IP访问
- 修改文件时间与创建新文件:touch
- Android玩乐系列:修改汇编代码支持原生高清来电大头贴(一)
- 带有文本的触摸屏界面设计(Labeling Touchscreen Interfaces)
- 修改zepto源代码,使支持wp8的ie10
- 支持Touch ID!EOS 项目进展速报