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