1 | /****************************************************************************
|
---|
2 | **
|
---|
3 | ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
---|
4 | ** All rights reserved.
|
---|
5 | ** Contact: Nokia Corporation (qt-info@nokia.com)
|
---|
6 | **
|
---|
7 | ** This file is part of the QtGui module of the Qt Toolkit.
|
---|
8 | **
|
---|
9 | ** $QT_BEGIN_LICENSE:LGPL$
|
---|
10 | ** Commercial Usage
|
---|
11 | ** Licensees holding valid Qt Commercial licenses may use this file in
|
---|
12 | ** accordance with the Qt Commercial License Agreement provided with the
|
---|
13 | ** Software or, alternatively, in accordance with the terms contained in
|
---|
14 | ** a written agreement between you and Nokia.
|
---|
15 | **
|
---|
16 | ** GNU Lesser General Public License Usage
|
---|
17 | ** Alternatively, this file may be used under the terms of the GNU Lesser
|
---|
18 | ** General Public License version 2.1 as published by the Free Software
|
---|
19 | ** Foundation and appearing in the file LICENSE.LGPL included in the
|
---|
20 | ** packaging of this file. Please review the following information to
|
---|
21 | ** ensure the GNU Lesser General Public License version 2.1 requirements
|
---|
22 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
---|
23 | **
|
---|
24 | ** In addition, as a special exception, Nokia gives you certain additional
|
---|
25 | ** rights. These rights are described in the Nokia Qt LGPL Exception
|
---|
26 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
---|
27 | **
|
---|
28 | ** GNU General Public License Usage
|
---|
29 | ** Alternatively, this file may be used under the terms of the GNU
|
---|
30 | ** General Public License version 3.0 as published by the Free Software
|
---|
31 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
---|
32 | ** packaging of this file. Please review the following information to
|
---|
33 | ** ensure the GNU General Public License version 3.0 requirements will be
|
---|
34 | ** met: http://www.gnu.org/copyleft/gpl.html.
|
---|
35 | **
|
---|
36 | ** If you have questions regarding the use of this file, please contact
|
---|
37 | ** Nokia at qt-info@nokia.com.
|
---|
38 | ** $QT_END_LICENSE$
|
---|
39 | **
|
---|
40 | ****************************************************************************/
|
---|
41 |
|
---|
42 | #include "qkbdqnx_qws.h"
|
---|
43 | #include "QtCore/qsocketnotifier.h"
|
---|
44 | #include "QtCore/qdebug.h"
|
---|
45 |
|
---|
46 | #include <sys/dcmd_input.h>
|
---|
47 | #include <photon/keycodes.h>
|
---|
48 |
|
---|
49 | #include "qplatformdefs.h"
|
---|
50 | #include <errno.h>
|
---|
51 |
|
---|
52 |
|
---|
53 | QT_BEGIN_NAMESPACE
|
---|
54 |
|
---|
55 | /*!
|
---|
56 | \class QWSQnxKeyboardHandler
|
---|
57 | \preliminary
|
---|
58 | \ingroup qws
|
---|
59 | \since 4.6
|
---|
60 | \internal
|
---|
61 |
|
---|
62 | \brief The QWSQnxKeyboardHandler class implements a keyboard driver
|
---|
63 | for the QNX \c{devi-hid} input manager.
|
---|
64 |
|
---|
65 | To be able to compile this mouse handler, \l{Qt for Embedded Linux}
|
---|
66 | must be configured with the \c -qt-kbd-qnx option, see the
|
---|
67 | \l{Qt for Embedded Linux Character Input} documentation for details.
|
---|
68 |
|
---|
69 | In order to use this keyboard handler, the \c{devi-hid} input manager
|
---|
70 | must be set up and run with the resource manager interface (option \c{-r}).
|
---|
71 | Also, Photon must not be running.
|
---|
72 |
|
---|
73 | Example invocation from command line: \c{/usr/photon/bin/devi-hid -Pr kbd mouse}
|
---|
74 | Note that after running \c{devi-hid}, you will not be able to use the local
|
---|
75 | shell anymore. It is suggested to run the command in a shell scrip, that launches
|
---|
76 | a Qt application after invocation of \c{devi-hid}.
|
---|
77 |
|
---|
78 | To make \l{Qt for Embedded Linux} explicitly choose the qnx keyboard
|
---|
79 | handler, set the QWS_KEYBOARD environment variable to \c{qnx}. By default,
|
---|
80 | the first keyboard device (\c{/dev/devi/keyboard0}) is used. To override, pass a device
|
---|
81 | name as the first and only parameter, for example
|
---|
82 | \c{QWS_KEYBOARD=qnx:/dev/devi/keyboard1; export QWS_KEYBOARD}.
|
---|
83 |
|
---|
84 | \sa {Qt for Embedded Linux Character Input}, {Qt for Embedded Linux}
|
---|
85 | */
|
---|
86 |
|
---|
87 | /*!
|
---|
88 | Constructs a keyboard handler for the specified \a device, defaulting to
|
---|
89 | \c{/dev/devi/keyboard0}.
|
---|
90 |
|
---|
91 | Note that you should never instanciate this class, instead let QKbdDriverFactory
|
---|
92 | handle the keyboard handlers.
|
---|
93 |
|
---|
94 | \sa QKbdDriverFactory
|
---|
95 | */
|
---|
96 | QWSQnxKeyboardHandler::QWSQnxKeyboardHandler(const QString &device)
|
---|
97 | {
|
---|
98 | // open the keyboard device
|
---|
99 | keyboardFD = QT_OPEN(device.isEmpty() ? "/dev/devi/keyboard0" : device.toLatin1().constData(),
|
---|
100 | QT_OPEN_RDONLY);
|
---|
101 | if (keyboardFD == -1) {
|
---|
102 | qErrnoWarning(errno, "QWSQnxKeyboardHandler: Unable to open device");
|
---|
103 | return;
|
---|
104 | }
|
---|
105 |
|
---|
106 | // create a socket notifier so we'll wake up whenever keyboard input is detected.
|
---|
107 | QSocketNotifier *notifier = new QSocketNotifier(keyboardFD, QSocketNotifier::Read, this);
|
---|
108 | connect(notifier, SIGNAL(activated(int)), SLOT(socketActivated()));
|
---|
109 |
|
---|
110 | qDebug() << "QWSQnxKeyboardHandler: connected.";
|
---|
111 |
|
---|
112 | }
|
---|
113 |
|
---|
114 | /*!
|
---|
115 | Destroys this keyboard handler and closes the connection to the keyboard device.
|
---|
116 | */
|
---|
117 | QWSQnxKeyboardHandler::~QWSQnxKeyboardHandler()
|
---|
118 | {
|
---|
119 | QT_CLOSE(keyboardFD);
|
---|
120 | }
|
---|
121 |
|
---|
122 | /*! \internal
|
---|
123 | Translates the QNX keyboard events to Qt keyboard events
|
---|
124 | */
|
---|
125 | void QWSQnxKeyboardHandler::socketActivated()
|
---|
126 | {
|
---|
127 | _keyboard_packet packet;
|
---|
128 |
|
---|
129 | // read one keyboard event
|
---|
130 | int bytesRead = QT_READ(keyboardFD, &packet, sizeof(_keyboard_packet));
|
---|
131 | if (bytesRead == -1) {
|
---|
132 | qErrnoWarning(errno, "QWSQnxKeyboardHandler::socketActivated(): Unable to read data.");
|
---|
133 | return;
|
---|
134 | }
|
---|
135 |
|
---|
136 | // the bytes read must be the size of a keyboard packet
|
---|
137 | Q_ASSERT(bytesRead == sizeof(_keyboard_packet));
|
---|
138 |
|
---|
139 | #if 0
|
---|
140 | qDebug() << "keyboard got scancode"
|
---|
141 | << hex << packet.data.modifiers
|
---|
142 | << packet.data.flags
|
---|
143 | << packet.data.key_cap
|
---|
144 | << packet.data.key_sym
|
---|
145 | << packet.data.key_scan;
|
---|
146 | #endif
|
---|
147 |
|
---|
148 | // QNX is nice enough to translate the raw keyboard data into a QNX data structure
|
---|
149 | // Now we just have to translate it into a format Qt understands.
|
---|
150 |
|
---|
151 | // figure out whether it's a press
|
---|
152 | bool isPress = packet.data.key_cap & KEY_DOWN;
|
---|
153 | // figure out whether the key is still pressed and the key event is repeated
|
---|
154 | bool isRepeat = packet.data.key_cap & KEY_REPEAT;
|
---|
155 |
|
---|
156 | Qt::Key key = Qt::Key_unknown;
|
---|
157 | int unicode = 0xffff;
|
---|
158 |
|
---|
159 | // TODO - this switch is not complete!
|
---|
160 | switch (packet.data.key_scan) {
|
---|
161 | case KEYCODE_SPACE: key = Qt::Key_Space; unicode = 0x20; break;
|
---|
162 | case KEYCODE_F1: key = Qt::Key_F1; break;
|
---|
163 | case KEYCODE_F2: key = Qt::Key_F2; break;
|
---|
164 | case KEYCODE_F3: key = Qt::Key_F3; break;
|
---|
165 | case KEYCODE_F4: key = Qt::Key_F4; break;
|
---|
166 | case KEYCODE_F5: key = Qt::Key_F5; break;
|
---|
167 | case KEYCODE_F6: key = Qt::Key_F6; break;
|
---|
168 | case KEYCODE_F7: key = Qt::Key_F7; break;
|
---|
169 | case KEYCODE_F8: key = Qt::Key_F8; break;
|
---|
170 | case KEYCODE_F9: key = Qt::Key_F9; break;
|
---|
171 | case KEYCODE_F10: key = Qt::Key_F10; break;
|
---|
172 | case KEYCODE_F11: key = Qt::Key_F11; break;
|
---|
173 | case KEYCODE_F12: key = Qt::Key_F12; break;
|
---|
174 | case KEYCODE_BACKSPACE: key = Qt::Key_Backspace; break;
|
---|
175 | case KEYCODE_TAB: key = Qt::Key_Tab; break;
|
---|
176 | case KEYCODE_RETURN: key = Qt::Key_Return; break;
|
---|
177 | case KEYCODE_KP_ENTER: key = Qt::Key_Enter; break;
|
---|
178 | case KEYCODE_UP:
|
---|
179 | case KEYCODE_KP_UP:
|
---|
180 | key = Qt::Key_Up; break;
|
---|
181 | case KEYCODE_DOWN:
|
---|
182 | case KEYCODE_KP_DOWN:
|
---|
183 | key = Qt::Key_Down; break;
|
---|
184 | case KEYCODE_LEFT:
|
---|
185 | case KEYCODE_KP_LEFT:
|
---|
186 | key = Qt::Key_Left; break;
|
---|
187 | case KEYCODE_RIGHT:
|
---|
188 | case KEYCODE_KP_RIGHT:
|
---|
189 | key = Qt::Key_Right; break;
|
---|
190 | case KEYCODE_HOME:
|
---|
191 | case KEYCODE_KP_HOME:
|
---|
192 | key = Qt::Key_Home; break;
|
---|
193 | case KEYCODE_END:
|
---|
194 | case KEYCODE_KP_END:
|
---|
195 | key = Qt::Key_End; break;
|
---|
196 | case KEYCODE_PG_UP:
|
---|
197 | case KEYCODE_KP_PG_UP:
|
---|
198 | key = Qt::Key_PageUp; break;
|
---|
199 | case KEYCODE_PG_DOWN:
|
---|
200 | case KEYCODE_KP_PG_DOWN:
|
---|
201 | key = Qt::Key_PageDown; break;
|
---|
202 | case KEYCODE_INSERT:
|
---|
203 | case KEYCODE_KP_INSERT:
|
---|
204 | key = Qt::Key_Insert; break;
|
---|
205 | case KEYCODE_DELETE:
|
---|
206 | case KEYCODE_KP_DELETE:
|
---|
207 | key = Qt::Key_Delete; break;
|
---|
208 | case KEYCODE_ESCAPE:
|
---|
209 | key = Qt::Key_Escape; break;
|
---|
210 | default: // none of the above, try the key_scan directly
|
---|
211 | unicode = packet.data.key_scan;
|
---|
212 | break;
|
---|
213 | }
|
---|
214 |
|
---|
215 | // figure out the modifiers that are currently pressed
|
---|
216 | Qt::KeyboardModifiers modifiers = Qt::NoModifier;
|
---|
217 | if (packet.data.flags & KEYMOD_SHIFT)
|
---|
218 | modifiers |= Qt::ShiftModifier;
|
---|
219 | if (packet.data.flags & KEYMOD_CTRL)
|
---|
220 | modifiers |= Qt::ControlModifier;
|
---|
221 | if (packet.data.flags & KEYMOD_ALT)
|
---|
222 | modifiers |= Qt::AltModifier;
|
---|
223 |
|
---|
224 | // if the unicode value is not ascii, we ignore it.
|
---|
225 | // TODO - do a complete mapping between all QNX scan codes and Qt codes
|
---|
226 | if (unicode != 0xffff && !isascii(unicode))
|
---|
227 | return; // unprintable character
|
---|
228 |
|
---|
229 | // call processKeyEvent. This is where all the magic happens to insert a
|
---|
230 | // key event into Qt's event loop.
|
---|
231 | // Note that for repeated key events, isPress must be true
|
---|
232 | // (on QNX, isPress is not set when the key event is repeated).
|
---|
233 | processKeyEvent(unicode, key, modifiers, isPress || isRepeat, isRepeat);
|
---|
234 | }
|
---|
235 |
|
---|
236 | QT_END_NAMESPACE
|
---|