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