Add protocol type B support to the evdevtouch plugin
Also adds optional support for libmtdev (a helper library which translates transparently from type A to B when using type A kernel drivers). Change-Id: Ic9c065b2fd130e9db2dd07e7dc103e9d45c08c99 Reviewed-by: Samuel Rødal <samuel.rodal@nokia.com>
This commit is contained in:
parent
c3a1af63ae
commit
88374c7963
@ -1,8 +1,14 @@
|
|||||||
Generic plug-in for evdev touch events. (protocol type A)
|
Generic plug-in for evdev touch (ABS_MT) events.
|
||||||
|
Supports protocol type A & B.
|
||||||
|
Type B is supported both directly and via libmtdev.
|
||||||
|
|
||||||
Tested with the following drivers: bcm5974, hid_magicmouse.
|
The protocol type will be detected automatically.
|
||||||
|
To enable libmtdev support uncomment the USE_MTDEV define in
|
||||||
|
evdevtouch.pro.
|
||||||
|
|
||||||
To use it, pass -plugin EvdevTouch on the command line.
|
Tested with the following kernel drivers: bcm5974, hid_magicmouse.
|
||||||
|
|
||||||
|
To use this "driver", pass -plugin EvdevTouch on the command line.
|
||||||
|
|
||||||
If automatic detection does not work, use -plugin
|
If automatic detection does not work, use -plugin
|
||||||
EvdevTouch:/dev/input/eventN to explicitly set the device file
|
EvdevTouch:/dev/input/eventN to explicitly set the device file
|
||||||
|
@ -15,3 +15,7 @@ QT += core-private platformsupport-private
|
|||||||
|
|
||||||
OTHER_FILES += \
|
OTHER_FILES += \
|
||||||
evdevtouch.json
|
evdevtouch.json
|
||||||
|
|
||||||
|
# DEFINES += USE_MTDEV
|
||||||
|
|
||||||
|
contains(DEFINES, USE_MTDEV): LIBS += -lmtdev
|
||||||
|
@ -49,8 +49,18 @@
|
|||||||
#include <QtPlatformSupport/private/qudevhelper_p.h>
|
#include <QtPlatformSupport/private/qudevhelper_p.h>
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
|
|
||||||
|
#ifdef USE_MTDEV
|
||||||
|
extern "C" {
|
||||||
|
#include <mtdev.h>
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
#ifndef ABS_MT_SLOT
|
||||||
|
#define ABS_MT_SLOT 0x2f
|
||||||
|
#endif
|
||||||
|
|
||||||
class QTouchScreenData
|
class QTouchScreenData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -75,8 +85,10 @@ public:
|
|||||||
x(0), y(0), maj(1), pressure(0),
|
x(0), y(0), maj(1), pressure(0),
|
||||||
state(Qt::TouchPointPressed), flags(0) { }
|
state(Qt::TouchPointPressed), flags(0) { }
|
||||||
};
|
};
|
||||||
QHash<int, Contact> m_contacts, m_lastContacts;
|
QHash<int, Contact> m_contacts; // The key is a tracking id for type A, slot number for type B.
|
||||||
|
QHash<int, Contact> m_lastContacts;
|
||||||
Contact m_currentData;
|
Contact m_currentData;
|
||||||
|
int m_currentSlot;
|
||||||
|
|
||||||
int findClosestContact(const QHash<int, Contact> &contacts, int x, int y, int *dist);
|
int findClosestContact(const QHash<int, Contact> &contacts, int x, int y, int *dist);
|
||||||
void reportPoints();
|
void reportPoints();
|
||||||
@ -91,11 +103,13 @@ public:
|
|||||||
QString hw_name;
|
QString hw_name;
|
||||||
bool m_forceToActiveWindow;
|
bool m_forceToActiveWindow;
|
||||||
QTouchDevice *m_device;
|
QTouchDevice *m_device;
|
||||||
|
bool m_typeB;
|
||||||
};
|
};
|
||||||
|
|
||||||
QTouchScreenData::QTouchScreenData(QTouchScreenHandler *q_ptr, const QStringList &args)
|
QTouchScreenData::QTouchScreenData(QTouchScreenHandler *q_ptr, const QStringList &args)
|
||||||
: q(q_ptr),
|
: q(q_ptr),
|
||||||
m_lastEventType(-1),
|
m_lastEventType(-1),
|
||||||
|
m_currentSlot(0),
|
||||||
hw_range_x_min(0), hw_range_x_max(0),
|
hw_range_x_min(0), hw_range_x_max(0),
|
||||||
hw_range_y_min(0), hw_range_y_max(0),
|
hw_range_y_min(0), hw_range_y_max(0),
|
||||||
hw_pressure_min(0), hw_pressure_max(0)
|
hw_pressure_min(0), hw_pressure_max(0)
|
||||||
@ -115,8 +129,19 @@ void QTouchScreenData::registerDevice()
|
|||||||
QWindowSystemInterface::registerTouchDevice(m_device);
|
QWindowSystemInterface::registerTouchDevice(m_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define LONG_BITS (sizeof(long) << 3)
|
||||||
|
#define NUM_LONGS(bits) (((bits) + LONG_BITS - 1) / LONG_BITS)
|
||||||
|
|
||||||
|
static inline bool testBit(long bit, const long *array)
|
||||||
|
{
|
||||||
|
return array[bit / LONG_BITS] & (1 << (bit & (LONG_BITS - 1)));
|
||||||
|
}
|
||||||
|
|
||||||
QTouchScreenHandler::QTouchScreenHandler(const QString &spec)
|
QTouchScreenHandler::QTouchScreenHandler(const QString &spec)
|
||||||
: m_notify(0), m_fd(-1), d(0)
|
: m_notify(0), m_fd(-1), d(0)
|
||||||
|
#ifdef USE_MTDEV
|
||||||
|
, m_mtdev(0)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
setObjectName(QLatin1String("Evdev Touch Handler"));
|
setObjectName(QLatin1String("Evdev Touch Handler"));
|
||||||
|
|
||||||
@ -141,6 +166,16 @@ QTouchScreenHandler::QTouchScreenHandler(const QString &spec)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_MTDEV
|
||||||
|
m_mtdev = static_cast<mtdev *>(calloc(1, sizeof(mtdev)));
|
||||||
|
int mtdeverr = mtdev_open(m_mtdev, m_fd);
|
||||||
|
if (mtdeverr) {
|
||||||
|
qWarning("mtdev_open failed: %d", mtdeverr);
|
||||||
|
QT_CLOSE(m_fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
d = new QTouchScreenData(this, args);
|
d = new QTouchScreenData(this, args);
|
||||||
|
|
||||||
input_absinfo absInfo;
|
input_absinfo absInfo;
|
||||||
@ -168,11 +203,30 @@ QTouchScreenHandler::QTouchScreenHandler(const QString &spec)
|
|||||||
qDebug("device name: %s", name);
|
qDebug("device name: %s", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_MTDEV
|
||||||
|
const char *mtdevStr = "(mtdev)";
|
||||||
|
d->m_typeB = true;
|
||||||
|
#else
|
||||||
|
const char *mtdevStr = "";
|
||||||
|
d->m_typeB = false;
|
||||||
|
long absbits[NUM_LONGS(ABS_CNT)];
|
||||||
|
if (ioctl(m_fd, EVIOCGBIT(EV_ABS, sizeof(absbits)), absbits) >= 0)
|
||||||
|
d->m_typeB = testBit(ABS_MT_SLOT, absbits);
|
||||||
|
#endif
|
||||||
|
qDebug("Protocol type %c %s", d->m_typeB ? 'B' : 'A', mtdevStr);
|
||||||
|
|
||||||
d->registerDevice();
|
d->registerDevice();
|
||||||
}
|
}
|
||||||
|
|
||||||
QTouchScreenHandler::~QTouchScreenHandler()
|
QTouchScreenHandler::~QTouchScreenHandler()
|
||||||
{
|
{
|
||||||
|
#ifdef USE_MTDEV
|
||||||
|
if (m_mtdev) {
|
||||||
|
mtdev_close(m_mtdev);
|
||||||
|
free(m_mtdev);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (m_fd >= 0)
|
if (m_fd >= 0)
|
||||||
QT_CLOSE(m_fd);
|
QT_CLOSE(m_fd);
|
||||||
|
|
||||||
@ -184,8 +238,13 @@ void QTouchScreenHandler::readData()
|
|||||||
::input_event buffer[32];
|
::input_event buffer[32];
|
||||||
int n = 0;
|
int n = 0;
|
||||||
for (; ;) {
|
for (; ;) {
|
||||||
|
#ifdef USE_MTDEV
|
||||||
|
n = mtdev_get(m_mtdev, m_fd, buffer, sizeof(buffer) / sizeof(::input_event));
|
||||||
|
if (n > 0)
|
||||||
|
n *= sizeof(::input_event);
|
||||||
|
#else
|
||||||
n = QT_READ(m_fd, reinterpret_cast<char*>(buffer) + n, sizeof(buffer) - n);
|
n = QT_READ(m_fd, reinterpret_cast<char*>(buffer) + n, sizeof(buffer) - n);
|
||||||
|
#endif
|
||||||
if (!n) {
|
if (!n) {
|
||||||
qWarning("Got EOF from input device");
|
qWarning("Got EOF from input device");
|
||||||
return;
|
return;
|
||||||
@ -215,16 +274,32 @@ void QTouchScreenData::processInputEvent(input_event *data)
|
|||||||
|
|
||||||
if (data->code == ABS_MT_POSITION_X) {
|
if (data->code == ABS_MT_POSITION_X) {
|
||||||
m_currentData.x = qBound(hw_range_x_min, data->value, hw_range_x_max);
|
m_currentData.x = qBound(hw_range_x_min, data->value, hw_range_x_max);
|
||||||
|
if (m_typeB)
|
||||||
|
m_contacts[m_currentSlot].x = m_currentData.x;
|
||||||
} else if (data->code == ABS_MT_POSITION_Y) {
|
} else if (data->code == ABS_MT_POSITION_Y) {
|
||||||
m_currentData.y = qBound(hw_range_y_min, data->value, hw_range_y_max);
|
m_currentData.y = qBound(hw_range_y_min, data->value, hw_range_y_max);
|
||||||
|
if (m_typeB)
|
||||||
|
m_contacts[m_currentSlot].y = m_currentData.y;
|
||||||
} else if (data->code == ABS_MT_TRACKING_ID) {
|
} else if (data->code == ABS_MT_TRACKING_ID) {
|
||||||
m_currentData.trackingId = data->value;
|
m_currentData.trackingId = data->value;
|
||||||
|
if (m_typeB) {
|
||||||
|
if (m_currentData.trackingId == -1)
|
||||||
|
m_contacts[m_currentSlot].state = Qt::TouchPointReleased;
|
||||||
|
else
|
||||||
|
m_contacts[m_currentSlot].trackingId = m_currentData.trackingId;
|
||||||
|
}
|
||||||
} else if (data->code == ABS_MT_TOUCH_MAJOR) {
|
} else if (data->code == ABS_MT_TOUCH_MAJOR) {
|
||||||
m_currentData.maj = data->value;
|
m_currentData.maj = data->value;
|
||||||
if (data->value == 0)
|
if (data->value == 0)
|
||||||
m_currentData.state = Qt::TouchPointReleased;
|
m_currentData.state = Qt::TouchPointReleased;
|
||||||
|
if (m_typeB)
|
||||||
|
m_contacts[m_currentSlot].maj = m_currentData.maj;
|
||||||
} else if (data->code == ABS_PRESSURE) {
|
} else if (data->code == ABS_PRESSURE) {
|
||||||
m_currentData.pressure = qBound(hw_pressure_min, data->value, hw_pressure_max);
|
m_currentData.pressure = qBound(hw_pressure_min, data->value, hw_pressure_max);
|
||||||
|
if (m_typeB)
|
||||||
|
m_contacts[m_currentSlot].pressure = m_currentData.pressure;
|
||||||
|
} else if (data->code == ABS_MT_SLOT) {
|
||||||
|
m_currentSlot = data->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (data->type == EV_SYN && data->code == SYN_MT_REPORT && m_lastEventType != EV_SYN) {
|
} else if (data->type == EV_SYN && data->code == SYN_MT_REPORT && m_lastEventType != EV_SYN) {
|
||||||
@ -254,8 +329,9 @@ void QTouchScreenData::processInputEvent(input_event *data)
|
|||||||
tp.id = contact.trackingId;
|
tp.id = contact.trackingId;
|
||||||
tp.flags = contact.flags;
|
tp.flags = contact.flags;
|
||||||
|
|
||||||
if (m_lastContacts.contains(contact.trackingId)) {
|
int key = m_typeB ? it.key() : contact.trackingId;
|
||||||
const Contact &prev(m_lastContacts.value(contact.trackingId));
|
if (m_lastContacts.contains(key)) {
|
||||||
|
const Contact &prev(m_lastContacts.value(key));
|
||||||
if (contact.state == Qt::TouchPointReleased) {
|
if (contact.state == Qt::TouchPointReleased) {
|
||||||
// Copy over the previous values for released points, just in case.
|
// Copy over the previous values for released points, just in case.
|
||||||
contact.x = prev.x;
|
contact.x = prev.x;
|
||||||
@ -269,7 +345,7 @@ void QTouchScreenData::processInputEvent(input_event *data)
|
|||||||
|
|
||||||
// Avoid reporting a contact in released state more than once.
|
// Avoid reporting a contact in released state more than once.
|
||||||
if (contact.state == Qt::TouchPointReleased
|
if (contact.state == Qt::TouchPointReleased
|
||||||
&& !m_lastContacts.contains(contact.trackingId)) {
|
&& !m_lastContacts.contains(key)) {
|
||||||
it.remove();
|
it.remove();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -293,6 +369,7 @@ void QTouchScreenData::processInputEvent(input_event *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_lastContacts = m_contacts;
|
m_lastContacts = m_contacts;
|
||||||
|
if (!m_typeB)
|
||||||
m_contacts.clear();
|
m_contacts.clear();
|
||||||
|
|
||||||
if (!m_touchPoints.isEmpty() && combinedStates != Qt::TouchPointStationary)
|
if (!m_touchPoints.isEmpty() && combinedStates != Qt::TouchPointStationary)
|
||||||
|
@ -54,6 +54,9 @@ QT_BEGIN_NAMESPACE
|
|||||||
|
|
||||||
class QSocketNotifier;
|
class QSocketNotifier;
|
||||||
class QTouchScreenData;
|
class QTouchScreenData;
|
||||||
|
#ifdef USE_MTDEV
|
||||||
|
struct mtdev;
|
||||||
|
#endif
|
||||||
|
|
||||||
class QTouchScreenHandler : public QObject
|
class QTouchScreenHandler : public QObject
|
||||||
{
|
{
|
||||||
@ -67,11 +70,12 @@ private slots:
|
|||||||
void readData();
|
void readData();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void pathFromUdev(QString *path);
|
|
||||||
|
|
||||||
QSocketNotifier *m_notify;
|
QSocketNotifier *m_notify;
|
||||||
int m_fd;
|
int m_fd;
|
||||||
QTouchScreenData *d;
|
QTouchScreenData *d;
|
||||||
|
#ifdef USE_MTDEV
|
||||||
|
mtdev *m_mtdev;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
class QTouchScreenHandlerThread : public QThread
|
class QTouchScreenHandlerThread : public QThread
|
||||||
|
Loading…
x
Reference in New Issue
Block a user