1 /*
2 * PROJECT: ReactOS HID Parser Library
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: lib/drivers/hidparser/context.c
5 * PURPOSE: HID Parser
6 * PROGRAMMERS:
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
9 */
10
11 #include "parser.h"
12
13 #define NDEBUG
14 #include <debug.h>
15
16 typedef struct
17 {
18 ULONG Size;
19 union
20 {
21 UCHAR RawData[1];
22 };
23 }HID_COLLECTION_CONTEXT, *PHID_COLLECTION_CONTEXT;
24
25 ULONG
HidParser_CalculateCollectionSize(IN PHID_COLLECTION Collection)26 HidParser_CalculateCollectionSize(
27 IN PHID_COLLECTION Collection)
28 {
29 ULONG Size = 0, Index;
30
31 Size = sizeof(HID_COLLECTION);
32
33 //
34 // add size required for the number of report items
35 //
36 for(Index = 0; Index < Collection->ReportCount; Index++)
37 {
38 //
39 // get report size
40 //
41 ASSERT(Collection->Reports[Index]->ItemCount);
42 Size += sizeof(HID_REPORT) + Collection->Reports[Index]->ItemCount * sizeof(HID_REPORT_ITEM);
43 }
44
45 //
46 // calculate size for sub collections
47 //
48 for(Index = 0; Index < Collection->NodeCount; Index++)
49 {
50 Size += HidParser_CalculateCollectionSize(Collection->Nodes[Index]);
51 }
52
53 //
54 // append size for the offset
55 //
56 Size += (Collection->ReportCount + Collection->NodeCount) * sizeof(ULONG);
57
58 //
59 // done
60 //
61 return Size;
62 }
63
64 ULONG
HidParser_CalculateContextSize(IN PHID_COLLECTION Collection)65 HidParser_CalculateContextSize(
66 IN PHID_COLLECTION Collection)
67 {
68 ULONG Size;
69
70 //
71 // minimum size is the size of the collection
72 //
73 Size = HidParser_CalculateCollectionSize(Collection);
74
75 //
76 // append collection context size
77 //
78 Size += sizeof(HID_COLLECTION_CONTEXT);
79 return Size;
80 }
81
82 ULONG
HidParser_StoreCollection(IN PHID_COLLECTION Collection,IN PHID_COLLECTION_CONTEXT CollectionContext,IN ULONG CurrentOffset)83 HidParser_StoreCollection(
84 IN PHID_COLLECTION Collection,
85 IN PHID_COLLECTION_CONTEXT CollectionContext,
86 IN ULONG CurrentOffset)
87 {
88 ULONG Index;
89 ULONG ReportSize;
90 ULONG InitialOffset;
91 ULONG CollectionSize;
92 PHID_COLLECTION TargetCollection;
93
94 //
95 // backup initial offset
96 //
97 InitialOffset = CurrentOffset;
98
99 //
100 // get target collection
101 //
102 TargetCollection = (PHID_COLLECTION)(&CollectionContext->RawData[CurrentOffset]);
103
104 //
105 // first copy the collection details
106 //
107 CopyFunction(TargetCollection, Collection, sizeof(HID_COLLECTION));
108
109 //
110 // calulcate collection size
111 //
112 CollectionSize = sizeof(HID_COLLECTION) + sizeof(ULONG) * (Collection->ReportCount + Collection->NodeCount);
113
114 //
115 // increase offset
116 //
117 CurrentOffset += CollectionSize;
118
119 //
120 // sanity check
121 //
122 ASSERT(CurrentOffset < CollectionContext->Size);
123
124 //
125 // first store the report items
126 //
127 for(Index = 0; Index < Collection->ReportCount; Index++)
128 {
129 //
130 // calculate report size
131 //
132 ReportSize = sizeof(HID_REPORT) + Collection->Reports[Index]->ItemCount * sizeof(HID_REPORT_ITEM);
133
134 //
135 // sanity check
136 //
137 ASSERT(CurrentOffset + ReportSize < CollectionContext->Size);
138
139 //
140 // copy report item
141 //
142 CopyFunction(&CollectionContext->RawData[CurrentOffset], Collection->Reports[Index], ReportSize);
143
144 //
145 // store offset to report item
146 //
147 TargetCollection->Offsets[Index] = CurrentOffset;
148
149 //
150 // move to next offset
151 //
152 CurrentOffset += ReportSize;
153 }
154
155 ASSERT(CurrentOffset <= CollectionContext->Size);
156
157 //
158 // now store the sub collections
159 //
160 for(Index = 0; Index < Collection->NodeCount; Index++)
161 {
162 //
163 // store offset
164 //
165 TargetCollection->Offsets[Collection->ReportCount + Index] = CurrentOffset;
166
167 //
168 // store sub collections
169 //
170 CurrentOffset += HidParser_StoreCollection(Collection->Nodes[Index], CollectionContext, CurrentOffset);
171
172 //
173 // sanity check
174 //
175 ASSERT(CurrentOffset < CollectionContext->Size);
176 }
177
178 //
179 // return size of collection
180 //
181 return CurrentOffset - InitialOffset;
182 }
183
184 NTSTATUS
HidParser_BuildCollectionContext(IN PHID_COLLECTION RootCollection,IN PVOID Context,IN ULONG ContextSize)185 HidParser_BuildCollectionContext(
186 IN PHID_COLLECTION RootCollection,
187 IN PVOID Context,
188 IN ULONG ContextSize)
189 {
190 PHID_COLLECTION_CONTEXT CollectionContext;
191 ULONG CollectionSize;
192
193 //
194 // init context
195 //
196 CollectionContext = (PHID_COLLECTION_CONTEXT)Context;
197 CollectionContext->Size = ContextSize;
198
199 //
200 // store collections
201 //
202 CollectionSize = HidParser_StoreCollection(RootCollection, CollectionContext, 0);
203
204 //
205 // sanity check
206 //
207 ASSERT(CollectionSize + sizeof(HID_COLLECTION_CONTEXT) == ContextSize);
208
209 DPRINT("CollectionContext %p\n", CollectionContext);
210 DPRINT("CollectionContext RawData %p\n", CollectionContext->RawData);
211 DPRINT("CollectionContext Size %lu\n", CollectionContext->Size);
212
213 //
214 // done
215 //
216 return HIDP_STATUS_SUCCESS;
217 }
218
219 PHID_REPORT
HidParser_SearchReportInCollection(IN PHID_COLLECTION_CONTEXT CollectionContext,IN PHID_COLLECTION Collection,IN UCHAR ReportType)220 HidParser_SearchReportInCollection(
221 IN PHID_COLLECTION_CONTEXT CollectionContext,
222 IN PHID_COLLECTION Collection,
223 IN UCHAR ReportType)
224 {
225 ULONG Index;
226 PHID_REPORT Report;
227 PHID_COLLECTION SubCollection;
228
229 //
230 // search first in local array
231 //
232 for(Index = 0; Index < Collection->ReportCount; Index++)
233 {
234 //
235 // get report
236 //
237 Report = (PHID_REPORT)(CollectionContext->RawData + Collection->Offsets[Index]);
238 if (Report->Type == ReportType)
239 {
240 //
241 // found report
242 //
243 return Report;
244 }
245 }
246
247 //
248 // now search in sub collections
249 //
250 for(Index = 0; Index < Collection->NodeCount; Index++)
251 {
252 //
253 // get collection
254 //
255 SubCollection = (PHID_COLLECTION)(CollectionContext->RawData + Collection->Offsets[Collection->ReportCount + Index]);
256
257 //
258 // recursively search collection
259 //
260 Report = HidParser_SearchReportInCollection(CollectionContext, SubCollection, ReportType);
261 if (Report)
262 {
263 //
264 // found report
265 //
266 return Report;
267 }
268 }
269
270 //
271 // not found
272 //
273 return NULL;
274 }
275
276 PHID_REPORT
HidParser_GetReportInCollection(IN PVOID Context,IN UCHAR ReportType)277 HidParser_GetReportInCollection(
278 IN PVOID Context,
279 IN UCHAR ReportType)
280 {
281 PHID_COLLECTION_CONTEXT CollectionContext = (PHID_COLLECTION_CONTEXT)Context;
282
283 //
284 // done
285 //
286 return HidParser_SearchReportInCollection(CollectionContext, (PHID_COLLECTION)&CollectionContext->RawData, ReportType);
287 }
288
289 PHID_COLLECTION
HidParser_GetCollectionFromContext(IN PVOID Context)290 HidParser_GetCollectionFromContext(
291 IN PVOID Context)
292 {
293 PHID_COLLECTION_CONTEXT CollectionContext = (PHID_COLLECTION_CONTEXT)Context;
294
295 //
296 // return root collection
297 //
298 return (PHID_COLLECTION)CollectionContext->RawData;
299 }
300
301 ULONG
HidParser_GetCollectionCount(IN PHID_COLLECTION_CONTEXT CollectionContext,IN PHID_COLLECTION Collection)302 HidParser_GetCollectionCount(
303 IN PHID_COLLECTION_CONTEXT CollectionContext,
304 IN PHID_COLLECTION Collection)
305 {
306 ULONG Index;
307 ULONG Count = Collection->NodeCount;
308 PHID_COLLECTION SubCollection;
309
310 for(Index = 0; Index < Collection->NodeCount; Index++)
311 {
312 //
313 // get offset to sub collection
314 //
315 SubCollection = (PHID_COLLECTION)(CollectionContext->RawData + Collection->Offsets[Collection->ReportCount + Index]);
316
317 //
318 // count collection for sub nodes
319 //
320 Count += HidParser_GetCollectionCount(CollectionContext, SubCollection);
321 }
322
323 //
324 // done
325 //
326 return Count;
327 }
328
329 ULONG
HidParser_GetTotalCollectionCount(IN PVOID Context)330 HidParser_GetTotalCollectionCount(
331 IN PVOID Context)
332 {
333 PHID_COLLECTION_CONTEXT CollectionContext;
334
335 //
336 // get parser context
337 //
338 CollectionContext = (PHID_COLLECTION_CONTEXT)Context;
339
340 //
341 // count collections
342 //
343 return HidParser_GetCollectionCount(CollectionContext, (PHID_COLLECTION)CollectionContext->RawData);
344 }
345