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/hidparser.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 NTSTATUS 17c2c66affSColin Finck TranslateHidParserStatus( 18c2c66affSColin Finck IN HIDPARSER_STATUS Status) 19c2c66affSColin Finck { 20c2c66affSColin Finck switch(Status) 21c2c66affSColin Finck { 22c2c66affSColin Finck case HIDPARSER_STATUS_INSUFFICIENT_RESOURCES: 23c2c66affSColin Finck return HIDP_STATUS_INTERNAL_ERROR; 24c2c66affSColin Finck case HIDPARSER_STATUS_NOT_IMPLEMENTED: 25c2c66affSColin Finck return HIDP_STATUS_NOT_IMPLEMENTED; 26c2c66affSColin Finck case HIDPARSER_STATUS_REPORT_NOT_FOUND: 27c2c66affSColin Finck return HIDP_STATUS_REPORT_DOES_NOT_EXIST; 28c2c66affSColin Finck case HIDPARSER_STATUS_INVALID_REPORT_LENGTH: 29c2c66affSColin Finck return HIDP_STATUS_INVALID_REPORT_LENGTH; 30c2c66affSColin Finck case HIDPARSER_STATUS_INVALID_REPORT_TYPE: 31c2c66affSColin Finck return HIDP_STATUS_INVALID_REPORT_TYPE; 32c2c66affSColin Finck case HIDPARSER_STATUS_BUFFER_TOO_SMALL: 33c2c66affSColin Finck return HIDP_STATUS_BUFFER_TOO_SMALL; 34c2c66affSColin Finck case HIDPARSER_STATUS_USAGE_NOT_FOUND: 35c2c66affSColin Finck return HIDP_STATUS_USAGE_NOT_FOUND; 36c2c66affSColin Finck case HIDPARSER_STATUS_I8042_TRANS_UNKNOWN: 37c2c66affSColin Finck return HIDP_STATUS_I8042_TRANS_UNKNOWN; 38c2c66affSColin Finck case HIDPARSER_STATUS_COLLECTION_NOT_FOUND: 39c2c66affSColin Finck return HIDP_STATUS_NOT_IMPLEMENTED; //FIXME 40c2c66affSColin Finck case HIDPARSER_STATUS_BAD_LOG_PHY_VALUES: 41c2c66affSColin Finck return HIDP_STATUS_BAD_LOG_PHY_VALUES; 42c2c66affSColin Finck } 43c2c66affSColin Finck DPRINT1("TranslateHidParserStatus Status %ld not implemented\n", Status); 44c2c66affSColin Finck return HIDP_STATUS_NOT_IMPLEMENTED; 45c2c66affSColin Finck } 46c2c66affSColin Finck 47c2c66affSColin Finck NTSTATUS 48c2c66affSColin Finck NTAPI 49c2c66affSColin Finck HidParser_GetCollectionDescription( 50c2c66affSColin Finck IN PHIDP_REPORT_DESCRIPTOR ReportDesc, 51c2c66affSColin Finck IN ULONG DescLength, 52c2c66affSColin Finck IN POOL_TYPE PoolType, 53c2c66affSColin Finck OUT PHIDP_DEVICE_DESC DeviceDescription) 54c2c66affSColin Finck { 55c2c66affSColin Finck HIDPARSER_STATUS ParserStatus; 56c2c66affSColin Finck ULONG CollectionCount; 57c2c66affSColin Finck ULONG Index; 58c2c66affSColin Finck PVOID ParserContext; 59c2c66affSColin Finck 60c2c66affSColin Finck // 61c2c66affSColin Finck // first parse the report descriptor 62c2c66affSColin Finck // 63*c151f8a1SHervé Poussineau ParserStatus = HidParser_ParseReportDescriptor(ReportDesc, DescLength, &ParserContext); 64c2c66affSColin Finck if (ParserStatus != HIDPARSER_STATUS_SUCCESS) 65c2c66affSColin Finck { 66c2c66affSColin Finck // 67c2c66affSColin Finck // failed to parse report descriptor 68c2c66affSColin Finck // 69*c151f8a1SHervé Poussineau DebugFunction("[HIDPARSER] Failed to parse report descriptor with %x\n", ParserStatus); 70c2c66affSColin Finck return ParserStatus; 71c2c66affSColin Finck } 72c2c66affSColin Finck 73c2c66affSColin Finck // 74c2c66affSColin Finck // get collection count 75c2c66affSColin Finck // 76c2c66affSColin Finck CollectionCount = HidParser_NumberOfTopCollections(ParserContext); 77c2c66affSColin Finck if (CollectionCount == 0) 78c2c66affSColin Finck { 79c2c66affSColin Finck // 80c2c66affSColin Finck // no top level collections found 81c2c66affSColin Finck // 82c2c66affSColin Finck ASSERT(FALSE); 83c2c66affSColin Finck return STATUS_NO_DATA_DETECTED; 84c2c66affSColin Finck } 85c2c66affSColin Finck 86c2c66affSColin Finck // 87c2c66affSColin Finck // zero description 88c2c66affSColin Finck // 89*c151f8a1SHervé Poussineau ZeroFunction(DeviceDescription, sizeof(HIDP_DEVICE_DESC)); 90c2c66affSColin Finck 91c2c66affSColin Finck // 92c2c66affSColin Finck // allocate collection 93c2c66affSColin Finck // 94*c151f8a1SHervé Poussineau DeviceDescription->CollectionDesc = (PHIDP_COLLECTION_DESC)AllocFunction(sizeof(HIDP_COLLECTION_DESC) * CollectionCount); 95c2c66affSColin Finck if (!DeviceDescription->CollectionDesc) 96c2c66affSColin Finck { 97c2c66affSColin Finck // 98c2c66affSColin Finck // no memory 99c2c66affSColin Finck // 100c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 101c2c66affSColin Finck } 102c2c66affSColin Finck 103c2c66affSColin Finck // 104c2c66affSColin Finck // allocate report description 105c2c66affSColin Finck // 106*c151f8a1SHervé Poussineau DeviceDescription->ReportIDs = (PHIDP_REPORT_IDS)AllocFunction(sizeof(HIDP_REPORT_IDS) * CollectionCount); 107c2c66affSColin Finck if (!DeviceDescription->ReportIDs) 108c2c66affSColin Finck { 109c2c66affSColin Finck // 110c2c66affSColin Finck // no memory 111c2c66affSColin Finck // 112*c151f8a1SHervé Poussineau FreeFunction(DeviceDescription->CollectionDesc); 113c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 114c2c66affSColin Finck } 115c2c66affSColin Finck 116c2c66affSColin Finck for(Index = 0; Index < CollectionCount; Index++) 117c2c66affSColin Finck { 118c2c66affSColin Finck // 119c2c66affSColin Finck // set preparsed data length 120c2c66affSColin Finck // 121*c151f8a1SHervé Poussineau DeviceDescription->CollectionDesc[Index].PreparsedDataLength = HidParser_GetContextSize(ParserContext, Index); 122*c151f8a1SHervé Poussineau ParserStatus = HidParser_BuildContext(ParserContext, Index, DeviceDescription->CollectionDesc[Index].PreparsedDataLength, (PVOID*)&DeviceDescription->CollectionDesc[Index].PreparsedData); 123c2c66affSColin Finck if (ParserStatus != HIDPARSER_STATUS_SUCCESS) 124c2c66affSColin Finck { 125c2c66affSColin Finck // 126c2c66affSColin Finck // no memory 127c2c66affSColin Finck // 128*c151f8a1SHervé Poussineau FreeFunction(DeviceDescription->CollectionDesc); 129*c151f8a1SHervé Poussineau FreeFunction(DeviceDescription->ReportIDs); 130c2c66affSColin Finck return ParserStatus; 131c2c66affSColin Finck } 132c2c66affSColin Finck 133c2c66affSColin Finck // 134c2c66affSColin Finck // init report description 135c2c66affSColin Finck // 136c2c66affSColin Finck DeviceDescription->ReportIDs[Index].CollectionNumber = Index + 1; 137c2c66affSColin Finck DeviceDescription->ReportIDs[Index].ReportID = Index; //FIXME 138c2c66affSColin Finck DeviceDescription->ReportIDs[Index].InputLength = HidParser_GetReportLength((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_INPUT); 139c2c66affSColin Finck DeviceDescription->ReportIDs[Index].OutputLength = HidParser_GetReportLength((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_OUTPUT); 140c2c66affSColin Finck DeviceDescription->ReportIDs[Index].FeatureLength = HidParser_GetReportLength((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_FEATURE); 141c2c66affSColin Finck 142c2c66affSColin Finck 143c2c66affSColin Finck DeviceDescription->ReportIDs[Index].InputLength += (HidParser_UsesReportId((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_INPUT) ? 1 : 0); 144c2c66affSColin Finck DeviceDescription->ReportIDs[Index].OutputLength += (HidParser_UsesReportId((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_OUTPUT) ? 1 : 0); 145c2c66affSColin Finck DeviceDescription->ReportIDs[Index].FeatureLength += (HidParser_UsesReportId((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_FEATURE) ? 1 : 0); 146c2c66affSColin Finck 147c2c66affSColin Finck 148c2c66affSColin Finck // 149c2c66affSColin Finck // init collection description 150c2c66affSColin Finck // 151c2c66affSColin Finck DeviceDescription->CollectionDesc[Index].CollectionNumber = Index + 1; 152c2c66affSColin Finck 153c2c66affSColin Finck // 154c2c66affSColin Finck // get collection usage page 155c2c66affSColin Finck // 156c2c66affSColin Finck ParserStatus = HidParser_GetCollectionUsagePage((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, &DeviceDescription->CollectionDesc[Index].Usage, &DeviceDescription->CollectionDesc[Index].UsagePage); 157c2c66affSColin Finck if (ParserStatus != HIDPARSER_STATUS_SUCCESS) 158c2c66affSColin Finck { 159c2c66affSColin Finck // collection not found 160*c151f8a1SHervé Poussineau FreeFunction(DeviceDescription->CollectionDesc); 161*c151f8a1SHervé Poussineau FreeFunction(DeviceDescription->ReportIDs); 162c2c66affSColin Finck return ParserStatus; 163c2c66affSColin Finck } 164c2c66affSColin Finck 165c2c66affSColin Finck // 166c2c66affSColin Finck // windows seems to prepend the report id, regardless if it is required 167c2c66affSColin Finck // 168c2c66affSColin Finck DeviceDescription->CollectionDesc[Index].CollectionNumber = Index + 1; 169c2c66affSColin Finck DeviceDescription->CollectionDesc[Index].InputLength = DeviceDescription->ReportIDs[Index].InputLength; 170c2c66affSColin Finck DeviceDescription->CollectionDesc[Index].OutputLength = DeviceDescription->ReportIDs[Index].OutputLength; 171c2c66affSColin Finck DeviceDescription->CollectionDesc[Index].FeatureLength = DeviceDescription->ReportIDs[Index].FeatureLength; 172c2c66affSColin Finck 173c2c66affSColin Finck DeviceDescription->CollectionDesc[Index].InputLength += (HidParser_UsesReportId((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_INPUT) == FALSE ? 1 : 0); 174c2c66affSColin Finck DeviceDescription->CollectionDesc[Index].OutputLength += (HidParser_UsesReportId((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_OUTPUT) == FALSE ? 1 : 0); 175c2c66affSColin Finck DeviceDescription->CollectionDesc[Index].FeatureLength += (HidParser_UsesReportId((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_FEATURE) == FALSE ? 1 : 0); 176c2c66affSColin Finck 177c2c66affSColin Finck 178c2c66affSColin Finck } 179c2c66affSColin Finck 180c2c66affSColin Finck // 181c2c66affSColin Finck // store collection & report count 182c2c66affSColin Finck // 183c2c66affSColin Finck DeviceDescription->CollectionDescLength = CollectionCount; 184c2c66affSColin Finck DeviceDescription->ReportIDsLength = CollectionCount; 185c2c66affSColin Finck 186c2c66affSColin Finck // 187c2c66affSColin Finck // done 188c2c66affSColin Finck // 189c2c66affSColin Finck return STATUS_SUCCESS; 190c2c66affSColin Finck } 191c2c66affSColin Finck 192c2c66affSColin Finck VOID 193c2c66affSColin Finck NTAPI 194c2c66affSColin Finck HidParser_FreeCollectionDescription( 195c2c66affSColin Finck IN PHIDP_DEVICE_DESC DeviceDescription) 196c2c66affSColin Finck { 197c2c66affSColin Finck ULONG Index; 198c2c66affSColin Finck 199c2c66affSColin Finck // 200c2c66affSColin Finck // first free all context 201c2c66affSColin Finck // 202c2c66affSColin Finck for(Index = 0; Index < DeviceDescription->CollectionDescLength; Index++) 203c2c66affSColin Finck { 204c2c66affSColin Finck // 205c2c66affSColin Finck // free collection context 206c2c66affSColin Finck // 207*c151f8a1SHervé Poussineau FreeFunction(DeviceDescription->CollectionDesc[Index].PreparsedData); 208c2c66affSColin Finck } 209c2c66affSColin Finck 210c2c66affSColin Finck // 211c2c66affSColin Finck // now free collection description 212c2c66affSColin Finck // 213*c151f8a1SHervé Poussineau FreeFunction(DeviceDescription->CollectionDesc); 214c2c66affSColin Finck 215c2c66affSColin Finck // 216c2c66affSColin Finck // free report description 217c2c66affSColin Finck // 218*c151f8a1SHervé Poussineau FreeFunction(DeviceDescription->ReportIDs); 219c2c66affSColin Finck } 220c2c66affSColin Finck 221c2c66affSColin Finck HIDAPI 222c2c66affSColin Finck NTSTATUS 223c2c66affSColin Finck NTAPI 224c2c66affSColin Finck HidParser_GetCaps( 225c2c66affSColin Finck IN PVOID CollectionContext, 226c2c66affSColin Finck OUT PHIDP_CAPS Capabilities) 227c2c66affSColin Finck { 228c2c66affSColin Finck // 229c2c66affSColin Finck // zero capabilities 230c2c66affSColin Finck // 231*c151f8a1SHervé Poussineau ZeroFunction(Capabilities, sizeof(HIDP_CAPS)); 232c2c66affSColin Finck 233c2c66affSColin Finck // 234c2c66affSColin Finck // init capabilities 235c2c66affSColin Finck // 236c2c66affSColin Finck HidParser_GetCollectionUsagePage(CollectionContext, &Capabilities->Usage, &Capabilities->UsagePage); 237c2c66affSColin Finck Capabilities->InputReportByteLength = HidParser_GetReportLength(CollectionContext, HID_REPORT_TYPE_INPUT); 238c2c66affSColin Finck Capabilities->OutputReportByteLength = HidParser_GetReportLength(CollectionContext, HID_REPORT_TYPE_OUTPUT); 239c2c66affSColin Finck Capabilities->FeatureReportByteLength = HidParser_GetReportLength(CollectionContext, HID_REPORT_TYPE_FEATURE); 240c2c66affSColin Finck 241c2c66affSColin Finck // 242c2c66affSColin Finck // always pre-prend report id 243c2c66affSColin Finck // 244c2c66affSColin Finck Capabilities->InputReportByteLength = (Capabilities->InputReportByteLength > 0 ? Capabilities->InputReportByteLength + 1 : 0); 245c2c66affSColin Finck Capabilities->OutputReportByteLength = (Capabilities->OutputReportByteLength > 0 ? Capabilities->OutputReportByteLength + 1 : 0); 246c2c66affSColin Finck Capabilities->FeatureReportByteLength = (Capabilities->FeatureReportByteLength > 0 ? Capabilities->FeatureReportByteLength + 1 : 0); 247c2c66affSColin Finck 248c2c66affSColin Finck // 249c2c66affSColin Finck // get number of link collection nodes 250c2c66affSColin Finck // 251c2c66affSColin Finck Capabilities->NumberLinkCollectionNodes = HidParser_GetTotalCollectionCount(CollectionContext); 252c2c66affSColin Finck 253c2c66affSColin Finck // 254c2c66affSColin Finck // get data indices 255c2c66affSColin Finck // 256c2c66affSColin Finck Capabilities->NumberInputDataIndices = HidParser_GetReportItemTypeCountFromReportType(CollectionContext, HID_REPORT_TYPE_INPUT, TRUE); 257c2c66affSColin Finck Capabilities->NumberOutputDataIndices = HidParser_GetReportItemTypeCountFromReportType(CollectionContext, HID_REPORT_TYPE_OUTPUT, TRUE); 258c2c66affSColin Finck Capabilities->NumberFeatureDataIndices = HidParser_GetReportItemTypeCountFromReportType(CollectionContext, HID_REPORT_TYPE_FEATURE, TRUE); 259c2c66affSColin Finck 260c2c66affSColin Finck // 261c2c66affSColin Finck // get value caps 262c2c66affSColin Finck // 263c2c66affSColin Finck Capabilities->NumberInputValueCaps = HidParser_GetReportItemTypeCountFromReportType(CollectionContext, HID_REPORT_TYPE_INPUT, FALSE); 264c2c66affSColin Finck Capabilities->NumberOutputValueCaps = HidParser_GetReportItemTypeCountFromReportType(CollectionContext, HID_REPORT_TYPE_OUTPUT, FALSE); 265c2c66affSColin Finck Capabilities->NumberFeatureValueCaps = HidParser_GetReportItemTypeCountFromReportType(CollectionContext, HID_REPORT_TYPE_FEATURE, FALSE); 266c2c66affSColin Finck 267c2c66affSColin Finck 268c2c66affSColin Finck // 269c2c66affSColin Finck // get button caps 270c2c66affSColin Finck // 271c2c66affSColin Finck Capabilities->NumberInputButtonCaps = HidParser_GetReportItemCountFromReportType(CollectionContext, HID_REPORT_TYPE_INPUT); 272c2c66affSColin Finck Capabilities->NumberOutputButtonCaps = HidParser_GetReportItemCountFromReportType(CollectionContext, HID_REPORT_TYPE_OUTPUT); 273c2c66affSColin Finck Capabilities->NumberFeatureButtonCaps = HidParser_GetReportItemCountFromReportType(CollectionContext, HID_REPORT_TYPE_FEATURE); 274c2c66affSColin Finck 275c2c66affSColin Finck // 276c2c66affSColin Finck // done 277c2c66affSColin Finck // 278c2c66affSColin Finck return HIDP_STATUS_SUCCESS; 279c2c66affSColin Finck } 280c2c66affSColin Finck 281c2c66affSColin Finck HIDAPI 282c2c66affSColin Finck ULONG 283c2c66affSColin Finck NTAPI 284c2c66affSColin Finck HidParser_MaxUsageListLength( 285c2c66affSColin Finck IN PVOID CollectionContext, 286c2c66affSColin Finck IN HIDP_REPORT_TYPE ReportType, 287c2c66affSColin Finck IN USAGE UsagePage OPTIONAL) 288c2c66affSColin Finck { 289c2c66affSColin Finck // 290c2c66affSColin Finck // FIXME test what should be returned when usage page is not defined 291c2c66affSColin Finck // 292c2c66affSColin Finck if (UsagePage == HID_USAGE_PAGE_UNDEFINED) 293c2c66affSColin Finck { 294c2c66affSColin Finck // 295c2c66affSColin Finck // implement me 296c2c66affSColin Finck // 297c2c66affSColin Finck UNIMPLEMENTED; 298c2c66affSColin Finck 299c2c66affSColin Finck // 300c2c66affSColin Finck // invalid report 301c2c66affSColin Finck // 302c2c66affSColin Finck return 0; 303c2c66affSColin Finck } 304c2c66affSColin Finck 305c2c66affSColin Finck if (ReportType == HidP_Input) 306c2c66affSColin Finck { 307c2c66affSColin Finck // 308c2c66affSColin Finck // input report 309c2c66affSColin Finck // 310c2c66affSColin Finck return HidParser_GetMaxUsageListLengthWithReportAndPage(CollectionContext, HID_REPORT_TYPE_INPUT, UsagePage); 311c2c66affSColin Finck } 312c2c66affSColin Finck else if (ReportType == HidP_Output) 313c2c66affSColin Finck { 314c2c66affSColin Finck // 315c2c66affSColin Finck // input report 316c2c66affSColin Finck // 317c2c66affSColin Finck return HidParser_GetMaxUsageListLengthWithReportAndPage(CollectionContext, HID_REPORT_TYPE_OUTPUT, UsagePage); 318c2c66affSColin Finck } 319c2c66affSColin Finck else if (ReportType == HidP_Feature) 320c2c66affSColin Finck { 321c2c66affSColin Finck // 322c2c66affSColin Finck // input report 323c2c66affSColin Finck // 324c2c66affSColin Finck return HidParser_GetMaxUsageListLengthWithReportAndPage(CollectionContext, HID_REPORT_TYPE_FEATURE, UsagePage); 325c2c66affSColin Finck } 326c2c66affSColin Finck else 327c2c66affSColin Finck { 328c2c66affSColin Finck // 329c2c66affSColin Finck // invalid report type 330c2c66affSColin Finck // 331c2c66affSColin Finck return 0; 332c2c66affSColin Finck } 333c2c66affSColin Finck } 334c2c66affSColin Finck 335c2c66affSColin Finck #undef HidParser_GetButtonCaps 336c2c66affSColin Finck 337c2c66affSColin Finck HIDAPI 338c2c66affSColin Finck NTSTATUS 339c2c66affSColin Finck NTAPI 340c2c66affSColin Finck HidParser_GetButtonCaps( 341c2c66affSColin Finck IN PVOID CollectionContext, 342c2c66affSColin Finck IN HIDP_REPORT_TYPE ReportType, 343c2c66affSColin Finck IN PHIDP_BUTTON_CAPS ButtonCaps, 344c2c66affSColin Finck IN PUSHORT ButtonCapsLength) 345c2c66affSColin Finck { 346*c151f8a1SHervé Poussineau return HidParser_GetSpecificButtonCaps(CollectionContext, ReportType, HID_USAGE_PAGE_UNDEFINED, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_PAGE_UNDEFINED, ButtonCaps, (PULONG)ButtonCapsLength); 347c2c66affSColin Finck } 348c2c66affSColin Finck 349c2c66affSColin Finck HIDAPI 350c2c66affSColin Finck NTSTATUS 351c2c66affSColin Finck NTAPI 352c2c66affSColin Finck HidParser_GetSpecificValueCaps( 353c2c66affSColin Finck IN PVOID CollectionContext, 354c2c66affSColin Finck IN HIDP_REPORT_TYPE ReportType, 355c2c66affSColin Finck IN USAGE UsagePage, 356c2c66affSColin Finck IN USHORT LinkCollection, 357c2c66affSColin Finck IN USAGE Usage, 358c2c66affSColin Finck OUT PHIDP_VALUE_CAPS ValueCaps, 359c2c66affSColin Finck IN OUT PUSHORT ValueCapsLength) 360c2c66affSColin Finck { 361c2c66affSColin Finck HIDPARSER_STATUS ParserStatus; 362c2c66affSColin Finck 363c2c66affSColin Finck // 364c2c66affSColin Finck // FIXME: implement searching in specific collection 365c2c66affSColin Finck // 366c2c66affSColin Finck ASSERT(LinkCollection == HIDP_LINK_COLLECTION_UNSPECIFIED); 367c2c66affSColin Finck 368c2c66affSColin Finck if (ReportType == HidP_Input) 369c2c66affSColin Finck { 370c2c66affSColin Finck // 371c2c66affSColin Finck // input report 372c2c66affSColin Finck // 373*c151f8a1SHervé Poussineau ParserStatus = HidParser_GetSpecificValueCapsWithReport(CollectionContext, HID_REPORT_TYPE_INPUT, UsagePage, Usage, ValueCaps, ValueCapsLength); 374c2c66affSColin Finck } 375c2c66affSColin Finck else if (ReportType == HidP_Output) 376c2c66affSColin Finck { 377c2c66affSColin Finck // 378c2c66affSColin Finck // input report 379c2c66affSColin Finck // 380*c151f8a1SHervé Poussineau ParserStatus = HidParser_GetSpecificValueCapsWithReport(CollectionContext, HID_REPORT_TYPE_OUTPUT, UsagePage, Usage, ValueCaps, ValueCapsLength); 381c2c66affSColin Finck } 382c2c66affSColin Finck else if (ReportType == HidP_Feature) 383c2c66affSColin Finck { 384c2c66affSColin Finck // 385c2c66affSColin Finck // input report 386c2c66affSColin Finck // 387*c151f8a1SHervé Poussineau ParserStatus = HidParser_GetSpecificValueCapsWithReport(CollectionContext, HID_REPORT_TYPE_FEATURE, UsagePage, Usage, ValueCaps, ValueCapsLength); 388c2c66affSColin Finck } 389c2c66affSColin Finck else 390c2c66affSColin Finck { 391c2c66affSColin Finck // 392c2c66affSColin Finck // invalid report type 393c2c66affSColin Finck // 394c2c66affSColin Finck return HIDP_STATUS_INVALID_REPORT_TYPE; 395c2c66affSColin Finck } 396c2c66affSColin Finck 397c2c66affSColin Finck 398c2c66affSColin Finck if (ParserStatus == HIDPARSER_STATUS_SUCCESS) 399c2c66affSColin Finck { 400c2c66affSColin Finck // 401c2c66affSColin Finck // success 402c2c66affSColin Finck // 403c2c66affSColin Finck return HIDP_STATUS_SUCCESS; 404c2c66affSColin Finck } 405c2c66affSColin Finck 406c2c66affSColin Finck // 407c2c66affSColin Finck // translate error 408c2c66affSColin Finck // 409c2c66affSColin Finck return TranslateHidParserStatus(ParserStatus); 410c2c66affSColin Finck } 411c2c66affSColin Finck 412c2c66affSColin Finck HIDAPI 413c2c66affSColin Finck NTSTATUS 414c2c66affSColin Finck NTAPI 415c2c66affSColin Finck HidParser_UsageListDifference( 416c2c66affSColin Finck IN PUSAGE PreviousUsageList, 417c2c66affSColin Finck IN PUSAGE CurrentUsageList, 418c2c66affSColin Finck OUT PUSAGE BreakUsageList, 419c2c66affSColin Finck OUT PUSAGE MakeUsageList, 420c2c66affSColin Finck IN ULONG UsageListLength) 421c2c66affSColin Finck { 422c2c66affSColin Finck ULONG Index, SubIndex, bFound, BreakUsageIndex = 0, MakeUsageIndex = 0; 423c2c66affSColin Finck USAGE CurrentUsage, Usage; 424c2c66affSColin Finck 425c2c66affSColin Finck if (UsageListLength) 426c2c66affSColin Finck { 427c2c66affSColin Finck Index = 0; 428c2c66affSColin Finck do 429c2c66affSColin Finck { 430c2c66affSColin Finck /* get current usage */ 431c2c66affSColin Finck CurrentUsage = PreviousUsageList[Index]; 432c2c66affSColin Finck 433c2c66affSColin Finck /* is the end of list reached? */ 434c2c66affSColin Finck if (!CurrentUsage) 435c2c66affSColin Finck break; 436c2c66affSColin Finck 437c2c66affSColin Finck /* start searching in current usage list */ 438c2c66affSColin Finck SubIndex = 0; 439c2c66affSColin Finck bFound = FALSE; 440c2c66affSColin Finck do 441c2c66affSColin Finck { 442c2c66affSColin Finck /* get usage of current list */ 443c2c66affSColin Finck Usage = CurrentUsageList[SubIndex]; 444c2c66affSColin Finck 445c2c66affSColin Finck /* end of list reached? */ 446c2c66affSColin Finck if (!Usage) 447c2c66affSColin Finck break; 448c2c66affSColin Finck 449c2c66affSColin Finck /* check if it matches the current one */ 450c2c66affSColin Finck if (CurrentUsage == Usage) 451c2c66affSColin Finck { 452c2c66affSColin Finck /* it does */ 453c2c66affSColin Finck bFound = TRUE; 454c2c66affSColin Finck break; 455c2c66affSColin Finck } 456c2c66affSColin Finck 457c2c66affSColin Finck /* move to next usage */ 458c2c66affSColin Finck SubIndex++; 459c2c66affSColin Finck }while(SubIndex < UsageListLength); 460c2c66affSColin Finck 461c2c66affSColin Finck /* was the usage found ?*/ 462c2c66affSColin Finck if (!bFound) 463c2c66affSColin Finck { 464c2c66affSColin Finck /* store it in the break usage list */ 465c2c66affSColin Finck BreakUsageList[BreakUsageIndex] = CurrentUsage; 466c2c66affSColin Finck BreakUsageIndex++; 467c2c66affSColin Finck } 468c2c66affSColin Finck 469c2c66affSColin Finck /* move to next usage */ 470c2c66affSColin Finck Index++; 471c2c66affSColin Finck 472c2c66affSColin Finck }while(Index < UsageListLength); 473c2c66affSColin Finck 474c2c66affSColin Finck /* now process the new items */ 475c2c66affSColin Finck Index = 0; 476c2c66affSColin Finck do 477c2c66affSColin Finck { 478c2c66affSColin Finck /* get current usage */ 479c2c66affSColin Finck CurrentUsage = CurrentUsageList[Index]; 480c2c66affSColin Finck 481c2c66affSColin Finck /* is the end of list reached? */ 482c2c66affSColin Finck if (!CurrentUsage) 483c2c66affSColin Finck break; 484c2c66affSColin Finck 485c2c66affSColin Finck /* start searching in current usage list */ 486c2c66affSColin Finck SubIndex = 0; 487c2c66affSColin Finck bFound = FALSE; 488c2c66affSColin Finck do 489c2c66affSColin Finck { 490c2c66affSColin Finck /* get usage of previous list */ 491c2c66affSColin Finck Usage = PreviousUsageList[SubIndex]; 492c2c66affSColin Finck 493c2c66affSColin Finck /* end of list reached? */ 494c2c66affSColin Finck if (!Usage) 495c2c66affSColin Finck break; 496c2c66affSColin Finck 497c2c66affSColin Finck /* check if it matches the current one */ 498c2c66affSColin Finck if (CurrentUsage == Usage) 499c2c66affSColin Finck { 500c2c66affSColin Finck /* it does */ 501c2c66affSColin Finck bFound = TRUE; 502c2c66affSColin Finck break; 503c2c66affSColin Finck } 504c2c66affSColin Finck 505c2c66affSColin Finck /* move to next usage */ 506c2c66affSColin Finck SubIndex++; 507c2c66affSColin Finck }while(SubIndex < UsageListLength); 508c2c66affSColin Finck 509c2c66affSColin Finck /* was the usage found ?*/ 510c2c66affSColin Finck if (!bFound) 511c2c66affSColin Finck { 512c2c66affSColin Finck /* store it in the make usage list */ 513c2c66affSColin Finck MakeUsageList[MakeUsageIndex] = CurrentUsage; 514c2c66affSColin Finck MakeUsageIndex++; 515c2c66affSColin Finck } 516c2c66affSColin Finck 517c2c66affSColin Finck /* move to next usage */ 518c2c66affSColin Finck Index++; 519c2c66affSColin Finck 520c2c66affSColin Finck }while(Index < UsageListLength); 521c2c66affSColin Finck } 522c2c66affSColin Finck 523c2c66affSColin Finck /* does the break list contain empty entries */ 524c2c66affSColin Finck if (BreakUsageIndex < UsageListLength) 525c2c66affSColin Finck { 526c2c66affSColin Finck /* zeroize entries */ 527c2c66affSColin Finck RtlZeroMemory(&BreakUsageList[BreakUsageIndex], sizeof(USAGE) * (UsageListLength - BreakUsageIndex)); 528c2c66affSColin Finck } 529c2c66affSColin Finck 530c2c66affSColin Finck /* does the make usage list contain empty entries */ 531c2c66affSColin Finck if (MakeUsageIndex < UsageListLength) 532c2c66affSColin Finck { 533c2c66affSColin Finck /* zeroize entries */ 534c2c66affSColin Finck RtlZeroMemory(&MakeUsageList[MakeUsageIndex], sizeof(USAGE) * (UsageListLength - MakeUsageIndex)); 535c2c66affSColin Finck } 536c2c66affSColin Finck 537c2c66affSColin Finck /* done */ 538c2c66affSColin Finck return HIDP_STATUS_SUCCESS; 539c2c66affSColin Finck } 540c2c66affSColin Finck 541c2c66affSColin Finck HIDAPI 542c2c66affSColin Finck NTSTATUS 543c2c66affSColin Finck NTAPI 544c2c66affSColin Finck HidParser_GetUsages( 545c2c66affSColin Finck IN PVOID CollectionContext, 546c2c66affSColin Finck IN HIDP_REPORT_TYPE ReportType, 547c2c66affSColin Finck IN USAGE UsagePage, 548c2c66affSColin Finck IN USHORT LinkCollection OPTIONAL, 549c2c66affSColin Finck OUT USAGE *UsageList, 550c2c66affSColin Finck IN OUT PULONG UsageLength, 551c2c66affSColin Finck IN PCHAR Report, 552c2c66affSColin Finck IN ULONG ReportLength) 553c2c66affSColin Finck { 554c2c66affSColin Finck HIDPARSER_STATUS ParserStatus; 555c2c66affSColin Finck 556c2c66affSColin Finck // 557c2c66affSColin Finck // FIXME: implement searching in specific collection 558c2c66affSColin Finck // 559c2c66affSColin Finck ASSERT(LinkCollection == HIDP_LINK_COLLECTION_UNSPECIFIED); 560c2c66affSColin Finck 561c2c66affSColin Finck if (ReportType == HidP_Input) 562c2c66affSColin Finck { 563c2c66affSColin Finck // 564c2c66affSColin Finck // input report 565c2c66affSColin Finck // 566*c151f8a1SHervé Poussineau ParserStatus = HidParser_GetUsagesWithReport(CollectionContext, HID_REPORT_TYPE_INPUT, UsagePage, UsageList, UsageLength, Report, ReportLength); 567c2c66affSColin Finck } 568c2c66affSColin Finck else if (ReportType == HidP_Output) 569c2c66affSColin Finck { 570c2c66affSColin Finck // 571c2c66affSColin Finck // input report 572c2c66affSColin Finck // 573*c151f8a1SHervé Poussineau ParserStatus = HidParser_GetUsagesWithReport(CollectionContext, HID_REPORT_TYPE_OUTPUT, UsagePage, UsageList, UsageLength, Report, ReportLength); 574c2c66affSColin Finck } 575c2c66affSColin Finck else if (ReportType == HidP_Feature) 576c2c66affSColin Finck { 577c2c66affSColin Finck // 578c2c66affSColin Finck // input report 579c2c66affSColin Finck // 580*c151f8a1SHervé Poussineau ParserStatus = HidParser_GetUsagesWithReport(CollectionContext, HID_REPORT_TYPE_FEATURE, UsagePage, UsageList, UsageLength, Report, ReportLength); 581c2c66affSColin Finck } 582c2c66affSColin Finck else 583c2c66affSColin Finck { 584c2c66affSColin Finck // 585c2c66affSColin Finck // invalid report type 586c2c66affSColin Finck // 587c2c66affSColin Finck return HIDP_STATUS_INVALID_REPORT_TYPE; 588c2c66affSColin Finck } 589c2c66affSColin Finck 590c2c66affSColin Finck if (ParserStatus == HIDPARSER_STATUS_SUCCESS) 591c2c66affSColin Finck { 592c2c66affSColin Finck // 593c2c66affSColin Finck // success 594c2c66affSColin Finck // 595c2c66affSColin Finck return HIDP_STATUS_SUCCESS; 596c2c66affSColin Finck } 597c2c66affSColin Finck 598c2c66affSColin Finck // 599c2c66affSColin Finck // translate error 600c2c66affSColin Finck // 601c2c66affSColin Finck return TranslateHidParserStatus(ParserStatus); 602c2c66affSColin Finck } 603c2c66affSColin Finck 604c2c66affSColin Finck HIDAPI 605c2c66affSColin Finck NTSTATUS 606c2c66affSColin Finck NTAPI 607c2c66affSColin Finck HidParser_GetScaledUsageValue( 608c2c66affSColin Finck IN PVOID CollectionContext, 609c2c66affSColin Finck IN HIDP_REPORT_TYPE ReportType, 610c2c66affSColin Finck IN USAGE UsagePage, 611c2c66affSColin Finck IN USHORT LinkCollection OPTIONAL, 612c2c66affSColin Finck IN USAGE Usage, 613c2c66affSColin Finck OUT PLONG UsageValue, 614c2c66affSColin Finck IN PCHAR Report, 615c2c66affSColin Finck IN ULONG ReportLength) 616c2c66affSColin Finck { 617c2c66affSColin Finck HIDPARSER_STATUS ParserStatus; 618c2c66affSColin Finck 619c2c66affSColin Finck // 620c2c66affSColin Finck // FIXME: implement searching in specific collection 621c2c66affSColin Finck // 622c2c66affSColin Finck ASSERT(LinkCollection == HIDP_LINK_COLLECTION_UNSPECIFIED); 623c2c66affSColin Finck 624c2c66affSColin Finck if (ReportType == HidP_Input) 625c2c66affSColin Finck { 626c2c66affSColin Finck // 627c2c66affSColin Finck // input report 628c2c66affSColin Finck // 629*c151f8a1SHervé Poussineau ParserStatus = HidParser_GetScaledUsageValueWithReport(CollectionContext, HID_REPORT_TYPE_INPUT, UsagePage, Usage, UsageValue, Report, ReportLength); 630c2c66affSColin Finck } 631c2c66affSColin Finck else if (ReportType == HidP_Output) 632c2c66affSColin Finck { 633c2c66affSColin Finck // 634c2c66affSColin Finck // input report 635c2c66affSColin Finck // 636*c151f8a1SHervé Poussineau ParserStatus = HidParser_GetScaledUsageValueWithReport(CollectionContext, HID_REPORT_TYPE_OUTPUT, UsagePage, Usage, UsageValue, Report, ReportLength); 637c2c66affSColin Finck } 638c2c66affSColin Finck else if (ReportType == HidP_Feature) 639c2c66affSColin Finck { 640c2c66affSColin Finck // 641c2c66affSColin Finck // input report 642c2c66affSColin Finck // 643*c151f8a1SHervé Poussineau ParserStatus = HidParser_GetScaledUsageValueWithReport(CollectionContext, HID_REPORT_TYPE_FEATURE, UsagePage, Usage, UsageValue, Report, ReportLength); 644c2c66affSColin Finck } 645c2c66affSColin Finck else 646c2c66affSColin Finck { 647c2c66affSColin Finck // 648c2c66affSColin Finck // invalid report type 649c2c66affSColin Finck // 650c2c66affSColin Finck return HIDP_STATUS_INVALID_REPORT_TYPE; 651c2c66affSColin Finck } 652c2c66affSColin Finck 653c2c66affSColin Finck if (ParserStatus == HIDPARSER_STATUS_SUCCESS) 654c2c66affSColin Finck { 655c2c66affSColin Finck // 656c2c66affSColin Finck // success 657c2c66affSColin Finck // 658c2c66affSColin Finck return HIDP_STATUS_SUCCESS; 659c2c66affSColin Finck } 660c2c66affSColin Finck 661c2c66affSColin Finck // 662c2c66affSColin Finck // translate error 663c2c66affSColin Finck // 664c2c66affSColin Finck return TranslateHidParserStatus(ParserStatus); 665c2c66affSColin Finck } 666c2c66affSColin Finck 667c2c66affSColin Finck HIDAPI 668c2c66affSColin Finck NTSTATUS 669c2c66affSColin Finck NTAPI 670c2c66affSColin Finck HidParser_TranslateUsageAndPagesToI8042ScanCodes( 671c2c66affSColin Finck IN PUSAGE_AND_PAGE ChangedUsageList, 672c2c66affSColin Finck IN ULONG UsageListLength, 673c2c66affSColin Finck IN HIDP_KEYBOARD_DIRECTION KeyAction, 674c2c66affSColin Finck IN OUT PHIDP_KEYBOARD_MODIFIER_STATE ModifierState, 675c2c66affSColin Finck IN PHIDP_INSERT_SCANCODES InsertCodesProcedure, 676c2c66affSColin Finck IN PVOID InsertCodesContext) 677c2c66affSColin Finck { 678c2c66affSColin Finck ULONG Index; 679c2c66affSColin Finck HIDPARSER_STATUS Status = HIDPARSER_STATUS_SUCCESS; 680c2c66affSColin Finck 681c2c66affSColin Finck for(Index = 0; Index < UsageListLength; Index++) 682c2c66affSColin Finck { 683c2c66affSColin Finck // 684c2c66affSColin Finck // check current usage 685c2c66affSColin Finck // 686c2c66affSColin Finck if (ChangedUsageList[Index].UsagePage == HID_USAGE_PAGE_KEYBOARD) 687c2c66affSColin Finck { 688c2c66affSColin Finck // 689c2c66affSColin Finck // process keyboard usage 690c2c66affSColin Finck // 691*c151f8a1SHervé Poussineau Status = HidParser_TranslateKbdUsage(ChangedUsageList[Index].Usage, KeyAction, ModifierState, InsertCodesProcedure, InsertCodesContext); 692c2c66affSColin Finck } 693c2c66affSColin Finck else if (ChangedUsageList[Index].UsagePage == HID_USAGE_PAGE_CONSUMER) 694c2c66affSColin Finck { 695c2c66affSColin Finck // 696c2c66affSColin Finck // process consumer usage 697c2c66affSColin Finck // 698*c151f8a1SHervé Poussineau Status = HidParser_TranslateCustUsage(ChangedUsageList[Index].Usage, KeyAction, ModifierState, InsertCodesProcedure, InsertCodesContext); 699c2c66affSColin Finck } 700c2c66affSColin Finck else 701c2c66affSColin Finck { 702c2c66affSColin Finck // 703c2c66affSColin Finck // invalid page / end of usage list page 704c2c66affSColin Finck // 705c2c66affSColin Finck return HIDP_STATUS_I8042_TRANS_UNKNOWN; 706c2c66affSColin Finck } 707c2c66affSColin Finck 708c2c66affSColin Finck // 709c2c66affSColin Finck // check status 710c2c66affSColin Finck // 711c2c66affSColin Finck if (Status != HIDPARSER_STATUS_SUCCESS) 712c2c66affSColin Finck { 713c2c66affSColin Finck // 714c2c66affSColin Finck // failed 715c2c66affSColin Finck // 716c2c66affSColin Finck return TranslateHidParserStatus(Status); 717c2c66affSColin Finck } 718c2c66affSColin Finck } 719c2c66affSColin Finck 720c2c66affSColin Finck if (Status != HIDPARSER_STATUS_SUCCESS) 721c2c66affSColin Finck { 722c2c66affSColin Finck // 723c2c66affSColin Finck // failed 724c2c66affSColin Finck // 725c2c66affSColin Finck return TranslateHidParserStatus(Status); 726c2c66affSColin Finck } 727c2c66affSColin Finck 728c2c66affSColin Finck // 729c2c66affSColin Finck // done 730c2c66affSColin Finck // 731c2c66affSColin Finck return HIDP_STATUS_SUCCESS; 732c2c66affSColin Finck } 733c2c66affSColin Finck 734c2c66affSColin Finck 735c2c66affSColin Finck HIDAPI 736c2c66affSColin Finck NTSTATUS 737c2c66affSColin Finck NTAPI 738c2c66affSColin Finck HidParser_GetUsagesEx( 739c2c66affSColin Finck IN PVOID CollectionContext, 740c2c66affSColin Finck IN HIDP_REPORT_TYPE ReportType, 741c2c66affSColin Finck IN USHORT LinkCollection, 742c2c66affSColin Finck OUT PUSAGE_AND_PAGE ButtonList, 743c2c66affSColin Finck IN OUT ULONG *UsageLength, 744c2c66affSColin Finck IN PCHAR Report, 745c2c66affSColin Finck IN ULONG ReportLength) 746c2c66affSColin Finck { 747*c151f8a1SHervé Poussineau return HidParser_GetUsages(CollectionContext, ReportType, HID_USAGE_PAGE_UNDEFINED, LinkCollection, (PUSAGE)ButtonList, UsageLength, Report, ReportLength); 748c2c66affSColin Finck } 749c2c66affSColin Finck 750c2c66affSColin Finck HIDAPI 751c2c66affSColin Finck NTSTATUS 752c2c66affSColin Finck NTAPI 753c2c66affSColin Finck HidParser_UsageAndPageListDifference( 754c2c66affSColin Finck IN PUSAGE_AND_PAGE PreviousUsageList, 755c2c66affSColin Finck IN PUSAGE_AND_PAGE CurrentUsageList, 756c2c66affSColin Finck OUT PUSAGE_AND_PAGE BreakUsageList, 757c2c66affSColin Finck OUT PUSAGE_AND_PAGE MakeUsageList, 758c2c66affSColin Finck IN ULONG UsageListLength) 759c2c66affSColin Finck { 760c2c66affSColin Finck ULONG Index, SubIndex, BreakUsageListIndex = 0, MakeUsageListIndex = 0, bFound; 761c2c66affSColin Finck PUSAGE_AND_PAGE CurrentUsage, Usage; 762c2c66affSColin Finck 763c2c66affSColin Finck if (UsageListLength) 764c2c66affSColin Finck { 765c2c66affSColin Finck /* process removed usages */ 766c2c66affSColin Finck Index = 0; 767c2c66affSColin Finck do 768c2c66affSColin Finck { 769c2c66affSColin Finck /* get usage from current index */ 770c2c66affSColin Finck CurrentUsage = &PreviousUsageList[Index]; 771c2c66affSColin Finck 772c2c66affSColin Finck /* end of list reached? */ 773c2c66affSColin Finck if (CurrentUsage->Usage == 0 && CurrentUsage->UsagePage == 0) 774c2c66affSColin Finck break; 775c2c66affSColin Finck 776c2c66affSColin Finck /* search in current list */ 777c2c66affSColin Finck SubIndex = 0; 778c2c66affSColin Finck bFound = FALSE; 779c2c66affSColin Finck do 780c2c66affSColin Finck { 781c2c66affSColin Finck /* get usage */ 782c2c66affSColin Finck Usage = &CurrentUsageList[SubIndex]; 783c2c66affSColin Finck 784c2c66affSColin Finck /* end of list reached? */ 785c2c66affSColin Finck if (Usage->Usage == 0 && Usage->UsagePage == 0) 786c2c66affSColin Finck break; 787c2c66affSColin Finck 788c2c66affSColin Finck /* does it match */ 789c2c66affSColin Finck if (Usage->Usage == CurrentUsage->Usage && Usage->UsagePage == CurrentUsage->UsagePage) 790c2c66affSColin Finck { 791c2c66affSColin Finck /* found match */ 792c2c66affSColin Finck bFound = TRUE; 793c2c66affSColin Finck } 794c2c66affSColin Finck 795c2c66affSColin Finck /* move to next index */ 796c2c66affSColin Finck SubIndex++; 797c2c66affSColin Finck 798c2c66affSColin Finck }while(SubIndex < UsageListLength); 799c2c66affSColin Finck 800c2c66affSColin Finck if (!bFound) 801c2c66affSColin Finck { 802c2c66affSColin Finck /* store it in break usage list */ 803c2c66affSColin Finck BreakUsageList[BreakUsageListIndex].Usage = CurrentUsage->Usage; 804c2c66affSColin Finck BreakUsageList[BreakUsageListIndex].UsagePage = CurrentUsage->UsagePage; 805c2c66affSColin Finck BreakUsageListIndex++; 806c2c66affSColin Finck } 807c2c66affSColin Finck 808c2c66affSColin Finck /* move to next index */ 809c2c66affSColin Finck Index++; 810c2c66affSColin Finck 811c2c66affSColin Finck }while(Index < UsageListLength); 812c2c66affSColin Finck 813c2c66affSColin Finck /* process new usages */ 814c2c66affSColin Finck Index = 0; 815c2c66affSColin Finck do 816c2c66affSColin Finck { 817c2c66affSColin Finck /* get usage from current index */ 818c2c66affSColin Finck CurrentUsage = &CurrentUsageList[Index]; 819c2c66affSColin Finck 820c2c66affSColin Finck /* end of list reached? */ 821c2c66affSColin Finck if (CurrentUsage->Usage == 0 && CurrentUsage->UsagePage == 0) 822c2c66affSColin Finck break; 823c2c66affSColin Finck 824c2c66affSColin Finck /* search in current list */ 825c2c66affSColin Finck SubIndex = 0; 826c2c66affSColin Finck bFound = FALSE; 827c2c66affSColin Finck do 828c2c66affSColin Finck { 829c2c66affSColin Finck /* get usage */ 830c2c66affSColin Finck Usage = &PreviousUsageList[SubIndex]; 831c2c66affSColin Finck 832c2c66affSColin Finck /* end of list reached? */ 833c2c66affSColin Finck if (Usage->Usage == 0 && Usage->UsagePage == 0) 834c2c66affSColin Finck break; 835c2c66affSColin Finck 836c2c66affSColin Finck /* does it match */ 837c2c66affSColin Finck if (Usage->Usage == CurrentUsage->Usage && Usage->UsagePage == CurrentUsage->UsagePage) 838c2c66affSColin Finck { 839c2c66affSColin Finck /* found match */ 840c2c66affSColin Finck bFound = TRUE; 841c2c66affSColin Finck } 842c2c66affSColin Finck 843c2c66affSColin Finck /* move to next index */ 844c2c66affSColin Finck SubIndex++; 845c2c66affSColin Finck 846c2c66affSColin Finck }while(SubIndex < UsageListLength); 847c2c66affSColin Finck 848c2c66affSColin Finck if (!bFound) 849c2c66affSColin Finck { 850c2c66affSColin Finck /* store it in break usage list */ 851c2c66affSColin Finck MakeUsageList[MakeUsageListIndex].Usage = CurrentUsage->Usage; 852c2c66affSColin Finck MakeUsageList[MakeUsageListIndex].UsagePage = CurrentUsage->UsagePage; 853c2c66affSColin Finck MakeUsageListIndex++; 854c2c66affSColin Finck } 855c2c66affSColin Finck 856c2c66affSColin Finck /* move to next index */ 857c2c66affSColin Finck Index++; 858c2c66affSColin Finck }while(Index < UsageListLength); 859c2c66affSColin Finck } 860c2c66affSColin Finck 861c2c66affSColin Finck /* are there remaining free list entries */ 862c2c66affSColin Finck if (BreakUsageListIndex < UsageListLength) 863c2c66affSColin Finck { 864c2c66affSColin Finck /* zero them */ 865c2c66affSColin Finck RtlZeroMemory(&BreakUsageList[BreakUsageListIndex], (UsageListLength - BreakUsageListIndex) * sizeof(USAGE_AND_PAGE)); 866c2c66affSColin Finck } 867c2c66affSColin Finck 868c2c66affSColin Finck /* are there remaining free list entries */ 869c2c66affSColin Finck if (MakeUsageListIndex < UsageListLength) 870c2c66affSColin Finck { 871c2c66affSColin Finck /* zero them */ 872c2c66affSColin Finck RtlZeroMemory(&MakeUsageList[MakeUsageListIndex], (UsageListLength - MakeUsageListIndex) * sizeof(USAGE_AND_PAGE)); 873c2c66affSColin Finck } 874c2c66affSColin Finck 875c2c66affSColin Finck /* done */ 876c2c66affSColin Finck return HIDP_STATUS_SUCCESS; 877c2c66affSColin Finck } 878c2c66affSColin Finck 879c2c66affSColin Finck HIDAPI 880c2c66affSColin Finck NTSTATUS 881c2c66affSColin Finck NTAPI 882c2c66affSColin Finck HidParser_GetSpecificButtonCaps( 883c2c66affSColin Finck IN PVOID CollectionContext, 884c2c66affSColin Finck IN HIDP_REPORT_TYPE ReportType, 885c2c66affSColin Finck IN USAGE UsagePage, 886c2c66affSColin Finck IN USHORT LinkCollection, 887c2c66affSColin Finck IN USAGE Usage, 888c2c66affSColin Finck OUT PHIDP_BUTTON_CAPS ButtonCaps, 889c2c66affSColin Finck IN OUT PULONG ButtonCapsLength) 890c2c66affSColin Finck { 891c2c66affSColin Finck UNIMPLEMENTED; 892c2c66affSColin Finck ASSERT(FALSE); 893c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 894c2c66affSColin Finck } 895c2c66affSColin Finck 896c2c66affSColin Finck 897c2c66affSColin Finck HIDAPI 898c2c66affSColin Finck NTSTATUS 899c2c66affSColin Finck NTAPI 900c2c66affSColin Finck HidParser_GetData( 901c2c66affSColin Finck IN PVOID CollectionContext, 902c2c66affSColin Finck IN HIDP_REPORT_TYPE ReportType, 903c2c66affSColin Finck OUT PHIDP_DATA DataList, 904c2c66affSColin Finck IN OUT PULONG DataLength, 905c2c66affSColin Finck IN PCHAR Report, 906c2c66affSColin Finck IN ULONG ReportLength) 907c2c66affSColin Finck { 908c2c66affSColin Finck UNIMPLEMENTED; 909c2c66affSColin Finck ASSERT(FALSE); 910c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 911c2c66affSColin Finck } 912c2c66affSColin Finck 913c2c66affSColin Finck HIDAPI 914c2c66affSColin Finck NTSTATUS 915c2c66affSColin Finck NTAPI 916c2c66affSColin Finck HidParser_GetExtendedAttributes( 917c2c66affSColin Finck IN PVOID CollectionContext, 918c2c66affSColin Finck IN HIDP_REPORT_TYPE ReportType, 919c2c66affSColin Finck IN USHORT DataIndex, 920c2c66affSColin Finck OUT PHIDP_EXTENDED_ATTRIBUTES Attributes, 921c2c66affSColin Finck IN OUT PULONG LengthAttributes) 922c2c66affSColin Finck { 923c2c66affSColin Finck UNIMPLEMENTED; 924c2c66affSColin Finck ASSERT(FALSE); 925c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 926c2c66affSColin Finck } 927c2c66affSColin Finck 928c2c66affSColin Finck HIDAPI 929c2c66affSColin Finck NTSTATUS 930c2c66affSColin Finck NTAPI 931c2c66affSColin Finck HidParser_GetLinkCollectionNodes( 932c2c66affSColin Finck IN PVOID CollectionContext, 933c2c66affSColin Finck OUT PHIDP_LINK_COLLECTION_NODE LinkCollectionNodes, 934c2c66affSColin Finck IN OUT PULONG LinkCollectionNodesLength) 935c2c66affSColin Finck { 936c2c66affSColin Finck UNIMPLEMENTED; 937c2c66affSColin Finck ASSERT(FALSE); 938c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 939c2c66affSColin Finck } 940c2c66affSColin Finck 941c2c66affSColin Finck HIDAPI 942c2c66affSColin Finck NTSTATUS 943c2c66affSColin Finck NTAPI 944c2c66affSColin Finck HidParser_GetUsageValue( 945c2c66affSColin Finck IN PVOID CollectionContext, 946c2c66affSColin Finck IN HIDP_REPORT_TYPE ReportType, 947c2c66affSColin Finck IN USAGE UsagePage, 948c2c66affSColin Finck IN USHORT LinkCollection, 949c2c66affSColin Finck IN USAGE Usage, 950c2c66affSColin Finck OUT PULONG UsageValue, 951c2c66affSColin Finck IN PCHAR Report, 952c2c66affSColin Finck IN ULONG ReportLength) 953c2c66affSColin Finck { 954c2c66affSColin Finck HIDPARSER_STATUS ParserStatus; 955c2c66affSColin Finck 956c2c66affSColin Finck // 957c2c66affSColin Finck // FIXME: implement searching in specific collection 958c2c66affSColin Finck // 959c2c66affSColin Finck ASSERT(LinkCollection == HIDP_LINK_COLLECTION_UNSPECIFIED); 960c2c66affSColin Finck 961c2c66affSColin Finck if (ReportType == HidP_Input) 962c2c66affSColin Finck { 963c2c66affSColin Finck // 964c2c66affSColin Finck // input report 965c2c66affSColin Finck // 966*c151f8a1SHervé Poussineau ParserStatus = HidParser_GetUsageValueWithReport(CollectionContext, HID_REPORT_TYPE_INPUT, UsagePage, Usage, UsageValue, Report, ReportLength); 967c2c66affSColin Finck } 968c2c66affSColin Finck else if (ReportType == HidP_Output) 969c2c66affSColin Finck { 970c2c66affSColin Finck // 971c2c66affSColin Finck // input report 972c2c66affSColin Finck // 973*c151f8a1SHervé Poussineau ParserStatus = HidParser_GetUsageValueWithReport(CollectionContext, HID_REPORT_TYPE_OUTPUT, UsagePage, Usage, UsageValue, Report, ReportLength); 974c2c66affSColin Finck } 975c2c66affSColin Finck else if (ReportType == HidP_Feature) 976c2c66affSColin Finck { 977c2c66affSColin Finck // 978c2c66affSColin Finck // input report 979c2c66affSColin Finck // 980*c151f8a1SHervé Poussineau ParserStatus = HidParser_GetUsageValueWithReport(CollectionContext, HID_REPORT_TYPE_FEATURE, UsagePage, Usage, UsageValue, Report, ReportLength); 981c2c66affSColin Finck } 982c2c66affSColin Finck else 983c2c66affSColin Finck { 984c2c66affSColin Finck // 985c2c66affSColin Finck // invalid report type 986c2c66affSColin Finck // 987c2c66affSColin Finck return HIDP_STATUS_INVALID_REPORT_TYPE; 988c2c66affSColin Finck } 989c2c66affSColin Finck 990c2c66affSColin Finck if (ParserStatus == HIDPARSER_STATUS_SUCCESS) 991c2c66affSColin Finck { 992c2c66affSColin Finck // 993c2c66affSColin Finck // success 994c2c66affSColin Finck // 995c2c66affSColin Finck return HIDP_STATUS_SUCCESS; 996c2c66affSColin Finck } 997c2c66affSColin Finck 998c2c66affSColin Finck // 999c2c66affSColin Finck // translate error 1000c2c66affSColin Finck // 1001c2c66affSColin Finck return TranslateHidParserStatus(ParserStatus); 1002c2c66affSColin Finck } 1003c2c66affSColin Finck 1004c2c66affSColin Finck NTSTATUS 1005c2c66affSColin Finck NTAPI 1006c2c66affSColin Finck HidParser_SysPowerEvent( 1007c2c66affSColin Finck IN PVOID CollectionContext, 1008c2c66affSColin Finck IN PCHAR HidPacket, 1009c2c66affSColin Finck IN USHORT HidPacketLength, 1010c2c66affSColin Finck OUT PULONG OutputBuffer) 1011c2c66affSColin Finck { 1012c2c66affSColin Finck UNIMPLEMENTED; 1013c2c66affSColin Finck ASSERT(FALSE); 1014c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 1015c2c66affSColin Finck } 1016c2c66affSColin Finck 1017c2c66affSColin Finck NTSTATUS 1018c2c66affSColin Finck NTAPI 1019c2c66affSColin Finck HidParser_SysPowerCaps ( 1020c2c66affSColin Finck IN PVOID CollectionContext, 1021c2c66affSColin Finck OUT PULONG OutputBuffer) 1022c2c66affSColin Finck { 1023c2c66affSColin Finck UNIMPLEMENTED; 1024c2c66affSColin Finck ASSERT(FALSE); 1025c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 1026c2c66affSColin Finck } 1027c2c66affSColin Finck 1028c2c66affSColin Finck HIDAPI 1029c2c66affSColin Finck NTSTATUS 1030c2c66affSColin Finck NTAPI 1031c2c66affSColin Finck HidParser_GetUsageValueArray( 1032c2c66affSColin Finck IN PVOID CollectionContext, 1033c2c66affSColin Finck IN HIDP_REPORT_TYPE ReportType, 1034c2c66affSColin Finck IN USAGE UsagePage, 1035c2c66affSColin Finck IN USHORT LinkCollection OPTIONAL, 1036c2c66affSColin Finck IN USAGE Usage, 1037c2c66affSColin Finck OUT PCHAR UsageValue, 1038c2c66affSColin Finck IN USHORT UsageValueByteLength, 1039c2c66affSColin Finck IN PCHAR Report, 1040c2c66affSColin Finck IN ULONG ReportLength) 1041c2c66affSColin Finck { 1042c2c66affSColin Finck UNIMPLEMENTED; 1043c2c66affSColin Finck ASSERT(FALSE); 1044c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 1045c2c66affSColin Finck } 1046c2c66affSColin Finck 1047c2c66affSColin Finck HIDAPI 1048c2c66affSColin Finck NTSTATUS 1049c2c66affSColin Finck NTAPI 1050c2c66affSColin Finck HidParser_UnsetUsages( 1051c2c66affSColin Finck IN PVOID CollectionContext, 1052c2c66affSColin Finck IN HIDP_REPORT_TYPE ReportType, 1053c2c66affSColin Finck IN USAGE UsagePage, 1054c2c66affSColin Finck IN USHORT LinkCollection, 1055c2c66affSColin Finck IN PUSAGE UsageList, 1056c2c66affSColin Finck IN OUT PULONG UsageLength, 1057c2c66affSColin Finck IN OUT PCHAR Report, 1058c2c66affSColin Finck IN ULONG ReportLength) 1059c2c66affSColin Finck { 1060c2c66affSColin Finck UNIMPLEMENTED; 1061c2c66affSColin Finck ASSERT(FALSE); 1062c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 1063c2c66affSColin Finck } 1064c2c66affSColin Finck 1065c2c66affSColin Finck HIDAPI 1066c2c66affSColin Finck NTSTATUS 1067c2c66affSColin Finck NTAPI 1068c2c66affSColin Finck HidParser_TranslateUsagesToI8042ScanCodes( 1069c2c66affSColin Finck IN PUSAGE ChangedUsageList, 1070c2c66affSColin Finck IN ULONG UsageListLength, 1071c2c66affSColin Finck IN HIDP_KEYBOARD_DIRECTION KeyAction, 1072c2c66affSColin Finck IN OUT PHIDP_KEYBOARD_MODIFIER_STATE ModifierState, 1073c2c66affSColin Finck IN PHIDP_INSERT_SCANCODES InsertCodesProcedure, 1074c2c66affSColin Finck IN PVOID InsertCodesContext) 1075c2c66affSColin Finck { 1076c2c66affSColin Finck UNIMPLEMENTED; 1077c2c66affSColin Finck ASSERT(FALSE); 1078c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 1079c2c66affSColin Finck } 1080c2c66affSColin Finck 1081c2c66affSColin Finck HIDAPI 1082c2c66affSColin Finck NTSTATUS 1083c2c66affSColin Finck NTAPI 1084c2c66affSColin Finck HidParser_SetUsages( 1085c2c66affSColin Finck IN PVOID CollectionContext, 1086c2c66affSColin Finck IN HIDP_REPORT_TYPE ReportType, 1087c2c66affSColin Finck IN USAGE UsagePage, 1088c2c66affSColin Finck IN USHORT LinkCollection, 1089c2c66affSColin Finck IN PUSAGE UsageList, 1090c2c66affSColin Finck IN OUT PULONG UsageLength, 1091c2c66affSColin Finck IN OUT PCHAR Report, 1092c2c66affSColin Finck IN ULONG ReportLength) 1093c2c66affSColin Finck { 1094c2c66affSColin Finck UNIMPLEMENTED; 1095c2c66affSColin Finck ASSERT(FALSE); 1096c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 1097c2c66affSColin Finck } 1098c2c66affSColin Finck 1099c2c66affSColin Finck HIDAPI 1100c2c66affSColin Finck NTSTATUS 1101c2c66affSColin Finck NTAPI 1102c2c66affSColin Finck HidParser_SetUsageValueArray( 1103c2c66affSColin Finck IN PVOID CollectionContext, 1104c2c66affSColin Finck IN HIDP_REPORT_TYPE ReportType, 1105c2c66affSColin Finck IN USAGE UsagePage, 1106c2c66affSColin Finck IN USHORT LinkCollection OPTIONAL, 1107c2c66affSColin Finck IN USAGE Usage, 1108c2c66affSColin Finck IN PCHAR UsageValue, 1109c2c66affSColin Finck IN USHORT UsageValueByteLength, 1110c2c66affSColin Finck OUT PCHAR Report, 1111c2c66affSColin Finck IN ULONG ReportLength) 1112c2c66affSColin Finck { 1113c2c66affSColin Finck UNIMPLEMENTED; 1114c2c66affSColin Finck ASSERT(FALSE); 1115c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 1116c2c66affSColin Finck } 1117c2c66affSColin Finck 1118c2c66affSColin Finck HIDAPI 1119c2c66affSColin Finck NTSTATUS 1120c2c66affSColin Finck NTAPI 1121c2c66affSColin Finck HidParser_SetUsageValue( 1122c2c66affSColin Finck IN PVOID CollectionContext, 1123c2c66affSColin Finck IN HIDP_REPORT_TYPE ReportType, 1124c2c66affSColin Finck IN USAGE UsagePage, 1125c2c66affSColin Finck IN USHORT LinkCollection, 1126c2c66affSColin Finck IN USAGE Usage, 1127c2c66affSColin Finck IN ULONG UsageValue, 1128c2c66affSColin Finck IN OUT PCHAR Report, 1129c2c66affSColin Finck IN ULONG ReportLength) 1130c2c66affSColin Finck { 1131c2c66affSColin Finck UNIMPLEMENTED; 1132c2c66affSColin Finck ASSERT(FALSE); 1133c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 1134c2c66affSColin Finck } 1135c2c66affSColin Finck 1136c2c66affSColin Finck HIDAPI 1137c2c66affSColin Finck NTSTATUS 1138c2c66affSColin Finck NTAPI 1139c2c66affSColin Finck HidParser_SetScaledUsageValue( 1140c2c66affSColin Finck IN PVOID CollectionContext, 1141c2c66affSColin Finck IN HIDP_REPORT_TYPE ReportType, 1142c2c66affSColin Finck IN USAGE UsagePage, 1143c2c66affSColin Finck IN USHORT LinkCollection OPTIONAL, 1144c2c66affSColin Finck IN USAGE Usage, 1145c2c66affSColin Finck IN LONG UsageValue, 1146c2c66affSColin Finck IN OUT PCHAR Report, 1147c2c66affSColin Finck IN ULONG ReportLength) 1148c2c66affSColin Finck { 1149c2c66affSColin Finck UNIMPLEMENTED; 1150c2c66affSColin Finck ASSERT(FALSE); 1151c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 1152c2c66affSColin Finck } 1153c2c66affSColin Finck 1154c2c66affSColin Finck HIDAPI 1155c2c66affSColin Finck NTSTATUS 1156c2c66affSColin Finck NTAPI 1157c2c66affSColin Finck HidParser_SetData( 1158c2c66affSColin Finck IN PVOID CollectionContext, 1159c2c66affSColin Finck IN HIDP_REPORT_TYPE ReportType, 1160c2c66affSColin Finck IN PHIDP_DATA DataList, 1161c2c66affSColin Finck IN OUT PULONG DataLength, 1162c2c66affSColin Finck IN OUT PCHAR Report, 1163c2c66affSColin Finck IN ULONG ReportLength) 1164c2c66affSColin Finck { 1165c2c66affSColin Finck UNIMPLEMENTED; 1166c2c66affSColin Finck ASSERT(FALSE); 1167c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 1168c2c66affSColin Finck } 1169c2c66affSColin Finck 1170c2c66affSColin Finck HIDAPI 1171c2c66affSColin Finck ULONG 1172c2c66affSColin Finck NTAPI 1173c2c66affSColin Finck HidParser_MaxDataListLength( 1174c2c66affSColin Finck IN PVOID CollectionContext, 1175c2c66affSColin Finck IN HIDP_REPORT_TYPE ReportType) 1176c2c66affSColin Finck { 1177c2c66affSColin Finck UNIMPLEMENTED; 1178c2c66affSColin Finck ASSERT(FALSE); 1179c2c66affSColin Finck return 0; 1180c2c66affSColin Finck } 1181c2c66affSColin Finck 1182c2c66affSColin Finck HIDAPI 1183c2c66affSColin Finck NTSTATUS 1184c2c66affSColin Finck NTAPI 1185c2c66affSColin Finck HidParser_InitializeReportForID( 1186c2c66affSColin Finck IN PVOID CollectionContext, 1187c2c66affSColin Finck IN HIDP_REPORT_TYPE ReportType, 1188c2c66affSColin Finck IN UCHAR ReportID, 1189c2c66affSColin Finck IN OUT PCHAR Report, 1190c2c66affSColin Finck IN ULONG ReportLength) 1191c2c66affSColin Finck { 1192c2c66affSColin Finck UNIMPLEMENTED; 1193c2c66affSColin Finck ASSERT(FALSE); 1194c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 1195c2c66affSColin Finck } 1196c2c66affSColin Finck 1197c2c66affSColin Finck #undef HidParser_GetValueCaps 1198c2c66affSColin Finck 1199c2c66affSColin Finck HIDAPI 1200c2c66affSColin Finck NTSTATUS 1201c2c66affSColin Finck NTAPI 1202c2c66affSColin Finck HidParser_GetValueCaps( 1203c2c66affSColin Finck IN PVOID CollectionContext, 1204c2c66affSColin Finck HIDP_REPORT_TYPE ReportType, 1205c2c66affSColin Finck PHIDP_VALUE_CAPS ValueCaps, 1206c2c66affSColin Finck PULONG ValueCapsLength) 1207c2c66affSColin Finck { 1208c2c66affSColin Finck UNIMPLEMENTED; 1209c2c66affSColin Finck ASSERT(FALSE); 1210c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 1211c2c66affSColin Finck } 1212