The Pedigree Project 0.1
TransferCompletion.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 USB_HCD_TRANSFER_COMPLETION_H
9#define USB_HCD_TRANSFER_COMPLETION_H
10
11#include "pedigree/kernel/Atomic.h"
12#include "pedigree/kernel/compiler.h"
13#include "pedigree/kernel/processor/types.h"
14#include "pedigree/kernel/utilities/assert.h"
15
16namespace UsbHcd {
27 public:
28 using Callback = void (*)(uintptr_t, ssize_t);
29
30 enum class State : size_t {
31 Idle,
32 Active,
33 Captured,
34 PublicationClaimed,
35 };
36
37 enum class Reason {
38 Natural,
39 Cancelled,
40 Teardown,
41 };
42
43 enum class CancellationDisposition {
44 NoMatch,
45 Claimed,
46 DrainPublished,
47 };
48
49 struct Claim {
50 Claim() : callback(nullptr), parameter(0), generation(0), result(0), reason(Reason::Teardown) {}
51
52 Callback callback;
53 uintptr_t parameter;
54 size_t generation;
55 ssize_t result;
56 Reason reason;
57 };
58
60 : m_State(static_cast<size_t>(State::Idle)),
61 m_Callback(nullptr),
62 m_Parameter(0),
63 m_Generation(0),
64 m_Result(0) {}
65
67 void arm(Callback callback, uintptr_t parameter, size_t generation) {
68 assert(generation);
69 assert(state() == State::Idle);
70 m_Callback = callback;
71 m_Parameter = parameter;
72 m_Generation = generation;
73 m_State = static_cast<size_t>(State::Active);
74 }
75
77 MUST_USE_RESULT bool captureNatural(ssize_t result) {
78 m_Result = result;
79 return transition(State::Active, State::Captured);
80 }
81
84 if (!transition(State::Captured, State::PublicationClaimed))
85 return false;
86
87 fillClaim(claim, Reason::Natural, m_Result);
88 return true;
89 }
90
98 MUST_USE_RESULT CancellationDisposition claimCancellation(Callback callback, uintptr_t parameter,
99 ssize_t cancellationResult,
100 Claim& claim) {
101 if (!matches(callback, parameter))
102 return CancellationDisposition::NoMatch;
103
104 while (true) {
105 const State observed = state();
106 if (observed == State::Active) {
107 if (transition(State::Active, State::PublicationClaimed)) {
108 fillClaim(claim, Reason::Cancelled, cancellationResult);
109 return CancellationDisposition::Claimed;
110 }
111 continue;
112 }
113 if (observed == State::Captured) {
114 if (claimCaptured(claim))
115 return CancellationDisposition::Claimed;
116 continue;
117 }
118 if (observed == State::PublicationClaimed) {
119 fillClaim(claim, Reason::Natural, 0);
120 return CancellationDisposition::DrainPublished;
121 }
122 return CancellationDisposition::NoMatch;
123 }
124 }
125
133 MUST_USE_RESULT bool claimForTeardown(ssize_t cancellationResult, Claim& claim) {
134 while (true) {
135 const State observed = state();
136 if (observed == State::Active) {
137 if (transition(State::Active, State::PublicationClaimed)) {
138 fillClaim(claim, Reason::Teardown, cancellationResult);
139 return true;
140 }
141 continue;
142 }
143 if (observed == State::Captured)
144 return claimCaptured(claim);
145 return false;
146 }
147 }
148
149 State state() const {
150 return static_cast<State>(static_cast<size_t>(m_State));
151 }
152
153 size_t generation() const {
154 return m_Generation;
155 }
156
157 private:
158 bool matches(Callback callback, uintptr_t parameter) const {
159 return state() != State::Idle && m_Callback == callback && m_Parameter == parameter;
160 }
161
162 bool transition(State from, State to) {
163 return m_State.compareAndSwap(static_cast<size_t>(from), static_cast<size_t>(to));
164 }
165
166 void fillClaim(Claim& claim, Reason reason, ssize_t result) const {
167 claim.callback = m_Callback;
168 claim.parameter = m_Parameter;
169 claim.generation = m_Generation;
170 claim.result = result;
171 claim.reason = reason;
172 }
173
174 Atomic<size_t> m_State;
175 Callback m_Callback;
176 uintptr_t m_Parameter;
177 size_t m_Generation;
178 ssize_t m_Result;
179
180 TransferCompletion(const TransferCompletion&) = delete;
181 TransferCompletion& operator=(const TransferCompletion&) = delete;
182};
183} // namespace UsbHcd
184
185#endif
MUST_USE_RESULT CancellationDisposition claimCancellation(Callback callback, uintptr_t parameter, ssize_t cancellationResult, Claim &claim)
void arm(Callback callback, uintptr_t parameter, size_t generation)
MUST_USE_RESULT bool claimForTeardown(ssize_t cancellationResult, Claim &claim)
MUST_USE_RESULT bool captureNatural(ssize_t result)
MUST_USE_RESULT bool claimCaptured(Claim &claim)