OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
UpDownDetection.c
Go to the documentation of this file.
1
8#include <Uefi.h>
10#include <Library/BaseLib.h>
11#include <Library/BaseMemoryLib.h>
12#include <Library/DebugLib.h>
13#include <Library/MemoryAllocationLib.h>
16#include <Library/OcMiscLib.h>
17#include <Library/OcTimerLib.h>
18#include <Library/TimerLib.h>
19
20VOID
22 OC_KEY_REPEAT_CONTEXT **Context
23 )
24{
25 ASSERT (Context != NULL);
26
27 if (*Context == NULL) {
28 return;
29 }
30
31 DEBUG ((DEBUG_INFO, "OCKM: Freeing key repeat context %p %p %p\n", *Context, (*Context)->KeysHeld, (*Context)->KeyHeldTimes));
32
33 FreePool ((*Context)->KeyHeldTimes);
34 FreePool ((*Context)->KeysHeld);
35 FreePool (*Context);
36
37 *Context = NULL;
38}
39
40EFI_STATUS
42 OUT OC_KEY_REPEAT_CONTEXT **Context,
44 IN UINTN MaxKeysHeld,
45 IN UINT64 InitialDelay,
46 IN UINT64 SubsequentDelay,
47 IN BOOLEAN PreventInitialRepeat
48 )
49{
50 EFI_STATUS Status;
51 APPLE_MODIFIER_MAP Modifiers;
52 UINTN NumKeysUp;
53 UINTN NumKeysDown;
54
55 DEBUG ((OC_TRACE_UPDOWNKEYS, "OCKM: Allocating %d for repeat context\n", sizeof (OC_KEY_REPEAT_CONTEXT)));
56 *Context = AllocatePool (sizeof (OC_KEY_REPEAT_CONTEXT));
57 if (*Context == NULL) {
58 DEBUG ((DEBUG_ERROR, "OCKM: Cannot allocate repeat context\n"));
59 return EFI_OUT_OF_RESOURCES;
60 }
61
62 if (MaxKeysHeld == 0) {
63 (*Context)->KeysHeld = NULL;
64 } else {
65 DEBUG ((OC_TRACE_UPDOWNKEYS, "OCKM: Allocating %d for keys held\n", MaxKeysHeld * sizeof ((*Context)->KeysHeld[0])));
66 (*Context)->KeysHeld = AllocatePool (MaxKeysHeld * sizeof ((*Context)->KeysHeld[0]));
67 if ((*Context)->KeysHeld == NULL) {
68 DEBUG ((DEBUG_ERROR, "OCKM: Cannot allocate keys held\n"));
69 FreePool (*Context);
70 *Context = NULL;
71 return EFI_OUT_OF_RESOURCES;
72 }
73
74 DEBUG ((OC_TRACE_UPDOWNKEYS, "OCKM: Allocating %d for key held times\n", MaxKeysHeld * sizeof ((*Context)->KeyHeldTimes[0])));
75 (*Context)->KeyHeldTimes = AllocatePool (MaxKeysHeld * sizeof ((*Context)->KeyHeldTimes[0]));
76 if ((*Context)->KeyHeldTimes == NULL) {
77 DEBUG ((DEBUG_ERROR, "OCKM: Cannot allocate key held times\n"));
78 FreePool ((*Context)->KeysHeld);
79 FreePool (*Context);
80 *Context = NULL;
81 return EFI_OUT_OF_RESOURCES;
82 }
83 }
84
85 (*Context)->KeyMap = KeyMap;
86
87 (*Context)->NumKeysHeld = 0;
88 (*Context)->MaxKeysHeld = MaxKeysHeld;
89
90 (*Context)->InitialDelay = InitialDelay;
91 (*Context)->SubsequentDelay = SubsequentDelay;
92 (*Context)->PreviousTime = 0;
93
94 if ((MaxKeysHeld == 0) || (PreventInitialRepeat == FALSE)) {
95 Status = EFI_SUCCESS;
96 } else {
97 //
98 // Prevent any keys which are down at init from appearring as immediate down key strokes or even repeating until released and then pressed again
99 //
100 NumKeysDown = MaxKeysHeld;
101
102 Status = OcGetUpDownKeys (
103 *Context,
104 &Modifiers,
105 &NumKeysUp,
106 NULL,
107 &NumKeysDown,
108 NULL,
109 MAX_INT64 >> 1 // == far future, creates massive but manageable negative delta on next call
110 );
111
112 if (EFI_ERROR (Status)) {
113 DEBUG ((DEBUG_ERROR, "OCKM: InitKeyRepeatContext initial GetUpDownKeys call - %r\n", Status));
114 OcFreeKeyRepeatContext (Context);
115 return Status;
116 }
117 }
118
119 DEBUG ((DEBUG_INFO, "OCKM: Allocated key repeat context %p %p %p\n", *Context, (*Context)->KeysHeld, (*Context)->KeyHeldTimes));
120
121 return Status;
122}
123
124EFI_STATUS
125EFIAPI
127 IN OUT OC_KEY_REPEAT_CONTEXT *RepeatContext,
128 OUT APPLE_MODIFIER_MAP *Modifiers,
129 IN OUT UINTN *NumKeysUp,
130 OUT APPLE_KEY_CODE *KeysUp OPTIONAL,
131 IN OUT UINTN *NumKeysDown,
132 OUT APPLE_KEY_CODE *KeysDown OPTIONAL,
133 IN UINT64 CurrentTime
134 )
135{
136 EFI_STATUS Status;
137 UINTN NumRawKeys;
139 UINTN NumKeysHeldInCopy;
140 UINTN MaxKeysHeldInCopy;
142 INT64 KeyHeldTimesCopy[OC_HELD_KEYS_DEFAULT_SIZE];
143 UINTN Index;
144 UINTN Index2;
145 APPLE_KEY_CODE Key;
146 INT64 KeyTime;
147 UINT64 DeltaTime;
148 BOOLEAN FoundHeldKey;
149
150 ASSERT (Modifiers != NULL);
151 ASSERT (NumKeysUp != NULL);
152 ASSERT (NumKeysDown != NULL);
153 ASSERT (RepeatContext != NULL);
154 ASSERT (RepeatContext->KeyMap != NULL);
155 ASSERT (RepeatContext->NumKeysHeld <= RepeatContext->MaxKeysHeld);
156
157 ASSERT_EQUALS (RepeatContext->KeysHeld == NULL, RepeatContext->KeyHeldTimes == NULL);
158
159 DeltaTime = CurrentTime - RepeatContext->PreviousTime;
160 RepeatContext->PreviousTime = CurrentTime;
161
162 if (RepeatContext->KeysHeld != NULL) {
163 //
164 // All held keys could potentially go into keys up
165 //
166 if ((KeysUp != NULL) && (RepeatContext->MaxKeysHeld > *NumKeysUp)) {
167 DEBUG ((DEBUG_ERROR, "OCKM: MaxKeysHeld %d exceeds NumKeysUp %d\n", RepeatContext->MaxKeysHeld, *NumKeysUp));
168 return EFI_UNSUPPORTED;
169 }
170
171 //
172 // All requested keys could potentially go into held keys
173 // (NumKeysDown is always used as the requested number of keys to scan, even if there is no KeysDown buffer to return down keycodes)
174 //
175 if ((KeysDown != NULL) && (*NumKeysDown > RepeatContext->MaxKeysHeld)) {
176 DEBUG ((DEBUG_ERROR, "OCKM: Number of keys requested %d exceeds MaxKeysHeld %d\n", *NumKeysDown, RepeatContext->MaxKeysHeld));
177 return EFI_UNSUPPORTED;
178 }
179
180 //
181 // Clone live entries of KeysHeld buffer
182 //
183 MaxKeysHeldInCopy = ARRAY_SIZE (KeysHeldCopy);
184 if (RepeatContext->MaxKeysHeld > MaxKeysHeldInCopy) {
185 DEBUG ((DEBUG_ERROR, "OCKM: MaxKeysHeld %d exceeds supported copy space %d\n", RepeatContext->MaxKeysHeld, MaxKeysHeldInCopy));
186 return EFI_UNSUPPORTED;
187 }
188
189 CopyMem (KeysHeldCopy, RepeatContext->KeysHeld, RepeatContext->NumKeysHeld * sizeof (RepeatContext->KeysHeld[0]));
190 CopyMem (KeyHeldTimesCopy, RepeatContext->KeyHeldTimes, RepeatContext->NumKeysHeld * sizeof (RepeatContext->KeyHeldTimes[0]));
191 NumKeysHeldInCopy = RepeatContext->NumKeysHeld;
192 } else {
193 NumKeysHeldInCopy = 0;
194 }
195
196 NumRawKeys = ARRAY_SIZE (RawKeys);
197 if (*NumKeysDown > NumRawKeys) {
198 DEBUG ((DEBUG_ERROR, "OCKM: Number of keys requested %d exceeds supported raw key bufsize %d\n", *NumKeysDown, NumRawKeys));
199 return EFI_UNSUPPORTED;
200 }
201
202 Status = RepeatContext->KeyMap->GetKeyStrokes (
203 RepeatContext->KeyMap,
204 Modifiers,
205 &NumRawKeys,
206 RawKeys
207 );
208
209 if (EFI_ERROR (Status)) {
210 return Status;
211 }
212
213 if ((KeysDown != NULL) && (NumRawKeys > *NumKeysDown)) {
214 return EFI_BUFFER_TOO_SMALL;
215 }
216
217 DEBUG ((OC_TRACE_UPDOWNKEYS, "OCKM: [%p] %ld %ld %ld\n", RepeatContext, RepeatContext->InitialDelay, RepeatContext->SubsequentDelay, DeltaTime));
218 DEBUG ((OC_TRACE_UPDOWNKEYS, "OCKM: [%p] I u:%d d:%d n:%d h:%d r:%d m:%d\n", RepeatContext, *NumKeysUp, *NumKeysDown, RepeatContext->MaxKeysHeld, RepeatContext->NumKeysHeld, NumRawKeys, *Modifiers));
219
220 *NumKeysUp = 0;
221 *NumKeysDown = 0;
222 RepeatContext->NumKeysHeld = 0;
223
224 //
225 // Loop through all keys which are currently down
226 //
227 for (Index = 0; Index < NumRawKeys; ++Index) {
228 Key = RawKeys[Index];
229 if (RepeatContext->KeysHeld != NULL) {
230 RepeatContext->KeysHeld[RepeatContext->NumKeysHeld] = Key;
231 }
232
233 FoundHeldKey = FALSE;
234 for (Index2 = 0; Index2 < NumKeysHeldInCopy; Index2++) {
235 if (KeysHeldCopy[Index2] == Key) {
236 FoundHeldKey = TRUE;
237 KeyTime = KeyHeldTimesCopy[Index2] + DeltaTime;
238 KeysHeldCopy[Index2] = 0; // Mark held key as still down
239 DEBUG ((OC_TRACE_UPDOWNKEYS, "OCKM: [%p] Still down 0x%X %ld\n", RepeatContext, Key, KeyTime));
240 if ((RepeatContext->InitialDelay != 0) && (KeyTime >= 0)) {
241 if (KeysDown != NULL) {
242 KeysDown[*NumKeysDown] = Key;
243 }
244
245 (*NumKeysDown)++;
246 KeyTime -= RepeatContext->SubsequentDelay;
247 DEBUG ((OC_TRACE_UPDOWNKEYS, "OCKM: [%p] Repeating 0x%X %ld\n", RepeatContext, Key, KeyTime));
248 }
249
250 break;
251 }
252 }
253
254 if (!FoundHeldKey) {
255 if (KeysDown != NULL) {
256 KeysDown[*NumKeysDown] = Key;
257 }
258
259 (*NumKeysDown)++;
260 KeyTime = -(INT64)RepeatContext->InitialDelay;
261 DEBUG ((OC_TRACE_UPDOWNKEYS, "OCKM: [%p] New down 0x%X %ld\n", RepeatContext, Key, KeyTime));
262 }
263
264 if (RepeatContext->KeysHeld != NULL) {
265 RepeatContext->KeyHeldTimes[RepeatContext->NumKeysHeld] = KeyTime;
266 RepeatContext->NumKeysHeld++;
267 }
268 }
269
270 //
271 // Process remaining held keys
272 //
273 for (Index = 0; Index < NumKeysHeldInCopy; Index++) {
274 Key = KeysHeldCopy[Index];
275 if (Key != 0) {
276 DEBUG ((OC_TRACE_UPDOWNKEYS, "OCKM: [%p] Gone up 0x%X %ld\n", RepeatContext, Key, KeyHeldTimesCopy[Index]));
277 if (KeysUp != NULL) {
278 KeysUp[*NumKeysUp] = Key;
279 }
280
281 (*NumKeysUp)++;
282 }
283 }
284
285 DEBUG ((OC_TRACE_UPDOWNKEYS, "OCKM: [%p] O u:%d d:%d n:%d h:%d r:%d\n", RepeatContext, *NumKeysUp, *NumKeysDown, RepeatContext->MaxKeysHeld, RepeatContext->NumKeysHeld, NumRawKeys));
286
287 return Status;
288}
APPLE_HID_USAGE APPLE_KEY_CODE
Definition AppleHid.h:317
UINT16 APPLE_MODIFIER_MAP
Definition AppleHid.h:102
#define ARRAY_SIZE(Array)
Definition AppleMacEfi.h:34
#define OC_HELD_KEYS_DEFAULT_SIZE
#define OC_TRACE_UPDOWNKEYS
#define OC_KEY_MAP_DEFAULT_SIZE
#define ASSERT_EQUALS(Expression, ExpectedValue)
Definition OcMiscLib.h:259
EFI_STATUS OcInitKeyRepeatContext(OUT OC_KEY_REPEAT_CONTEXT **Context, IN APPLE_KEY_MAP_AGGREGATOR_PROTOCOL *KeyMap, IN UINTN MaxKeysHeld, IN UINT64 InitialDelay, IN UINT64 SubsequentDelay, IN BOOLEAN PreventInitialRepeat)
EFI_STATUS EFIAPI OcGetUpDownKeys(IN OUT OC_KEY_REPEAT_CONTEXT *RepeatContext, OUT APPLE_MODIFIER_MAP *Modifiers, IN OUT UINTN *NumKeysUp, OUT APPLE_KEY_CODE *KeysUp OPTIONAL, IN OUT UINTN *NumKeysDown, OUT APPLE_KEY_CODE *KeysDown OPTIONAL, IN UINT64 CurrentTime)
VOID OcFreeKeyRepeatContext(OC_KEY_REPEAT_CONTEXT **Context)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
#define ASSERT(x)
Definition coder.h:55
APPLE_KEY_CODE * KeysHeld