// Kernel input core. This file owns canonical keyboard and mouse state shared by input drivers and syscalls. #include #include #include #include #include #include #include #include #include #include #include #include #include #define MANAGER_QUEUE_SIZE 256u #define MANAGER_QUEUE_MASK (MANAGER_QUEUE_SIZE - 1u) static KE_INPUT_CONTEXT gDefaultInputContext; static KE_INPUT_MANAGER gInputManager; static KE_ID_ALLOCATOR gInputDeviceIds = KE_ID_ALLOCATOR_INIT(1u); // Updates the waitable manager event to match queued physical input. static void KiInputRefreshManagerEvent(KE_INPUT_CONTEXT* context) { if (!context->ManagerWaitEvent) return; if (context->ManagerHead != context->ManagerTail) KeSignalEvent(context->ManagerWaitEvent); else KeClearEvent(context->ManagerWaitEvent); } // Queues one normalized physical event for the delegated input manager. static void KiInputQueueManagerEvent(KE_INPUT_CONTEXT* context, const KE_INPUT_MANAGER_EVENT* event) { if (!context || !event) return; int next = (context->ManagerTail + 1) & (int)MANAGER_QUEUE_MASK; if (next == context->ManagerHead) return; KE_INPUT_MANAGER_EVENT queued = *event; queued.Sequence = (uint64_t)NtlAtomicIncrement64(&context->ManagerSequence); context->ManagerQueue[context->ManagerTail] = queued; context->ManagerTail = next; KiInputRefreshManagerEvent(context); } // Implements the input Initialize operation. void KeInputInitialize(const HAL_API* hal) { KE_INPUT_CONTEXT* context = &gDefaultInputContext; ObInitializeObjectHeader(&gInputManager.Header, ObjectTypeInputManager); context->Hal = hal; context->ManagerHead = context->ManagerTail = 0; context->ManagerSequence = 0; context->MouseBoundsWidth = 1920; context->MouseBoundsHeight = 1080; if (!context->ManagerWaitEvent) { KSTATUS s = KeEventCreate(EventManualReset, 0, &context->ManagerWaitEvent); if (!KSUCCESS(s)) DbgPrint("Input: manager wait event create failed st=0x%x\n", s); } KiInputRefreshManagerEvent(context); int32_t w = 1920, h = 1080; DISPLAY_MODE mode; if (KSUCCESS(KeDisplayGetMode(&mode))) { w = (int)mode.Width; h = (int)mode.Height; } KeInputMouseSetBounds(w, h); KeInputMouseSetPosition(w / 2, h / 2); KeDisplayShowCursor(true); DbgPrint("Input: kernel input core initialized (%dx%d)\n", w, h); } // References the singleton input-manager authority object used for bootstrap delegation. KSTATUS KeInputReferenceManager(KE_INPUT_MANAGER** managerOut) { if (!managerOut) return NTLSTATUS_INVALID_PARAMETER; *managerOut = &gInputManager; ObReferenceObject(&gInputManager.Header); return NTLSTATUS_SUCCESS; } // Reads one normalized physical event from the singleton manager stream. KSTATUS KeInputManagerReadEvent(KE_INPUT_MANAGER* manager, uint64_t timeoutMs, SYS_INPUT_MANAGER_EVENT* eventOut) { KE_INPUT_CONTEXT* context = &gDefaultInputContext; if (!manager || manager != &gInputManager || !eventOut) return NTLSTATUS_INVALID_PARAMETER; for (;;) { if (context->ManagerHead != context->ManagerTail) { KE_INPUT_MANAGER_EVENT event = context->ManagerQueue[context->ManagerHead]; context->ManagerHead = (context->ManagerHead + 1) & (int)MANAGER_QUEUE_MASK; KiInputRefreshManagerEvent(context); memset(eventOut, 0, sizeof(*eventOut)); eventOut->Size = sizeof(*eventOut); eventOut->Type = event.Type; eventOut->Sequence = event.Sequence; if (event.Type == SYS_INPUT_MANAGER_EVENT_KEY) eventOut->Data.Key = event.Data.Key; else if (event.Type == SYS_INPUT_MANAGER_EVENT_MOUSE) eventOut->Data.Mouse = event.Data.Mouse; else return NTLSTATUS_FAILURE; return NTLSTATUS_SUCCESS; } if (timeoutMs == 0) return NTLSTATUS_WOULD_BLOCK; if (!context->ManagerWaitEvent) return NTLSTATUS_FAILURE; EVENT* waitEvent = context->ManagerWaitEvent; uint32_t selected = 0; KSTATUS status = KeWaitForMultipleEvents(&waitEvent, 1, 0, timeoutMs, &selected); if (!KSUCCESS(status)) return status; } } // Implements the input Register Device operation. __declspec(dllexport) KSTATUS KeInputRegisterDevice(const char* name, uint32_t flags, uint32_t* outDeviceId) { (void)flags; uint32_t id = 0; KSTATUS status = KeAllocateId32(&gInputDeviceIds, &id); if (!KSUCCESS(status)) return status; if (outDeviceId) *outDeviceId = id; DbgPrint("Input: registered device %u (%s)\n", id, name ? name : "unnamed"); return NTLSTATUS_SUCCESS; } // Implements the input Submit Key operation. __declspec(dllexport) void KeInputSubmitKey(const INPUT_KEY_EVENT* event) { KE_INPUT_CONTEXT* context = &gDefaultInputContext; if (!event) return; INPUT_KEY key = event->Key; if (key == INPUT_KEY_NONE || key >= 256u) return; // Forward physical transitions without interpreting key state or repeat policy. KE_INPUT_MANAGER_EVENT managerEvent = {0}; managerEvent.Type = SYS_INPUT_MANAGER_EVENT_KEY; managerEvent.Data.Key = *event; KiInputQueueManagerEvent(context, &managerEvent); } // Implements the input Commit Mouse Position operation. static void KiInputCommitMousePosition(KE_INPUT_CONTEXT* context, int32_t nx, int32_t ny) { int32_t bw = context->MouseBoundsWidth; int32_t bh = context->MouseBoundsHeight; if (bw < 1) bw = 1; if (bh < 1) bh = 1; if (nx < 0) nx = 0; if (ny < 0) ny = 0; if (nx >= bw) nx = bw - 1; if (ny >= bh) ny = bh - 1; context->MouseX = nx; context->MouseY = ny; } // Implements the input Submit Mouse operation. __declspec(dllexport) void KeInputSubmitMouse(const INPUT_MOUSE_EVENT* event) { KE_INPUT_CONTEXT* context = &gDefaultInputContext; if (!event) return; KE_INPUT_MANAGER_EVENT managerEvent; memset(&managerEvent, 0, sizeof(managerEvent)); managerEvent.Type = SYS_INPUT_MANAGER_EVENT_MOUSE; managerEvent.Data.Mouse = *event; KiInputQueueManagerEvent(context, &managerEvent); int32_t oldX = context->MouseX; int32_t oldY = context->MouseY; int32_t nx = oldX + event->dx; int32_t ny = oldY + event->dy; KiInputCommitMousePosition(context, nx, ny); } // Implements the input Submit Mouse Absolute operation. __declspec(dllexport) void KeInputSubmitMouseAbsolute(const INPUT_MOUSE_ABSOLUTE_EVENT* event) { KE_INPUT_CONTEXT* context = &gDefaultInputContext; if (!event) return; int32_t oldX = context->MouseX; int32_t oldY = context->MouseY; INPUT_MOUSE_EVENT managerMouse; managerMouse.dx = event->x - oldX; managerMouse.dy = event->y - oldY; managerMouse.wheel = event->wheel; managerMouse.buttons = event->buttons; KE_INPUT_MANAGER_EVENT managerEvent; memset(&managerEvent, 0, sizeof(managerEvent)); managerEvent.Type = SYS_INPUT_MANAGER_EVENT_MOUSE; managerEvent.Data.Mouse = managerMouse; KiInputQueueManagerEvent(context, &managerEvent); KiInputCommitMousePosition(context, event->x, event->y); } // Implements the input Submit Mouse Absolute Scaled operation. __declspec(dllexport) void KeInputSubmitMouseAbsoluteScaled(uint32_t rawX, uint32_t rawY, uint32_t maxX, uint32_t maxY, int32_t wheel, uint8_t buttons) { KE_INPUT_CONTEXT* context = &gDefaultInputContext; int32_t bw = context->MouseBoundsWidth; int32_t bh = context->MouseBoundsHeight; if (bw < 1) bw = 1; if (bh < 1) bh = 1; INPUT_MOUSE_ABSOLUTE_EVENT ev; ev.x = maxX ? (int32_t)(((uint64_t)rawX * (uint64_t)(bw - 1)) / (uint64_t)maxX) : 0; ev.y = maxY ? (int32_t)(((uint64_t)rawY * (uint64_t)(bh - 1)) / (uint64_t)maxY) : 0; ev.wheel = wheel; ev.buttons = buttons; KeInputSubmitMouseAbsolute(&ev); } // Implements the input Mouse Set Position operation. void KeInputMouseSetPosition(int32_t x, int32_t y) { KE_INPUT_CONTEXT* context = &gDefaultInputContext; int32_t bw = context->MouseBoundsWidth; int32_t bh = context->MouseBoundsHeight; if (bw < 1) bw = 1; if (bh < 1) bh = 1; if (x < 0) x = 0; if (y < 0) y = 0; if (x >= bw) x = bw - 1; if (y >= bh) y = bh - 1; context->MouseX = x; context->MouseY = y; } // Implements the input Mouse Set Bounds operation. void KeInputMouseSetBounds(int32_t w, int32_t h) { KE_INPUT_CONTEXT* context = &gDefaultInputContext; if (w < 1) w = 1; if (h < 1) h = 1; context->MouseBoundsWidth = w; context->MouseBoundsHeight = h; KeInputMouseSetPosition(context->MouseX, context->MouseY); }