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