xref: /reactos/sdk/lib/drivers/hidparser/context.c (revision d7fd62d4)
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_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
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
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
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->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
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