Qt 4.8
qbbbuttoneventnotifier.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Research In Motion <blackberry-qt@qnx.com>
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qbbbuttoneventnotifier.h"
43 
44 #include <QtGui/QApplication>
46 
47 #include <QtCore/QDebug>
48 #include <QtCore/QMetaEnum>
49 #include <QtCore/QSocketNotifier>
50 #include <QtCore/private/qcore_unix_p.h>
51 
52 //#define QBBBUTTON_DEBUG
53 
54 #ifdef QBBBUTTON_DEBUG
55 #define qButtonDebug qDebug
56 #else
57 #define qButtonDebug QT_NO_QDEBUG_MACRO
58 #endif
59 
61 
62 static const char *ppsPath = "/pps/system/buttons/status";
63 static const int ppsBufferSize = 256;
64 
66  : QObject(parent),
67  mFd(-1),
68  mReadNotifier(0)
69 {
70  // Set initial state of buttons to ButtonUp and
71  // fetch the new button ids
72  int enumeratorIndex = QBBButtonEventNotifier::staticMetaObject.indexOfEnumerator("ButtonId");
74  for (int buttonId = bid_minus; buttonId < ButtonCount; ++buttonId) {
75  mButtonKeys.append(enumerator.valueToKey(buttonId));
76  mState[buttonId] = ButtonUp;
77  }
78 }
79 
81 {
82  close();
83 }
84 
86 {
87  qButtonDebug() << Q_FUNC_INFO << "starting hardware button event processing";
88  if (mFd != -1)
89  return;
90 
91  // Open the pps interface
92  errno = 0;
94  if (mFd == -1) {
95  qWarning("QQNX: failed to open buttons pps, errno=%d", errno);
96  return;
97  }
98 
100  QObject::connect(mReadNotifier, SIGNAL(activated(int)), this, SLOT(updateButtonStates()));
101 
102  qButtonDebug() << Q_FUNC_INFO << "successfully connected to Navigator. fd =" << mFd;
103 }
104 
106 {
107  // Allocate buffer for pps data
108  char buffer[ppsBufferSize];
109 
110  // Attempt to read pps data
111  errno = 0;
112  int bytes = qt_safe_read(mFd, buffer, ppsBufferSize - 1);
113  qButtonDebug() << "Read" << bytes << "bytes of data";
114  if (bytes == -1) {
115  qWarning("QQNX: failed to read hardware buttons pps object, errno=%d", errno);
116  return;
117  }
118 
119  // We seem to get a spurious read notification after the real one. Ignore it
120  if (bytes == 0)
121  return;
122 
123  // Ensure data is null terminated
124  buffer[bytes] = '\0';
125 
126  qButtonDebug() << Q_FUNC_INFO << "received PPS message:\n" << buffer;
127 
128  // Process received message
129  QByteArray ppsData = QByteArray::fromRawData(buffer, bytes);
131  if (!parsePPS(ppsData, &fields))
132  return;
133 
134  // Update our state and inject key events as needed
135  for (int buttonId = bid_minus; buttonId < ButtonCount; ++buttonId) {
136  // Extract the new button state
137  QByteArray key = mButtonKeys.at(buttonId);
138  ButtonState newState = (fields.value(key) == QByteArray("b_up") ? ButtonUp : ButtonDown);
139 
140  // If state has changed, update our state and inject a keypress event
141  if (mState[buttonId] != newState) {
142  qButtonDebug() << "Hardware button event: button =" << key << "state =" << fields.value(key);
143  mState[buttonId] = newState;
144 
145  // Is it a key press or key release event?
147 
148  Qt::Key key;
149  switch (buttonId) {
150  case bid_minus:
151  key = Qt::Key_VolumeDown;
152  break;
153 
154  case bid_playpause:
155  key = Qt::Key_Play;
156  break;
157 
158  case bid_plus:
159  key = Qt::Key_VolumeUp;
160  break;
161 
162  case bid_power:
163  key = Qt::Key_PowerDown;
164  break;
165 
166  default:
167  qButtonDebug() << "Unknown hardware button";
168  continue;
169  }
170 
171  // No modifiers
172  Qt::KeyboardModifiers modifier = Qt::NoModifier;
173 
174  // Post the event
176  }
177  }
178 }
179 
181 {
182  delete mReadNotifier;
183  mReadNotifier = 0;
184 
185  if (mFd != -1) {
187  mFd = -1;
188  }
189 }
190 
192 {
193  // tokenize pps data into lines
194  QList<QByteArray> lines = ppsData.split('\n');
195 
196  // validate pps object
197  if (lines.size() == 0 || !lines.at(0).contains(QByteArray("@status"))) {
198  qWarning("QQNX: unrecognized pps object, data=%s", ppsData.constData());
199  return false;
200  }
201 
202  // parse pps object attributes and extract values
203  for (int i = 1; i < lines.size(); i++) {
204 
205  // tokenize current attribute
206  const QByteArray &attr = lines.at(i);
207 
208  qButtonDebug() << Q_FUNC_INFO << "attr=" << attr;
209 
210  int doubleColon = attr.indexOf(QByteArray("::"));
211  if (doubleColon == -1) {
212  // abort - malformed attribute
213  continue;
214  }
215 
216  QByteArray key = attr.left(doubleColon);
217  QByteArray value = attr.mid(doubleColon + 2);
218  messageFields->insert(key, value);
219  }
220  return true;
221 }
222 
int type
Definition: qmetatype.cpp:239
The QMetaEnum class provides meta-data about an enumerator.
Definition: qmetaobject.h:147
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
QSocketNotifier * mReadNotifier
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
static QWidget * activeWindow()
Returns the application top-level window that has the keyboard input focus, or 0 if no application wi...
#define SLOT(a)
Definition: qobjectdefs.h:226
#define O_RDONLY
QBBButtonEventNotifier(QObject *parent=0)
static void handleKeyEvent(QWidget *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString &text=QString(), bool autorep=false, ushort count=1)
const char * valueToKey(int value) const
Returns the string that is used as the name of the given enumeration value, or 0 if value is not defi...
static const QMetaObject staticMetaObject
This variable stores the meta-object for the class.
Definition: qobject.h:128
static int qt_safe_close(int fd)
Definition: qcore_unix_p.h:297
The QHash class is a template class that provides a hash-table-based dictionary.
Definition: qdatastream.h:66
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
const T value(const Key &key) const
Returns the value associated with the key.
Definition: qhash.h:606
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition: qhash.h:753
The QSocketNotifier class provides support for monitoring activity on a file descriptor.
#define SIGNAL(a)
Definition: qobjectdefs.h:227
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
static int qt_safe_open(const char *pathname, int flags, mode_t mode=0777)
Definition: qcore_unix_p.h:171
static bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Creates a connection of the given type from the signal in the sender object to the method in the rece...
Definition: qobject.cpp:2580
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
static QByteArray fromRawData(const char *, int size)
Constructs a QByteArray that uses the first size bytes of the data array.
Q_CORE_EXPORT void qWarning(const char *,...)
QByteArray mid(int index, int len=-1) const
Returns a byte array containing len bytes from this byte array, starting at position pos...
int indexOf(char c, int from=0) const
Returns the index position of the first occurrence of the character ch in the byte array...
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
QList< QByteArray > mButtonKeys
QList< QByteArray > split(char sep) const
Splits the byte array into subarrays wherever sep occurs, and returns the list of those arrays...
#define qButtonDebug
Type
This enum type defines the valid event types in Qt.
Definition: qcoreevent.h:62
static const int ppsBufferSize
int key
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
QMetaEnum enumerator(int index) const
Returns the meta-data for the enumerator with the given index.
static const char * ppsPath
int indexOfEnumerator(const char *name) const
Finds enumerator name and returns its index; otherwise returns -1.
ButtonState mState[ButtonCount]
static qint64 qt_safe_read(int fd, void *data, qint64 maxlen)
Definition: qcore_unix_p.h:273
int errno
QBool contains(char c) const
Returns true if the byte array contains the character ch; otherwise returns false.
Definition: qbytearray.h:525
bool parsePPS(const QByteArray &ppsData, QHash< QByteArray, QByteArray > *messageFields) const
#define Q_FUNC_INFO
Definition: qglobal.h:1871