The Pedigree Project 0.1
HidInputManager.cc
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include "pedigree/kernel/LockGuard.h"
21#include "pedigree/kernel/Log.h"
22#include "pedigree/kernel/machine/HidInputManager.h"
23#include "pedigree/kernel/machine/InputManager.h"
24#include "pedigree/kernel/machine/KeymapManager.h"
25#include "pedigree/kernel/machine/Machine.h"
26#include "pedigree/kernel/machine/Timer.h"
27#include "pedigree/kernel/utilities/Iterator.h"
28#include "pedigree/kernel/utilities/utility.h"
29
31
32HidInputManager::HidInputManager() : m_pTimer(nullptr), m_NextArmed(0) {}
33
35 Timer* timer = nullptr;
36 {
39 m_pTimer = nullptr;
40 }
41 if (timer && !timer->unregisterHandler(this)) {
42 FATAL("HidInputManager could not drain its timer callback");
43 }
44}
45
46void HidInputManager::keyDown(uint8_t keyCode, const void* source) {
48 KeymapManager& keymapManager = KeymapManager::instance();
49
50 KeyState* keyState = m_KeyStates.lookup(keyCode);
51 if (keyState) {
52 for (const void* heldSource : keyState->sources) {
53 if (heldSource == source) {
54 return;
55 }
56 }
57 keyState->sources.pushBack(source);
58 return;
59 }
60
61 keyState = new KeyState;
62 keyState->key = 0;
63 keyState->nextRepeat = 0;
64 keyState->sources.pushBack(source);
65 m_KeyStates.insert(keyCode, keyState);
66
67 InputManager::instance().rawKeyUpdate(keyCode, false);
68
69 if (keymapManager.handleHidModifier(keyCode, true)) {
70 updateKeysLocked();
71 return;
72 }
73
74 if (!m_pTimer) {
75 Timer* timer = Machine::instance().getTimer();
76 if (timer && timer->registerHandler(this)) {
78 } else {
79 ERROR("HidInputManager could not register key repeat");
80 }
81 }
82
83 keyState->key = keymapManager.resolveHidKeycode(keyCode);
84 keyState->nextRepeat = Time::getTicks() + 600000000;
85 armNextRepeatLocked();
86
87 if (keyState->key) {
89 }
90}
91
92void HidInputManager::keyUp(uint8_t keyCode, const void* source) {
94 KeyState* keyState = m_KeyStates.lookup(keyCode);
95 if (!keyState) {
96 return;
97 }
98 size_t index = 0;
99 while (index < keyState->sources.count() && keyState->sources[index] != source) {
100 ++index;
101 }
102 if (index == keyState->sources.count()) {
103 return;
104 }
105 keyState->sources.erase(index);
106 if (keyState->sources.count()) {
107 return;
108 }
109 m_KeyStates.remove(keyCode);
110 delete keyState;
111 InputManager::instance().rawKeyUpdate(keyCode, true);
112 if (KeymapManager::instance().handleHidModifier(keyCode, false)) {
113 updateKeysLocked();
114 }
115 armNextRepeatLocked();
116}
117
118void HidInputManager::timer(uint64_t delta) {
119 (void)delta;
121
122 const uint64_t now = Time::getTicks();
123 for (Tree<uint8_t, KeyState*>::Iterator it = m_KeyStates.begin(); it != m_KeyStates.end(); ++it) {
124 KeyState* keyState = it.value();
125 if (keyState->nextRepeat && keyState->nextRepeat <= now) {
126 keyState->nextRepeat = now + 40000000;
127 if (keyState->key)
129 }
130 }
131
132 armNextRepeatLocked();
133
134 // Modifiers alone do not need periodic repeat callbacks.
135 if (!m_NextArmed && m_pTimer && !m_pTimer->supportsDeadlines()) {
137 m_pTimer = nullptr;
138
139 // Self-removal is intentionally deferred until this callback returns.
140 // A new key can reactivate the same slot after m_KeyLock is released.
141 timer->unregisterHandler(this);
142 }
143}
144
145void HidInputManager::armNextRepeatLocked() {
146 uint64_t next = 0;
147 for (Tree<uint8_t, KeyState*>::Iterator it = m_KeyStates.begin(); it != m_KeyStates.end(); ++it) {
148 const uint64_t deadline = it.value()->nextRepeat;
149 if (deadline && (!next || deadline < next)) {
150 next = deadline;
151 }
152 }
153 if (!m_pTimer || !m_pTimer->supportsDeadlines()) {
154 m_NextArmed = next;
155 return;
156 }
157 if (next == m_NextArmed) {
158 return;
159 }
160 if (!m_pTimer->armHandler(this, next)) {
161 FATAL("HidInputManager could not arm key repeat");
162 }
163 m_NextArmed = next;
164}
165
168 updateKeysLocked();
169}
170
171void HidInputManager::updateKeysLocked() {
172 KeymapManager& keymapManager = KeymapManager::instance();
173 for (Tree<uint8_t, KeyState*>::Iterator it = m_KeyStates.begin(); it != m_KeyStates.end(); ++it) {
174 KeyState* keyState = it.value();
175 if (keyState->nextRepeat) {
176 keyState->key = keymapManager.resolveHidKeycode(it.key());
177 }
178 }
179}
void keyDown(uint8_t keyCode, const void *source=nullptr)
Called when a key transitions to the "down" state.
void timer(uint64_t delta)
Tree< uint8_t, KeyState * > m_KeyStates
Current key states (for periodic callbacks while a key is down)
void updateKeys()
Apply modifier or keymap changes to all keys in down state.
void keyUp(uint8_t keyCode, const void *source=nullptr)
Called when a key transitions to the "up" state.
HidInputManager()
Default constructor.
static HidInputManager m_Instance
Static instance.
virtual ~HidInputManager()
Default destructor.
static InputManager & instance()
Singleton design.
void rawKeyUpdate(uint8_t scancode, bool bKeyUp)
void keyPressed(uint64_t key)
Called whenever a key is pressed and needs to be added to the queue.
bool handleHidModifier(uint8_t keyCode, bool bDown)
static KeymapManager & instance()
Singleton design.
uint64_t resolveHidKeycode(uint8_t keyCode)
virtual Timer * getTimer()=0
virtual bool supportsDeadlines() const
virtual bool armHandler(TimerHandler *, uint64_t)
An iterator applicable for many data structures.
Definition Iterator.h:147
void erase(size_t index)
Definition Vector.h:389
void pushBack(const T &value)
Definition Vector.h:275
size_t count() const
Definition Vector.h:270
Vector< const void * > sources
Devices still holding this key, including modifiers.
uint64_t key
The resolved key.
uint64_t nextRepeat
Monotonic time of the next key repeat.