The Pedigree Project 0.1
Ps2MouseCallbackRegistry.h
1/*
2 * Copyright (c) 2026, Pedigree Developers
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted.
6 */
7
8#ifndef PEDIGREE_PS2_MOUSE_CALLBACK_REGISTRY_H
9#define PEDIGREE_PS2_MOUSE_CALLBACK_REGISTRY_H
10#include "pedigree/kernel/Spinlock.h"
11#include "pedigree/kernel/compiler.h"
12#include "pedigree/kernel/process/WaitQueue.h"
13#include "pedigree/kernel/processor/types.h"
14
15#include <config.h>
16
18 private:
19 struct CallbackSlot;
20
21 public:
22 using Handler = void (*)(void*, const void*, size_t);
23
24 class EXPORTED_PUBLIC Registration {
25 private:
26 using UnregisterThunk = bool (*)(void*, void*, size_t, Registration*);
27
28 public:
31
39 bool reset();
40
41 explicit operator bool() const {
42 return m_pSlot != nullptr;
43 }
44
45 private:
46 friend class Ps2MouseCallbackRegistry;
47
48 Registration(const Registration&) = delete;
49 Registration& operator=(const Registration&) = delete;
50
51 void adopt(void* owner, void* slot, size_t generation, UnregisterThunk unregister) {
52 m_pOwner = owner;
53 m_pSlot = slot;
54 m_Generation = generation;
55 m_Unregister = unregister;
56 }
57
58 void releaseFromOwner(void* owner, void* slot, size_t generation) {
59 if (m_pOwner == owner && m_pSlot == slot && m_Generation == generation) {
60 m_pOwner = nullptr;
61 m_pSlot = nullptr;
62 m_Generation = 0;
63 m_Unregister = nullptr;
64 }
65 }
66
67 void* m_pOwner;
68 void* m_pSlot;
69 size_t m_Generation;
70 UnregisterThunk m_Unregister;
71 };
72
75
76 MUST_USE_RESULT bool subscribe(Handler handler, void* parameter, Registration& registration);
77
78 void dispatch(const void* buffer, size_t length);
79
80#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
81 using CallbackPinHook = void (*)(Handler, void*);
82
83 void setCallbackPinHook(CallbackPinHook hook);
84#endif
85
86 private:
87 static constexpr size_t MaxCallbacks = 32;
88
90 void* owner;
91 CallbackDispatch* next;
92 };
93
94 struct CallbackSlot {
96
97 Handler handler;
98 void* parameter;
99 Registration* registration;
100 size_t generation;
101 size_t inFlight;
102 bool enabled;
103 bool draining;
104 bool deferredRemoval;
105 CallbackDispatch* dispatches;
106 WaitQueue drainWaiters;
107 };
108
109 static void* currentDispatchOwner();
110 static bool unregisterThunk(void* owner, void* slot, size_t generation,
111 Registration* registration);
112 void clearSlot(CallbackSlot& slot);
113
114 bool unregister(CallbackSlot* slot, size_t generation, Registration* registration);
115 bool isCallbackContext(void* owner) const;
116 void releaseCallback(CallbackSlot& slot, CallbackDispatch& dispatch);
117
118 CallbackSlot m_Callbacks[MaxCallbacks];
119 Spinlock m_CallbackLock;
120
121#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
122 CallbackPinHook m_CallbackPinHook;
123#endif
124};
125
126#endif