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