[USB]
[reactos.git] / reactos / 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
12 #include "parser.h"
13
14 typedef struct
15 {
16 ULONG Size;
17 union
18 {
19 UCHAR RawData[1];
20 };
21 }HID_COLLECTION_CONTEXT, *PHID_COLLECTION_CONTEXT;
22
23 ULONG
24 HidParser_CalculateCollectionSize(
25 IN PHID_COLLECTION Collection)
26 {
27 ULONG Size = 0, Index;
28
29 Size = sizeof(HID_COLLECTION);
30
31 //
32 // add size required for the number of report items
33 //
34 for(Index = 0; Index < Collection->ReportCount; Index++)
35 {
36 //
37 // get report size
38 //
39 ASSERT(Collection->Reports[Index]->ItemCount);
40 Size += sizeof(HID_REPORT) + Collection->Reports[Index]->ItemCount * sizeof(HID_REPORT_ITEM);
41 }
42
43 //
44 // calculate size for sub collections
45 //
46 for(Index = 0; Index < Collection->NodeCount; Index++)
47 {
48 Size += HidParser_CalculateCollectionSize(Collection->Nodes[Index]);
49 }
50
51 //
52 // append size for the offset
53 //
54 Size += (Collection->ReportCount + Collection->NodeCount) * sizeof(ULONG);
55
56 //
57 // done
58 //
59 return Size;
60 }
61
62 ULONG
63 HidParser_CalculateContextSize(
64 IN PHID_COLLECTION Collection)
65 {
66 ULONG Size;
67
68 //
69 // minimum size is the size of the collection
70 //
71 Size = HidParser_CalculateCollectionSize(Collection);
72
73 //
74 // append collection context size
75 //
76 Size += sizeof(HID_COLLECTION_CONTEXT);
77 return Size;
78 }
79
80 ULONG
81 HidParser_StoreCollection(
82 IN PHID_PARSER Parser,
83 IN PHID_COLLECTION Collection,
84 IN PHID_COLLECTION_CONTEXT CollectionContext,
85 IN ULONG CurrentOffset)
86 {
87 ULONG Index;
88 ULONG ReportSize;
89 ULONG InitialOffset;
90 ULONG CollectionSize;
91 PHID_COLLECTION TargetCollection;
92
93 //
94 // backup initial offset
95 //
96 InitialOffset = CurrentOffset;
97
98 //
99 // get target collection
100 //
101 TargetCollection = (PHID_COLLECTION)(&CollectionContext->RawData[CurrentOffset]);
102
103 //
104 // first copy the collection details
105 //
106 Parser->Copy(TargetCollection, Collection, sizeof(HID_COLLECTION));
107
108 //
109 // calulcate collection size
110 //
111 CollectionSize = sizeof(HID_COLLECTION) + sizeof(ULONG) * (Collection->ReportCount + Collection->NodeCount);
112
113 //
114 // increase offset
115 //
116 CurrentOffset += CollectionSize;
117
118 //
119 // sanity check
120 //
121 ASSERT(CurrentOffset < CollectionContext->Size);
122
123 //
124 // first store the report items
125 //
126 for(Index = 0; Index < Collection->ReportCount; Index++)
127 {
128 //
129 // calculate report size
130 //
131 ReportSize = sizeof(HID_REPORT) + Collection->Reports[Index]->ItemCount * sizeof(HID_REPORT_ITEM);
132
133 //
134 // sanity check
135 //
136 ASSERT(CurrentOffset + ReportSize < CollectionContext->Size);
137
138 //
139 // copy report item
140 //
141 Parser->Copy(&CollectionContext->RawData[CurrentOffset], Collection->Reports[Index], ReportSize);
142
143 //
144 // store offset to report item
145 //
146 TargetCollection->Offsets[Index] = CurrentOffset;
147
148 //
149 // move to next offset
150 //
151 CurrentOffset += ReportSize;
152 }
153
154 ASSERT(CurrentOffset <= CollectionContext->Size);
155
156 //
157 // now store the sub collections
158 //
159 for(Index = 0; Index < Collection->NodeCount; Index++)
160 {
161 //
162 // store offset
163 //
164 TargetCollection->Offsets[Collection->NodeCount + Index] = CurrentOffset;
165
166 //
167 // store sub collections
168 //
169 CurrentOffset += HidParser_StoreCollection(Parser, Collection->Nodes[Index], CollectionContext, CurrentOffset);
170
171 //
172 // sanity check
173 //
174 ASSERT(CurrentOffset < CollectionContext->Size);
175 }
176
177 //
178 // return size of collection
179 //
180 return CurrentOffset - InitialOffset;
181 }
182
183 HIDPARSER_STATUS
184 HidParser_BuildCollectionContext(
185 IN PHID_PARSER Parser,
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(Parser, RootCollection, CollectionContext, 0);
203
204 //
205 // sanity check
206 //
207 ASSERT(CollectionSize + sizeof(HID_COLLECTION_CONTEXT) == ContextSize);
208
209 DPRINT1("CollectionContext %p\n", CollectionContext);
210 DPRINT1("CollectionContext RawData %p\n", CollectionContext->RawData);
211 DPRINT1("CollectionContext Size %lu\n", CollectionContext->Size);
212
213 //
214 // done
215 //
216 return HIDPARSER_STATUS_SUCCESS;
217 }
218
219 PHID_REPORT
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->NodeCount + 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
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
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
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->NodeCount + 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
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 }