[NTOSKRNL_VISTA] Implement IoGetIrpExtraCreateParameter
[reactos.git] / sdk / lib / drivers / hidparser / context.c
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
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
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
83 HidParser_StoreCollection(
84 IN PHID_PARSER Parser,
85 IN PHID_COLLECTION Collection,
86 IN PHID_COLLECTION_CONTEXT CollectionContext,
87 IN ULONG CurrentOffset)
88 {
89 ULONG Index;
90 ULONG ReportSize;
91 ULONG InitialOffset;
92 ULONG CollectionSize;
93 PHID_COLLECTION TargetCollection;
94
95 //
96 // backup initial offset
97 //
98 InitialOffset = CurrentOffset;
99
100 //
101 // get target collection
102 //
103 TargetCollection = (PHID_COLLECTION)(&CollectionContext->RawData[CurrentOffset]);
104
105 //
106 // first copy the collection details
107 //
108 Parser->Copy(TargetCollection, Collection, sizeof(HID_COLLECTION));
109
110 //
111 // calulcate collection size
112 //
113 CollectionSize = sizeof(HID_COLLECTION) + sizeof(ULONG) * (Collection->ReportCount + Collection->NodeCount);
114
115 //
116 // increase offset
117 //
118 CurrentOffset += CollectionSize;
119
120 //
121 // sanity check
122 //
123 ASSERT(CurrentOffset < CollectionContext->Size);
124
125 //
126 // first store the report items
127 //
128 for(Index = 0; Index < Collection->ReportCount; Index++)
129 {
130 //
131 // calculate report size
132 //
133 ReportSize = sizeof(HID_REPORT) + Collection->Reports[Index]->ItemCount * sizeof(HID_REPORT_ITEM);
134
135 //
136 // sanity check
137 //
138 ASSERT(CurrentOffset + ReportSize < CollectionContext->Size);
139
140 //
141 // copy report item
142 //
143 Parser->Copy(&CollectionContext->RawData[CurrentOffset], Collection->Reports[Index], ReportSize);
144
145 //
146 // store offset to report item
147 //
148 TargetCollection->Offsets[Index] = CurrentOffset;
149
150 //
151 // move to next offset
152 //
153 CurrentOffset += ReportSize;
154 }
155
156 ASSERT(CurrentOffset <= CollectionContext->Size);
157
158 //
159 // now store the sub collections
160 //
161 for(Index = 0; Index < Collection->NodeCount; Index++)
162 {
163 //
164 // store offset
165 //
166 TargetCollection->Offsets[Collection->ReportCount + Index] = CurrentOffset;
167
168 //
169 // store sub collections
170 //
171 CurrentOffset += HidParser_StoreCollection(Parser, Collection->Nodes[Index], CollectionContext, CurrentOffset);
172
173 //
174 // sanity check
175 //
176 ASSERT(CurrentOffset < CollectionContext->Size);
177 }
178
179 //
180 // return size of collection
181 //
182 return CurrentOffset - InitialOffset;
183 }
184
185 HIDPARSER_STATUS
186 HidParser_BuildCollectionContext(
187 IN PHID_PARSER Parser,
188 IN PHID_COLLECTION RootCollection,
189 IN PVOID Context,
190 IN ULONG ContextSize)
191 {
192 PHID_COLLECTION_CONTEXT CollectionContext;
193 ULONG CollectionSize;
194
195 //
196 // init context
197 //
198 CollectionContext = (PHID_COLLECTION_CONTEXT)Context;
199 CollectionContext->Size = ContextSize;
200
201 //
202 // store collections
203 //
204 CollectionSize = HidParser_StoreCollection(Parser, RootCollection, CollectionContext, 0);
205
206 //
207 // sanity check
208 //
209 ASSERT(CollectionSize + sizeof(HID_COLLECTION_CONTEXT) == ContextSize);
210
211 DPRINT("CollectionContext %p\n", CollectionContext);
212 DPRINT("CollectionContext RawData %p\n", CollectionContext->RawData);
213 DPRINT("CollectionContext Size %lu\n", CollectionContext->Size);
214
215 //
216 // done
217 //
218 return HIDPARSER_STATUS_SUCCESS;
219 }
220
221 PHID_REPORT
222 HidParser_SearchReportInCollection(
223 IN PHID_COLLECTION_CONTEXT CollectionContext,
224 IN PHID_COLLECTION Collection,
225 IN UCHAR ReportType)
226 {
227 ULONG Index;
228 PHID_REPORT Report;
229 PHID_COLLECTION SubCollection;
230
231 //
232 // search first in local array
233 //
234 for(Index = 0; Index < Collection->ReportCount; Index++)
235 {
236 //
237 // get report
238 //
239 Report = (PHID_REPORT)(CollectionContext->RawData + Collection->Offsets[Index]);
240 if (Report->Type == ReportType)
241 {
242 //
243 // found report
244 //
245 return Report;
246 }
247 }
248
249 //
250 // now search in sub collections
251 //
252 for(Index = 0; Index < Collection->NodeCount; Index++)
253 {
254 //
255 // get collection
256 //
257 SubCollection = (PHID_COLLECTION)(CollectionContext->RawData + Collection->Offsets[Collection->ReportCount + Index]);
258
259 //
260 // recursively search collection
261 //
262 Report = HidParser_SearchReportInCollection(CollectionContext, SubCollection, ReportType);
263 if (Report)
264 {
265 //
266 // found report
267 //
268 return Report;
269 }
270 }
271
272 //
273 // not found
274 //
275 return NULL;
276 }
277
278 PHID_REPORT
279 HidParser_GetReportInCollection(
280 IN PVOID Context,
281 IN UCHAR ReportType)
282 {
283 PHID_COLLECTION_CONTEXT CollectionContext = (PHID_COLLECTION_CONTEXT)Context;
284
285 //
286 // done
287 //
288 return HidParser_SearchReportInCollection(CollectionContext, (PHID_COLLECTION)&CollectionContext->RawData, ReportType);
289 }
290
291 PHID_COLLECTION
292 HidParser_GetCollectionFromContext(
293 IN PVOID Context)
294 {
295 PHID_COLLECTION_CONTEXT CollectionContext = (PHID_COLLECTION_CONTEXT)Context;
296
297 //
298 // return root collection
299 //
300 return (PHID_COLLECTION)CollectionContext->RawData;
301 }
302
303 ULONG
304 HidParser_GetCollectionCount(
305 IN PHID_COLLECTION_CONTEXT CollectionContext,
306 IN PHID_COLLECTION Collection)
307 {
308 ULONG Index;
309 ULONG Count = Collection->NodeCount;
310 PHID_COLLECTION SubCollection;
311
312 for(Index = 0; Index < Collection->NodeCount; Index++)
313 {
314 //
315 // get offset to sub collection
316 //
317 SubCollection = (PHID_COLLECTION)(CollectionContext->RawData + Collection->Offsets[Collection->ReportCount + Index]);
318
319 //
320 // count collection for sub nodes
321 //
322 Count += HidParser_GetCollectionCount(CollectionContext, SubCollection);
323 }
324
325 //
326 // done
327 //
328 return Count;
329 }
330
331 ULONG
332 HidParser_GetTotalCollectionCount(
333 IN PVOID Context)
334 {
335 PHID_COLLECTION_CONTEXT CollectionContext;
336
337 //
338 // get parser context
339 //
340 CollectionContext = (PHID_COLLECTION_CONTEXT)Context;
341
342 //
343 // count collections
344 //
345 return HidParser_GetCollectionCount(CollectionContext, (PHID_COLLECTION)CollectionContext->RawData);
346 }