/* GPIO interrupt handler. * Called when TOHKBD keyboard part is attached to the base, and * when there is new input report due a key press. */ void Tohkbd::handleGpioInterrupt() { if (gpioInterruptCounter == 0) { gpioInterruptFloodDetect.start(); } /* If there are > 100 interrupts within one sec, there must be something wrong */ if (++gpioInterruptCounter >= 100) { int tmsec = gpioInterruptFloodDetect.elapsed(); printf("100 interrputs in %d ms\n", tmsec); if (tmsec < 1000) { /* Turn keyboard off */ setVddState(false); } gpioInterruptCounter = 0; } if (!keypadIsPresent) { checkKeypadPresence(); } else { int retries = 3; do { QByteArray r = tca8424->readInputReport(); if (!r.isEmpty()) { presenceTimer->start(); /* Process report only if it has correct length of 11 */ if (r.at(0) == 0x0b && r.at(1) == 0x00) { keymap->process(r); retries = -1; } else { retries--; } } else { printf("Something wrong here now, retrying... %d\n", retries); retries--; QThread::msleep(100); } } while (retries > 0); if (retries == 0) /* Did we loose keyboard */ checkKeypadPresence(); } }
/* Will check is keyboard still there */ void Tohkbd::presenceTimerTimeout() { if (checkKeypadPresence()) { presenceTimer->start(); } }
/* GPIO interrupt handler. * Called when TOHKBD keyboard part is attached to the base, and * when there is new input report due a key press. */ void Tohkbd::handleGpioInterrupt() { if (!keypadIsPresent) { checkKeypadPresence(); } else { keymap->process(tca8424->readInputReport()); } }
/* Will check is keyboard still there */ void Tohkbd::presenceTimerTimeout() { if (checkKeypadPresence()) { presenceTimer->start(); if (readOneLineFromFile("/sys/class/gpio/gpio" GPIO_INT "/value") == "0") { printf("checkKeypadPresence: interrupt is active, trying to handle it now.\n"); handleGpioInterrupt(); } } }
/* Main */ Tohkbd::Tohkbd(QObject *parent) : QObject(parent) { dbusRegistered = false; interruptsEnabled = false; vddEnabled = false; capsLockSeq = 0; vkbLayoutIsTohkbd = false; currentActiveLayout = QString(); currentOrientationLock = QString(); keypadIsPresent = false; gpio_fd = -1; displayIsOn = false; keyIsPressed = false; keyRepeat = false; slideEventEmitted = false; taskSwitcherVisible = false; ssNotifyReplacesId = 0; ssFilename = QString(); tohkbd2user = new QDBusInterface("com.kimmoli.tohkbd2user", "/", "com.kimmoli.tohkbd2user", QDBusConnection::sessionBus(), this); tohkbd2user->setTimeout(2000); thread = new QThread(); worker = new Worker(); worker->moveToThread(thread); connect(worker, SIGNAL(gpioInterruptCaptured()), this, SLOT(handleGpioInterrupt())); connect(worker, SIGNAL(workRequested()), thread, SLOT(start())); connect(thread, SIGNAL(started()), worker, SLOT(doWork())); connect(worker, SIGNAL(finished()), thread, SLOT(quit()), Qt::DirectConnection); backlightTimer = new QTimer(this); backlightTimer->setSingleShot(true); connect(backlightTimer, SIGNAL(timeout()), this, SLOT(backlightTimerTimeout())); presenceTimer = new QTimer(this); presenceTimer->setInterval(2000); presenceTimer->setSingleShot(true); connect(presenceTimer, SIGNAL(timeout()), this, SLOT(presenceTimerTimeout())); repeatTimer = new QTimer(this); repeatTimer->setSingleShot(true); connect(repeatTimer, SIGNAL(timeout()), this, SLOT(repeatTimerTimeout())); /* do this automatically at startup */ setVddState(true); setInterruptEnable(true); uinputif = new UinputIf(); uinputif->openUinputDevice(); tca8424 = new tca8424driver(0x3b); keymap = new keymapping(); FKEYS.clear(); FKEYS.append(KEY_F1); FKEYS.append(KEY_F2); FKEYS.append(KEY_F3); FKEYS.append(KEY_F4); FKEYS.append(KEY_F5); FKEYS.append(KEY_F6); FKEYS.append(KEY_F7); FKEYS.append(KEY_F8); FKEYS.append(KEY_F9); FKEYS.append(KEY_F10); FKEYS.append(KEY_F11); FKEYS.append(KEY_F12); reloadSettings(); if (currentActiveLayout.isEmpty()) changeActiveLayout(true); if (currentOrientationLock.isEmpty()) { changeOrientationLock(true); saveOrientation(); } checkKeypadPresence(); connect(keymap, SIGNAL(shiftChanged()), this, SLOT(handleShiftChanged())); connect(keymap, SIGNAL(ctrlChanged()), this, SLOT(handleCtrlChanged())); connect(keymap, SIGNAL(altChanged()), this, SLOT(handleAltChanged())); connect(keymap, SIGNAL(symChanged()), this, SLOT(handleSymChanged())); connect(keymap, SIGNAL(keyPressed(QList< QPair<int, int> >)), this, SLOT(handleKeyPressed(QList< QPair<int, int> >))); connect(keymap, SIGNAL(keyReleased()), this, SLOT(handleKeyReleased())); }
/* Main */ Tohkbd::Tohkbd(QObject *parent) : QObject(parent) { dbusRegistered = false; interruptsEnabled = false; vddEnabled = false; vkbLayoutIsTohkbd = false; currentActiveLayout = QString(); currentOrientationLock = QString(); keypadIsPresent = false; gpio_fd = -1; displayIsOn = false; keyIsPressed = false; keyRepeat = false; slideEventEmitted = false; taskSwitcherVisible = false; selfieLedOn = false; gpioInterruptCounter = 0; actualSailfishVersion = QString(); fix_CapsLock = !checkSailfishVersion("1.1.7.0"); capsLock = false; tohkbd2user = new ComKimmoliTohkbd2userInterface("com.kimmoli.tohkbd2user", "/", QDBusConnection::sessionBus(), this); tohkbd2user->setTimeout(2000); thread = new QThread(); worker = new Worker(); worker->moveToThread(thread); connect(worker, SIGNAL(gpioInterruptCaptured()), this, SLOT(handleGpioInterrupt())); connect(worker, SIGNAL(workRequested()), thread, SLOT(start())); connect(thread, SIGNAL(started()), worker, SLOT(doWork())); connect(worker, SIGNAL(finished()), thread, SLOT(quit()), Qt::DirectConnection); backlightTimer = new QTimer(this); backlightTimer->setSingleShot(true); connect(backlightTimer, SIGNAL(timeout()), this, SLOT(backlightTimerTimeout())); presenceTimer = new QTimer(this); presenceTimer->setInterval(2000); presenceTimer->setSingleShot(true); connect(presenceTimer, SIGNAL(timeout()), this, SLOT(presenceTimerTimeout())); repeatTimer = new QTimer(this); repeatTimer->setSingleShot(true); connect(repeatTimer, SIGNAL(timeout()), this, SLOT(repeatTimerTimeout())); /* do this automatically at startup */ setVddState(true); setInterruptEnable(true); uinputif = new UinputIf(); uinputif->openUinputDevice(); uinputevpoll = new UinputEvPoll(); evpollThread = new QThread(); uinputevpoll->moveToThread(evpollThread); connect(uinputevpoll, SIGNAL(capsLockLedChanged(bool)), this, SLOT(capsLockLedState(bool))); connect(uinputevpoll, SIGNAL(pollingRequested()), evpollThread, SLOT(start())); connect(evpollThread, SIGNAL(started()), uinputevpoll, SLOT(doPoll())); connect(uinputevpoll, SIGNAL(finished()), evpollThread, SLOT(quit()), Qt::DirectConnection); uinputevpoll->requestPolling(uinputif->getFd()); printf("uinputevpoll->requestPolling(uinputif->getFd());\n"); tca8424 = new tca8424driver(0x3b); keymap = new keymapping(); FKEYS.clear(); FKEYS.append(KEY_F1); FKEYS.append(KEY_F2); FKEYS.append(KEY_F3); FKEYS.append(KEY_F4); FKEYS.append(KEY_F5); FKEYS.append(KEY_F6); FKEYS.append(KEY_F7); FKEYS.append(KEY_F8); FKEYS.append(KEY_F9); FKEYS.append(KEY_F10); FKEYS.append(KEY_F11); FKEYS.append(KEY_F12); reloadSettings(); keymap->setLayout(masterLayout); if (currentActiveLayout.isEmpty()) changeActiveLayout(true); if (currentOrientationLock.isEmpty()) { changeOrientationLock(true); saveOrientation(); } checkKeypadPresence(); connect(keymap, SIGNAL(shiftChanged()), this, SLOT(handleShiftChanged())); connect(keymap, SIGNAL(ctrlChanged()), this, SLOT(handleCtrlChanged())); connect(keymap, SIGNAL(altChanged()), this, SLOT(handleAltChanged())); connect(keymap, SIGNAL(symChanged()), this, SLOT(handleSymChanged())); connect(keymap, SIGNAL(toggleCapsLock()), this, SLOT(toggleCapsLock())); connect(keymap, SIGNAL(keyPressed(QList< QPair<int, int> >)), this, SLOT(handleKeyPressed(QList< QPair<int, int> >))); connect(keymap, SIGNAL(keyReleased()), this, SLOT(handleKeyReleased())); connect(keymap, SIGNAL(bogusDetected()), tca8424, SLOT(reset())); }