1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui 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 The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file. Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #if !defined(QT_NO_QWS_KEYBOARD) && !defined(QT_NO_QWS_KBD_INTEGRITY)
43
44 #include "qkbdintegrity_qws.h"
45 #include <qwindowsystem_qws.h>
46 #include <qapplication.h>
47 #include <qtimer.h>
48 #include <INTEGRITY.h>
49 #include <QThread>
50 #include <device/hiddriver.h>
51
52 //===========================================================================
53
54 QT_BEGIN_NAMESPACE
55
56 //
57 // INTEGRITY keyboard
58 //
59
60 static const struct KeyMapEntryStruct {
61 int key;
62 QChar qchar;
63 } keyMap[] = {
64 { 0, 0 },
65 { Qt::Key_Escape, 0 },
66 { Qt::Key_1, '1' },
67 { Qt::Key_2, '2' },
68 { Qt::Key_3, '3' },
69 { Qt::Key_4, '4' },
70 { Qt::Key_5, '5' },
71 { Qt::Key_6, '6' },
72 { Qt::Key_7, '7' },
73 { Qt::Key_8, '8' },
74 { Qt::Key_9, '9' },
75 { Qt::Key_0, '0' },
76 { Qt::Key_Minus, '-' },
77 { Qt::Key_Equal, '=' },
78 { Qt::Key_Backspace, 0 },
79 { Qt::Key_Tab, '\t' },
80 { Qt::Key_Q, 'q' },
81 { Qt::Key_W, 'w' },
82 { Qt::Key_E, 'e' },
83 { Qt::Key_R, 'r' },
84 { Qt::Key_T, 't' },
85 { Qt::Key_Y, 'y' },
86 { Qt::Key_U, 'u' },
87 { Qt::Key_I, 'i' },
88 { Qt::Key_O, 'o' },
89 { Qt::Key_P, 'p' },
90 { Qt::Key_BraceLeft, '{' },
91 { Qt::Key_BraceRight, '}' },
92 { Qt::Key_Enter, '\n' },
93 { Qt::Key_Control, 0 },
94 { Qt::Key_A, 'a' },
95 { Qt::Key_S, 's' },
96 { Qt::Key_D, 'd' },
97 { Qt::Key_F, 'f' },
98 { Qt::Key_G, 'g' },
99 { Qt::Key_H, 'h' },
100 { Qt::Key_J, 'j' },
101 { Qt::Key_K, 'k' },
102 { Qt::Key_L, 'l' },
103 { Qt::Key_Semicolon, ';' },
104 { Qt::Key_Apostrophe, '\'' },
105 { Qt::Key_Dead_Grave, 0 },
106 { Qt::Key_Shift, 0 },
107 { Qt::Key_Backslash, '\\' },
108 { Qt::Key_Z, 'z' },
109 { Qt::Key_X, 'x' },
110 { Qt::Key_C, 'c' },
111 { Qt::Key_V, 'v' },
112 { Qt::Key_B, 'b' },
113 { Qt::Key_N, 'n' },
114 { Qt::Key_M, 'm' },
115 { Qt::Key_Comma, ',' },
116 { Qt::Key_NumberSign, '.' },
117 { Qt::Key_Slash, '/' },
118 { Qt::Key_Shift, 0 },
119 { Qt::Key_Asterisk, '*' },
120 { Qt::Key_Alt, 0 },
121 };
122
123
124 class QIntKeyboardListenThread;
125
126 class QWSIntKbPrivate : public QObject
127 {
128 Q_OBJECT
129 friend class QIntKeyboardListenThread;
130 public:
131 QWSIntKbPrivate(QWSKeyboardHandler *, const QString &device);
132 ~QWSIntKbPrivate();
dataReady(uint32_t keycode,bool pressed)133 void dataReady(uint32_t keycode, bool pressed) { emit kbdDataAvailable(keycode, pressed); }
134
135 Q_SIGNALS:
136 void kbdDataAvailable(uint32_t keycode, bool pressed);
137
138 private Q_SLOTS:
139 void readKeyboardData(uint32_t keycode, bool pressed);
140
141 private:
142 QWSKeyboardHandler *handler;
143 QIntKeyboardListenThread *kbdthread;
144 };
145 class QIntKeyboardListenThread : public QThread
146 {
147 protected:
148 QWSIntKbPrivate *imp;
149 bool loop;
150 QList<HIDHandle> handleList;
151 QList<Activity> actList;
152 Semaphore loopsem;
153 public:
QIntKeyboardListenThread(QWSIntKbPrivate * im)154 QIntKeyboardListenThread(QWSIntKbPrivate *im) : QThread(), imp(im) {};
~QIntKeyboardListenThread()155 ~QIntKeyboardListenThread() {};
156 bool setup(QString driverName, uint32_t index);
157 void run();
stoploop()158 void stoploop() { loop = false; ReleaseSemaphore(loopsem); };
159 };
160
161
QWSIntKeyboardHandler(const QString & device)162 QWSIntKeyboardHandler::QWSIntKeyboardHandler(const QString &device)
163 : QWSKeyboardHandler(device)
164 {
165 d = new QWSIntKbPrivate(this, device);
166 }
167
~QWSIntKeyboardHandler()168 QWSIntKeyboardHandler::~QWSIntKeyboardHandler()
169 {
170 delete d;
171 }
172
setup(QString driverName,uint32_t index)173 bool QIntKeyboardListenThread::setup(QString driverName, uint32_t index)
174 {
175 int i;
176 int devices;
177 Error driverError, deviceError;
178 HIDDriver *driver;
179 HIDHandle handle;
180 /* FIXME : take a list of driver names/indexes for setup */
181 devices = 0;
182 i = 0;
183 do {
184 driverError = gh_hid_get_driver(i, &driver);
185 if (driverError == Success) {
186 int j = 0;
187 do {
188 deviceError = gh_hid_init_device(driver, j, &handle);
189 if (deviceError == Success) {
190 int32_t type;
191 /* only accept non-pointing devices */
192 deviceError = gh_hid_get_setting(handle, HID_SETTING_CAPABILITIES, &type);
193 if ((deviceError == Success) && !(type & HID_TYPE_AXIS)) {
194 handleList.append(handle);
195 devices++;
196 } else
197 gh_hid_close(handle);
198 j++;
199 }
200 } while (deviceError == Success);
201 i++;
202 }
203 } while (driverError == Success);
204 return (devices > 0);
205 }
206
run(void)207 void QIntKeyboardListenThread::run(void)
208 {
209 Value id;
210 HIDEvent event;
211 Activity loopact;
212 QPoint currentpos(0,0);
213 Qt::MouseButtons currentbutton = Qt::NoButton;
214 Qt::KeyboardModifiers keymod;
215
216 /* first create all Activities for the main loop.
217 * We couldn't do this in setup() because this Task is different */
218 Activity act;
219 int i = 0;
220 foreach (HIDHandle h, handleList) {
221 CheckSuccess(CreateActivity(CurrentTask(), 2, false, i, &act));
222 actList.append(act);
223 i++;
224 CheckSuccess(gh_hid_async_wait_for_event(h, act));
225 }
226
227 /* setup a Semaphore used to watch for a request for exit */
228 CheckSuccess(CreateSemaphore(0, &loopsem));
229 CheckSuccess(CreateActivity(CurrentTask(), 2, false, 0, &loopact));
230 CheckSuccess(AsynchronousReceive(loopact, (Object)loopsem, NULL));
231
232 loop = true;
233 do {
234 Boolean nokeynotify = false;
235 uint32_t num_events = 1;
236 WaitForActivity(&id);
237 if (loop) {
238 while (gh_hid_get_event(handleList.at(id), &event, &num_events) == Success) {
239 if (event.type == HID_TYPE_KEY) {
240 switch (event.index) {
241 case HID_KEY_LEFTALT:
242 case HID_KEY_RIGHTALT:
243 if (event.value)
244 keymod |= Qt::AltModifier;
245 else
246 keymod &= ~Qt::AltModifier;
247 break;
248 case HID_KEY_LEFTSHIFT:
249 case HID_KEY_RIGHTSHIFT:
250 if (event.value)
251 keymod |= Qt::ShiftModifier;
252 else
253 keymod &= ~Qt::ShiftModifier;
254 break;
255 case HID_KEY_LEFTCTRL:
256 case HID_KEY_RIGHTCTRL:
257 if (event.value)
258 keymod |= Qt::ControlModifier;
259 else
260 keymod &= ~Qt::ControlModifier;
261 break;
262 default:
263 break;
264 }
265 QEvent::Type type;
266 if (event.value)
267 type = QEvent::KeyPress;
268 else
269 type = QEvent::KeyRelease;
270 //QWindowSystemInterface::handleKeyEvent(0, type,
271 //keyMap[event.index].key, keymod, keyMap[event.index].qchar);
272 imp->dataReady(event.index, event.value);
273 }
274 }
275 CheckSuccess(gh_hid_async_wait_for_event(handleList.at(id), actList.at(id)));
276 }
277 } while (loop);
278 QThread::exit(0);
279 }
280
readKeyboardData(uint32_t keycode,bool pressed)281 void QWSIntKbPrivate::readKeyboardData(uint32_t keycode, bool pressed)
282 {
283 handler->processKeycode(keycode, pressed, false);
284 }
285
QWSIntKbPrivate(QWSKeyboardHandler * h,const QString & device)286 QWSIntKbPrivate::QWSIntKbPrivate(QWSKeyboardHandler *h, const QString &device) : handler(h)
287 {
288 connect(this, SIGNAL(kbdDataAvailable(uint32_t, bool)), this, SLOT(readKeyboardData(uint32_t, bool)));
289 this->handler = handler;
290 qDebug("Opening INTEGRITY keyboard");
291 kbdthread = new QIntKeyboardListenThread(this);
292 kbdthread->start();
293 }
294
~QWSIntKbPrivate()295 QWSIntKbPrivate::~QWSIntKbPrivate()
296 {
297 kbdthread->stoploop();
298 kbdthread->wait();
299 delete kbdthread;
300 }
301
302 QT_END_NAMESPACE
303
304 #include "qkbdintegrity_qws.moc"
305
306 #endif // QT_NO_QWS_KEYBOARD || QT_NO_QWS_KBD_TTY
307