Qt 4.8
qkbdtty_qws.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
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 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 "qkbdtty_qws.h"
43 
44 #if !defined(QT_NO_QWS_KEYBOARD) && !defined(QT_NO_QWS_KBD_TTY)
45 
46 #include <QSocketNotifier>
47 #include <QStringList>
48 
49 #include <qplatformdefs.h>
50 #include <private/qcore_unix_p.h> // overrides QT_OPEN
51 
52 #include <errno.h>
53 #include <termios.h>
54 
55 #if defined Q_OS_LINUX
56 # include <linux/kd.h>
57 # include <linux/vt.h> //TODO: move vt handling somewhere else (QLinuxFbScreen?)
58 
59 # include "qscreen_qws.h"
60 # include "qwindowsystem_qws.h"
61 # include "qapplication.h"
62 # include "private/qwindowsurface_qws_p.h"
63 # include "private/qwssignalhandler_p.h"
64 
65 # define VTACQSIG SIGUSR1
66 # define VTRELSIG SIGUSR2
67 #endif
68 
69 
71 
72 class QWSTtyKbPrivate : public QObject
73 {
74  Q_OBJECT
75 public:
78 
79 private:
80  void switchLed(char, bool);
81  void switchConsole(int vt);
82 
83 private Q_SLOTS:
84  void readKeycode();
85  void handleConsoleSwitch(int sig);
86 
87 private:
89  int m_tty_fd;
90  struct termios m_tty_attr;
92  int m_vt_qws;
94 };
95 
96 
98  : QWSKeyboardHandler(device)
99 {
100  d = new QWSTtyKbPrivate(this, device);
101 }
102 
104 {
105  delete d;
106 }
107 
109 {
110  return false;
111 }
112 
114  : m_handler(h), m_tty_fd(-1), m_last_keycode(0), m_vt_qws(0), m_orig_kbmode(K_XLATE)
115 {
116  setObjectName(QLatin1String("TTY Keyboard Handler"));
117 #ifndef QT_NO_QWS_SIGNALHANDLER
119 #endif
120 
121  QString dev = QLatin1String("/dev/tty0");
122  int repeat_delay = -1;
123  int repeat_rate = -1;
124 
125  QStringList args = device.split(QLatin1Char(':'));
126  foreach (const QString &arg, args) {
127  if (arg.startsWith(QLatin1String("repeat-delay=")))
128  repeat_delay = arg.mid(13).toInt();
129  else if (arg.startsWith(QLatin1String("repeat-rate=")))
130  repeat_rate = arg.mid(12).toInt();
131  else if (arg.startsWith(QLatin1String("/dev/")))
132  dev = arg;
133  }
134 
136  if (m_tty_fd >= 0) {
137  if (repeat_delay > 0 && repeat_rate > 0) {
138 #if defined(Q_OS_LINUX)
139  struct ::kbd_repeat kbdrep = { repeat_delay, repeat_rate };
140  ::ioctl(m_tty_fd, KDKBDREP, &kbdrep);
141 #endif
142  }
143 
144  QSocketNotifier *notifier;
145  notifier = new QSocketNotifier(m_tty_fd, QSocketNotifier::Read, this);
146  connect(notifier, SIGNAL(activated(int)), this, SLOT(readKeycode()));
147 
148  // save tty config for restore.
149  tcgetattr(m_tty_fd, &m_tty_attr);
150 
151  struct ::termios termdata;
152  tcgetattr(m_tty_fd, &termdata);
153 
154 #if defined(Q_OS_LINUX)
155  // record the original mode so we can restore it again in the destructor.
156  ::ioctl(m_tty_fd, KDGKBMODE, &m_orig_kbmode);
157 
158  // PLEASE NOTE:
159  // the tty keycode interface can only report keycodes 0x01 .. 0x7f
160  // KEY_MAX is however defined to 0x1ff. In practice this is sufficient
161  // for a PC style keyboard though.
162  // we don't support K_RAW anymore - if you need that, you have to add
163  // a scan- to keycode converter yourself.
164  ::ioctl(m_tty_fd, KDSKBMODE, K_MEDIUMRAW);
165 #endif
166 
167  // set the tty layer to pass-through
168  termdata.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP);
169  termdata.c_oflag = 0;
170  termdata.c_cflag = CREAD | CS8;
171  termdata.c_lflag = 0;
172  termdata.c_cc[VTIME]=0;
173  termdata.c_cc[VMIN]=1;
174  cfsetispeed(&termdata, 9600);
175  cfsetospeed(&termdata, 9600);
176  tcsetattr(m_tty_fd, TCSANOW, &termdata);
177 
178 #if defined(Q_OS_LINUX)
179  // VT switching is handled via unix signals
180  connect(QApplication::instance(), SIGNAL(unixSignal(int)), this, SLOT(handleConsoleSwitch(int)));
183 
184  struct ::vt_mode vtMode;
185  if (::ioctl(m_tty_fd, VT_GETMODE, &vtMode) == 0) {
186  vtMode.mode = VT_PROCESS;
187  vtMode.relsig = VTRELSIG;
188  vtMode.acqsig = VTACQSIG;
189 
190  if (::ioctl(m_tty_fd, VT_SETMODE, &vtMode) == 0) {
191  struct ::vt_stat vtStat;
192  ::memset(&vtStat, 0, sizeof(vtStat));
193 
194  if (::ioctl(m_tty_fd, VT_GETSTATE, &vtStat) == 0 ) {
195  m_vt_qws = vtStat.v_active;
196  }
197  }
198  }
199 
200  if (!m_vt_qws)
201  qWarning("Could not initialize virtual console switching");
202 #endif
203  } else {
204  qWarning("Cannot open input device '%s': %s", qPrintable(dev), strerror(errno));
205  return;
206  }
207 
208 }
209 
211 {
212  if (m_tty_fd >= 0) {
213 #if defined(Q_OS_LINUX)
214  ::ioctl(m_tty_fd, KDSKBMODE, m_orig_kbmode);
215 #endif
216  tcsetattr(m_tty_fd, TCSANOW, &m_tty_attr);
218  }
219 }
220 
221 
222 
223 void QWSTtyKbPrivate::switchLed(char led, bool state)
224 {
225 #if defined(Q_OS_LINUX)
226  char ledstate;
227 
228  ::ioctl(m_tty_fd, KDGETLED, &ledstate);
229  if (state)
230  ledstate |= led;
231  else
232  ledstate &= ~led;
233  ::ioctl(m_tty_fd, KDSETLED, ledstate);
234 #endif
235 }
236 
238 {
239  char buffer[32];
240  int n = 0;
241 
242  forever {
243  n = QT_READ(m_tty_fd, buffer + n, 32 - n);
244 
245  if (n == 0) {
246  qWarning("Got EOF from the input device.");
247  return;
248  } else if (n < 0 && (errno != EINTR && errno != EAGAIN)) {
249  qWarning("Could not read from input device: %s", strerror(errno));
250  return;
251  } else {
252  break;
253  }
254  }
255 
256  for (int i = 0; i < n; ++i) {
257  if (m_handler->filterKeycode(buffer[i]))
258  continue;
259 
261  ka = m_handler->processKeycode(buffer[i] & 0x7f, (buffer[i] & 0x80) == 0x00, buffer[i] == m_last_keycode);
262  m_last_keycode = buffer[i];
263 
264  switch (ka) {
268  break;
269 
273  break;
274 
278  break;
279 
281  switchConsole(qBound(1, m_vt_qws - 1, 10));
282  break;
283 
285  switchConsole(qBound(1, m_vt_qws + 1, 10));
286  break;
287 
288  default:
292  }
293  //ignore reboot
294  break;
295  }
296  }
297 }
298 
299 
301 {
302 #if defined(Q_OS_LINUX)
303  if (m_vt_qws && vt && (m_tty_fd >= 0 ))
304  ::ioctl(m_tty_fd, VT_ACTIVATE, vt);
305 #endif
306 }
307 
309 {
310 #if defined(Q_OS_LINUX)
311  // received a notification from the kernel that the current VT is
312  // changing: either enable or disable QWS painting accordingly.
313 
314  if (sig == VTACQSIG) {
315  if (::ioctl(m_tty_fd, VT_RELDISP, VT_ACKACQ) == 0) {
316  qwsServer->enablePainting(true);
317  qt_screen->restore();
319  qwsServer->refresh();
320  }
321  } else if (sig == VTRELSIG) {
322  qwsServer->enablePainting(false);
323 
324  // Check for reserved surfaces which might still do painting
325  bool allWindowsHidden = true;
327  for (int i = 0; i < windows.size(); ++i) {
328  const QWSWindow *w = windows.at(i);
330  if (s && s->isRegionReserved() && !w->allocatedRegion().isEmpty()) {
331  allWindowsHidden = false;
332  break;
333  }
334  }
335 
336  if (!allWindowsHidden) {
337  ::ioctl(m_tty_fd, VT_RELDISP, 0); // abort console switch
338  qwsServer->enablePainting(true);
339  } else if (::ioctl(m_tty_fd, VT_RELDISP, 1) == 0) {
340  qt_screen->save();
342  } else {
343  qwsServer->enablePainting(true);
344  }
345  }
346 #endif
347 }
348 
350 
351 #include "qkbdtty_qws.moc"
352 
353 #endif // QT_NO_QWS_KEYBOARD || QT_NO_QWS_KBD_TTY
Q_GUI_EXPORT QScreen * qt_screen
Definition: qscreen_qws.cpp:69
The QWSWindowSurface class provides the drawing area for top-level windows in Qt for Embedded Linux...
The QWSKeyboardHandler class is a base class for keyboard drivers in Qt for Embedded Linux...
Definition: qkbd_qws.h:57
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
static QWSServer * instance()
int toInt(bool *ok=0, int base=10) const
Returns the string converted to an int using base base, which is 10 by default and must be between 2 ...
Definition: qstring.cpp:6090
void refresh()
Refreshes the display by making the screen driver update the entire display.
#define VTACQSIG
Definition: qkbdtty_qws.cpp:65
#define SLOT(a)
Definition: qobjectdefs.h:226
virtual void restore()
Restores the previously saved state of the graphics card.
void switchConsole(int vt)
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition: qstring.cpp:3734
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
QRegion allocatedRegion() const
Returns the region that the window is allowed to draw onto, including any window decorations but excl...
#define Q_SLOTS
Definition: qobjectdefs.h:71
The QString class provides a Unicode character string.
Definition: qstring.h:83
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
#define QT_READ
Definition: qcore_unix_p.h:280
void addObject(QObject *object)
The QSocketNotifier class provides support for monitoring activity on a file descriptor.
void setObjectName(const QString &name)
Definition: qobject.cpp:1112
static QWSSignalHandler * instance()
The QWSWindow class encapsulates a top-level window in Qt for Embedded Linux.
#define SIGNAL(a)
Definition: qobjectdefs.h:227
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
static void watchUnixSignal(int signal, bool watch)
void enablePainting(bool)
Enables painting onto the screen if enable is true; otherwise painting is disabled.
void switchLed(char, bool)
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
bool isEmpty() const
Returns true if the region is empty; otherwise returns false.
Definition: qregion.cpp:4098
void resumeMouse()
Resumes pointer handling by reactivating all the mouse drivers registered by the QWS_MOUSE_PROTO envi...
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
QWSTtyKbPrivate(QWSTtyKeyboardHandler *handler, const QString &device)
Q_CORE_EXPORT void qWarning(const char *,...)
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
KeycodeAction
This enum describes the various special actions that actual QWSKeyboardHandler implementations have t...
Definition: qkbd_qws.h:67
virtual bool filterKeycode(char &code)
QWSTtyKeyboardHandler * m_handler
Definition: qkbdtty_qws.cpp:88
QByteArray toLocal8Bit() const Q_REQUIRED_RESULT
Returns the local 8-bit representation of the string as a QByteArray.
Definition: qstring.cpp:4049
struct termios m_tty_attr
Definition: qkbdtty_qws.cpp:90
#define Q_OBJECT
Definition: qobjectdefs.h:157
void suspendMouse()
Suspends pointer handling by deactivating all the mouse drivers registered by the QWS_MOUSE_PROTO env...
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
QString mid(int position, int n=-1) const Q_REQUIRED_RESULT
Returns a string that contains n characters of this string, starting at the specified position index...
Definition: qstring.cpp:3706
#define QT_OPEN
Definition: qcore_unix_p.h:186
virtual void save()
Saves the current state of the graphics card.
static QCoreApplication * instance()
Returns a pointer to the application&#39;s QCoreApplication (or QApplication) instance.
#define VTRELSIG
Definition: qkbdtty_qws.cpp:66
virtual ~QWSTtyKeyboardHandler()
QWSTtyKbPrivate * d
Definition: qkbdtty_qws.h:68
bool isRegionReserved() const
Returns true if the QWSWindowSurface::RegionReserved is set; otherwise returns false.
Q_DECL_CONSTEXPR const T & qBound(const T &min, const T &val, const T &max)
Definition: qglobal.h:1219
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
QWSWindowSurface * windowSurface() const
QStringList split(const QString &sep, SplitBehavior behavior=KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const Q_REQUIRED_RESULT
Splits the string into substrings wherever sep occurs, and returns the list of those strings...
Definition: qstring.cpp:6526
QImageIOHandler * handler
#define qPrintable(string)
Definition: qglobal.h:1750
KeycodeAction processKeycode(quint16 keycode, bool pressed, bool autorepeat)
Maps keycode according to a keymap and sends that key event to the Qt for Embedded Linux server appli...
Definition: qkbd_qws.cpp:521
#define O_RDWR
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
void handleConsoleSwitch(int sig)
QWSServer Q_GUI_EXPORT * qwsServer
int errno
const QList< QWSWindow * > & clientWindows()
Returns the list of current top-level windows.
The QList class is a template class that provides lists.
Definition: qdatastream.h:62
#define QT_CLOSE
Definition: qcore_unix_p.h:304
QWSTtyKeyboardHandler(const QString &)
Definition: qkbdtty_qws.cpp:97
#define forever
This macro is provided for convenience for writing infinite loops.
Definition: qglobal.h:2452