[USB-BRINGUP-TRUNK]
authorCameron Gutman <aicommander@gmail.com>
Fri, 20 Jan 2012 21:19:37 +0000 (21:19 +0000)
committerCameron Gutman <aicommander@gmail.com>
Fri, 20 Jan 2012 21:19:37 +0000 (21:19 +0000)
- Merge 54115-54859

svn path=/branches/usb-bringup-trunk/; revision=55020

1  2  3  4  5  6  7  8  9  10  11  12 
drivers/hid/hidparse/hidparse.c
drivers/hid/kbdhid/kbdhid.c
drivers/hid/kbdhid/kbdhid.h
lib/drivers/CMakeLists.txt
lib/drivers/hidparser/api.c
lib/drivers/hidparser/hidparser.c
lib/drivers/hidparser/hidparser.h
media/inf/CMakeLists.txt
media/inf/syssetup.inf.tpl
ntoskrnl/ob/obname.c

index c3cce18,0000000,fea2650,fea2650,fea2650,fea2650,fea2650,0000000,265cbcd,fea2650,265cbcd,265cbcd..68db33a
mode 100644,000000,100644,100644,100644,100644,100644,000000,100644,100644,100644,100644..100644
--- /dev/null
--- /dev/null
@@@@@@@@@@@@@ -1,499 -1,0 -1,727 -1,727 -1,727 -1,727 -1,727 -1,0 -1,648 -1,727 -1,648 -1,648 +1,663 @@@@@@@@@@@@@
-           
-           VOID
-           HidP_FreeCollectionDescription (
-               IN PHIDP_DEVICE_DESC   DeviceDescription)
 +     +    /*
 +     +     * PROJECT:     ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
 +     +     * LICENSE:     GPL - See COPYING in the top level directory
 +     +     * FILE:        drivers/usb/hidparse/hidparse.c
 +     +     * PURPOSE:     HID Parser
 +     +     * PROGRAMMERS:
 +     +     *              Michael Martin (michael.martin@reactos.org)
 +     +     *              Johannes Anderwald (johannes.anderwald@reactos.org)
 +     +     */
 +     +    
 +     +    #include "hidparse.h"
 +     +    
-               DPRINT1("HidP_FreeCollectionDescription DeviceDescription %p\n", DeviceDescription);
++++++++ +  PVOID
++++++++ +  NTAPI
++++++++ +  AllocFunction(
++++++++ +      IN ULONG ItemSize)
 +++++++ +  {
-               // free collection
++++++++ +      PVOID Item = ExAllocatePool(NonPagedPool, ItemSize);
++++++++ +      if (Item)
++++++++ +      {
++++++++ +          //
++++++++ +          // zero item
++++++++ +          //
++++++++ +          RtlZeroMemory(Item, ItemSize);
++++++++ +      }
 +++++++ +  
 +++++++ +      //
-               ExFreePool(DeviceDescription->CollectionDesc);
++++++++ +      // done
 +++++++ +      //
  -----  -  HidP_FreeCollectionDescription (
  -----  -      IN PHIDP_DEVICE_DESC   DeviceDescription)
++++++++ +      return Item;
++++++++ +  }
 +     +    
++     +    VOID
++     +    NTAPI
  -----  -      DPRINT1("HidP_FreeCollectionDescription DeviceDescription %p\n", DeviceDescription);
  -----  -  
++++++++ +  FreeFunction(
++++++++ +      IN PVOID Item)
++     +    {
-               // free report ids
  -----  -      // free collection
 +     +        //
-               ExFreePool(DeviceDescription->ReportIDs);
  -----  -      ExFreePool(DeviceDescription->CollectionDesc);
++++++++ +      // free item
 +     +        //
-               // free description itself
  -----  -      // free report ids
++++++++ +      ExFreePool(Item);
++++++++ +  }
 +     +    
++++++++ +  VOID
++++++++ +  NTAPI
++++++++ +  ZeroFunction(
++++++++ +      IN PVOID Item,
++++++++ +      IN ULONG ItemSize)
++++++++ +  {
 +     +        //
-               ExFreePool(DeviceDescription);
  -----  -      ExFreePool(DeviceDescription->ReportIDs);
++++++++ +      // zero item
 +     +        //
  -----  -  #undef HidP_GetButtonCaps
++++++++ +      RtlZeroMemory(Item, ItemSize);
++     +    }
 +     +    
- -----  -  HIDAPI
- -----  -  NTSTATUS
++++++++ +  VOID
++++++++ +  NTAPI
++++++++ +  CopyFunction(
++++++++ +      IN PVOID Target,
++++++++ +      IN PVOID Source,
++++++++ +      IN ULONG Length)
++++++++ +  {
++++++++ +      //
++++++++ +      // copy item
++++++++ +      //
++++++++ +      RtlCopyMemory(Target, Source, Length);
 +++++++ +  }
 +     +    
- -----  -  HidP_GetButtonCaps(
- -----  -      HIDP_REPORT_TYPE ReportType,
- -----  -      PHIDP_BUTTON_CAPS ButtonCaps,
- -----  -      PUSHORT ButtonCapsLength,
- -----  -      PHIDP_PREPARSED_DATA PreparsedData)
++++++++ +  VOID
 +     +    NTAPI
-               return HidP_GetSpecificButtonCaps(ReportType, 0, 0, 0, ButtonCaps, (PULONG)ButtonCapsLength, PreparsedData);
  -----  -      return HidP_GetSpecificButtonCaps(ReportType, HID_USAGE_PAGE_UNDEFINED, 0, 0, ButtonCaps, (PULONG)ButtonCapsLength, PreparsedData);
++++++++ +  DebugFunction(
++++++++ +      IN LPCSTR FormatStr, ...)
 +     +    {
- -----  -  HIDAPI
- -----  -  NTSTATUS
++++++++ +  
++++++++ +      va_list args;
++++++++ +      unsigned int i;
++++++++ +       char printbuffer[1024];
++++++++ +  
++++++++ +       va_start(args, FormatStr);
++++++++ +       i = vsprintf(printbuffer, FormatStr, args);
++++++++ +       va_end(args);
++++++++ +  
++++++++ +       DbgPrint(printbuffer);
 +     +    }
 +     +    
- -----  -  HidP_GetSpecificButtonCaps(
- -----  -    IN HIDP_REPORT_TYPE  ReportType,
- -----  -    IN USAGE  UsagePage,
- -----  -    IN USHORT  LinkCollection,
- -----  -    IN USAGE  Usage,
- -----  -    OUT PHIDP_BUTTON_CAPS  ButtonCaps,
- -----  -    IN OUT PULONG  ButtonCapsLength,
- -----  -    IN PHIDP_PREPARSED_DATA  PreparsedData)
++++++++ +  VOID
 +     +    NTAPI
- -----  -      UNIMPLEMENTED
- -----  -      ASSERT(FALSE);
- -----  -      return STATUS_NOT_IMPLEMENTED;
++++++++ +  HidP_FreeCollectionDescription (
++++++++ +      IN PHIDP_DEVICE_DESC   DeviceDescription)
 +     +    {
- -----  -      UNIMPLEMENTED
- -----  -      ASSERT(FALSE);
- -----  -      return STATUS_NOT_IMPLEMENTED;
++++++++ +      HID_PARSER Parser;
++++++++ +  
++++++++ +      //
++++++++ +      // init parser
++++++++ +      //
++++++++ +      HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, NULL, &Parser);
++++++++ +  
++++++++ +      //
++++++++ +      // free collection
++++++++ +      //
++++++++ +      HidParser_FreeCollectionDescription(&Parser, DeviceDescription);
 +     +    }
 +     +    
 +     +    
 +     +    HIDAPI
 +     +    NTSTATUS
 +     +    NTAPI
 +     +    HidP_GetCaps(
 +     +        IN PHIDP_PREPARSED_DATA  PreparsedData,
 +     +        OUT PHIDP_CAPS  Capabilities)
 +     +    {
- -----  -      UNIMPLEMENTED
- -----  -      ASSERT(FALSE);
- -----  -      return STATUS_NOT_IMPLEMENTED;
++++++++ +      HID_PARSER Parser;
++++++++ +  
++++++++ +      //
++++++++ +      // init parser
++++++++ +      //
++++++++ +      HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, PreparsedData, &Parser);
++++++++ +  
++++++++ +      //
++++++++ +      // get caps
++++++++ +      //
++++++++ +      return HidParser_GetCaps(&Parser, Capabilities);
 +     +    }
 +     +    
 +     +    NTSTATUS
++     +    NTAPI
 +     +    HidP_GetCollectionDescription(
 +     +        IN PHIDP_REPORT_DESCRIPTOR ReportDesc,
 +     +        IN ULONG DescLength,
 +     +        IN POOL_TYPE PoolType,
 +     +        OUT PHIDP_DEVICE_DESC DeviceDescription)
 +     +    {
- -----  -  HidP_GetData(
++++++++ +      PHID_PARSER Parser;
++++++++ +      HIDPARSER_STATUS Status;
++++++++ +  
++++++++ +      //
++++++++ +      // first allocate the parser
++++++++ +      //
++++++++ +      Status = HidParser_AllocateParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, &Parser);
++++++++ +      if (Status != HIDPARSER_STATUS_SUCCESS)
++++++++ +      {
++++++++ +          //
++++++++ +          // not enough memory
++++++++ +          //
++++++++ +          return STATUS_INSUFFICIENT_RESOURCES;
++++++++ +      }
++++++++ +  
++++++++ +      //
++++++++ +      // get description;
++++++++ +      //
++++++++ +      Status = HidParser_GetCollectionDescription(Parser, ReportDesc, DescLength, PoolType, DeviceDescription);
++++++++ +  
++++++++ +      //
++++++++ +      // FIXME parser memory leak
++++++++ +      //
++++++++ +      return Status;
++++++++ +  }
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  ULONG
++++++++ +  NTAPI
++++++++ +  HidP_MaxUsageListLength(
++++++++ +    IN HIDP_REPORT_TYPE  ReportType,
++++++++ +    IN USAGE  UsagePage  OPTIONAL,
++++++++ +    IN PHIDP_PREPARSED_DATA  PreparsedData)
++++++++ +  {
++++++++ +      HID_PARSER Parser;
++++++++ +  
++++++++ +      //
++++++++ +      // sanity check
++++++++ +      //
++++++++ +      ASSERT(ReportType == HidP_Input || ReportType == HidP_Output || ReportType == HidP_Feature);
++++++++ +  
++++++++ +      //
++++++++ +      // init parser
++++++++ +      //
++++++++ +      HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, PreparsedData, &Parser);
++++++++ +  
++++++++ +  
++++++++ +      //
++++++++ +      // get usage length
++++++++ +      //
++++++++ +      return HidParser_MaxUsageListLength(&Parser, ReportType, UsagePage);
 +     +    }
 +     +    
 +     +    HIDAPI
 +     +    NTSTATUS
 +     +    NTAPI
- -----  -    OUT PHIDP_DATA  DataList,
- -----  -    IN OUT PULONG  DataLength,
  -----  -    IN PHIDP_PREPARSED_DATA  PreparsedData,
  -----  -    IN PCHAR  Report,
  -----  -    IN ULONG  ReportLength)
++++++++ +  HidP_GetSpecificValueCaps(
 +     +      IN HIDP_REPORT_TYPE  ReportType,
  -----  -      UNIMPLEMENTED
  -----  -      ASSERT(FALSE);
  -----  -      return STATUS_NOT_IMPLEMENTED;
++++++++ +    IN USAGE  UsagePage,
++++++++ +    IN USHORT  LinkCollection,
++++++++ +    IN USAGE  Usage,
++++++++ +    OUT PHIDP_VALUE_CAPS  ValueCaps,
++++++++ +    IN OUT PULONG  ValueCapsLength,
++++++++ +    IN PHIDP_PREPARSED_DATA  PreparsedData)
++     +    {
  -----  -  HidP_GetExtendedAttributes(
++++++++ +      HID_PARSER Parser;
++++++++ +  
++++++++ +      //
++++++++ +      // sanity check
++++++++ +      //
++++++++ +      ASSERT(ReportType == HidP_Input || ReportType == HidP_Output || ReportType == HidP_Feature);
++++++++ +  
++++++++ +      //
++++++++ +      // init parser
++++++++ +      //
++++++++ +      HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, PreparsedData, &Parser);
++++++++ +  
++++++++ +      //
++++++++ +      // get value caps
++++++++ +      //
++++++++ +      return HidParser_GetSpecificValueCaps(&Parser, ReportType, UsagePage, LinkCollection, Usage, ValueCaps, ValueCapsLength);
++     +    }
++     +    
++     +    HIDAPI
++     +    NTSTATUS
++     +    NTAPI
  -----  -    IN USHORT  DataIndex,
++++++++ +  HidP_GetUsages(
++     +      IN HIDP_REPORT_TYPE  ReportType,
  -----  -    OUT PHIDP_EXTENDED_ATTRIBUTES  Attributes,
  -----  -    IN OUT PULONG  LengthAttributes)
++++++++ +    IN USAGE  UsagePage,
++++++++ +    IN USHORT  LinkCollection  OPTIONAL,
++++++++ +    OUT USAGE  *UsageList,
++++++++ +    IN OUT ULONG  *UsageLength,
 +     +      IN PHIDP_PREPARSED_DATA  PreparsedData,
- -----  -      UNIMPLEMENTED
- -----  -      ASSERT(FALSE);
- -----  -      return STATUS_NOT_IMPLEMENTED;
 +++++++ +    IN PCHAR  Report,
 +++++++ +    IN ULONG  ReportLength)
 +     +    {
-           HidP_GetExtendedAttributes(
  -----  -  HidP_GetLinkCollectionNodes(
  -----  -      OUT PHIDP_LINK_COLLECTION_NODE  LinkCollectionNodes,
  -----  -      IN OUT PULONG  LinkCollectionNodesLength,
  -----  -      IN PHIDP_PREPARSED_DATA  PreparsedData)
++++++++ +      HID_PARSER Parser;
++++++++ +  
++++++++ +      //
++++++++ +      // sanity check
++++++++ +      //
++++++++ +      ASSERT(ReportType == HidP_Input || ReportType == HidP_Output || ReportType == HidP_Feature);
++++++++ +  
++++++++ +      //
++++++++ +      // init parser
++++++++ +      //
++++++++ +      HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, PreparsedData, &Parser);
++++++++ +  
++++++++ +      //
++++++++ +      // get usages
++++++++ +      //
++++++++ +      return HidParser_GetUsages(&Parser, ReportType, UsagePage, LinkCollection, UsageList, UsageLength, Report, ReportLength);
 +     +    }
 +     +    
++++++++ +  
++++++++ +  #undef HidP_GetButtonCaps
++++++++ +  
 +     +    HIDAPI
 +     +    NTSTATUS
 +     +    NTAPI
  -----  -      UNIMPLEMENTED
  -----  -      ASSERT(FALSE);
  -----  -      return STATUS_NOT_IMPLEMENTED;
++++++++ +  HidP_UsageListDifference(
++++++++ +    IN PUSAGE  PreviousUsageList,
++++++++ +    IN PUSAGE  CurrentUsageList,
++++++++ +    OUT PUSAGE  BreakUsageList,
++++++++ +    OUT PUSAGE  MakeUsageList,
++++++++ +    IN ULONG  UsageListLength)
++     +    {
  -----  -  HidP_GetScaledUsageValue(
++++++++ +      return HidParser_UsageListDifference(PreviousUsageList, CurrentUsageList, BreakUsageList, MakeUsageList, UsageListLength);
++     +    }
++     +    
++     +    HIDAPI
++     +    NTSTATUS
++     +    NTAPI
-             IN USHORT  DataIndex,
  -----  -    IN USAGE  UsagePage,
  -----  -    IN USHORT  LinkCollection  OPTIONAL,
  -----  -    IN USAGE  Usage,
  -----  -    OUT PLONG  UsageValue,
++++++++ +  HidP_GetUsagesEx(
 +     +      IN HIDP_REPORT_TYPE  ReportType,
-             OUT PHIDP_EXTENDED_ATTRIBUTES  Attributes,
-             IN OUT PULONG  LengthAttributes)
++++++++ +    IN USHORT  LinkCollection,
++++++++ +    OUT PUSAGE_AND_PAGE  ButtonList,
++++++++ +    IN OUT ULONG  *UsageLength,
 +     +      IN PHIDP_PREPARSED_DATA  PreparsedData,
- -----  -      UNIMPLEMENTED
- -----  -      ASSERT(FALSE);
- -----  -      return STATUS_NOT_IMPLEMENTED;
++     +      IN PCHAR  Report,
++     +      IN ULONG  ReportLength)
 +     +    {
-           HidP_GetLinkCollectionNodes(
-               OUT PHIDP_LINK_COLLECTION_NODE  LinkCollectionNodes,
-               IN OUT PULONG  LinkCollectionNodesLength,
-               IN PHIDP_PREPARSED_DATA  PreparsedData)
  -----  -  HidP_GetUsageValue(
++++++++ +      return HidP_GetUsages(ReportType, HID_USAGE_PAGE_UNDEFINED, LinkCollection, (PUSAGE)ButtonList, UsageLength, PreparsedData, Report, ReportLength);
 +     +    }
 +     +    
 +     +    HIDAPI
 +     +    NTSTATUS
 +     +    NTAPI
-               UNIMPLEMENTED
-               ASSERT(FALSE);
-               return STATUS_NOT_IMPLEMENTED;
++++++++ +  HidP_UsageAndPageListDifference(
++++++++ +     IN PUSAGE_AND_PAGE  PreviousUsageList,
++++++++ +     IN PUSAGE_AND_PAGE  CurrentUsageList,
++++++++ +     OUT PUSAGE_AND_PAGE  BreakUsageList,
++++++++ +     OUT PUSAGE_AND_PAGE  MakeUsageList,
++++++++ +     IN ULONG  UsageListLength)
 +++++++ +  {
  -----  -    IN USHORT  LinkCollection,
++++++++ +      return HidParser_UsageAndPageListDifference(PreviousUsageList, CurrentUsageList, BreakUsageList, MakeUsageList, UsageListLength);
 +++++++ +  }
 +++++++ +  
 +++++++ +  HIDAPI
 +++++++ +  NTSTATUS
 +++++++ +  NTAPI
 +++++++ +  HidP_GetScaledUsageValue(
 +     +      IN HIDP_REPORT_TYPE  ReportType,
 +     +      IN USAGE  UsagePage,
  -----  -    OUT PULONG  UsageValue,
 +++++++ +    IN USHORT  LinkCollection  OPTIONAL,
 +     +      IN USAGE  Usage,
- -----  -      UNIMPLEMENTED
- -----  -      ASSERT(FALSE);
- -----  -      return STATUS_NOT_IMPLEMENTED;
  -----  -  }
 +++++++ +    OUT PLONG  UsageValue,
 +     +      IN PHIDP_PREPARSED_DATA  PreparsedData,
 +     +      IN PCHAR  Report,
 +     +      IN ULONG  ReportLength)
 +     +    {
-           HidP_GetUsageValue(
  -----  -  HidP_UsageListDifference(
  -----  -    IN PUSAGE  PreviousUsageList,
  -----  -    IN PUSAGE  CurrentUsageList,
  -----  -    OUT PUSAGE  BreakUsageList,
  -----  -    OUT PUSAGE  MakeUsageList,
  -----  -    IN ULONG  UsageListLength)
++++++++ +      HID_PARSER Parser;
++     +    
++++++++ +      //
++++++++ +      // sanity check
++++++++ +      //
++++++++ +      ASSERT(ReportType == HidP_Input || ReportType == HidP_Output || ReportType == HidP_Feature);
++     +    
++++++++ +      //
++++++++ +      // init parser
++++++++ +      //
++++++++ +      HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, PreparsedData, &Parser);
++++++++ +  
++++++++ +      //
++++++++ +      // get scaled usage value
++++++++ +      //
++++++++ +      return HidParser_GetScaledUsageValue(&Parser, ReportType, UsagePage, LinkCollection, Usage, UsageValue, Report, ReportLength);
 +++++++ +  }
 +     +    
 +     ++ ++HIDAPI
 +     ++ ++NTSTATUS
 +     ++ ++NTAPI
  -----  -      ULONG Index, SubIndex, bFound, BreakUsageIndex = 0, MakeUsageIndex = 0;
  -----  -      USAGE CurrentUsage, Usage;
++++++++++++HidP_TranslateUsageAndPagesToI8042ScanCodes(
++++++++++++   IN PUSAGE_AND_PAGE  ChangedUsageList,
++++++++++++   IN ULONG  UsageListLength,
++++++++++++   IN HIDP_KEYBOARD_DIRECTION  KeyAction,
++++++++++++   IN OUT PHIDP_KEYBOARD_MODIFIER_STATE  ModifierState,
++++++++++++   IN PHIDP_INSERT_SCANCODES  InsertCodesProcedure,
++++++++++++   IN PVOID  InsertCodesContext)
++     ++ ++{
  -----  -      if (UsageListLength)
  -----  -      {
  -----  -          Index = 0;
  -----  -          do
  -----  -          {
  -----  -              /* get current usage */
  -----  -              CurrentUsage = PreviousUsageList[Index];
  -----  -  
  -----  -              /* is the end of list reached? */
  -----  -              if (!CurrentUsage)
  -----  -                  break;
  -----  -  
  -----  -              /* start searching in current usage list */
  -----  -              SubIndex = 0;
  -----  -              bFound = FALSE;
  -----  -              do
  -----  -              {
  -----  -                  /* get usage of current list */
  -----  -                  Usage = CurrentUsageList[SubIndex];
  -----  -  
  -----  -                  /* end of list reached? */
  -----  -                  if (!Usage)
  -----  -                      break;
  -----  -  
  -----  -                  /* check if it matches the current one */
  -----  -                  if (CurrentUsage == Usage)
  -----  -                  {
  -----  -                      /* it does */
  -----  -                      bFound = TRUE;
  -----  -                      break;
  -----  -                  }
  -----  -  
  -----  -                  /* move to next usage */
  -----  -                  SubIndex++;
  -----  -              }while(SubIndex < UsageListLength);
  -----  -  
  -----  -              /* was the usage found ?*/
  -----  -              if (!bFound)
  -----  -              {
  -----  -                  /* store it in the break usage list */
  -----  -                  BreakUsageList[BreakUsageIndex] = CurrentUsage;
  -----  -                  BreakUsageIndex++;
  -----  -              }
  -----  -  
  -----  -              /* move to next usage */
  -----  -              Index++;
  -----  -  
  -----  -          }while(Index < UsageListLength);
  -----  -  
  -----  -          /* now process the new items */
  -----  -          Index = 0;
  -----  -          do
  -----  -          {
  -----  -              /* get current usage */
  -----  -              CurrentUsage = CurrentUsageList[Index];
  -----  -  
  -----  -              /* is the end of list reached? */
  -----  -              if (!CurrentUsage)
  -----  -                  break;
  -----  -  
  -----  -              /* start searching in current usage list */
  -----  -              SubIndex = 0;
  -----  -              bFound = FALSE;
  -----  -              do
  -----  -              {
  -----  -                  /* get usage of previous list */
  -----  -                  Usage = PreviousUsageList[SubIndex];
  -----  -  
  -----  -                  /* end of list reached? */
  -----  -                  if (!Usage)
  -----  -                      break;
  -----  -  
  -----  -                  /* check if it matches the current one */
  -----  -                  if (CurrentUsage == Usage)
  -----  -                  {
  -----  -                      /* it does */
  -----  -                      bFound = TRUE;
  -----  -                      break;
  -----  -                  }
  -----  -  
  -----  -                  /* move to next usage */
  -----  -                  SubIndex++;
  -----  -              }while(SubIndex < UsageListLength);
  -----  -  
  -----  -              /* was the usage found ?*/
  -----  -              if (!bFound)
  -----  -              {
  -----  -                  /* store it in the make usage list */
  -----  -                  MakeUsageList[MakeUsageIndex] = CurrentUsage;
  -----  -                  MakeUsageIndex++;
  -----  -              }
  -----  -  
  -----  -              /* move to next usage */
  -----  -              Index++;
  -----  -  
  -----  -          }while(Index < UsageListLength);
  -----  -      }
++++++++++++    HID_PARSER Parser;
++     ++ ++
  -----  -      /* does the break list contain empty entries */
  -----  -      if (BreakUsageIndex < UsageListLength)
  -----  -      {
  -----  -          /* zeroize entries */
  -----  -          RtlZeroMemory(&BreakUsageList[BreakUsageIndex], sizeof(USAGE) * (UsageListLength - BreakUsageIndex));
  -----  -      }
++++++++++++    //
++++++++++++    // sanity check
++++++++++++    //
++++++++++++    ASSERT(ReportType == HidP_Input || ReportType == HidP_Output || ReportType == HidP_Feature);
++     ++ ++
  -----  -      /* does the make usage list contain empty entries */
  -----  -      if (MakeUsageIndex < UsageListLength)
  -----  -      {
  -----  -          /* zeroize entries */
  -----  -          RtlZeroMemory(&MakeUsageList[MakeUsageIndex], sizeof(USAGE) * (UsageListLength - MakeUsageIndex));
  -----  -      }
++++++++++++    //
++++++++++++    // init parser
++++++++++++    //
++++++++++++    HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, NULL, &Parser);
++++++++++++
++++++++++++    //
++++++++++++    // translate usage pages
++++++++++++    //
++++++++++++    return HidParser_TranslateUsageAndPagesToI8042ScanCodes(Parser, UsageListLength, KeyAction, ModifierState, InsertCodesProcedure, InsertCodesContext);
++++++++++++}
++     ++ ++
  -----  -      /* done */
  -----  -      return HIDP_STATUS_SUCCESS;
++     ++ ++
  -----  -  HidP_GetSpecificValueCaps(
++++++++++++
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidP_GetButtonCaps(
++++++++ +      HIDP_REPORT_TYPE ReportType,
++++++++ +      PHIDP_BUTTON_CAPS ButtonCaps,
++++++++ +      PUSHORT ButtonCapsLength,
++++++++ +      PHIDP_PREPARSED_DATA PreparsedData)
++++++++ +  {
++++++++ +      return HidP_GetSpecificButtonCaps(ReportType, HID_USAGE_PAGE_UNDEFINED, 0, 0, ButtonCaps, (PULONG)ButtonCapsLength, PreparsedData);
++     +    }
++     +    
++     +    HIDAPI
++     +    NTSTATUS
++     +    NTAPI
-             OUT PULONG  UsageValue,
-             IN PHIDP_PREPARSED_DATA  PreparsedData,
-             IN PCHAR  Report,
-             IN ULONG  ReportLength)
  -----  -    OUT PHIDP_VALUE_CAPS  ValueCaps,
  -----  -    IN OUT PULONG  ValueCapsLength,
++++++++ +  HidP_GetSpecificButtonCaps(
 +     +      IN HIDP_REPORT_TYPE  ReportType,
 +     +      IN USAGE  UsagePage,
 +     +      IN USHORT  LinkCollection,
 +     +      IN USAGE  Usage,
-           
-           
++++++++ +    OUT PHIDP_BUTTON_CAPS  ButtonCaps,
++++++++ +    IN OUT PULONG  ButtonCapsLength,
++     +      IN PHIDP_PREPARSED_DATA  PreparsedData)
 +     +    {
 +     +        UNIMPLEMENTED
 +     +        ASSERT(FALSE);
 +     +        return STATUS_NOT_IMPLEMENTED;
 +     +    }
 +     +    
  -----  -  ULONG
 +     +    HIDAPI
-           HidP_UsageListDifference(
-             IN PUSAGE  PreviousUsageList,
-             IN PUSAGE  CurrentUsageList,
-             OUT PUSAGE  BreakUsageList,
-             OUT PUSAGE  MakeUsageList,
-             IN ULONG  UsageListLength)
  -----  -  HidP_MaxUsageListLength(
 +++++++ +  NTSTATUS
 +     +    NTAPI
  -----  -    IN USAGE  UsagePage  OPTIONAL,
  -----  -    IN PHIDP_PREPARSED_DATA  PreparsedData)
++++++++ +  HidP_GetData(
++     +      IN HIDP_REPORT_TYPE  ReportType,
-           HidP_GetSpecificValueCaps(
  -----  -  HidP_GetUsages(
++++++++ +    OUT PHIDP_DATA  DataList,
++++++++ +    IN OUT PULONG  DataLength,
++++++++ +    IN PHIDP_PREPARSED_DATA  PreparsedData,
++++++++ +    IN PCHAR  Report,
++++++++ +    IN ULONG  ReportLength)
 +     +    {
 +     +        UNIMPLEMENTED
 +     +        ASSERT(FALSE);
 +     +        return STATUS_NOT_IMPLEMENTED;
 +     +    }
 +     +    
 +     +    HIDAPI
 +     +    NTSTATUS
 +     +    NTAPI
-             IN USHORT  LinkCollection,
-             IN USAGE  Usage,
-             OUT PHIDP_VALUE_CAPS  ValueCaps,
-             IN OUT PULONG  ValueCapsLength,
-             IN PHIDP_PREPARSED_DATA  PreparsedData)
  -----  -    IN USHORT  LinkCollection  OPTIONAL,
  -----  -    OUT USAGE  *UsageList,
  -----  -    IN OUT ULONG  *UsageLength,
++++++++ +  HidP_GetExtendedAttributes(
 +     +      IN HIDP_REPORT_TYPE  ReportType,
 +     +      IN USAGE  UsagePage,
-           ULONG
++++++++ +    IN PHIDP_PREPARSED_DATA  PreparsedData,
++++++++ +    OUT PHIDP_EXTENDED_ATTRIBUTES  Attributes,
++++++++ +    IN OUT PULONG  LengthAttributes)
 +++++++ +  {
 +++++++ +      UNIMPLEMENTED
 +++++++ +      ASSERT(FALSE);
 +++++++ +      return STATUS_NOT_IMPLEMENTED;
 +++++++ +  }
 +++++++ +  
 +++++++ +  HIDAPI
-           HidP_MaxUsageListLength(
-             IN HIDP_REPORT_TYPE  ReportType,
-             IN USAGE  UsagePage  OPTIONAL,
-             IN PHIDP_PREPARSED_DATA  PreparsedData)
++++++++ +  NTSTATUS
 +++++++ +  NTAPI
-           HidP_GetUsages(
++++++++ +  HidP_GetLinkCollectionNodes(
++++++++ +      OUT PHIDP_LINK_COLLECTION_NODE  LinkCollectionNodes,
++++++++ +      IN OUT PULONG  LinkCollectionNodesLength,
++++++++ +      IN PHIDP_PREPARSED_DATA  PreparsedData)
 +++++++ +  {
 +++++++ +      UNIMPLEMENTED
 +++++++ +      ASSERT(FALSE);
 +++++++ +      return STATUS_NOT_IMPLEMENTED;
 +++++++ +  }
 +++++++ +  
 +++++++ +  HIDAPI
 +++++++ +  NTSTATUS
 +++++++ +  NTAPI
-             IN USHORT  LinkCollection  OPTIONAL,
-             OUT USAGE  *UsageList,
-             IN OUT ULONG  *UsageLength,
++++++++ +  HidP_GetUsageValue(
 +++++++ +    IN HIDP_REPORT_TYPE  ReportType,
 +++++++ +    IN USAGE  UsagePage,
- -----  -  HIDAPI
- -----  -  NTSTATUS
- -----  -  NTAPI
- -----  -  HidP_GetUsagesEx(
- -----  -    IN HIDP_REPORT_TYPE  ReportType,
- -----  -    IN USHORT  LinkCollection,
- -----  -    OUT PUSAGE_AND_PAGE  ButtonList,
- -----  -    IN OUT ULONG  *UsageLength,
- -----  -    IN PHIDP_PREPARSED_DATA  PreparsedData,
- -----  -    IN PCHAR  Report,
- -----  -    IN ULONG  ReportLength)
- -----  -  {
-               UNIMPLEMENTED
-               ASSERT(FALSE);
-               return STATUS_NOT_IMPLEMENTED;
  -----  -      return HidP_GetUsages(ReportType, HID_USAGE_PAGE_UNDEFINED, LinkCollection, (PUSAGE)ButtonList, UsageLength, PreparsedData, Report, ReportLength);
- -----  -  }
- -----  -  
- -----  -  
- -----  -  HIDAPI
- -----  -  NTSTATUS
- -----  -  NTAPI
- -----  -  HidP_UsageAndPageListDifference(
- -----  -     IN PUSAGE_AND_PAGE  PreviousUsageList,
- -----  -     IN PUSAGE_AND_PAGE  CurrentUsageList,
- -----  -     OUT PUSAGE_AND_PAGE  BreakUsageList,
- -----  -     OUT PUSAGE_AND_PAGE  MakeUsageList,
- -----  -     IN ULONG  UsageListLength)
- -----  -  {
-               UNIMPLEMENTED
-               ASSERT(FALSE);
-               return STATUS_NOT_IMPLEMENTED;
  -----  -      ULONG Index, SubIndex, BreakUsageListIndex = 0, MakeUsageListIndex = 0, bFound;
  -----  -      PUSAGE_AND_PAGE CurrentUsage, Usage;
  -----  -  
  -----  -      if (UsageListLength)
  -----  -      {
  -----  -          /* process removed usages */
  -----  -          Index = 0;
  -----  -          do
  -----  -          {
  -----  -              /* get usage from current index */
  -----  -              CurrentUsage = &PreviousUsageList[Index];
  -----  -  
  -----  -              /* end of list reached? */
  -----  -              if (CurrentUsage->Usage == 0 && CurrentUsage->UsagePage == 0)
  -----  -                  break;
  -----  -  
  -----  -              /* search in current list */
  -----  -              SubIndex = 0;
  -----  -              bFound = FALSE;
  -----  -              do
  -----  -              {
  -----  -                  /* get usage */
  -----  -                  Usage = &CurrentUsageList[SubIndex];
  -----  -  
  -----  -                  /* end of list reached? */
  -----  -                  if (Usage->Usage == 0 && Usage->UsagePage == 0)
  -----  -                      break;
  -----  -  
  -----  -                  /* does it match */
  -----  -                  if (Usage->Usage == CurrentUsage->Usage && Usage->UsagePage == CurrentUsage->UsagePage)
  -----  -                  {
  -----  -                      /* found match */
  -----  -                      bFound = TRUE;
  -----  -                  }
  -----  -  
  -----  -                  /* move to next index */
  -----  -                  SubIndex++;
  -----  -  
  -----  -              }while(SubIndex < UsageListLength);
  -----  -  
  -----  -              if (!bFound)
  -----  -              {
  -----  -                  /* store it in break usage list */
  -----  -                  BreakUsageList[BreakUsageListIndex].Usage = CurrentUsage->Usage;
  -----  -                  BreakUsageList[BreakUsageListIndex].UsagePage = CurrentUsage->UsagePage;
  -----  -                  BreakUsageListIndex++;
  -----  -              }
  -----  -  
  -----  -              /* move to next index */
  -----  -              Index++;
  -----  -  
  -----  -          }while(Index < UsageListLength);
  -----  -  
  -----  -          /* process new usages */
  -----  -          Index = 0;
  -----  -          do
  -----  -          {
  -----  -              /* get usage from current index */
  -----  -              CurrentUsage = &CurrentUsageList[Index];
  -----  -  
  -----  -              /* end of list reached? */
  -----  -              if (CurrentUsage->Usage == 0 && CurrentUsage->UsagePage == 0)
  -----  -                  break;
  -----  -  
  -----  -              /* search in current list */
  -----  -              SubIndex = 0;
  -----  -              bFound = FALSE;
  -----  -              do
  -----  -              {
  -----  -                  /* get usage */
  -----  -                  Usage = &PreviousUsageList[SubIndex];
  -----  -  
  -----  -                  /* end of list reached? */
  -----  -                  if (Usage->Usage == 0 && Usage->UsagePage == 0)
  -----  -                      break;
  -----  -  
  -----  -                  /* does it match */
  -----  -                  if (Usage->Usage == CurrentUsage->Usage && Usage->UsagePage == CurrentUsage->UsagePage)
  -----  -                  {
  -----  -                      /* found match */
  -----  -                      bFound = TRUE;
  -----  -                  }
  -----  -  
  -----  -                  /* move to next index */
  -----  -                  SubIndex++;
  -----  -  
  -----  -              }while(SubIndex < UsageListLength);
  -----  -  
  -----  -              if (!bFound)
  -----  -              {
  -----  -                  /* store it in break usage list */
  -----  -                  MakeUsageList[MakeUsageListIndex].Usage = CurrentUsage->Usage;
  -----  -                  MakeUsageList[MakeUsageListIndex].UsagePage = CurrentUsage->UsagePage;
  -----  -                  MakeUsageListIndex++;
  -----  -              }
  -----  -  
  -----  -              /* move to next index */
  -----  -              Index++;
  -----  -          }while(Index < UsageListLength);
  -----  -      }
  -----  -  
  -----  -      /* are there remaining free list entries */
  -----  -      if (BreakUsageListIndex < UsageListLength)
  -----  -      {
  -----  -          /* zero them */
  -----  -          RtlZeroMemory(&BreakUsageList[BreakUsageListIndex], (UsageListLength - BreakUsageListIndex) * sizeof(USAGE_AND_PAGE));
  -----  -      }
  -----  -  
  -----  -      /* are there remaining free list entries */
  -----  -      if (MakeUsageListIndex < UsageListLength)
  -----  -      {
  -----  -          /* zero them */
  -----  -          RtlZeroMemory(&MakeUsageList[MakeUsageListIndex], (UsageListLength - MakeUsageListIndex) * sizeof(USAGE_AND_PAGE));
  -----  -      }
  -----  -  
  -----  -      /* done */
  -----  -      return HIDP_STATUS_SUCCESS;
- -----  -  }
++++++++ +    IN USHORT  LinkCollection,
++++++++ +    IN USAGE  Usage,
++++++++ +    OUT PULONG  UsageValue,
 +     +      IN PHIDP_PREPARSED_DATA  PreparsedData,
 +     +      IN PCHAR  Report,
 +     +      IN ULONG  ReportLength)
 +     +    {
 +     +        UNIMPLEMENTED
 +     +        ASSERT(FALSE);
 +     +        return STATUS_NOT_IMPLEMENTED;
 +     +    }
 +     +    
 +     +    NTSTATUS
++     +    NTAPI
 +     +    HidP_SysPowerEvent (
 +     +        IN PCHAR HidPacket,
 +     +        IN USHORT HidPacketLength,
 +     +        IN PHIDP_PREPARSED_DATA Ppd,
 +     +        OUT PULONG OutputBuffer)
 +     +    {
 +     +        UNIMPLEMENTED
 +     +        ASSERT(FALSE);
 +     +        return STATUS_NOT_IMPLEMENTED;
 +     +    }
 +     +    
 +     +    NTSTATUS
++     +    NTAPI
 +     +    HidP_SysPowerCaps (
 +     +        IN PHIDP_PREPARSED_DATA Ppd,
 +     +        OUT PULONG OutputBuffer)
 +     +    {
 +     +        UNIMPLEMENTED
 +     +        ASSERT(FALSE);
 +     +        return STATUS_NOT_IMPLEMENTED;
 +     +    }
 +     +    
 +     +    HIDAPI
 +     +    NTSTATUS
 +     +    NTAPI
 +     +    HidP_GetUsageValueArray(
 +     +      IN HIDP_REPORT_TYPE  ReportType,
 +     +      IN USAGE  UsagePage,
 +     +      IN USHORT  LinkCollection  OPTIONAL,
 +     +      IN USAGE  Usage,
 +     +      OUT PCHAR  UsageValue,
 +     +      IN USHORT  UsageValueByteLength,
 +     +      IN PHIDP_PREPARSED_DATA  PreparsedData,
 +     +      IN PCHAR  Report,
 +     +      IN ULONG  ReportLength)
 +     +    {
 +     +        UNIMPLEMENTED
 +     +        ASSERT(FALSE);
 +     +        return STATUS_NOT_IMPLEMENTED;
 +     +    }
 +     +    
- ----- ----HIDAPI
- ----- ----NTSTATUS
- ----- ----NTAPI
- ----- ----HidP_TranslateUsageAndPagesToI8042ScanCodes(
- ----- ----   IN PUSAGE_AND_PAGE  ChangedUsageList,
- ----- ----   IN ULONG  UsageListLength,
- ----- ----   IN HIDP_KEYBOARD_DIRECTION  KeyAction,
- ----- ----   IN OUT PHIDP_KEYBOARD_MODIFIER_STATE  ModifierState,
- ----- ----   IN PHIDP_INSERT_SCANCODES  InsertCodesProcedure,
- ----- ----   IN PVOID  InsertCodesContext)
- ----- ----{
- ----- ----    UNIMPLEMENTED
- ----- ----    ASSERT(FALSE);
- ----- ----    return STATUS_NOT_IMPLEMENTED;
- ----- ----}
- ----- ----
 +     +    
 +     +    HIDAPI
 +     +    NTSTATUS
 +     +    NTAPI
 +     +    HidP_UnsetUsages(
 +     +      IN HIDP_REPORT_TYPE  ReportType,
 +     +      IN USAGE  UsagePage,
 +     +      IN USHORT  LinkCollection,
 +     +      IN PUSAGE  UsageList,
 +     +      IN OUT PULONG  UsageLength,
 +     +      IN PHIDP_PREPARSED_DATA  PreparsedData,
 +     +      IN OUT PCHAR  Report,
 +     +      IN ULONG  ReportLength)
 +     +    {
 +     +        UNIMPLEMENTED
 +     +        ASSERT(FALSE);
 +     +        return STATUS_NOT_IMPLEMENTED;
 +     +    }
 +     +    
 +     +    HIDAPI
 +     +    NTSTATUS
 +     +    NTAPI
 +     +    HidP_TranslateUsagesToI8042ScanCodes(
 +     +      IN PUSAGE  ChangedUsageList,
 +     +      IN ULONG  UsageListLength,
 +     +      IN HIDP_KEYBOARD_DIRECTION  KeyAction,
 +     +      IN OUT PHIDP_KEYBOARD_MODIFIER_STATE  ModifierState,
 +     +      IN PHIDP_INSERT_SCANCODES  InsertCodesProcedure,
 +     +      IN PVOID  InsertCodesContext)
 +     +    {
 +     +        UNIMPLEMENTED
 +     +        ASSERT(FALSE);
 +     +        return STATUS_NOT_IMPLEMENTED;
 +     +    }
 +     +    
 +     +    HIDAPI
 +     +    NTSTATUS
 +     +    NTAPI
 +     +    HidP_SetUsages(
 +     +      IN HIDP_REPORT_TYPE  ReportType,
 +     +      IN USAGE  UsagePage,
 +     +      IN USHORT  LinkCollection,
 +     +      IN PUSAGE  UsageList,
 +     +      IN OUT PULONG  UsageLength,
 +     +      IN PHIDP_PREPARSED_DATA  PreparsedData,
 +     +      IN OUT PCHAR  Report,
 +     +      IN ULONG  ReportLength)
 +     +    {
 +     +        UNIMPLEMENTED
 +     +        ASSERT(FALSE);
 +     +        return STATUS_NOT_IMPLEMENTED;
 +     +    }
 +     +    
 +     +    HIDAPI
 +     +    NTSTATUS
 +     +    NTAPI
 +     +    HidP_SetUsageValueArray(
 +     +      IN HIDP_REPORT_TYPE  ReportType,
 +     +      IN USAGE  UsagePage,
 +     +      IN USHORT  LinkCollection  OPTIONAL,
 +     +      IN USAGE  Usage,
 +     +      IN PCHAR  UsageValue,
 +     +      IN USHORT  UsageValueByteLength,
 +     +      IN PHIDP_PREPARSED_DATA  PreparsedData,
 +     +      OUT PCHAR  Report,
 +     +      IN ULONG  ReportLength)
 +     +    {
 +     +        UNIMPLEMENTED
 +     +        ASSERT(FALSE);
 +     +        return STATUS_NOT_IMPLEMENTED;
 +     +    }
 +     +    
 +     +    HIDAPI
 +     +    NTSTATUS
 +     +    NTAPI
 +     +    HidP_SetUsageValue(
 +     +      IN HIDP_REPORT_TYPE  ReportType,
 +     +      IN USAGE  UsagePage,
 +     +      IN USHORT  LinkCollection,
 +     +      IN USAGE  Usage,
 +     +      IN ULONG  UsageValue,
 +     +      IN PHIDP_PREPARSED_DATA  PreparsedData,
 +     +      IN OUT PCHAR  Report,
 +     +      IN ULONG  ReportLength)
 +     +    {
 +     +        UNIMPLEMENTED
 +     +        ASSERT(FALSE);
 +     +        return STATUS_NOT_IMPLEMENTED;
 +     +    }
 +     +    
 +     +    HIDAPI
 +     +    NTSTATUS
 +     +    NTAPI
 +     +    HidP_SetScaledUsageValue(
 +     +      IN HIDP_REPORT_TYPE  ReportType,
 +     +      IN USAGE  UsagePage,
 +     +      IN USHORT  LinkCollection  OPTIONAL,
 +     +      IN USAGE  Usage,
 +     +      IN LONG  UsageValue,
 +     +      IN PHIDP_PREPARSED_DATA  PreparsedData,
 +     +      IN OUT PCHAR  Report,
 +     +      IN ULONG  ReportLength)
 +     +    {
 +     +        UNIMPLEMENTED
 +     +        ASSERT(FALSE);
 +     +        return STATUS_NOT_IMPLEMENTED;
 +     +    }
 +     +    
 +     +    HIDAPI
 +     +    NTSTATUS
 +     +    NTAPI
 +     +    HidP_SetData(
 +     +      IN HIDP_REPORT_TYPE  ReportType,
 +     +      IN PHIDP_DATA  DataList,
 +     +      IN OUT PULONG  DataLength,
 +     +      IN PHIDP_PREPARSED_DATA  PreparsedData,
 +     +      IN OUT PCHAR  Report,
 +     +      IN ULONG  ReportLength)
 +     +    {
 +     +        UNIMPLEMENTED
 +     +        ASSERT(FALSE);
 +     +        return STATUS_NOT_IMPLEMENTED;
 +     +    }
 +     +    
 +     +    HIDAPI
 +     +    ULONG
 +     +    NTAPI
 +     +    HidP_MaxDataListLength(
 +     +      IN HIDP_REPORT_TYPE  ReportType,
 +     +      IN PHIDP_PREPARSED_DATA  PreparsedData)
 +     +    {
 +     +        UNIMPLEMENTED
 +     +        ASSERT(FALSE);
 +     +        return STATUS_NOT_IMPLEMENTED;
 +     +    }
 +     +    
 +     +    HIDAPI
 +     +    NTSTATUS
 +     +    NTAPI
 +     +    HidP_InitializeReportForID(
 +     +      IN HIDP_REPORT_TYPE  ReportType,
 +     +      IN UCHAR  ReportID,
 +     +      IN PHIDP_PREPARSED_DATA  PreparsedData,
 +     +      IN OUT PCHAR  Report,
 +     +      IN ULONG  ReportLength)
 +     +    {
 +     +        UNIMPLEMENTED
 +     +        ASSERT(FALSE);
 +     +        return STATUS_NOT_IMPLEMENTED;
 +     +    }
 +     +    
++     +    #undef HidP_GetValueCaps
++     +    
 +     +    HIDAPI
 +     +    NTSTATUS
 +     +    NTAPI
 +     +    HidP_GetValueCaps(
 +     +      HIDP_REPORT_TYPE ReportType,
 +     +      PHIDP_VALUE_CAPS ValueCaps,
 +     +      PULONG ValueCapsLength,
 +     +      PHIDP_PREPARSED_DATA PreparsedData)
 +     +    {
 +     +        UNIMPLEMENTED
 +     +        ASSERT(FALSE);
 +     +        return STATUS_NOT_IMPLEMENTED;
 +     +    }
 +     +    
 +     +    NTSTATUS
 +     +    NTAPI
 +     +    DriverEntry(
 +     +        IN PDRIVER_OBJECT DriverObject,
 +     +        IN PUNICODE_STRING RegPath)
 +     +    {
 +     +    
 +     +        DPRINT1("********* HID PARSE *********\n");
 +     +        return STATUS_SUCCESS;
 +     +    }
index 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000,d0ad1e5,0000000,0000000,0000000..d2d4866
mode 000000,000000,000000,000000,000000,000000,000000,000000,100644,000000,000000,000000..100644
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
@@@@@@@@@@@@@ -1,0 -1,0 -1,0 -1,0 -1,0 -1,0 -1,0 -1,0 -1,674 -1,0 -1,0 -1,0 +1,855 @@@@@@@@@@@@@
        -       IN PKEYBOARD_INPUT_DATA InputData,
        -       IN ULONG InputDataLength)
++++++++ +++/*
++++++++ +++ * PROJECT:     ReactOS HID Stack
++++++++ +++ * LICENSE:     GPL - See COPYING in the top level directory
++++++++ +++ * FILE:        drivers/hid/kbdhid/kbdhid.c
++++++++ +++ * PURPOSE:     Keyboard HID Driver
++++++++ +++ * PROGRAMMERS:
++++++++ +++ *              Michael Martin (michael.martin@reactos.org)
++++++++ +++ *              Johannes Anderwald (johannes.anderwald@reactos.org)
++++++++ +++ */
++++++++ +++
++++++++ +++#include "kbdhid.h"
++++++++ +++
++++++++ +++VOID
++++++++ +++KbdHid_DispatchInputData(
++++++++ +++    IN PKBDHID_DEVICE_EXTENSION DeviceExtension,
        -       (*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ClassService)(DeviceExtension->ClassDeviceObject, InputData, InputData + InputDataLength + 1, &InputDataConsumed);
++++++++++++    IN PKEYBOARD_INPUT_DATA InputData)
++++++++ +++{
++++++++ +++    KIRQL OldIrql;
++++++++ +++    ULONG InputDataConsumed;
++++++++ +++
++++++++ +++    if (!DeviceExtension->ClassService)
++++++++ +++        return;
++++++++ +++
++++++++ +++    /* sanity check */
++++++++ +++    ASSERT(DeviceExtension->ClassService);
++++++++ +++    ASSERT(DeviceExtension->ClassDeviceObject);
++++++++ +++
++++++++ +++    /* raise irql */
++++++++ +++    KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
++++++++ +++
++++++++ +++    /* dispatch input data */
        -       UNIMPLEMENTED
        -       ASSERT(FALSE);
++++++++++++    (*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ClassService)(DeviceExtension->ClassDeviceObject, InputData, InputData + 1, &InputDataConsumed);
++++++++ +++
++++++++ +++    /* lower irql to previous level */
++++++++ +++    KeLowerIrql(OldIrql);
++++++++ +++}
++++++++ +++
++++++++++++BOOLEAN
++++++++++++NTAPI
++++++++++++KbdHid_InsertScanCodes(
++++++++++++    IN PVOID  Context,
++++++++++++    IN PCHAR  NewScanCodes,
++++++++++++    IN ULONG  Length)
++++++++++++{
++++++++++++    KEYBOARD_INPUT_DATA InputData;
++++++++++++    ULONG Index;
++++++++++++
++++++++++++    for(Index = 0; Index < Length; Index++)
++++++++++++    {
++++++++++++        DPRINT1("[KBDHID] ScanCode Index %lu ScanCode %x\n", Index, NewScanCodes[Index] & 0xFF);
++++++++++++        //
++++++++++++        // TODO: set up input data
++++++++++++        //
++++++++++++        //KbdHid_DispatchInputData((PKBDHID_DEVICE_EXTENSION)Context, &InputData);
++++++++++++    }
++++++++++++
++++++++++++    //
++++++++++++    // done
++++++++++++    //
++++++++++++    return TRUE;
++++++++++++}
++++++++++++
++++++++++++
++++++++ +++NTSTATUS
++++++++ +++NTAPI
++++++++ +++KbdHid_ReadCompletion(
++++++++ +++    IN PDEVICE_OBJECT  DeviceObject,
++++++++ +++    IN PIRP  Irp,
++++++++ +++    IN PVOID  Context)
++++++++ +++{
++++++++ +++    PKBDHID_DEVICE_EXTENSION DeviceExtension;
++++++++++++    NTSTATUS Status;
++++++++++++    ULONG ButtonLength;
++++++++ +++
++++++++ +++    /* get device extension */
++++++++ +++    DeviceExtension = (PKBDHID_DEVICE_EXTENSION)Context;
++++++++ +++
++++++++ +++    if (Irp->IoStatus.Status == STATUS_PRIVILEGE_NOT_HELD ||
++++++++ +++        Irp->IoStatus.Status == STATUS_DEVICE_NOT_CONNECTED ||
++++++++ +++        Irp->IoStatus.Status == STATUS_CANCELLED ||
++++++++ +++        DeviceExtension->StopReadReport)
++++++++ +++    {
++++++++ +++        /* failed to read or should be stopped*/
++++++++ +++        DPRINT1("[KBDHID] ReadCompletion terminating read Status %x\n", Irp->IoStatus.Status);
++++++++ +++
++++++++ +++        /* report no longer active */
++++++++ +++        DeviceExtension->ReadReportActive = FALSE;
++++++++ +++
++++++++ +++        /* request stopping of the report cycle */
++++++++ +++        DeviceExtension->StopReadReport = FALSE;
++++++++ +++
++++++++ +++        /* signal completion event */
++++++++ +++        KeSetEvent(&DeviceExtension->ReadCompletionEvent, 0, 0);
++++++++ +++        return STATUS_MORE_PROCESSING_REQUIRED;
++++++++ +++    }
++++++++ +++
        -       /* dispatch mouse action */
        -       //KbdHid_DispatchInputData(DeviceExtension, &InputData);
++++++++++++    /* get current usages */
++++++++++++    ButtonLength = DeviceExtension->UsageListLength;
++++++++++++    Status = HidP_GetUsagesEx(HidP_Input, HIDP_LINK_COLLECTION_UNSPECIFIED, DeviceExtension->CurrentUsageList, &ButtonLength, DeviceExtension->PreparsedData, DeviceExtension->Report, DeviceExtension->ReportLength);
++++++++++++    ASSERT(Status == HIDP_STATUS_SUCCESS);
++++++++++++
++++++++++++    /* FIXME check if needs mapping */
++++++++++++
++++++++++++    /* get usage difference */
++++++++++++    Status = HidP_UsageAndPageListDifference(DeviceExtension->PreviousUsageList, DeviceExtension->CurrentUsageList, DeviceExtension->BreakUsageList, DeviceExtension->MakeUsageList, DeviceExtension->UsageListLength);
++++++++++++    ASSERT(Status == HIDP_STATUS_SUCCESS);
++++++++++++
++++++++++++    /* replace previous usage list with current list */
++++++++++++    RtlMoveMemory(DeviceExtension->PreviousUsageList, DeviceExtension->CurrentUsageList, sizeof(USAGE_AND_PAGE) * DeviceExtension->UsageListLength);
++++++++ +++
        -       DPRINT1("[KBDHID] Unknown DeviceControl %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
++++++++++++    /* translate break usage list */
++++++++++++    HidP_TranslateUsageAndPagesToI8042ScanCodes(DeviceExtension->BreakUsageList, DeviceExtension->UsageListLength, HidP_Keyboard_Break, &DeviceExtension->ModifierState, KbdHid_InsertScanCodes, DeviceExtension);
++++++++++++    ASSERT(Status == HIDP_STATUS_SUCCESS);
++++++++++++
++++++++++++    /* translate new usage list */
++++++++++++    HidP_TranslateUsageAndPagesToI8042ScanCodes(DeviceExtension->MakeUsageList, DeviceExtension->UsageListLength, HidP_Keyboard_Make, &DeviceExtension->ModifierState, KbdHid_InsertScanCodes, DeviceExtension);
++++++++++++    ASSERT(Status == HIDP_STATUS_SUCCESS);
++++++++ +++
++++++++ +++    /* re-init read */
++++++++ +++    KbdHid_InitiateRead(DeviceExtension);
++++++++ +++
++++++++ +++    /* stop completion */
++++++++ +++    return STATUS_MORE_PROCESSING_REQUIRED;
++++++++ +++}
++++++++ +++
++++++++ +++NTSTATUS
++++++++ +++KbdHid_InitiateRead(
++++++++ +++    IN PKBDHID_DEVICE_EXTENSION DeviceExtension)
++++++++ +++{
++++++++ +++    PIO_STACK_LOCATION IoStack;
++++++++ +++    NTSTATUS Status;
++++++++ +++
++++++++ +++    /* re-use irp */
++++++++ +++    IoReuseIrp(DeviceExtension->Irp, STATUS_SUCCESS);
++++++++ +++
++++++++ +++    /* init irp */
++++++++ +++    DeviceExtension->Irp->MdlAddress = DeviceExtension->ReportMDL;
++++++++ +++
++++++++ +++    /* get next stack location */
++++++++ +++    IoStack = IoGetNextIrpStackLocation(DeviceExtension->Irp);
++++++++ +++
++++++++ +++    /* init stack location */
++++++++ +++    IoStack->Parameters.Read.Length = DeviceExtension->ReportLength;
++++++++ +++    IoStack->Parameters.Read.Key = 0;
++++++++ +++    IoStack->Parameters.Read.ByteOffset.QuadPart = 0LL;
++++++++ +++    IoStack->MajorFunction = IRP_MJ_READ;
++++++++ +++    IoStack->FileObject = DeviceExtension->FileObject;
++++++++ +++
++++++++ +++    /* set completion routine */
++++++++ +++    IoSetCompletionRoutine(DeviceExtension->Irp, KbdHid_ReadCompletion, DeviceExtension, TRUE, TRUE, TRUE);
++++++++ +++
++++++++ +++    /* read is active */
++++++++ +++    DeviceExtension->ReadReportActive = TRUE;
++++++++ +++
++++++++ +++    /* start the read */
++++++++ +++    Status = IoCallDriver(DeviceExtension->NextDeviceObject, DeviceExtension->Irp);
++++++++ +++
++++++++ +++    /* done */
++++++++ +++    return Status;
++++++++ +++}
++++++++ +++
++++++++ +++NTSTATUS
++++++++ +++NTAPI
++++++++ +++KbdHid_CreateCompletion(
++++++++ +++    IN PDEVICE_OBJECT  DeviceObject,
++++++++ +++    IN PIRP  Irp,
++++++++ +++    IN PVOID  Context)
++++++++ +++{
++++++++ +++    KeSetEvent((PKEVENT)Context, 0, FALSE);
++++++++ +++    return STATUS_MORE_PROCESSING_REQUIRED;
++++++++ +++}
++++++++ +++
++++++++ +++
++++++++ +++NTSTATUS
++++++++ +++NTAPI
++++++++ +++KbdHid_Create(
++++++++ +++    IN PDEVICE_OBJECT DeviceObject,
++++++++ +++    IN PIRP Irp)
++++++++ +++{
++++++++ +++    PIO_STACK_LOCATION IoStack;
++++++++ +++    NTSTATUS Status;
++++++++ +++    KEVENT Event;
++++++++ +++    PKBDHID_DEVICE_EXTENSION DeviceExtension;
++++++++ +++
++++++++ +++    DPRINT1("[KBDHID]: IRP_MJ_CREATE\n");
++++++++ +++
++++++++ +++    /* get device extension */
++++++++ +++    DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
++++++++ +++
++++++++ +++    /* get stack location */
++++++++ +++    IoStack = IoGetCurrentIrpStackLocation(Irp);
++++++++ +++
++++++++ +++    /* copy stack location to next */
++++++++ +++    IoCopyCurrentIrpStackLocationToNext(Irp);
++++++++ +++
++++++++ +++    /* init event */
++++++++ +++    KeInitializeEvent(&Event, NotificationEvent, FALSE);
++++++++ +++
++++++++ +++    /* prepare irp */
++++++++ +++    IoSetCompletionRoutine(Irp, KbdHid_CreateCompletion, &Event, TRUE, TRUE, TRUE);
++++++++ +++
++++++++ +++    /* call lower driver */
++++++++ +++    Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
++++++++ +++    if (Status == STATUS_PENDING)
++++++++ +++    {
++++++++ +++        /* request pending */
++++++++ +++        KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
++++++++ +++    }
++++++++ +++
++++++++ +++    /* check for success */
++++++++ +++    if (!NT_SUCCESS(Status))
++++++++ +++    {
++++++++ +++        /* failed */
++++++++ +++        Irp->IoStatus.Status = Status;
++++++++ +++        IoCompleteRequest(Irp, IO_NO_INCREMENT);
++++++++ +++        return Status;
++++++++ +++    }
++++++++ +++
++++++++ +++    /* is the driver already in use */
++++++++ +++    if (DeviceExtension->FileObject == NULL)
++++++++ +++    {
++++++++ +++         /* did the caller specify correct attributes */
++++++++ +++         ASSERT(IoStack->Parameters.Create.SecurityContext);
++++++++ +++         if (IoStack->Parameters.Create.SecurityContext->DesiredAccess)
++++++++ +++         {
++++++++ +++             /* store file object */
++++++++ +++             DeviceExtension->FileObject = IoStack->FileObject;
++++++++ +++
++++++++ +++             /* reset event */
++++++++ +++             KeResetEvent(&DeviceExtension->ReadCompletionEvent);
++++++++ +++
++++++++ +++             /* initiating read */
++++++++ +++             Status = KbdHid_InitiateRead(DeviceExtension);
++++++++ +++             DPRINT1("[KBDHID] KbdHid_InitiateRead: status %x\n", Status);
++++++++ +++             if (Status == STATUS_PENDING)
++++++++ +++             {
++++++++ +++                 /* report irp is pending */
++++++++ +++                 Status = STATUS_SUCCESS;
++++++++ +++             }
++++++++ +++         }
++++++++ +++    }
++++++++ +++
++++++++ +++    /* complete request */
++++++++ +++    Irp->IoStatus.Status = Status;
++++++++ +++    IoCompleteRequest(Irp, IO_NO_INCREMENT);
++++++++ +++    return Status;
++++++++ +++}
++++++++ +++
++++++++ +++
++++++++ +++NTSTATUS
++++++++ +++NTAPI
++++++++ +++KbdHid_Close(
++++++++ +++    IN PDEVICE_OBJECT DeviceObject,
++++++++ +++    IN PIRP Irp)
++++++++ +++{
++++++++ +++    PKBDHID_DEVICE_EXTENSION DeviceExtension;
++++++++ +++
++++++++ +++    /* get device extension */
++++++++ +++    DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
++++++++ +++
++++++++ +++    DPRINT("[KBDHID] IRP_MJ_CLOSE ReadReportActive %x\n", DeviceExtension->ReadReportActive);
++++++++ +++
++++++++ +++    if (DeviceExtension->ReadReportActive)
++++++++ +++    {
++++++++ +++        /* request stopping of the report cycle */
++++++++ +++        DeviceExtension->StopReadReport = TRUE;
++++++++ +++
++++++++ +++        /* wait until the reports have been read */
++++++++ +++        KeWaitForSingleObject(&DeviceExtension->ReadCompletionEvent, Executive, KernelMode, FALSE, NULL);
++++++++ +++
++++++++ +++        /* cancel irp */
++++++++ +++        IoCancelIrp(DeviceExtension->Irp);
++++++++ +++    }
++++++++ +++
++++++++ +++    DPRINT("[KBDHID] IRP_MJ_CLOSE ReadReportActive %x\n", DeviceExtension->ReadReportActive);
++++++++ +++
++++++++ +++    /* remove file object */
++++++++ +++    DeviceExtension->FileObject = NULL;
++++++++ +++
++++++++ +++    /* skip location */
++++++++ +++    IoSkipCurrentIrpStackLocation(Irp);
++++++++ +++
++++++++ +++    /* pass irp to down the stack */
++++++++ +++    return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
++++++++ +++}
++++++++ +++
++++++++ +++NTSTATUS
++++++++ +++NTAPI
++++++++ +++KbdHid_InternalDeviceControl(
++++++++ +++    IN PDEVICE_OBJECT DeviceObject,
++++++++ +++    IN PIRP Irp)
++++++++ +++{
++++++++ +++    PIO_STACK_LOCATION IoStack;
++++++++ +++    PKBDHID_DEVICE_EXTENSION DeviceExtension;
++++++++++++    PCONNECT_DATA Data;
++++++++++++    PKEYBOARD_ATTRIBUTES Attributes;
++++++++ +++
++++++++ +++    /* get current stack location */
++++++++ +++    IoStack = IoGetCurrentIrpStackLocation(Irp);
++++++++ +++
++++++++ +++    DPRINT1("[KBDHID] InternalDeviceControl %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
++++++++ +++
++++++++ +++    /* get device extension */
++++++++ +++    DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
++++++++ +++
        -       ASSERT(FALSE);
++++++++++++    if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_QUERY_ATTRIBUTES)
++++++++++++    {
++++++++++++        /* verify output buffer length */
++++++++++++        if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUSE_ATTRIBUTES))
++++++++++++        {
++++++++++++            /* invalid request */
++++++++++++            DPRINT1("[MOUHID] IOCTL_MOUSE_QUERY_ATTRIBUTES Buffer too small\n");
++++++++++++            Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
++++++++++++            IoCompleteRequest(Irp, IO_NO_INCREMENT);
++++++++++++            return STATUS_BUFFER_TOO_SMALL;
++++++++++++        }
++++++++++++
++++++++++++        /* get output buffer */
++++++++++++        Attributes = (PKEYBOARD_ATTRIBUTES)Irp->AssociatedIrp.SystemBuffer;
++++++++++++
++++++++++++        /* copy attributes */
++++++++++++        RtlCopyMemory(Attributes, &DeviceExtension->Attributes, sizeof(KEYBOARD_ATTRIBUTES));
++++++++++++
++++++++++++         /* complete request */
++++++++++++         Irp->IoStatus.Information = sizeof(MOUSE_ATTRIBUTES);
++++++++++++         Irp->IoStatus.Status = STATUS_SUCCESS;
++++++++++++         IoCompleteRequest(Irp, IO_NO_INCREMENT);
++++++++++++         return STATUS_SUCCESS;
++++++++++++    }
++++++++++++    else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_KEYBOARD_CONNECT)
++++++++++++    {
++++++++++++         /* verify input buffer length */
++++++++++++         if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(CONNECT_DATA))
++++++++++++         {
++++++++++++             /* invalid request */
++++++++++++             Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
++++++++++++             IoCompleteRequest(Irp, IO_NO_INCREMENT);
++++++++++++             return STATUS_INVALID_PARAMETER;
++++++++++++         }
++++++++++++
++++++++++++         /* is it already connected */
++++++++++++         if (DeviceExtension->ClassService)
++++++++++++         {
++++++++++++             /* already connected */
++++++++++++             Irp->IoStatus.Status = STATUS_SHARING_VIOLATION;
++++++++++++             IoCompleteRequest(Irp, IO_NO_INCREMENT);
++++++++++++             return STATUS_SHARING_VIOLATION;
++++++++++++         }
++++++++++++
++++++++++++         /* get connect data */
++++++++++++         Data = (PCONNECT_DATA)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
++++++++ +++
++++++++++++         /* store connect details */
++++++++++++         DeviceExtension->ClassDeviceObject = Data->ClassDeviceObject;
++++++++++++         DeviceExtension->ClassService = Data->ClassService;
++++++++++++
++++++++++++         /* completed successfully */
++++++++++++         Irp->IoStatus.Status = STATUS_SUCCESS;
++++++++++++         IoCompleteRequest(Irp, IO_NO_INCREMENT);
++++++++++++         return STATUS_SUCCESS;
++++++++++++    }
++++++++++++    else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_KEYBOARD_DISCONNECT)
++++++++++++    {
++++++++++++        /* not implemented */
++++++++++++        Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
++++++++++++        IoCompleteRequest(Irp, IO_NO_INCREMENT);
++++++++++++        return STATUS_NOT_IMPLEMENTED;
++++++++++++    }
++++++++++++    else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_KEYBOARD_ENABLE)
++++++++++++    {
++++++++++++        /* not supported */
++++++++++++        Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
++++++++++++        IoCompleteRequest(Irp, IO_NO_INCREMENT);
++++++++++++        return STATUS_NOT_SUPPORTED;
++++++++++++    }
++++++++++++    else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_KEYBOARD_DISABLE)
++++++++++++    {
++++++++++++        /* not supported */
++++++++++++        Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
++++++++++++        IoCompleteRequest(Irp, IO_NO_INCREMENT);
++++++++++++        return STATUS_NOT_SUPPORTED;
++++++++++++    }
++++++++++++    else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_QUERY_INDICATORS)
++++++++++++    {
++++++++++++        /* not implemented */
++++++++++++        DPRINT1("IOCTL_KEYBOARD_QUERY_INDICATORS not implemented\n");
++++++++++++        ASSERT(FALSE);
++++++++++++        Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
++++++++++++        IoCompleteRequest(Irp, IO_NO_INCREMENT);
++++++++++++        return STATUS_NOT_IMPLEMENTED;
++++++++++++    }
++++++++++++    else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_QUERY_TYPEMATIC)
++++++++++++    {
++++++++++++        /* not implemented */
++++++++++++        DPRINT1("IOCTL_KEYBOARD_QUERY_TYPEMATIC not implemented\n");
++++++++++++        ASSERT(FALSE);
++++++++++++        Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
++++++++++++        IoCompleteRequest(Irp, IO_NO_INCREMENT);
++++++++++++        return STATUS_NOT_IMPLEMENTED;
++++++++++++    }
++++++++++++    else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_SET_INDICATORS)
++++++++++++    {
++++++++++++        /* not implemented */
++++++++++++        DPRINT1("IOCTL_KEYBOARD_SET_INDICATORS not implemented\n");
++++++++++++        ASSERT(FALSE);
++++++++++++        Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
++++++++++++        IoCompleteRequest(Irp, IO_NO_INCREMENT);
++++++++++++        return STATUS_NOT_IMPLEMENTED;
++++++++++++    }
++++++++++++    else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_SET_TYPEMATIC)
++++++++++++    {
++++++++++++        /* not implemented */
++++++++++++        DPRINT1("IOCTL_KEYBOARD_SET_TYPEMATIC not implemented\n");
++++++++++++        ASSERT(FALSE);
++++++++++++        Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
++++++++++++        IoCompleteRequest(Irp, IO_NO_INCREMENT);
++++++++++++        return STATUS_NOT_IMPLEMENTED;
++++++++++++    }
++++++++++++    else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION)
++++++++++++    {
++++++++++++        /* not implemented */
++++++++++++        DPRINT1("IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION not implemented\n");
++++++++++++        ASSERT(FALSE);
++++++++++++        Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
++++++++++++        IoCompleteRequest(Irp, IO_NO_INCREMENT);
++++++++++++        return STATUS_NOT_IMPLEMENTED;
++++++++++++    }
++++++++++++
++++++++++++    /* unknown control code */
++++++++++++    DPRINT1("[KBDHID] Unknown DeviceControl %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
++++++++ +++    /* unknown request not supported */
++++++++ +++    Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
++++++++ +++    IoCompleteRequest(Irp, IO_NO_INCREMENT);
++++++++ +++    return STATUS_NOT_SUPPORTED;
++++++++ +++}
++++++++ +++
++++++++ +++NTSTATUS
++++++++ +++NTAPI
++++++++ +++KbdHid_DeviceControl(
++++++++ +++    IN PDEVICE_OBJECT DeviceObject,
++++++++ +++    IN PIRP Irp)
++++++++ +++{
++++++++ +++    PKBDHID_DEVICE_EXTENSION DeviceExtension;
++++++++ +++
++++++++ +++    /* get device extension */
++++++++ +++    DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
++++++++ +++
++++++++ +++    /* skip stack location */
++++++++ +++    IoSkipCurrentIrpStackLocation(Irp);
++++++++ +++
++++++++ +++    /* pass and forget */
++++++++ +++    return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
++++++++ +++}
++++++++ +++
++++++++ +++NTSTATUS
++++++++ +++NTAPI
++++++++ +++KbdHid_Power(
++++++++ +++    IN PDEVICE_OBJECT DeviceObject,
++++++++ +++    IN PIRP Irp)
++++++++ +++{
++++++++ +++    UNIMPLEMENTED
++++++++ +++    return STATUS_NOT_IMPLEMENTED;
++++++++ +++}
++++++++ +++
++++++++ +++NTSTATUS
++++++++ +++KbdHid_SubmitRequest(
++++++++ +++    PDEVICE_OBJECT DeviceObject,
++++++++ +++    ULONG IoControlCode,
++++++++ +++    ULONG InputBufferSize,
++++++++ +++    PVOID InputBuffer,
++++++++ +++    ULONG OutputBufferSize,
++++++++ +++    PVOID OutputBuffer)
++++++++ +++{
++++++++ +++    KEVENT Event;
++++++++ +++    PKBDHID_DEVICE_EXTENSION DeviceExtension;
++++++++ +++    PIRP Irp;
++++++++ +++    NTSTATUS Status;
++++++++ +++    IO_STATUS_BLOCK IoStatus;
++++++++ +++
++++++++ +++    /* get device extension */
++++++++ +++    DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
++++++++ +++
++++++++ +++    /* init event */
++++++++ +++    KeInitializeEvent(&Event, NotificationEvent, FALSE);
++++++++ +++
++++++++ +++    /* build request */
++++++++ +++    Irp = IoBuildDeviceIoControlRequest(IoControlCode, DeviceExtension->NextDeviceObject, InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize, FALSE, &Event, &IoStatus);
++++++++ +++    if (!Irp)
++++++++ +++    {
++++++++ +++        /* no memory */
++++++++ +++        return STATUS_INSUFFICIENT_RESOURCES;
++++++++ +++    }
++++++++ +++
++++++++ +++    /* send request */
++++++++ +++    Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
++++++++ +++    if (Status == STATUS_PENDING)
++++++++ +++    {
++++++++ +++        /* wait for request to complete */
++++++++ +++        KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
++++++++ +++        Status = IoStatus.Status;
++++++++ +++    }
++++++++ +++
++++++++ +++    /* done */
++++++++ +++    return Status;
++++++++ +++}
++++++++ +++
++++++++ +++NTSTATUS
++++++++ +++NTAPI
++++++++ +++KbdHid_StartDevice(
++++++++ +++    IN PDEVICE_OBJECT DeviceObject)
++++++++ +++{
++++++++ +++    NTSTATUS Status;
++++++++ +++    ULONG Buttons;
++++++++ +++    HID_COLLECTION_INFORMATION Information;
++++++++ +++    PHIDP_PREPARSED_DATA PreparsedData;
++++++++ +++    HIDP_CAPS Capabilities;
++++++++ +++    PKBDHID_DEVICE_EXTENSION DeviceExtension;
++++++++ +++    PUSAGE_AND_PAGE Buffer;
++++++++ +++
++++++++ +++    /* get device extension */
++++++++ +++    DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
++++++++ +++
++++++++ +++    /* query collection information */
++++++++ +++    Status = KbdHid_SubmitRequest(DeviceObject, IOCTL_HID_GET_COLLECTION_INFORMATION, 0, NULL, sizeof(HID_COLLECTION_INFORMATION), &Information);
++++++++ +++    if (!NT_SUCCESS(Status))
++++++++ +++    {
++++++++ +++        /* failed to query collection information */
++++++++ +++        DPRINT1("[KBDHID] failed to obtain collection information with %x\n", Status);
++++++++ +++        return Status;
++++++++ +++    }
++++++++ +++
++++++++ +++    /* lets allocate space for preparsed data */
++++++++ +++    PreparsedData = (PHIDP_PREPARSED_DATA)ExAllocatePool(NonPagedPool, Information.DescriptorSize);
++++++++ +++    if (!PreparsedData)
++++++++ +++    {
++++++++ +++        /* no memory */
++++++++ +++        DPRINT1("[KBDHID] no memory size %u\n", Information.DescriptorSize);
++++++++ +++        return STATUS_INSUFFICIENT_RESOURCES;
++++++++ +++    }
++++++++ +++
++++++++ +++    /* now obtain the preparsed data */
++++++++ +++    Status = KbdHid_SubmitRequest(DeviceObject, IOCTL_HID_GET_COLLECTION_DESCRIPTOR, 0, NULL, Information.DescriptorSize, PreparsedData);
++++++++ +++    if (!NT_SUCCESS(Status))
++++++++ +++    {
++++++++ +++        /* failed to get preparsed data */
++++++++ +++        DPRINT1("[KBDHID] failed to obtain collection information with %x\n", Status);
++++++++ +++        ExFreePool(PreparsedData);
++++++++ +++        return Status;
++++++++ +++    }
++++++++ +++
++++++++ +++    /* lets get the caps */
++++++++ +++    Status = HidP_GetCaps(PreparsedData, &Capabilities);
++++++++ +++    if (Status != HIDP_STATUS_SUCCESS)
++++++++ +++    {
++++++++ +++        /* failed to get capabilities */
++++++++ +++        DPRINT1("[KBDHID] failed to obtain caps with %x\n", Status);
++++++++ +++        ExFreePool(PreparsedData);
++++++++ +++        return Status;
++++++++ +++    }
++++++++ +++
++++++++ +++    DPRINT1("[KBDHID] Usage %x UsagePage %x InputReportLength %lu\n", Capabilities.Usage, Capabilities.UsagePage, Capabilities.InputReportByteLength);
++++++++ +++
++++++++ +++    /* init input report*/
++++++++ +++    DeviceExtension->ReportLength = Capabilities.InputReportByteLength;
++++++++ +++    ASSERT(DeviceExtension->ReportLength);
++++++++ +++    DeviceExtension->Report = (PUCHAR)ExAllocatePool(NonPagedPool, DeviceExtension->ReportLength);
++++++++ +++    ASSERT(DeviceExtension->Report);
++++++++ +++    RtlZeroMemory(DeviceExtension->Report, DeviceExtension->ReportLength);
++++++++ +++
++++++++ +++    /* build mdl */
++++++++ +++    DeviceExtension->ReportMDL = IoAllocateMdl(DeviceExtension->Report, DeviceExtension->ReportLength, FALSE, FALSE, NULL);
++++++++ +++    ASSERT(DeviceExtension->ReportMDL);
++++++++ +++
++++++++ +++    /* init mdl */
++++++++ +++    MmBuildMdlForNonPagedPool(DeviceExtension->ReportMDL);
++++++++ +++
++++++++ +++    /* get max number of buttons */
++++++++ +++    Buttons = HidP_MaxUsageListLength(HidP_Input, HID_USAGE_PAGE_BUTTON, PreparsedData);
++++++++ +++    DPRINT1("[KBDHID] Buttons %lu\n", Buttons);
++++++++ +++    ASSERT(Buttons > 0);
++++++++ +++
++++++++ +++    /* now allocate an array for those buttons */
++++++++ +++    Buffer = (PUSAGE_AND_PAGE)ExAllocatePool(NonPagedPool, sizeof(USAGE_AND_PAGE) * 4 * Buttons);
++++++++ +++    if (!Buffer)
++++++++ +++    {
++++++++ +++        /* no memory */
++++++++ +++        ExFreePool(PreparsedData);
++++++++ +++        return STATUS_INSUFFICIENT_RESOURCES;
++++++++ +++    }
++++++++ +++
++++++++ +++    /* init usage lists */
++++++++ +++    RtlZeroMemory(Buffer, sizeof(USAGE_AND_PAGE) * 4 * Buttons);
++++++++ +++    DeviceExtension->CurrentUsageList = Buffer;
++++++++ +++    Buffer += Buttons;
++++++++ +++    DeviceExtension->PreviousUsageList = Buffer;
++++++++ +++    Buffer += Buttons;
++++++++ +++    DeviceExtension->MakeUsageList = Buffer;
++++++++ +++    Buffer += Buttons;
++++++++ +++    DeviceExtension->BreakUsageList = Buffer;
++++++++ +++
++++++++ +++    //
++++++++ +++    // FIMXE: implement device hacks
++++++++ +++    //
++++++++ +++    // UsageMappings
++++++++ +++    // KeyboardTypeOverride
++++++++ +++    // KeyboardSubTypeOverride
++++++++ +++    // KeyboardNumberTotalKeysOverride
++++++++ +++    // KeyboardNumberFunctionKeysOverride
++++++++ +++    // KeyboardNumberIndicatorsOverride
++++++++ +++
++++++++ +++    /* store number of buttons */
++++++++ +++    DeviceExtension->UsageListLength = (USHORT)Buttons;
++++++++ +++
++++++++ +++    /* store preparsed data */
++++++++ +++    DeviceExtension->PreparsedData = PreparsedData;
++++++++ +++
++++++++ +++    /* completed successfully */
++++++++ +++    return STATUS_SUCCESS;
++++++++ +++}
++++++++ +++
++++++++ +++NTSTATUS
++++++++ +++NTAPI
++++++++ +++KbdHid_StartDeviceCompletion(
++++++++ +++    IN PDEVICE_OBJECT  DeviceObject,
++++++++ +++    IN PIRP  Irp,
++++++++ +++    IN PVOID  Context)
++++++++ +++{
++++++++ +++    KeSetEvent((PKEVENT)Context, 0, FALSE);
++++++++ +++    return STATUS_MORE_PROCESSING_REQUIRED;
++++++++ +++}
++++++++ +++
++++++++ +++NTSTATUS
++++++++ +++NTAPI
++++++++ +++KbdHid_Flush(
++++++++ +++    IN PDEVICE_OBJECT DeviceObject,
++++++++ +++    IN PIRP Irp)
++++++++ +++{
++++++++ +++    PIO_STACK_LOCATION IoStack;
++++++++ +++    PKBDHID_DEVICE_EXTENSION DeviceExtension;
++++++++ +++
++++++++ +++    /* get device extension */
++++++++ +++    DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
++++++++ +++
++++++++ +++    /* skip current stack location */
++++++++ +++    IoSkipCurrentIrpStackLocation(Irp);
++++++++ +++
++++++++ +++    /* get next stack location */
++++++++ +++    IoStack = IoGetNextIrpStackLocation(Irp);
++++++++ +++
++++++++ +++    /* change request to hid flush queue request */
++++++++ +++    IoStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
++++++++ +++    IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_HID_FLUSH_QUEUE;
++++++++ +++
++++++++ +++    /* call device */
++++++++ +++    return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
++++++++ +++}
++++++++ +++
++++++++ +++NTSTATUS
++++++++ +++NTAPI
++++++++ +++KbdHid_Pnp(
++++++++ +++    IN PDEVICE_OBJECT DeviceObject,
++++++++ +++    IN PIRP Irp)
++++++++ +++{
++++++++ +++    PIO_STACK_LOCATION IoStack;
++++++++ +++    KEVENT Event;
++++++++ +++    NTSTATUS Status;
++++++++ +++    PKBDHID_DEVICE_EXTENSION DeviceExtension;
++++++++ +++
++++++++ +++    /* get device extension */
++++++++ +++    DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
++++++++ +++
++++++++ +++    /* get current irp stack */
++++++++ +++    IoStack = IoGetCurrentIrpStackLocation(Irp);
++++++++ +++    DPRINT1("[KBDHID] IRP_MJ_PNP Request: %x\n", IoStack->MinorFunction);
++++++++ +++
++++++++ +++    if (IoStack->MinorFunction == IRP_MN_STOP_DEVICE || IoStack->MinorFunction == IRP_MN_CANCEL_REMOVE_DEVICE || IoStack->MinorFunction == IRP_MN_QUERY_STOP_DEVICE || IoStack->MinorFunction == IRP_MN_CANCEL_STOP_DEVICE)
++++++++ +++    {
++++++++ +++        /* indicate success */
++++++++ +++        Irp->IoStatus.Status = STATUS_SUCCESS;
++++++++ +++
++++++++ +++        /* skip irp stack location */
++++++++ +++        IoSkipCurrentIrpStackLocation(Irp);
++++++++ +++
++++++++ +++        /* dispatch to lower device */
++++++++ +++        return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
++++++++ +++    }
++++++++ +++    else if (IoStack->MinorFunction == IRP_MN_REMOVE_DEVICE)
++++++++ +++    {
++++++++ +++        /* FIXME synchronization */
++++++++ +++
++++++++ +++        /* cancel irp */
++++++++ +++        IoCancelIrp(DeviceExtension->Irp);
++++++++ +++
++++++++ +++        /* indicate success */
++++++++ +++        Irp->IoStatus.Status = STATUS_SUCCESS;
++++++++ +++
++++++++ +++        /* skip irp stack location */
++++++++ +++        IoSkipCurrentIrpStackLocation(Irp);
++++++++ +++
++++++++ +++        /* dispatch to lower device */
++++++++ +++        Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
++++++++ +++
++++++++ +++        IoFreeIrp(DeviceExtension->Irp);
++++++++ +++        IoDetachDevice(DeviceExtension->NextDeviceObject);
++++++++ +++        IoDeleteDevice(DeviceObject);
++++++++ +++        return Status;
++++++++ +++    }
++++++++ +++    else if (IoStack->MinorFunction == IRP_MN_START_DEVICE)
++++++++ +++    {
++++++++ +++        /* init event */
++++++++ +++        KeInitializeEvent(&Event, NotificationEvent, FALSE);
++++++++ +++
++++++++ +++        /* copy stack location */
++++++++ +++        IoCopyCurrentIrpStackLocationToNext (Irp);
++++++++ +++
++++++++ +++        /* set completion routine */
++++++++ +++        IoSetCompletionRoutine(Irp, KbdHid_StartDeviceCompletion, &Event, TRUE, TRUE, TRUE);
++++++++ +++        Irp->IoStatus.Status = 0;
++++++++ +++
++++++++ +++        /* pass request */
++++++++ +++        Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
++++++++ +++        if (Status == STATUS_PENDING)
++++++++ +++        {
++++++++ +++            KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
++++++++ +++            Status = Irp->IoStatus.Status;
++++++++ +++        }
++++++++ +++
++++++++ +++        if (!NT_SUCCESS(Status))
++++++++ +++        {
++++++++ +++            /* failed */
++++++++ +++            Irp->IoStatus.Status = Status;
++++++++ +++            IoCompleteRequest(Irp, IO_NO_INCREMENT);
++++++++ +++            return Status;
++++++++ +++        }
++++++++ +++
++++++++ +++        /* lets start the device */
++++++++ +++        Status = KbdHid_StartDevice(DeviceObject);
++++++++ +++        DPRINT1("KbdHid_StartDevice %x\n", Status);
++++++++ +++
++++++++ +++        /* complete request */
++++++++ +++        Irp->IoStatus.Status = Status;
++++++++ +++        IoCompleteRequest(Irp, IO_NO_INCREMENT);
++++++++ +++
++++++++ +++        /* done */
++++++++ +++        return Status;
++++++++ +++    }
++++++++ +++    else
++++++++ +++    {
++++++++ +++        /* skip irp stack location */
++++++++ +++        IoSkipCurrentIrpStackLocation(Irp);
++++++++ +++
++++++++ +++        /* dispatch to lower device */
++++++++ +++        return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
++++++++ +++    }
++++++++ +++}
++++++++ +++
++++++++ +++NTSTATUS
++++++++ +++NTAPI
++++++++ +++KbdHid_AddDevice(
++++++++ +++    IN PDRIVER_OBJECT DriverObject,
++++++++ +++    IN PDEVICE_OBJECT PhysicalDeviceObject)
++++++++ +++{
++++++++ +++    NTSTATUS Status;
++++++++ +++    PDEVICE_OBJECT DeviceObject, NextDeviceObject;
++++++++ +++    PKBDHID_DEVICE_EXTENSION DeviceExtension;
++++++++ +++    POWER_STATE State;
++++++++ +++
++++++++ +++    /* create device object */
++++++++ +++    Status = IoCreateDevice(DriverObject, sizeof(KBDHID_DEVICE_EXTENSION), NULL, FILE_DEVICE_KEYBOARD, 0, FALSE, &DeviceObject);
++++++++ +++    if (!NT_SUCCESS(Status))
++++++++ +++    {
++++++++ +++        /* failed to create device object */
++++++++ +++        return Status;
++++++++ +++    }
++++++++ +++
++++++++ +++    /* now attach it */
++++++++ +++    NextDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
++++++++ +++    if (!NextDeviceObject)
++++++++ +++    {
++++++++ +++        /* failed to attach */
++++++++ +++        IoDeleteDevice(DeviceObject);
++++++++ +++        return STATUS_DEVICE_NOT_CONNECTED;
++++++++ +++    }
++++++++ +++
++++++++ +++    /* get device extension */
++++++++ +++    DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
++++++++ +++
++++++++ +++    /* zero extension */
++++++++ +++    RtlZeroMemory(DeviceExtension, sizeof(KBDHID_DEVICE_EXTENSION));
++++++++ +++
++++++++ +++    /* init device extension */
++++++++ +++    DeviceExtension->NextDeviceObject = NextDeviceObject;
++++++++ +++    KeInitializeEvent(&DeviceExtension->ReadCompletionEvent, NotificationEvent, FALSE);
++++++++++++
++++++++++++    /* init keyboard attributes */
++++++++++++    DeviceExtension->Attributes.KeyboardIdentifier.Type = KEYBOARD_TYPE_UNKNOWN;
++++++++++++    DeviceExtension->Attributes.KeyboardIdentifier.Subtype = MICROSOFT_KBD_101_TYPE;
++++++++++++    DeviceExtension->Attributes.NumberOfFunctionKeys = MICROSOFT_KBD_FUNC;
++++++++++++    DeviceExtension->Attributes.NumberOfIndicators = 3; // caps, num lock, scroll lock
++++++++++++    DeviceExtension->Attributes.NumberOfKeysTotal = 101;
++++++++++++    DeviceExtension->Attributes.InputDataQueueLength = 1;
++++++++++++    DeviceExtension->Attributes.KeyRepeatMinimum.Rate = KEYBOARD_TYPEMATIC_RATE_MINIMUM;
++++++++++++    DeviceExtension->Attributes.KeyRepeatMinimum.Delay = KEYBOARD_TYPEMATIC_DELAY_MINIMUM;
++++++++++++    DeviceExtension->Attributes.KeyRepeatMaximum.Rate = KEYBOARD_TYPEMATIC_RATE_DEFAULT;
++++++++++++    DeviceExtension->Attributes.KeyRepeatMaximum.Delay = KEYBOARD_TYPEMATIC_DELAY_MAXIMUM;
++++++++++++
++++++++++++    /* allocate irp */
++++++++ +++    DeviceExtension->Irp = IoAllocateIrp(NextDeviceObject->StackSize, FALSE);
++++++++ +++
++++++++ +++    /* FIXME handle allocation error */
++++++++ +++    ASSERT(DeviceExtension->Irp);
++++++++ +++
++++++++ +++    /* set power state to D0 */
++++++++ +++    State.DeviceState =  PowerDeviceD0;
++++++++ +++    PoSetPowerState(DeviceObject, DevicePowerState, State);
++++++++ +++
++++++++ +++    /* init device object */
++++++++ +++    DeviceObject->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
++++++++ +++    DeviceObject->Flags  &= ~DO_DEVICE_INITIALIZING;
++++++++ +++
++++++++ +++    /* completed successfully */
++++++++ +++    return STATUS_SUCCESS;
++++++++ +++}
++++++++ +++
++++++++ +++VOID
++++++++ +++NTAPI
++++++++ +++KbdHid_Unload(
++++++++ +++    IN PDRIVER_OBJECT DriverObject)
++++++++ +++{
++++++++ +++    UNIMPLEMENTED
++++++++ +++}
++++++++ +++
++++++++ +++
++++++++ +++NTSTATUS
++++++++ +++NTAPI
++++++++ +++DriverEntry(
++++++++ +++    IN PDRIVER_OBJECT DriverObject,
++++++++ +++    IN PUNICODE_STRING RegPath)
++++++++ +++{
++++++++ +++    /* initialize driver object */
++++++++ +++    DriverObject->DriverUnload = KbdHid_Unload;
++++++++ +++    DriverObject->DriverExtension->AddDevice = KbdHid_AddDevice;
++++++++ +++    DriverObject->MajorFunction[IRP_MJ_CREATE] = KbdHid_Create;
++++++++ +++    DriverObject->MajorFunction[IRP_MJ_CLOSE] = KbdHid_Close;
++++++++ +++    DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = KbdHid_Flush;
++++++++ +++    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = KbdHid_DeviceControl;
++++++++ +++    DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = KbdHid_InternalDeviceControl;
++++++++ +++    DriverObject->MajorFunction[IRP_MJ_POWER] = KbdHid_Power;
++++++++ +++    DriverObject->MajorFunction[IRP_MJ_PNP] = KbdHid_Pnp;
++++++++ +++    DriverObject->DriverUnload = KbdHid_Unload;
++++++++ +++    DriverObject->DriverExtension->AddDevice = KbdHid_AddDevice;
++++++++ +++
++++++++ +++    /* done */
++++++++ +++    return STATUS_SUCCESS;
++++++++ +++}
index 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000,8add178,0000000,0000000,0000000..0324ad4
mode 000000,000000,000000,000000,000000,000000,000000,000000,100644,000000,000000,000000..100644
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
@@@@@@@@@@@@@ -1,0 -1,0 -1,0 -1,0 -1,0 -1,0 -1,0 -1,0 -1,106 -1,0 -1,0 -1,0 +1,133 @@@@@@@@@@@@@
        -   #include <ntddmou.h>
++++++++ +++#pragma once
++++++++ +++
++++++++ +++#define _HIDPI_NO_FUNCTION_MACROS_
++++++++ +++#include <ntddk.h>
++++++++ +++#include <hidclass.h>
++++++++ +++#include <hidpddi.h>
++++++++ +++#include <hidpi.h>
++++++++ +++#include <debug.h>
        -       PVOID PreparsedData;
++++++++ +++#include <kbdmou.h>
++++++++++++//#include <kbd.h>
++++++++++++#include <ntddkbd.h>
++++++++ +++#include <debug.h>
++++++++ +++
++++++++ +++
++++++++ +++typedef struct
++++++++ +++{
++++++++ +++    //
++++++++ +++    // lower device object
++++++++ +++    //
++++++++ +++    PDEVICE_OBJECT NextDeviceObject;
++++++++ +++
++++++++ +++    //
++++++++ +++    // irp which is used for reading input reports
++++++++ +++    //
++++++++ +++    PIRP Irp;
++++++++ +++
++++++++ +++    //
++++++++ +++    // event 
++++++++ +++    //
++++++++ +++    KEVENT ReadCompletionEvent;
++++++++ +++
++++++++ +++    //
++++++++ +++    // device object for class callback
++++++++ +++    //
++++++++ +++    PDEVICE_OBJECT ClassDeviceObject;
++++++++ +++
++++++++ +++    //
++++++++ +++    // class callback
++++++++ +++    //
++++++++ +++    PVOID ClassService;
++++++++ +++
++++++++ +++    //
++++++++ +++    // usage list length
++++++++ +++    //
++++++++ +++    USHORT UsageListLength;
++++++++ +++
++++++++ +++    //
++++++++ +++    // current usage list length
++++++++ +++    //
++++++++ +++    PUSAGE_AND_PAGE CurrentUsageList;
++++++++ +++
++++++++ +++    //
++++++++ +++    // previous usage list
++++++++ +++    //
++++++++ +++    PUSAGE_AND_PAGE PreviousUsageList;
++++++++ +++
++++++++ +++    //
++++++++ +++    // removed usage item list
++++++++ +++    //
++++++++ +++    PUSAGE_AND_PAGE BreakUsageList;
++++++++ +++
++++++++ +++    //
++++++++ +++    // new item usage list
++++++++ +++    //
++++++++ +++    PUSAGE_AND_PAGE MakeUsageList;
++++++++ +++
++++++++ +++    //
++++++++ +++    // preparsed data
++++++++ +++    //
        -       PUCHAR Report;
++++++++++++    PHIDP_PREPARSED_DATA PreparsedData;
++++++++ +++
++++++++ +++    //
++++++++ +++    // mdl for reading input report
++++++++ +++    //
++++++++ +++    PMDL ReportMDL;
++++++++ +++
++++++++ +++    //
++++++++ +++    // input report buffer
++++++++ +++    //
++++++++++++    PCHAR Report;
++++++++ +++
++++++++ +++    //
++++++++ +++    // input report length
++++++++ +++    //
++++++++ +++    ULONG ReportLength;
++++++++ +++
++++++++ +++    //
++++++++ +++    // file object the device is reading reports from
++++++++ +++    //
++++++++ +++    PFILE_OBJECT FileObject;
++++++++ +++
++++++++ +++    //
++++++++ +++    // report read is active
++++++++ +++    //
++++++++ +++    UCHAR ReadReportActive;
++++++++ +++
++++++++ +++    //
++++++++ +++    // stop reading flag
++++++++ +++    //
++++++++ +++    UCHAR StopReadReport;
++++++++ +++
++++++++++++    //
++++++++++++    // keyboard attributes
++++++++++++    //
++++++++++++    KEYBOARD_ATTRIBUTES Attributes;
++++++++++++
++++++++++++    //
++++++++++++    // keyboard modifier state
++++++++++++    //
++++++++++++    HIDP_KEYBOARD_MODIFIER_STATE ModifierState;
++++++++++++
++++++++ +++}KBDHID_DEVICE_EXTENSION, *PKBDHID_DEVICE_EXTENSION;
++++++++ +++
++++++++++++/* defaults from kbfiltr.h */
++++++++++++#define KEYBOARD_TYPEMATIC_RATE_MINIMUM 2 
++++++++++++#define KEYBOARD_TYPEMATIC_RATE_MAXIMUM 30 
++++++++++++#define KEYBOARD_TYPEMATIC_RATE_DEFAULT 30 
++++++++++++#define KEYBOARD_TYPEMATIC_DELAY_MINIMUM 250 
++++++++++++#define KEYBOARD_TYPEMATIC_DELAY_MAXIMUM 1000 
++++++++++++#define KEYBOARD_TYPEMATIC_DELAY_DEFAULT 250 
++++++++++++
++++++++++++/* FIXME: write kbd.h */
++++++++++++#define MICROSOFT_KBD_FUNC              12
++++++++++++#define KEYBOARD_TYPE_UNKNOWN   (0x51)
++++++++++++#define MICROSOFT_KBD_101_TYPE           0
++++++++++++
++++++++++++
++++++++++++
++++++++ +++
++++++++ +++NTSTATUS
++++++++ +++KbdHid_InitiateRead(
++++++++ +++    IN PKBDHID_DEVICE_EXTENSION DeviceExtension);
++++++++++++
@@@@@@@@@@@@@ -1,6 -1,6 -1,6 -1,6 -1,6 -1,6 -1,6 -1,6 -1,7 -1,6 -1,7 -1,7 +1,7 @@@@@@@@@@@@@
            
            add_subdirectory(chew)
            add_subdirectory(csq)
++++++++ +  add_subdirectory(hidparser)
            add_subdirectory(ip)
 -----------add_subdirectory(oskittcp)
 +++++++++++add_subdirectory(lwip)
            add_subdirectory(sound)
index 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000,45765f0,0000000,45765f0,45765f0..6c39d10
mode 000000,000000,000000,000000,000000,000000,000000,000000,100644,000000,100644,100644..100644
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
@@@@@@@@@@@@@ -1,0 -1,0 -1,0 -1,0 -1,0 -1,0 -1,0 -1,0 -1,953 -1,0 -1,953 -1,953 +1,1077 @@@@@@@@@@@@@
++++++++ +  /*
++++++++ +   * PROJECT:     ReactOS HID Parser Library
++++++++ +   * LICENSE:     GPL - See COPYING in the top level directory
++++++++ +   * FILE:        lib/drivers/hidparser/api.c
++++++++ +   * PURPOSE:     HID Parser
++++++++ +   * PROGRAMMERS:
++++++++ +   *              Michael Martin (michael.martin@reactos.org)
++++++++ +   *              Johannes Anderwald (johannes.anderwald@reactos.org)
++++++++ +   */
++++++++ +  
++++++++ +  
++++++++ +  #include "parser.h"
++++++++ +  
++++++++++++static ULONG KeyboardScanCodes[256] =
++++++++++++{
++++++++++++    0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
++++++++++++    50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,
++++++++++++    4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14, 15, 57, 12, 13, 26,
++++++++++++    27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
++++++++++++    65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
++++++++++++    105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
++++++++++++    72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
++++++++++++    191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
++++++++++++    115,114,  0,  0,  0,121,  0, 89, 93,124, 92, 94, 95,  0,  0,  0,
++++++++++++    122,123, 90, 91, 85,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++++++++++++    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++++++++++++    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++++++++++++    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++++++++++++    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++++++++++++    29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
++++++++++++    150,158,159,128,136,177,178,176,142,152,173,140
++++++++++++};
++++++++++++
++++++++++++
++++++++ +  
++++++++ +  ULONG
++++++++ +  HidParser_NumberOfTopCollections(
++++++++ +      IN PHID_PARSER Parser)
++++++++ +  {
++++++++ +      PHID_PARSER_CONTEXT ParserContext;
++++++++ +  
++++++++ +      //
++++++++ +      // get parser context
++++++++ +      //
++++++++ +      ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
++++++++ +  
++++++++ +      //
++++++++ +      // sanity checks
++++++++ +      //
++++++++ +      ASSERT(ParserContext);
++++++++ +      ASSERT(ParserContext->RootCollection);
++++++++ +      ASSERT(ParserContext->RootCollection->NodeCount);
++++++++ +  
++++++++ +      //
++++++++ +      // number of top collections
++++++++ +      //
++++++++ +      return ParserContext->RootCollection->NodeCount;
++++++++ +  }
++++++++ +  
++++++++ +  PHID_COLLECTION
++++++++ +  HidParser_GetCollection(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      IN ULONG CollectionNumber)
++++++++ +  {
++++++++ +      PHID_PARSER_CONTEXT ParserContext;
++++++++ +  
++++++++ +      //
++++++++ +      // get parser context
++++++++ +      //
++++++++ +      ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
++++++++ +  
++++++++ +      //
++++++++ +      // sanity checks
++++++++ +      //
++++++++ +      ASSERT(ParserContext);
++++++++ +      ASSERT(ParserContext->RootCollection);
++++++++ +      ASSERT(ParserContext->RootCollection->NodeCount);
++++++++ +  
++++++++ +      //
++++++++ +      // is collection index out of bounds
++++++++ +      //
++++++++ +      if (CollectionNumber < ParserContext->RootCollection->NodeCount)
++++++++ +      {
++++++++ +          //
++++++++ +          // valid collection
++++++++ +          //
++++++++ +          return ParserContext->RootCollection->Nodes[CollectionNumber];
++++++++ +      }
++++++++ +  
++++++++ +      //
++++++++ +      // no such collection
++++++++ +      //
++++++++ +      Parser->Debug("HIDPARSE] No such collection %lu\n", CollectionNumber);
++++++++ +      return NULL;
++++++++ +  }
++++++++ +  
++++++++ +  PHID_REPORT
++++++++ +  HidParser_GetReportByType(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      IN ULONG ReportType)
++++++++ +  {
++++++++ +      PHID_PARSER_CONTEXT ParserContext;
++++++++ +      ULONG Index;
++++++++ +      ULONG ReportCount = 0;
++++++++ +  
++++++++ +      //
++++++++ +      // get parser context
++++++++ +      //
++++++++ +      ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
++++++++ +  
++++++++ +      //
++++++++ +      // sanity checks
++++++++ +      //
++++++++ +      ASSERT(ParserContext);
++++++++ +  
++++++++ +      //
++++++++ +      // FIXME support multiple top collecions
++++++++ +      //
++++++++ +      ASSERT(ParserContext->RootCollection->NodeCount == 1);
++++++++ +      for(Index = 0; Index < ParserContext->ReportCount; Index++)
++++++++ +      {
++++++++ +          //
++++++++ +          // check if the report type match
++++++++ +          //
++++++++ +          if (ParserContext->Reports[Index]->Type == ReportType)
++++++++ +          {
++++++++ +              //
++++++++ +              // found report
++++++++ +              //
++++++++ +              return ParserContext->Reports[Index];
++++++++ +          }
++++++++ +      }
++++++++ +  
++++++++ +      //
++++++++ +      // report not found
++++++++ +      //
++++++++ +      return NULL;
++++++++ +  }
++++++++ +  
++++++++ +  
++++++++ +  ULONG
++++++++ +  HidParser_NumberOfReports(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      IN ULONG ReportType)
++++++++ +  {
++++++++ +      PHID_PARSER_CONTEXT ParserContext;
++++++++ +      ULONG Index;
++++++++ +      ULONG ReportCount = 0;
++++++++ +  
++++++++ +      //
++++++++ +      // get parser context
++++++++ +      //
++++++++ +      ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
++++++++ +  
++++++++ +      //
++++++++ +      // sanity checks
++++++++ +      //
++++++++ +      ASSERT(ParserContext);
++++++++ +  
++++++++ +      //
++++++++ +      // FIXME support multiple top collecions
++++++++ +      //
++++++++ +      ASSERT(ParserContext->RootCollection->NodeCount == 1);
++++++++ +      for(Index = 0; Index < ParserContext->ReportCount; Index++)
++++++++ +      {
++++++++ +          //
++++++++ +          // check if the report type match
++++++++ +          //
++++++++ +          if (ParserContext->Reports[Index]->Type == ReportType)
++++++++ +          {
++++++++ +              //
++++++++ +              // found report
++++++++ +              //
++++++++ +              ReportCount++;
++++++++ +          }
++++++++ +      }
++++++++ +  
++++++++ +      //
++++++++ +      // done
++++++++ +      //
++++++++ +      return ReportCount;
++++++++ +  }
++++++++ +  
++++++++ +  HIDPARSER_STATUS
++++++++ +  HidParser_GetCollectionUsagePage(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      IN ULONG CollectionIndex,
++++++++ +      OUT PUSHORT Usage,
++++++++ +      OUT PUSHORT UsagePage)
++++++++ +  {
++++++++ +      PHID_COLLECTION Collection;
++++++++ +  
++++++++ +      //
++++++++ +      // find collection
++++++++ +      //
++++++++ +      Collection = HidParser_GetCollection(Parser, CollectionIndex);
++++++++ +      if (!Collection)
++++++++ +      {
++++++++ +          //
++++++++ +          // collection not found
++++++++ +          //
++++++++ +          return HIDPARSER_STATUS_COLLECTION_NOT_FOUND;
++++++++ +      }
++++++++ +  
++++++++ +      //
++++++++ +      // store result
++++++++ +      //
++++++++ +      *UsagePage = (Collection->Usage >> 16);
++++++++ +      *Usage = (Collection->Usage & 0xFFFF);
++++++++ +      return HIDPARSER_STATUS_SUCCESS;
++++++++ +  }
++++++++ +  
++++++++ +  ULONG
++++++++ +  HidParser_GetReportLength(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      IN ULONG ReportType)
++++++++ +  {
++++++++ +      PHID_PARSER_CONTEXT ParserContext;
++++++++ +      PHID_REPORT Report;
++++++++ +      ULONG ReportLength;
++++++++ +  
++++++++ +      //
++++++++ +      // get parser context
++++++++ +      //
++++++++ +      ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
++++++++ +  
++++++++ +      //
++++++++ +      // sanity checks
++++++++ +      //
++++++++ +      ASSERT(ParserContext);
++++++++ +  
++++++++ +      //
++++++++ +      // FIXME support multiple top collecions
++++++++ +      //
++++++++ +      ASSERT(ParserContext->RootCollection->NodeCount == 1);
++++++++ +  
++++++++ +      //
++++++++ +      // get first report
++++++++ +      //
++++++++ +      Report = HidParser_GetReportByType(Parser, ReportType);
++++++++ +      if (!Report)
++++++++ +      {
++++++++ +          //
++++++++ +          // no report found
++++++++ +          //
++++++++ +          return 0;
++++++++ +      }
++++++++ +  
++++++++ +      //
++++++++ +      // get report length
++++++++ +      //
++++++++ +      ReportLength = Report->ReportSize;
++++++++ +  
++++++++ +      //
++++++++ +      // done
++++++++ +      //
++++++++ +      if (ReportLength)
++++++++ +      {
++++++++ +          //
++++++++ +          // byte aligned length
++++++++ +          //
++++++++ +          ASSERT(ReportLength % 8 == 0);
++++++++ +          return ReportLength / 8;
++++++++ +      }
++++++++ +      return ReportLength;
++++++++ +  }
++++++++ +  
++++++++ +  UCHAR
++++++++ +  HidParser_IsReportIDUsed(
++++++++ +      IN PHID_PARSER Parser)
++++++++ +  {
++++++++ +      PHID_PARSER_CONTEXT ParserContext;
++++++++ +  
++++++++ +      //
++++++++ +      // get parser context
++++++++ +      //
++++++++ +      ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
++++++++ +  
++++++++ +      //
++++++++ +      // sanity checks
++++++++ +      //
++++++++ +      ASSERT(ParserContext);
++++++++ +  
++++++++ +      //
++++++++ +      // return flag
++++++++ +      //
++++++++ +      return ParserContext->UseReportIDs;
++++++++ +  }
++++++++ +  
++++++++ +  ULONG
++++++++ +  HidParser_GetReportItemCountFromReportType(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      IN ULONG ReportType)
++++++++ +  {
++++++++ +      PHID_PARSER_CONTEXT ParserContext;
++++++++ +      PHID_REPORT Report;
++++++++ +  
++++++++ +      //
++++++++ +      // get parser context
++++++++ +      //
++++++++ +      ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
++++++++ +  
++++++++ +      //
++++++++ +      // sanity checks
++++++++ +      //
++++++++ +      ASSERT(ParserContext);
++++++++ +  
++++++++ +      //
++++++++ +      // FIXME support multiple top collecions
++++++++ +      //
++++++++ +      ASSERT(ParserContext->RootCollection->NodeCount == 1);
++++++++ +  
++++++++ +      //
++++++++ +      // get report
++++++++ +      //
++++++++ +      Report = HidParser_GetReportByType(Parser, ReportType);
++++++++ +      if (!Report)
++++++++ +      {
++++++++ +          //
++++++++ +          // no such report
++++++++ +          //
++++++++ +          return 0;
++++++++ +      }
++++++++ +  
++++++++ +      //
++++++++ +      // return report item count
++++++++ +      //
++++++++ +      return Report->ItemCount;
++++++++ +  }
++++++++ +  
++++++++ +  
++++++++ +  ULONG
++++++++ +  HidParser_GetReportItemTypeCountFromReportType(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      IN ULONG ReportType,
++++++++ +      IN ULONG bData)
++++++++ +  {
++++++++ +      PHID_PARSER_CONTEXT ParserContext;
++++++++ +      ULONG Index;
++++++++ +      PHID_REPORT Report;
++++++++ +      ULONG ItemCount = 0;
++++++++ +  
++++++++ +      //
++++++++ +      // get parser context
++++++++ +      //
++++++++ +      ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
++++++++ +  
++++++++ +      //
++++++++ +      // sanity checks
++++++++ +      //
++++++++ +      ASSERT(ParserContext);
++++++++ +  
++++++++ +      //
++++++++ +      // FIXME support multiple top collecions
++++++++ +      //
++++++++ +      ASSERT(ParserContext->RootCollection->NodeCount == 1);
++++++++ +  
++++++++ +      //
++++++++ +      // get report
++++++++ +      //
++++++++ +      Report = HidParser_GetReportByType(Parser, ReportType);
++++++++ +      if (!Report)
++++++++ +      {
++++++++ +          //
++++++++ +          // no such report
++++++++ +          //
++++++++ +          return 0;
++++++++ +      }
++++++++ +  
++++++++ +      //
++++++++ +      // enumerate all items
++++++++ +      //
++++++++ +      for(Index = 0; Index < Report->ItemCount; Index++)
++++++++ +      {
++++++++ +          //
++++++++ +          // check item type
++++++++ +          //
++++++++ +          if (Report->Items[Index]->HasData && bData == TRUE)
++++++++ +          {
++++++++ +              //
++++++++ +              // found data item
++++++++ +              //
++++++++ +              ItemCount++;
++++++++ +          }
++++++++ +          else if (Report->Items[Index]->HasData == FALSE && bData == FALSE)
++++++++ +          {
++++++++ +              //
++++++++ +              // found value item
++++++++ +              //
++++++++ +              ItemCount++;
++++++++ +          }
++++++++ +      }
++++++++ +  
++++++++ +      //
++++++++ +      // no report items
++++++++ +      //
++++++++ +      return ItemCount;
++++++++ +  }
++++++++ +  
++++++++ +  ULONG
++++++++ +  HidParser_GetContextSize(
++++++++ +      IN PHID_PARSER Parser)
++++++++ +  {
++++++++ +      //
++++++++ +      // FIXME the context must contain all parsed info
++++++++ +      //
++++++++ +      return sizeof(HID_PARSER_CONTEXT);
++++++++ +  }
++++++++ +  
++++++++ +  VOID
++++++++ +  HidParser_FreeContext(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      IN PUCHAR Context,
++++++++ +      IN ULONG ContextLength)
++++++++ +  {
++++++++ +      //
++++++++ +      // FIXME implement freeing of parsed info
++++++++ +      //
++++++++ +  }
++++++++ +  
++++++++ +  HIDPARSER_STATUS
++++++++ +  HidParser_AllocateParser(
++++++++ +      IN PHIDPARSER_ALLOC_FUNCTION AllocFunction,
++++++++ +      IN PHIDPARSER_FREE_FUNCTION FreeFunction,
++++++++ +      IN PHIDPARSER_ZERO_FUNCTION ZeroFunction,
++++++++ +      IN PHIDPARSER_COPY_FUNCTION CopyFunction,
++++++++ +      IN PHIDPARSER_DEBUG_FUNCTION DebugFunction,
++++++++ +      OUT PHID_PARSER *OutParser)
++++++++ +  {
++++++++ +      PHID_PARSER Parser;
++++++++ +      PHID_PARSER_CONTEXT ParserContext;
++++++++ +  
++++++++ +      //
++++++++ +      // allocate 
++++++++ +      //
++++++++ +      Parser = (PHID_PARSER)AllocFunction(sizeof(HID_PARSER));
++++++++ +      if (!Parser)
++++++++ +      {
++++++++ +          //
++++++++ +          // no memory
++++++++ +          //
++++++++ +          return HIDPARSER_STATUS_INSUFFICIENT_RESOURCES;
++++++++ +      }
++++++++ +  
++++++++ +      //
++++++++ +      // allocate parser context
++++++++ +      //
++++++++ +      ParserContext = (PHID_PARSER_CONTEXT)AllocFunction(sizeof(HID_PARSER_CONTEXT));
++++++++ +      if (!ParserContext)
++++++++ +      {
++++++++ +          //
++++++++ +          // no memory
++++++++ +          //
++++++++ +          FreeFunction(Parser);
++++++++ +          return HIDPARSER_STATUS_INSUFFICIENT_RESOURCES;
++++++++ +      }
++++++++ +  
++++++++ +  
++++++++ +      //
++++++++ +      // init parser
++++++++ +      //
++++++++ +      Parser->Alloc = AllocFunction;
++++++++ +      Parser->Free = FreeFunction;
++++++++ +      Parser->Zero = ZeroFunction;
++++++++ +      Parser->Copy = CopyFunction;
++++++++ +      Parser->Debug = DebugFunction;
++++++++ +      Parser->ParserContext = ParserContext;
++++++++ +  
++++++++ +      //
++++++++ +      // store result
++++++++ +      //
++++++++ +      *OutParser = Parser;
++++++++ +      //
++++++++ +      // success
++++++++ +      //
++++++++ +      return HIDPARSER_STATUS_SUCCESS;
++++++++ +  }
++++++++ +  
++++++++ +  VOID
++++++++ +  HidParser_InitParser(
++++++++ +      IN PHIDPARSER_ALLOC_FUNCTION AllocFunction,
++++++++ +      IN PHIDPARSER_FREE_FUNCTION FreeFunction,
++++++++ +      IN PHIDPARSER_ZERO_FUNCTION ZeroFunction,
++++++++ +      IN PHIDPARSER_COPY_FUNCTION CopyFunction,
++++++++ +      IN PHIDPARSER_DEBUG_FUNCTION DebugFunction,
++++++++ +      IN PVOID ParserContext,
++++++++ +      OUT PHID_PARSER Parser)
++++++++ +  {
++++++++ +      Parser->Alloc = AllocFunction;
++++++++ +      Parser->Free = FreeFunction;
++++++++ +      Parser->Zero = ZeroFunction;
++++++++ +      Parser->Copy = CopyFunction;
++++++++ +      Parser->Debug = DebugFunction;
++++++++ +      Parser->ParserContext = ParserContext;
++++++++ +  }
++++++++ +  
++++++++ +  ULONG
++++++++ +  HidParser_GetCollectionCount(
++++++++ +      IN PHID_COLLECTION Collection)
++++++++ +  {
++++++++ +      ULONG Index;
++++++++ +      ULONG Count = Collection->NodeCount;
++++++++ +  
++++++++ +      for(Index = 0; Index < Collection->NodeCount; Index++)
++++++++ +      {
++++++++ +          //
++++++++ +          // count collection for sub nodes
++++++++ +          //
++++++++ +          Count += HidParser_GetCollectionCount(Collection->Nodes[Index]);
++++++++ +      }
++++++++ +  
++++++++ +      //
++++++++ +      // done
++++++++ +      //
++++++++ +      return Count;
++++++++ +  }
++++++++ +  
++++++++ +  ULONG
++++++++ +  HidParser_GetTotalCollectionCount(
++++++++ +      IN PHID_PARSER Parser)
++++++++ +  {
++++++++ +      PHID_PARSER_CONTEXT ParserContext;
++++++++ +  
++++++++ +      //
++++++++ +      // get parser context
++++++++ +      //
++++++++ +      ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
++++++++ +  
++++++++ +      //
++++++++ +      // sanity check
++++++++ +      //
++++++++ +      ASSERT(ParserContext);
++++++++ +      ASSERT(ParserContext->RootCollection);
++++++++ +  
++++++++ +      //
++++++++ +      // count collections
++++++++ +      //
++++++++ +      return HidParser_GetCollectionCount(ParserContext->RootCollection);
++++++++ +  }
++++++++ +  
++++++++ +  ULONG
++++++++ +  HidParser_GetMaxUsageListLengthWithReportAndPage(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      IN ULONG ReportType,
++++++++ +      IN USAGE  UsagePage  OPTIONAL)
++++++++ +  {
++++++++ +      PHID_PARSER_CONTEXT ParserContext;
++++++++ +      ULONG Index;
++++++++ +      PHID_REPORT Report;
++++++++ +      ULONG ItemCount = 0;
++++++++ +      USHORT CurrentUsagePage;
++++++++ +  
++++++++ +      //
++++++++ +      // get parser context
++++++++ +      //
++++++++ +      ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
++++++++ +  
++++++++ +      //
++++++++ +      // sanity checks
++++++++ +      //
++++++++ +      ASSERT(ParserContext);
++++++++ +  
++++++++ +      //
++++++++ +      // FIXME support multiple top collecions
++++++++ +      //
++++++++ +      ASSERT(ParserContext->RootCollection->NodeCount == 1);
++++++++ +  
++++++++ +      //
++++++++ +      // get report
++++++++ +      //
++++++++ +      Report = HidParser_GetReportByType(Parser, ReportType);
++++++++ +      if (!Report)
++++++++ +      {
++++++++ +          //
++++++++ +          // no such report
++++++++ +          //
++++++++ +          return 0;
++++++++ +      }
++++++++ +  
++++++++ +      for(Index = 0; Index < Report->ItemCount; Index++)
++++++++ +      {
++++++++ +          //
++++++++ +          // check usage page
++++++++ +          //
++++++++ +          CurrentUsagePage = (Report->Items[Index]->UsageMinimum >> 16);
++++++++ +          if (CurrentUsagePage == UsagePage && Report->Items[Index]->HasData)
++++++++ +          {
++++++++ +              //
++++++++ +              // found item
++++++++ +              //
++++++++ +              ItemCount++;
++++++++ +          }
++++++++ +      }
++++++++ +  
++++++++ +      //
++++++++ +      // done
++++++++ +      //
++++++++ +      return ItemCount;
++++++++ +  }
++++++++ +  
++++++++ +  HIDPARSER_STATUS
++++++++ +  HidParser_GetSpecificValueCapsWithReport(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      IN ULONG ReportType,
++++++++ +      IN USHORT UsagePage,
++++++++ +      IN USHORT Usage,
++++++++ +      OUT PHIDP_VALUE_CAPS  ValueCaps,
++++++++ +      IN OUT PULONG  ValueCapsLength)
++++++++ +  {
++++++++ +      PHID_PARSER_CONTEXT ParserContext;
++++++++ +      ULONG Index;
++++++++ +      PHID_REPORT Report;
++++++++ +      ULONG ItemCount = 0;
++++++++ +      USHORT CurrentUsagePage;
++++++++ +      USHORT CurrentUsage;
++++++++ +  
++++++++ +      //
++++++++ +      // get parser context
++++++++ +      //
++++++++ +      ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
++++++++ +  
++++++++ +      //
++++++++ +      // sanity checks
++++++++ +      //
++++++++ +      ASSERT(ParserContext);
++++++++ +  
++++++++ +      //
++++++++ +      // FIXME support multiple top collecions
++++++++ +      //
++++++++ +      ASSERT(ParserContext->RootCollection->NodeCount == 1);
++++++++ +  
++++++++ +      //
++++++++ +      // get report
++++++++ +      //
++++++++ +      Report = HidParser_GetReportByType(Parser, ReportType);
++++++++ +      if (!Report)
++++++++ +      {
++++++++ +          //
++++++++ +          // no such report
++++++++ +          //
++++++++ +          return HIDPARSER_STATUS_REPORT_NOT_FOUND;
++++++++ +      }
++++++++ +  
++++++++ +      for(Index = 0; Index < Report->ItemCount; Index++)
++++++++ +      {
++++++++ +          //
++++++++ +          // check usage page
++++++++ +          //
++++++++ +          CurrentUsagePage = (Report->Items[Index]->UsageMinimum >> 16);
++++++++ +          CurrentUsage = (Report->Items[Index]->UsageMinimum & 0xFFFF);
++++++++ +  
++++++++ +          if ((Usage == CurrentUsage && UsagePage == CurrentUsagePage) || (Usage == 0 && UsagePage == CurrentUsagePage) || (Usage == CurrentUsage && UsagePage == 0) || (Usage == 0 && UsagePage == 0))
++++++++ +          {
++++++++ +              //
++++++++ +              // check if there is enough place for the caps
++++++++ +              //
++++++++ +              if (ItemCount < *ValueCapsLength)
++++++++ +              {
++++++++ +                  //
++++++++ +                  // zero caps
++++++++ +                  //
++++++++ +                  Parser->Zero(&ValueCaps[ItemCount], sizeof(HIDP_VALUE_CAPS));
++++++++ +  
++++++++ +                  //
++++++++ +                  // init caps
++++++++ +                  //
++++++++ +                  ValueCaps[ItemCount].UsagePage = CurrentUsagePage;
++++++++ +                  ValueCaps[ItemCount].ReportID = Report->ReportID;
++++++++ +                  ValueCaps[ItemCount].LogicalMin = Report->Items[Index]->Minimum;
++++++++ +                  ValueCaps[ItemCount].LogicalMax = Report->Items[Index]->Maximum;
++++++++ +                  ValueCaps[ItemCount].IsAbsolute = !Report->Items[Index]->Relative;
++++++++ +                  ValueCaps[ItemCount].BitSize = Report->Items[Index]->BitCount;
++++++++ +  
++++++++ +                  //
++++++++ +                  // FIXME: FILLMEIN
++++++++ +                  //
++++++++ +              }
++++++++ +  
++++++++ +  
++++++++ +              //
++++++++ +              // found item
++++++++ +              //
++++++++ +              ItemCount++;
++++++++ +          }
++++++++ +      }
++++++++ +  
++++++++ +      //
++++++++ +      // store result
++++++++ +      //
++++++++ +      *ValueCapsLength = ItemCount;
++++++++ +  
++++++++ +      if (ItemCount)
++++++++ +      {
++++++++ +          //
++++++++ +          // success
++++++++ +          //
++++++++ +          return HIDPARSER_STATUS_SUCCESS;
++++++++ +      }
++++++++ +  
++++++++ +      //
++++++++ +      // item not found
++++++++ +      //
++++++++ +      return HIDPARSER_STATUS_USAGE_NOT_FOUND;
++++++++ +  }
++++++++ +  
++++++++ +  HIDPARSER_STATUS
++++++++ +  HidParser_GetUsagesWithReport(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      IN ULONG  ReportType,
++++++++ +      IN USAGE  UsagePage,
++++++++ +      OUT USAGE  *UsageList,
++++++++ +      IN OUT PULONG UsageLength,
++++++++ +      IN PCHAR  ReportDescriptor,
++++++++ +      IN ULONG  ReportDescriptorLength)
++++++++ +  {
++++++++ +      PHID_PARSER_CONTEXT ParserContext;
++++++++ +      ULONG Index;
++++++++ +      PHID_REPORT Report;
++++++++ +      ULONG ItemCount = 0;
++++++++ +      USHORT CurrentUsagePage;
++++++++ +      PHID_REPORT_ITEM ReportItem;
++++++++ +      UCHAR Activated;
++++++++ +      ULONG Data;
++++++++ +  
++++++++ +      //
++++++++ +      // get parser context
++++++++ +      //
++++++++ +      ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
++++++++ +  
++++++++ +      //
++++++++ +      // sanity checks
++++++++ +      //
++++++++ +      ASSERT(ParserContext);
++++++++ +  
++++++++ +      //
++++++++ +      // FIXME support multiple top collecions
++++++++ +      //
++++++++ +      ASSERT(ParserContext->RootCollection->NodeCount == 1);
++++++++ +  
++++++++ +      //
++++++++ +      // get report
++++++++ +      //
++++++++ +      Report = HidParser_GetReportByType(Parser, ReportType);
++++++++ +      if (!Report)
++++++++ +      {
++++++++ +          //
++++++++ +          // no such report
++++++++ +          //
++++++++ +          return HIDPARSER_STATUS_REPORT_NOT_FOUND;
++++++++ +      }
++++++++ +  
++++++++ +      if (Report->ReportSize / 8 != (ReportDescriptorLength - 1))
++++++++ +      {
++++++++ +          //
++++++++ +          // invalid report descriptor length
++++++++ +          //
++++++++ +          return HIDPARSER_STATUS_INVALID_REPORT_LENGTH;
++++++++ +      }
++++++++ +  
++++++++ +      for(Index = 0; Index < Report->ItemCount; Index++)
++++++++ +      {
++++++++ +          //
++++++++ +          // get report item
++++++++ +          //
++++++++ +          ReportItem = Report->Items[Index];
++++++++ +  
++++++++ +          //
++++++++ +          // does it have data
++++++++ +          //
++++++++ +          if (!ReportItem->HasData)
++++++++ +              continue;
++++++++ +  
++++++++ +          //
++++++++ +          // check usage page
++++++++ +          //
++++++++ +          CurrentUsagePage = (ReportItem->UsageMinimum >> 16);
++++++++ +  
++++++++ +          //
++++++++ +          // does usage match
++++++++ +          //
++++++++ +          if (UsagePage != CurrentUsagePage)
++++++++ +              continue;
++++++++ +  
++++++++ +          //
++++++++ +          // check if the specified usage is activated
++++++++ +          //
++++++++ +          ASSERT(ReportItem->ByteOffset < ReportDescriptorLength);
++++++++ +          ASSERT(ReportItem->BitCount < 8);
++++++++ +  
++++++++ +          //
++++++++ +          // one extra shift for skipping the prepended report id
++++++++ +          //
++++++++ +          Data = ReportDescriptor[ReportItem->ByteOffset + 1];
++++++++ +  
++++++++ +          //
++++++++ +          // shift data
++++++++ +          //
++++++++ +          Data >>= ReportItem->Shift;
++++++++ +  
++++++++ +          //
++++++++ +          // clear unwanted bits
++++++++ +          //
++++++++ +          Data &= ReportItem->Mask;
++++++++ +  
++++++++ +          //
++++++++ +          // is it activated
++++++++ +          //
++++++++ +          Activated = (Data != 0);
++++++++ +  
++++++++ +          if (!Activated)
++++++++ +              continue;
++++++++ +  
++++++++ +          //
++++++++ +          // is there enough space for the usage
++++++++ +          //
++++++++ +          if (ItemCount >= *UsageLength)
++++++++ +          {
++++++++ +              ItemCount++;
++++++++ +              continue;
++++++++ +          }
++++++++ +  
++++++++ +          //
++++++++ +          // store item
++++++++ +          //
++++++++ +          UsageList[ItemCount] = (ReportItem->UsageMinimum & 0xFFFF);
++++++++ +          ItemCount++;
++++++++ +      }
++++++++ +  
++++++++ +      if (ItemCount > *UsageLength)
++++++++ +      {
++++++++ +          //
++++++++ +          // list too small
++++++++ +          //
++++++++ +          return HIDPARSER_STATUS_BUFFER_TOO_SMALL;
++++++++ +      }
++++++++ +  
++++++++ +      //
++++++++ +      // success, clear rest of array
++++++++ +      //
++++++++ +      Parser->Zero(&UsageList[ItemCount], (*UsageLength - ItemCount) * sizeof(USAGE));
++++++++ +  
++++++++ +      //
++++++++ +      // store result size
++++++++ +      //
++++++++ +      *UsageLength = ItemCount;
++++++++ +  
++++++++ +      //
++++++++ +      // done
++++++++ +      //
++++++++ +      return HIDPARSER_STATUS_SUCCESS;
++++++++ +  }
++++++++ +  
++++++++ +  HIDPARSER_STATUS
++++++++ +  HidParser_GetScaledUsageValueWithReport(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      IN ULONG ReportType,
++++++++ +      IN USAGE UsagePage,
++++++++ +      IN USAGE  Usage,
++++++++ +      OUT PLONG UsageValue,
++++++++ +      IN PCHAR ReportDescriptor,
++++++++ +      IN ULONG ReportDescriptorLength)
++++++++ +  {
++++++++ +      PHID_PARSER_CONTEXT ParserContext;
++++++++ +      ULONG Index;
++++++++ +      PHID_REPORT Report;
++++++++ +      ULONG ItemCount = 0;
++++++++ +      USHORT CurrentUsagePage;
++++++++ +      PHID_REPORT_ITEM ReportItem;
++++++++ +      ULONG Data;
++++++++ +  
++++++++ +      //
++++++++ +      // get parser context
++++++++ +      //
++++++++ +      ParserContext = (PHID_PARSER_CONTEXT)Parser->ParserContext;
++++++++ +  
++++++++ +      //
++++++++ +      // sanity checks
++++++++ +      //
++++++++ +      ASSERT(ParserContext);
++++++++ +  
++++++++ +      //
++++++++ +      // FIXME support multiple top collecions
++++++++ +      //
++++++++ +      ASSERT(ParserContext->RootCollection->NodeCount == 1);
++++++++ +  
++++++++ +      //
++++++++ +      // get report
++++++++ +      //
++++++++ +      Report = HidParser_GetReportByType(Parser, ReportType);
++++++++ +      if (!Report)
++++++++ +      {
++++++++ +          //
++++++++ +          // no such report
++++++++ +          //
++++++++ +          return HIDPARSER_STATUS_REPORT_NOT_FOUND;
++++++++ +      }
++++++++ +  
++++++++ +      if (Report->ReportSize / 8 != (ReportDescriptorLength - 1))
++++++++ +      {
++++++++ +          //
++++++++ +          // invalid report descriptor length
++++++++ +          //
++++++++ +          return HIDPARSER_STATUS_INVALID_REPORT_LENGTH;
++++++++ +      }
++++++++ +  
++++++++ +      for(Index = 0; Index < Report->ItemCount; Index++)
++++++++ +      {
++++++++ +          //
++++++++ +          // get report item
++++++++ +          //
++++++++ +          ReportItem = Report->Items[Index];
++++++++ +  
++++++++ +          //
++++++++ +          // check usage page
++++++++ +          //
++++++++ +          CurrentUsagePage = (ReportItem->UsageMinimum >> 16);
++++++++ +  
++++++++ +          //
++++++++ +          // does usage page match
++++++++ +          //
++++++++ +          if (UsagePage != CurrentUsagePage)
++++++++ +              continue;
++++++++ +  
++++++++ +          //
++++++++ +          // does the usage match
++++++++ +          //
++++++++ +          if (Usage != (ReportItem->UsageMinimum & 0xFFFF))
++++++++ +              continue;
++++++++ +  
++++++++ +          //
++++++++ +          // check if the specified usage is activated
++++++++ +          //
++++++++ +          ASSERT(ReportItem->ByteOffset < ReportDescriptorLength);
++++++++ +  
++++++++ +          //
++++++++ +          // one extra shift for skipping the prepended report id
++++++++ +          //
++++++++ +          Data = 0;
++++++++ +          Parser->Copy(&Data, &ReportDescriptor[ReportItem->ByteOffset +1], min(sizeof(ULONG), ReportDescriptorLength - (ReportItem->ByteOffset + 1)));
++++++++ +          Data = ReportDescriptor[ReportItem->ByteOffset + 1];
++++++++ +  
++++++++ +          //
++++++++ +          // shift data
++++++++ +          //
++++++++ +          Data >>= ReportItem->Shift;
++++++++ +  
++++++++ +          //
++++++++ +          // clear unwanted bits
++++++++ +          //
++++++++ +          Data &= ReportItem->Mask;
++++++++ +  
++++++++ +          if (ReportItem->Minimum > ReportItem->Maximum)
++++++++ +          {
++++++++ +              //
++++++++ +              // logical boundaries are signed values
++++++++ +              //
++++++++ +              if ((Data & ~(ReportItem->Mask >> 1)) != 0)
++++++++ +              {
++++++++ +                  Data |= ~ReportItem->Mask;
++++++++ +              }
++++++++ +          }
++++++++ +  
++++++++ +          //
++++++++ +          // store result
++++++++ +          //
++++++++ +          *UsageValue = Data;
++++++++ +          return HIDPARSER_STATUS_SUCCESS;
++++++++ +      }
++++++++ +  
++++++++ +      //
++++++++ +      // usage not found
++++++++ +      //
++++++++ +      return HIDPARSER_STATUS_USAGE_NOT_FOUND;
++++++++ +  }
++++++++++++
++++++++++++ULONG
++++++++++++HidParser_GetScanCode(
++++++++++++    IN USAGE Usage)
++++++++++++{
++++++++++++    if (Usage < sizeof(KeyboardScanCodes) / sizeof(KeyboardScanCodes[0]))
++++++++++++    {
++++++++++++        //
++++++++++++        // valid usage
++++++++++++        //
++++++++++++        return KeyboardScanCodes[Usage];
++++++++++++    }
++++++++++++
++++++++++++    //
++++++++++++    // invalid usage
++++++++++++    //
++++++++++++    return 0;
++++++++++++}
++++++++++++
++++++++++++VOID
++++++++++++HidParser_DispatchKey(
++++++++++++    IN PCHAR ScanCodes,
++++++++++++    IN HIDP_KEYBOARD_DIRECTION KeyAction,
++++++++++++    IN PHIDP_INSERT_SCANCODES InsertCodesProcedure,
++++++++++++    IN PVOID InsertCodesContext)
++++++++++++{
++++++++++++    ULONG Index;
++++++++++++    ULONG Length = 0;
++++++++++++
++++++++++++    //
++++++++++++    // count code length
++++++++++++    //
++++++++++++    for(Index = 0; Index < sizeof(ULONG); Index++)
++++++++++++    {
++++++++++++        if (ScanCodes[Index] == 0)
++++++++++++        {
++++++++++++            //
++++++++++++            // last scan code
++++++++++++            //
++++++++++++            break;
++++++++++++        }
++++++++++++
++++++++++++        //
++++++++++++        // is this a key break
++++++++++++        //
++++++++++++        if (KeyAction == HidP_KeyboardBreak)
++++++++++++        {
++++++++++++            //
++++++++++++            // add break
++++++++++++            //
++++++++++++            ScanCodes[Index] |= KEY_BREAK;
++++++++++++        }
++++++++++++
++++++++++++        //
++++++++++++        // more scan counts
++++++++++++        //
++++++++++++        Length++;
++++++++++++    }
++++++++++++
++++++++++++    if (Length > 0)
++++++++++++    {
++++++++++++         //
++++++++++++         // dispatch scan codes
++++++++++++         //
++++++++++++         InsertCodesProcedure(InsertCodesContext, ScanCodes, Length);
++++++++++++    }
++++++++++++}
++++++++++++
++++++++++++
++++++++++++HIDPARSER_STATUS
++++++++++++HidParser_TranslateUsage(
++++++++++++    IN PHID_PARSER Parser,
++++++++++++    IN USAGE Usage,
++++++++++++    IN HIDP_KEYBOARD_DIRECTION  KeyAction,
++++++++++++    IN OUT PHIDP_KEYBOARD_MODIFIER_STATE  ModifierState,
++++++++++++    IN PHIDP_INSERT_SCANCODES  InsertCodesProcedure,
++++++++++++    IN PVOID  InsertCodesContext)
++++++++++++{
++++++++++++    ULONG ScanCode;
++++++++++++
++++++++++++    //
++++++++++++    // get scan code
++++++++++++    //
++++++++++++    ScanCode = HidParser_GetScanCode(Usage);
++++++++++++    if (!ScanCode)
++++++++++++    {
++++++++++++        //
++++++++++++        // invalid lookup or no scan code available
++++++++++++        //
++++++++++++        return HIDPARSER_STATUS_I8042_TRANS_UNKNOWN;
++++++++++++    }
++++++++++++
++++++++++++    //
++++++++++++    // FIXME: translate modifier states
++++++++++++    //
++++++++++++
++++++++++++    HidParser_DispatchKey((PCHAR)&ScanCode, KeyAction, InsertCodesProcedure, InsertCodesContext);
++++++++++++
++++++++++++    //
++++++++++++    // done
++++++++++++    //
++++++++++++    return HIDPARSER_STATUS_SUCCESS;
++++++++++++}
index 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000,ddde2f7,0000000,ddde2f7,ddde2f7..1a1fce5
mode 000000,000000,000000,000000,000000,000000,000000,000000,100644,000000,100644,100644..100644
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
@@@@@@@@@@@@@ -1,0 -1,0 -1,0 -1,0 -1,0 -1,0 -1,0 -1,0 -1,1083 -1,0 -1,1083 -1,1083 +1,1159 @@@@@@@@@@@@@
        - --    UNIMPLEMENTED
        - --    return STATUS_NOT_IMPLEMENTED;
++++++++ +  /*
++++++++ +   * PROJECT:     ReactOS HID Parser Library
++++++++ +   * LICENSE:     GPL - See COPYING in the top level directory
++++++++ +   * FILE:        lib/drivers/hidparser/hidparser.c
++++++++ +   * PURPOSE:     HID Parser
++++++++ +   * PROGRAMMERS:
++++++++ +   *              Michael Martin (michael.martin@reactos.org)
++++++++ +   *              Johannes Anderwald (johannes.anderwald@reactos.org)
++++++++ +   */
++++++++ +  
++++++++ +  #include "parser.h"
++++++++ +  
++++++++ +  NTSTATUS
++++++++ +  TranslateHidParserStatus(
++++++++ +      IN HIDPARSER_STATUS Status)
++++++++ +  {
        - --HIDAPI
        - --NTSTATUS
        - --NTAPI
        - --HidParser_TranslateUsageAndPagesToI8042ScanCodes(
        - --   IN PUSAGE_AND_PAGE  ChangedUsageList,
        - --   IN ULONG  UsageListLength,
        - --   IN HIDP_KEYBOARD_DIRECTION  KeyAction,
        - --   IN OUT PHIDP_KEYBOARD_MODIFIER_STATE  ModifierState,
        - --   IN PHIDP_INSERT_SCANCODES  InsertCodesProcedure,
        - --   IN PVOID  InsertCodesContext)
        - --{
        - --    UNIMPLEMENTED
        - --    ASSERT(FALSE);
        - --    return STATUS_NOT_IMPLEMENTED;
        - --}
        - --
++++++++++++    switch(Status)
++++++++++++    {
++++++++++++        case HIDPARSER_STATUS_INSUFFICIENT_RESOURCES:
++++++++++++             return HIDP_STATUS_INTERNAL_ERROR;
++++++++++++        case HIDPARSER_STATUS_NOT_IMPLEMENTED:
++++++++++++            return HIDP_STATUS_NOT_IMPLEMENTED;
++++++++++++        case HIDPARSER_STATUS_REPORT_NOT_FOUND:
++++++++++++            return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
++++++++++++        case HIDPARSER_STATUS_INVALID_REPORT_LENGTH:
++++++++++++            return HIDP_STATUS_INVALID_REPORT_LENGTH;
++++++++++++        case HIDPARSER_STATUS_INVALID_REPORT_TYPE:
++++++++++++            return HIDP_STATUS_INVALID_REPORT_TYPE;
++++++++++++        case HIDPARSER_STATUS_BUFFER_TOO_SMALL:
++++++++++++            return HIDP_STATUS_BUFFER_TOO_SMALL;
++++++++++++        case HIDPARSER_STATUS_USAGE_NOT_FOUND:
++++++++++++            return HIDP_STATUS_USAGE_NOT_FOUND;
++++++++++++        case HIDPARSER_STATUS_I8042_TRANS_UNKNOWN:
++++++++++++            return HIDP_STATUS_I8042_TRANS_UNKNOWN;
++++++++++++        case HIDPARSER_STATUS_COLLECTION_NOT_FOUND:
++++++++++++            return HIDP_STATUS_NOT_IMPLEMENTED; //FIXME
++++++++++++    }
++++++++++++    DPRINT1("TranslateHidParserStatus Status %ld not implemented\n", Status);
++++++++++++    return HIDP_STATUS_NOT_IMPLEMENTED;
++++++++ +  }
++++++++ +  
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_GetCollectionDescription(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      IN PHIDP_REPORT_DESCRIPTOR ReportDesc,
++++++++ +      IN ULONG DescLength,
++++++++ +      IN POOL_TYPE PoolType,
++++++++ +      OUT PHIDP_DEVICE_DESC DeviceDescription)
++++++++ +  {
++++++++ +      HIDPARSER_STATUS ParserStatus;
++++++++ +      ULONG CollectionCount, ReportCount;
++++++++ +      ULONG Index;
++++++++ +  
++++++++ +      //
++++++++ +      // first parse the report descriptor
++++++++ +      //
++++++++ +      ParserStatus = HidParser_ParseReportDescriptor(Parser, ReportDesc, DescLength);
++++++++ +      if (ParserStatus != HIDPARSER_STATUS_SUCCESS)
++++++++ +      {
++++++++ +          //
++++++++ +          // failed to parse report descriptor
++++++++ +          //
++++++++ +          Parser->Debug("[HIDPARSER] Failed to parse report descriptor with %x\n", ParserStatus);
++++++++ +          return TranslateHidParserStatus(ParserStatus);
++++++++ +      }
++++++++ +  
++++++++ +      //
++++++++ +      // get collection count
++++++++ +      //
++++++++ +      CollectionCount = HidParser_NumberOfTopCollections(Parser);
++++++++ +  
++++++++ +      //
++++++++ +      // FIXME: only one top level collection is supported
++++++++ +      //
++++++++ +      ASSERT(CollectionCount <= 1);
++++++++ +      if (CollectionCount == 0)
++++++++ +      {
++++++++ +          //
++++++++ +          // no top level collections found
++++++++ +          //
++++++++ +          return STATUS_NO_DATA_DETECTED;
++++++++ +      }
++++++++ +  
++++++++ +      //
++++++++ +      // zero description
++++++++ +      //
++++++++ +      Parser->Zero(DeviceDescription, sizeof(HIDP_DEVICE_DESC));
++++++++ +  
++++++++ +      //
++++++++ +      // allocate collection
++++++++ +      //
++++++++ +      DeviceDescription->CollectionDesc = (PHIDP_COLLECTION_DESC)Parser->Alloc(sizeof(HIDP_COLLECTION_DESC) * CollectionCount);
++++++++ +      if (!DeviceDescription->CollectionDesc)
++++++++ +      {
++++++++ +          //
++++++++ +          // no memory
++++++++ +          //
++++++++ +          return STATUS_INSUFFICIENT_RESOURCES;
++++++++ +      }
++++++++ +  
++++++++ +      //
++++++++ +      // allocate report description
++++++++ +      //
++++++++ +      DeviceDescription->ReportIDs = (PHIDP_REPORT_IDS)Parser->Alloc(sizeof(HIDP_REPORT_IDS) * CollectionCount);
++++++++ +      if (!DeviceDescription->ReportIDs)
++++++++ +      {
++++++++ +          //
++++++++ +          // no memory
++++++++ +          //
++++++++ +          Parser->Free(DeviceDescription->CollectionDesc);
++++++++ +          return STATUS_INSUFFICIENT_RESOURCES;
++++++++ +      }
++++++++ +  
++++++++ +      for(Index = 0; Index < CollectionCount; Index++)
++++++++ +      {
++++++++ +          //
++++++++ +          // init report description
++++++++ +          //
++++++++ +          DeviceDescription->ReportIDs[Index].CollectionNumber = Index + 1;
++++++++ +          DeviceDescription->ReportIDs[Index].ReportID = Index; //FIXME
++++++++ +          DeviceDescription->ReportIDs[Index].InputLength = HidParser_GetReportLength(Parser, HID_REPORT_TYPE_INPUT);
++++++++ +          DeviceDescription->ReportIDs[Index].OutputLength = HidParser_GetReportLength(Parser, HID_REPORT_TYPE_OUTPUT);
++++++++ +          DeviceDescription->ReportIDs[Index].FeatureLength = HidParser_GetReportLength(Parser, HID_REPORT_TYPE_FEATURE);
++++++++ +  
++++++++ +          //
++++++++ +          // init collection description
++++++++ +          //
++++++++ +          DeviceDescription->CollectionDesc[Index].CollectionNumber = Index + 1;
++++++++ +  
++++++++ +          //
++++++++ +          // get collection usage page
++++++++ +          //
++++++++ +          ParserStatus = HidParser_GetCollectionUsagePage(Parser, Index, &DeviceDescription->CollectionDesc[Index].Usage, &DeviceDescription->CollectionDesc[Index].UsagePage);
++++++++ +  
++++++++ +          //
++++++++ +          // windows seems to prepend the report id, regardless if it is required
++++++++ +          //
++++++++ +          DeviceDescription->CollectionDesc[Index].InputLength = (DeviceDescription->ReportIDs[Index].InputLength > 0 ? DeviceDescription->ReportIDs[Index].InputLength + 1 : 0);
++++++++ +          DeviceDescription->CollectionDesc[Index].OutputLength = (DeviceDescription->ReportIDs[Index].OutputLength > 0 ? DeviceDescription->ReportIDs[Index].OutputLength + 1 : 0);
++++++++ +          DeviceDescription->CollectionDesc[Index].FeatureLength = (DeviceDescription->ReportIDs[Index].FeatureLength > 0 ? DeviceDescription->ReportIDs[Index].FeatureLength + 1 : 0);
++++++++ +  
++++++++ +          //
++++++++ +          // set preparsed data length
++++++++ +          //
++++++++ +          DeviceDescription->CollectionDesc[Index].PreparsedDataLength = HidParser_GetContextSize(Parser);
++++++++ +          DeviceDescription->CollectionDesc[Index].PreparsedData = Parser->Alloc(DeviceDescription->CollectionDesc[Index].PreparsedDataLength);
++++++++ +          if (!DeviceDescription->CollectionDesc[Index].PreparsedData)
++++++++ +          {
++++++++ +              //
++++++++ +              // no memory
++++++++ +              //
++++++++ +              return STATUS_INSUFFICIENT_RESOURCES;
++++++++ +          }
++++++++ +  
++++++++ +          //
++++++++ +          // copy context
++++++++ +          //
++++++++ +          Parser->Copy(DeviceDescription->CollectionDesc[Index].PreparsedData, Parser->ParserContext, DeviceDescription->CollectionDesc[Index].PreparsedDataLength);
++++++++ +      }
++++++++ +  
++++++++ +      //
++++++++ +      // store collection & report count
++++++++ +      //
++++++++ +      DeviceDescription->CollectionDescLength = CollectionCount;
++++++++ +      DeviceDescription->ReportIDsLength = CollectionCount;
++++++++ +  
++++++++ +      //
++++++++ +      // done
++++++++ +      //
++++++++ +      return STATUS_SUCCESS;
++++++++ +  }
++++++++ +  
++++++++ +  VOID
++++++++ +  NTAPI
++++++++ +  HidParser_FreeCollectionDescription(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      IN PHIDP_DEVICE_DESC   DeviceDescription)
++++++++ +  {
++++++++ +      ULONG Index;
++++++++ +  
++++++++ +      //
++++++++ +      // first free all context
++++++++ +      //
++++++++ +      for(Index = 0; Index < DeviceDescription->CollectionDescLength; Index++)
++++++++ +      {
++++++++ +          //
++++++++ +          // free parser context
++++++++ +          //
++++++++ +          HidParser_FreeContext(Parser, (PUCHAR)DeviceDescription->CollectionDesc[Index].PreparsedData, DeviceDescription->CollectionDesc[Index].PreparsedDataLength);
++++++++ +      }
++++++++ +  
++++++++ +      //
++++++++ +      // now free collection description
++++++++ +      //
++++++++ +      Parser->Free(DeviceDescription->CollectionDesc);
++++++++ +  
++++++++ +      //
++++++++ +      // free report description
++++++++ +      //
++++++++ +      ExFreePool(DeviceDescription->ReportIDs);
++++++++ +  }
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_GetCaps(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      OUT PHIDP_CAPS  Capabilities)
++++++++ +  {
++++++++ +      ULONG CollectionNumber;
++++++++ +      //
++++++++ +      // zero capabilities
++++++++ +      //
++++++++ +      Parser->Zero(Capabilities, sizeof(HIDP_CAPS));
++++++++ +  
++++++++ +      //
++++++++ +      // FIXME support multiple top level collections
++++++++ +      //
++++++++ +      CollectionNumber = 0;
++++++++ +  
++++++++ +      //
++++++++ +      // init capabilities
++++++++ +      //
++++++++ +      HidParser_GetCollectionUsagePage(Parser, CollectionNumber, &Capabilities->Usage, &Capabilities->UsagePage);
++++++++ +      Capabilities->InputReportByteLength = HidParser_GetReportLength(Parser, HID_REPORT_TYPE_INPUT);
++++++++ +      Capabilities->OutputReportByteLength = HidParser_GetReportLength(Parser, HID_REPORT_TYPE_OUTPUT);
++++++++ +      Capabilities->FeatureReportByteLength = HidParser_GetReportLength(Parser, HID_REPORT_TYPE_FEATURE);
++++++++ +  
++++++++ +      //
++++++++ +      // always pre-prend report id
++++++++ +      //
++++++++ +      Capabilities->InputReportByteLength = (Capabilities->InputReportByteLength > 0 ? Capabilities->InputReportByteLength + 1 : 0);
++++++++ +      Capabilities->OutputReportByteLength = (Capabilities->OutputReportByteLength > 0 ? Capabilities->OutputReportByteLength + 1 : 0);
++++++++ +      Capabilities->FeatureReportByteLength = (Capabilities->FeatureReportByteLength > 0 ? Capabilities->FeatureReportByteLength + 1 : 0);
++++++++ +  
++++++++ +      //
++++++++ +      // get number of link collection nodes
++++++++ +      //
++++++++ +      Capabilities->NumberLinkCollectionNodes = HidParser_GetTotalCollectionCount(Parser);
++++++++ +  
++++++++ +      //
++++++++ +      // get data indices
++++++++ +      //
++++++++ +      Capabilities->NumberInputDataIndices = HidParser_GetReportItemTypeCountFromReportType(Parser, HID_REPORT_TYPE_INPUT, TRUE);
++++++++ +      Capabilities->NumberOutputDataIndices = HidParser_GetReportItemTypeCountFromReportType(Parser, HID_REPORT_TYPE_OUTPUT, TRUE);
++++++++ +      Capabilities->NumberFeatureDataIndices = HidParser_GetReportItemTypeCountFromReportType(Parser, HID_REPORT_TYPE_FEATURE, TRUE);
++++++++ +  
++++++++ +      //
++++++++ +      // get value caps
++++++++ +      //
++++++++ +      Capabilities->NumberInputValueCaps = HidParser_GetReportItemTypeCountFromReportType(Parser, HID_REPORT_TYPE_INPUT, FALSE);
++++++++ +      Capabilities->NumberOutputValueCaps = HidParser_GetReportItemTypeCountFromReportType(Parser, HID_REPORT_TYPE_OUTPUT, FALSE);
++++++++ +      Capabilities->NumberFeatureValueCaps = HidParser_GetReportItemTypeCountFromReportType(Parser, HID_REPORT_TYPE_FEATURE, FALSE);
++++++++ +  
++++++++ +  
++++++++ +      //
++++++++ +      // get button caps
++++++++ +      //
++++++++ +      Capabilities->NumberInputButtonCaps = HidParser_GetReportItemCountFromReportType(Parser, HID_REPORT_TYPE_INPUT);
++++++++ +      Capabilities->NumberOutputButtonCaps = HidParser_GetReportItemCountFromReportType(Parser, HID_REPORT_TYPE_OUTPUT);
++++++++ +      Capabilities->NumberFeatureButtonCaps = HidParser_GetReportItemCountFromReportType(Parser, HID_REPORT_TYPE_FEATURE);
++++++++ +  
++++++++ +      //
++++++++ +      // done
++++++++ +      //
++++++++ +      return HIDP_STATUS_SUCCESS;
++++++++ +  }
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  ULONG
++++++++ +  NTAPI
++++++++ +  HidParser_MaxUsageListLength(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      IN HIDP_REPORT_TYPE  ReportType,
++++++++ +      IN USAGE  UsagePage  OPTIONAL)
++++++++ +  {
++++++++ +      //
++++++++ +      // FIXME test what should be returned when usage page is not defined
++++++++ +      //
++++++++ +      if (UsagePage == HID_USAGE_PAGE_UNDEFINED)
++++++++ +      {
++++++++ +          //
++++++++ +          // implement me
++++++++ +          //
++++++++ +          UNIMPLEMENTED
++++++++ +  
++++++++ +          //
++++++++ +          // invalid report
++++++++ +          //
++++++++ +          return 0;
++++++++ +      }
++++++++ +  
++++++++ +      if (ReportType == HidP_Input)
++++++++ +      {
++++++++ +          //
++++++++ +          // input report
++++++++ +          //
++++++++ +          return HidParser_GetMaxUsageListLengthWithReportAndPage(Parser, HID_REPORT_TYPE_INPUT, UsagePage);
++++++++ +      }
++++++++ +      else if (ReportType == HidP_Output)
++++++++ +      {
++++++++ +          //
++++++++ +          // input report
++++++++ +          //
++++++++ +          return HidParser_GetMaxUsageListLengthWithReportAndPage(Parser, HID_REPORT_TYPE_OUTPUT, UsagePage);
++++++++ +      }
++++++++ +      else if (ReportType == HidP_Feature)
++++++++ +      {
++++++++ +          //
++++++++ +          // input report
++++++++ +          //
++++++++ +          return HidParser_GetMaxUsageListLengthWithReportAndPage(Parser, HID_REPORT_TYPE_FEATURE, UsagePage);
++++++++ +      }
++++++++ +      else
++++++++ +      {
++++++++ +          //
++++++++ +          // invalid report type
++++++++ +          //
++++++++ +          return 0;
++++++++ +      }
++++++++ +  }
++++++++ +  
++++++++ +  #undef HidParser_GetButtonCaps
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_GetButtonCaps(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      IN HIDP_REPORT_TYPE ReportType,
++++++++ +      IN PHIDP_BUTTON_CAPS ButtonCaps,
++++++++ +      IN PUSHORT ButtonCapsLength)
++++++++ +  {
++++++++ +      return HidParser_GetSpecificButtonCaps(Parser, ReportType, HID_USAGE_PAGE_UNDEFINED, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_PAGE_UNDEFINED, ButtonCaps, (PULONG)ButtonCapsLength);
++++++++ +  }
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_GetSpecificValueCaps(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      IN HIDP_REPORT_TYPE  ReportType,
++++++++ +      IN USAGE  UsagePage,
++++++++ +      IN USHORT  LinkCollection,
++++++++ +      IN USAGE  Usage,
++++++++ +      OUT PHIDP_VALUE_CAPS  ValueCaps,
++++++++ +      IN OUT PULONG  ValueCapsLength)
++++++++ +  {
++++++++ +      HIDPARSER_STATUS ParserStatus;
++++++++ +  
++++++++ +      //
++++++++ +      // FIXME: implement searching in specific collection
++++++++ +      //
++++++++ +      ASSERT(LinkCollection == HIDP_LINK_COLLECTION_UNSPECIFIED);
++++++++ +  
++++++++ +      if (ReportType == HidP_Input)
++++++++ +      {
++++++++ +          //
++++++++ +          // input report
++++++++ +          //
++++++++ +          ParserStatus = HidParser_GetSpecificValueCapsWithReport(Parser, HID_REPORT_TYPE_INPUT, UsagePage, Usage, ValueCaps, ValueCapsLength);
++++++++ +      }
++++++++ +      else if (ReportType == HidP_Output)
++++++++ +      {
++++++++ +          //
++++++++ +          // input report
++++++++ +          //
++++++++ +          ParserStatus = HidParser_GetSpecificValueCapsWithReport(Parser, HID_REPORT_TYPE_OUTPUT, UsagePage, Usage, ValueCaps, ValueCapsLength);
++++++++ +      }
++++++++ +      else if (ReportType == HidP_Feature)
++++++++ +      {
++++++++ +          //
++++++++ +          // input report
++++++++ +          //
++++++++ +          ParserStatus = HidParser_GetSpecificValueCapsWithReport(Parser, HID_REPORT_TYPE_FEATURE, UsagePage, Usage, ValueCaps, ValueCapsLength);
++++++++ +      }
++++++++ +      else
++++++++ +      {
++++++++ +          //
++++++++ +          // invalid report type
++++++++ +          //
++++++++ +          return HIDP_STATUS_INVALID_REPORT_TYPE;
++++++++ +      }
++++++++ +  
++++++++ +  
++++++++ +      if (ParserStatus == HIDPARSER_STATUS_SUCCESS)
++++++++ +      {
++++++++ +          //
++++++++ +          // success
++++++++ +          //
++++++++ +          return HIDP_STATUS_SUCCESS;
++++++++ +      }
++++++++ +  
++++++++ +      //
++++++++ +      // translate error
++++++++ +      //
++++++++ +      return TranslateHidParserStatus(ParserStatus);
++++++++ +  }
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_UsageListDifference(
++++++++ +    IN PUSAGE  PreviousUsageList,
++++++++ +    IN PUSAGE  CurrentUsageList,
++++++++ +    OUT PUSAGE  BreakUsageList,
++++++++ +    OUT PUSAGE  MakeUsageList,
++++++++ +    IN ULONG  UsageListLength)
++++++++ +  {
++++++++ +      ULONG Index, SubIndex, bFound, BreakUsageIndex = 0, MakeUsageIndex = 0;
++++++++ +      USAGE CurrentUsage, Usage;
++++++++ +  
++++++++ +      if (UsageListLength)
++++++++ +      {
++++++++ +          Index = 0;
++++++++ +          do
++++++++ +          {
++++++++ +              /* get current usage */
++++++++ +              CurrentUsage = PreviousUsageList[Index];
++++++++ +  
++++++++ +              /* is the end of list reached? */
++++++++ +              if (!CurrentUsage)
++++++++ +                  break;
++++++++ +  
++++++++ +              /* start searching in current usage list */
++++++++ +              SubIndex = 0;
++++++++ +              bFound = FALSE;
++++++++ +              do
++++++++ +              {
++++++++ +                  /* get usage of current list */
++++++++ +                  Usage = CurrentUsageList[SubIndex];
++++++++ +  
++++++++ +                  /* end of list reached? */
++++++++ +                  if (!Usage)
++++++++ +                      break;
++++++++ +  
++++++++ +                  /* check if it matches the current one */
++++++++ +                  if (CurrentUsage == Usage)
++++++++ +                  {
++++++++ +                      /* it does */
++++++++ +                      bFound = TRUE;
++++++++ +                      break;
++++++++ +                  }
++++++++ +  
++++++++ +                  /* move to next usage */
++++++++ +                  SubIndex++;
++++++++ +              }while(SubIndex < UsageListLength);
++++++++ +  
++++++++ +              /* was the usage found ?*/
++++++++ +              if (!bFound)
++++++++ +              {
++++++++ +                  /* store it in the break usage list */
++++++++ +                  BreakUsageList[BreakUsageIndex] = CurrentUsage;
++++++++ +                  BreakUsageIndex++;
++++++++ +              }
++++++++ +  
++++++++ +              /* move to next usage */
++++++++ +              Index++;
++++++++ +  
++++++++ +          }while(Index < UsageListLength);
++++++++ +  
++++++++ +          /* now process the new items */
++++++++ +          Index = 0;
++++++++ +          do
++++++++ +          {
++++++++ +              /* get current usage */
++++++++ +              CurrentUsage = CurrentUsageList[Index];
++++++++ +  
++++++++ +              /* is the end of list reached? */
++++++++ +              if (!CurrentUsage)
++++++++ +                  break;
++++++++ +  
++++++++ +              /* start searching in current usage list */
++++++++ +              SubIndex = 0;
++++++++ +              bFound = FALSE;
++++++++ +              do
++++++++ +              {
++++++++ +                  /* get usage of previous list */
++++++++ +                  Usage = PreviousUsageList[SubIndex];
++++++++ +  
++++++++ +                  /* end of list reached? */
++++++++ +                  if (!Usage)
++++++++ +                      break;
++++++++ +  
++++++++ +                  /* check if it matches the current one */
++++++++ +                  if (CurrentUsage == Usage)
++++++++ +                  {
++++++++ +                      /* it does */
++++++++ +                      bFound = TRUE;
++++++++ +                      break;
++++++++ +                  }
++++++++ +  
++++++++ +                  /* move to next usage */
++++++++ +                  SubIndex++;
++++++++ +              }while(SubIndex < UsageListLength);
++++++++ +  
++++++++ +              /* was the usage found ?*/
++++++++ +              if (!bFound)
++++++++ +              {
++++++++ +                  /* store it in the make usage list */
++++++++ +                  MakeUsageList[MakeUsageIndex] = CurrentUsage;
++++++++ +                  MakeUsageIndex++;
++++++++ +              }
++++++++ +  
++++++++ +              /* move to next usage */
++++++++ +              Index++;
++++++++ +  
++++++++ +          }while(Index < UsageListLength);
++++++++ +      }
++++++++ +  
++++++++ +      /* does the break list contain empty entries */
++++++++ +      if (BreakUsageIndex < UsageListLength)
++++++++ +      {
++++++++ +          /* zeroize entries */
++++++++ +          RtlZeroMemory(&BreakUsageList[BreakUsageIndex], sizeof(USAGE) * (UsageListLength - BreakUsageIndex));
++++++++ +      }
++++++++ +  
++++++++ +      /* does the make usage list contain empty entries */
++++++++ +      if (MakeUsageIndex < UsageListLength)
++++++++ +      {
++++++++ +          /* zeroize entries */
++++++++ +          RtlZeroMemory(&MakeUsageList[MakeUsageIndex], sizeof(USAGE) * (UsageListLength - MakeUsageIndex));
++++++++ +      }
++++++++ +  
++++++++ +      /* done */
++++++++ +      return HIDP_STATUS_SUCCESS;
++++++++ +  }
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_GetUsages(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      IN HIDP_REPORT_TYPE  ReportType,
++++++++ +      IN USAGE  UsagePage,
++++++++ +      IN USHORT  LinkCollection  OPTIONAL,
++++++++ +      OUT USAGE  *UsageList,
++++++++ +      IN OUT PULONG UsageLength,
++++++++ +      IN PCHAR  Report,
++++++++ +      IN ULONG  ReportLength)
++++++++ +  {
++++++++ +      HIDPARSER_STATUS ParserStatus;
++++++++ +  
++++++++ +      //
++++++++ +      // FIXME: implement searching in specific collection
++++++++ +      //
++++++++ +      ASSERT(LinkCollection == HIDP_LINK_COLLECTION_UNSPECIFIED);
++++++++ +  
++++++++ +      if (ReportType == HidP_Input)
++++++++ +      {
++++++++ +          //
++++++++ +          // input report
++++++++ +          //
++++++++ +          ParserStatus = HidParser_GetUsagesWithReport(Parser, HID_REPORT_TYPE_INPUT, UsagePage, UsageList, UsageLength, Report, ReportLength);
++++++++ +      }
++++++++ +      else if (ReportType == HidP_Output)
++++++++ +      {
++++++++ +          //
++++++++ +          // input report
++++++++ +          //
++++++++ +          ParserStatus = HidParser_GetUsagesWithReport(Parser, HID_REPORT_TYPE_OUTPUT, UsagePage, UsageList, UsageLength, Report, ReportLength);
++++++++ +      }
++++++++ +      else if (ReportType == HidP_Feature)
++++++++ +      {
++++++++ +          //
++++++++ +          // input report
++++++++ +          //
++++++++ +          ParserStatus = HidParser_GetUsagesWithReport(Parser, HID_REPORT_TYPE_FEATURE, UsagePage, UsageList, UsageLength, Report, ReportLength);
++++++++ +      }
++++++++ +      else
++++++++ +      {
++++++++ +          //
++++++++ +          // invalid report type
++++++++ +          //
++++++++ +          return HIDP_STATUS_INVALID_REPORT_TYPE;
++++++++ +      }
++++++++ +  
++++++++ +      if (ParserStatus == HIDPARSER_STATUS_SUCCESS)
++++++++ +      {
++++++++ +          //
++++++++ +          // success
++++++++ +          //
++++++++ +          return HIDP_STATUS_SUCCESS;
++++++++ +      }
++++++++ +  
++++++++ +      //
++++++++ +      // translate error
++++++++ +      //
++++++++ +      return TranslateHidParserStatus(ParserStatus);
++++++++ +  }
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_GetScaledUsageValue(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      IN HIDP_REPORT_TYPE  ReportType,
++++++++ +      IN USAGE  UsagePage,
++++++++ +      IN USHORT  LinkCollection  OPTIONAL,
++++++++ +      IN USAGE  Usage,
++++++++ +      OUT PLONG  UsageValue,
++++++++ +      IN PCHAR  Report,
++++++++ +      IN ULONG  ReportLength)
++++++++ +  {
++++++++ +      HIDPARSER_STATUS ParserStatus;
++++++++ +  
++++++++ +      //
++++++++ +      // FIXME: implement searching in specific collection
++++++++ +      //
++++++++ +      ASSERT(LinkCollection == HIDP_LINK_COLLECTION_UNSPECIFIED);
++++++++ +  
++++++++ +      if (ReportType == HidP_Input)
++++++++ +      {
++++++++ +          //
++++++++ +          // input report
++++++++ +          //
++++++++ +          ParserStatus = HidParser_GetScaledUsageValueWithReport(Parser, HID_REPORT_TYPE_INPUT, UsagePage, Usage, UsageValue, Report, ReportLength);
++++++++ +      }
++++++++ +      else if (ReportType == HidP_Output)
++++++++ +      {
++++++++ +          //
++++++++ +          // input report
++++++++ +          //
++++++++ +          ParserStatus = HidParser_GetScaledUsageValueWithReport(Parser, HID_REPORT_TYPE_OUTPUT, UsagePage, Usage, UsageValue, Report, ReportLength);
++++++++ +      }
++++++++ +      else if (ReportType == HidP_Feature)
++++++++ +      {
++++++++ +          //
++++++++ +          // input report
++++++++ +          //
++++++++ +          ParserStatus = HidParser_GetScaledUsageValueWithReport(Parser, HID_REPORT_TYPE_FEATURE,  UsagePage, Usage, UsageValue, Report, ReportLength);
++++++++ +      }
++++++++ +      else
++++++++ +      {
++++++++ +          //
++++++++ +          // invalid report type
++++++++ +          //
++++++++ +          return HIDP_STATUS_INVALID_REPORT_TYPE;
++++++++ +      }
++++++++ +  
++++++++ +      if (ParserStatus == HIDPARSER_STATUS_SUCCESS)
++++++++ +      {
++++++++ +          //
++++++++ +          // success
++++++++ +          //
++++++++ +          return HIDP_STATUS_SUCCESS;
++++++++ +      }
++++++++ +  
++++++++ +      //
++++++++ +      // translate error
++++++++ +      //
++++++++ +      return TranslateHidParserStatus(ParserStatus);
++++++++ +  }
++++++++ +  
++++++++++++HIDAPI
++++++++++++NTSTATUS
++++++++++++NTAPI
++++++++++++HidParser_TranslateUsageAndPagesToI8042ScanCodes(
++++++++++++   IN PHID_PARSER Parser,
++++++++++++   IN PUSAGE_AND_PAGE  ChangedUsageList,
++++++++++++   IN ULONG  UsageListLength,
++++++++++++   IN HIDP_KEYBOARD_DIRECTION  KeyAction,
++++++++++++   IN OUT PHIDP_KEYBOARD_MODIFIER_STATE  ModifierState,
++++++++++++   IN PHIDP_INSERT_SCANCODES  InsertCodesProcedure,
++++++++++++   IN PVOID  InsertCodesContext)
++++++++++++{
++++++++++++    ULONG Index;
++++++++++++    HIDPARSER_STATUS Status = HIDPARSER_STATUS_SUCCESS;
++++++++++++
++++++++++++    for(Index = 0; Index < UsageListLength; Index++)
++++++++++++    {
++++++++++++        //
++++++++++++        // check current usage
++++++++++++        //
++++++++++++        if (ChangedUsageList[Index].UsagePage == HID_USAGE_PAGE_KEYBOARD)
++++++++++++        {
++++++++++++            //
++++++++++++            // process usage
++++++++++++            //
++++++++++++            Status = HidParser_TranslateUsage(Parser, ChangedUsageList[Index].Usage, KeyAction, ModifierState, InsertCodesProcedure, InsertCodesContext);
++++++++++++        }
++++++++++++        else if (ChangedUsageList[Index].UsagePage == HID_USAGE_PAGE_CONSUMER)
++++++++++++        {
++++++++++++            //
++++++++++++            // FIXME: implement me
++++++++++++            //
++++++++++++            UNIMPLEMENTED
++++++++++++            Status = HIDPARSER_STATUS_NOT_IMPLEMENTED;
++++++++++++        }
++++++++++++        else
++++++++++++        {
++++++++++++            //
++++++++++++            // invalid page
++++++++++++            //
++++++++++++            DPRINT1("[HIDPARSE] Error unexpected usage page %x\n", ChangedUsageList[Index].UsagePage);
++++++++++++            return HIDP_STATUS_I8042_TRANS_UNKNOWN;
++++++++++++        }
++++++++++++
++++++++++++        //
++++++++++++        // check status
++++++++++++        //
++++++++++++        if (Status != HIDPARSER_STATUS_SUCCESS)
++++++++++++        {
++++++++++++            //
++++++++++++            // failed
++++++++++++            //
++++++++++++            return TranslateHidParserStatus(Status);
++++++++++++        }
++++++++++++    }
++++++++++++
++++++++++++    if (Status != HIDPARSER_STATUS_SUCCESS)
++++++++++++    {
++++++++++++        //
++++++++++++        // failed
++++++++++++        //
++++++++++++        return TranslateHidParserStatus(Status);
++++++++++++    }
++++++++++++
++++++++++++    //
++++++++++++    // done
++++++++++++    //
++++++++++++    return HIDP_STATUS_SUCCESS;
++++++++++++}
++++++++++++
++++++++++++
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_GetUsagesEx(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      IN HIDP_REPORT_TYPE  ReportType,
++++++++ +      IN USHORT  LinkCollection,
++++++++ +      OUT PUSAGE_AND_PAGE  ButtonList,
++++++++ +      IN OUT ULONG  *UsageLength,
++++++++ +      IN PCHAR  Report,
++++++++ +      IN ULONG  ReportLength)
++++++++ +  {
++++++++ +      return HidParser_GetUsages(Parser, ReportType, HID_USAGE_PAGE_UNDEFINED, LinkCollection, (PUSAGE)ButtonList, UsageLength, Report, ReportLength);
++++++++ +  }
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_UsageAndPageListDifference(
++++++++ +     IN PUSAGE_AND_PAGE  PreviousUsageList,
++++++++ +     IN PUSAGE_AND_PAGE  CurrentUsageList,
++++++++ +     OUT PUSAGE_AND_PAGE  BreakUsageList,
++++++++ +     OUT PUSAGE_AND_PAGE  MakeUsageList,
++++++++ +     IN ULONG  UsageListLength)
++++++++ +  {
++++++++ +      ULONG Index, SubIndex, BreakUsageListIndex = 0, MakeUsageListIndex = 0, bFound;
++++++++ +      PUSAGE_AND_PAGE CurrentUsage, Usage;
++++++++ +  
++++++++ +      if (UsageListLength)
++++++++ +      {
++++++++ +          /* process removed usages */
++++++++ +          Index = 0;
++++++++ +          do
++++++++ +          {
++++++++ +              /* get usage from current index */
++++++++ +              CurrentUsage = &PreviousUsageList[Index];
++++++++ +  
++++++++ +              /* end of list reached? */
++++++++ +              if (CurrentUsage->Usage == 0 && CurrentUsage->UsagePage == 0)
++++++++ +                  break;
++++++++ +  
++++++++ +              /* search in current list */
++++++++ +              SubIndex = 0;
++++++++ +              bFound = FALSE;
++++++++ +              do
++++++++ +              {
++++++++ +                  /* get usage */
++++++++ +                  Usage = &CurrentUsageList[SubIndex];
++++++++ +  
++++++++ +                  /* end of list reached? */
++++++++ +                  if (Usage->Usage == 0 && Usage->UsagePage == 0)
++++++++ +                      break;
++++++++ +  
++++++++ +                  /* does it match */
++++++++ +                  if (Usage->Usage == CurrentUsage->Usage && Usage->UsagePage == CurrentUsage->UsagePage)
++++++++ +                  {
++++++++ +                      /* found match */
++++++++ +                      bFound = TRUE;
++++++++ +                  }
++++++++ +  
++++++++ +                  /* move to next index */
++++++++ +                  SubIndex++;
++++++++ +  
++++++++ +              }while(SubIndex < UsageListLength);
++++++++ +  
++++++++ +              if (!bFound)
++++++++ +              {
++++++++ +                  /* store it in break usage list */
++++++++ +                  BreakUsageList[BreakUsageListIndex].Usage = CurrentUsage->Usage;
++++++++ +                  BreakUsageList[BreakUsageListIndex].UsagePage = CurrentUsage->UsagePage;
++++++++ +                  BreakUsageListIndex++;
++++++++ +              }
++++++++ +  
++++++++ +              /* move to next index */
++++++++ +              Index++;
++++++++ +  
++++++++ +          }while(Index < UsageListLength);
++++++++ +  
++++++++ +          /* process new usages */
++++++++ +          Index = 0;
++++++++ +          do
++++++++ +          {
++++++++ +              /* get usage from current index */
++++++++ +              CurrentUsage = &CurrentUsageList[Index];
++++++++ +  
++++++++ +              /* end of list reached? */
++++++++ +              if (CurrentUsage->Usage == 0 && CurrentUsage->UsagePage == 0)
++++++++ +                  break;
++++++++ +  
++++++++ +              /* search in current list */
++++++++ +              SubIndex = 0;
++++++++ +              bFound = FALSE;
++++++++ +              do
++++++++ +              {
++++++++ +                  /* get usage */
++++++++ +                  Usage = &PreviousUsageList[SubIndex];
++++++++ +  
++++++++ +                  /* end of list reached? */
++++++++ +                  if (Usage->Usage == 0 && Usage->UsagePage == 0)
++++++++ +                      break;
++++++++ +  
++++++++ +                  /* does it match */
++++++++ +                  if (Usage->Usage == CurrentUsage->Usage && Usage->UsagePage == CurrentUsage->UsagePage)
++++++++ +                  {
++++++++ +                      /* found match */
++++++++ +                      bFound = TRUE;
++++++++ +                  }
++++++++ +  
++++++++ +                  /* move to next index */
++++++++ +                  SubIndex++;
++++++++ +  
++++++++ +              }while(SubIndex < UsageListLength);
++++++++ +  
++++++++ +              if (!bFound)
++++++++ +              {
++++++++ +                  /* store it in break usage list */
++++++++ +                  MakeUsageList[MakeUsageListIndex].Usage = CurrentUsage->Usage;
++++++++ +                  MakeUsageList[MakeUsageListIndex].UsagePage = CurrentUsage->UsagePage;
++++++++ +                  MakeUsageListIndex++;
++++++++ +              }
++++++++ +  
++++++++ +              /* move to next index */
++++++++ +              Index++;
++++++++ +          }while(Index < UsageListLength);
++++++++ +      }
++++++++ +  
++++++++ +      /* are there remaining free list entries */
++++++++ +      if (BreakUsageListIndex < UsageListLength)
++++++++ +      {
++++++++ +          /* zero them */
++++++++ +          RtlZeroMemory(&BreakUsageList[BreakUsageListIndex], (UsageListLength - BreakUsageListIndex) * sizeof(USAGE_AND_PAGE));
++++++++ +      }
++++++++ +  
++++++++ +      /* are there remaining free list entries */
++++++++ +      if (MakeUsageListIndex < UsageListLength)
++++++++ +      {
++++++++ +          /* zero them */
++++++++ +          RtlZeroMemory(&MakeUsageList[MakeUsageListIndex], (UsageListLength - MakeUsageListIndex) * sizeof(USAGE_AND_PAGE));
++++++++ +      }
++++++++ +  
++++++++ +      /* done */
++++++++ +      return HIDP_STATUS_SUCCESS;
++++++++ +  }
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_GetSpecificButtonCaps(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      IN HIDP_REPORT_TYPE  ReportType,
++++++++ +      IN USAGE  UsagePage,
++++++++ +      IN USHORT  LinkCollection,
++++++++ +      IN USAGE  Usage,
++++++++ +      OUT PHIDP_BUTTON_CAPS  ButtonCaps,
++++++++ +      IN OUT PULONG  ButtonCapsLength)
++++++++ +  {
++++++++ +      UNIMPLEMENTED
++++++++ +      ASSERT(FALSE);
++++++++ +      return STATUS_NOT_IMPLEMENTED;
++++++++ +  }
++++++++ +  
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_GetData(
++++++++ +    IN HIDP_REPORT_TYPE  ReportType,
++++++++ +    OUT PHIDP_DATA  DataList,
++++++++ +    IN OUT PULONG  DataLength,
++++++++ +    IN PHIDP_PREPARSED_DATA  PreparsedData,
++++++++ +    IN PCHAR  Report,
++++++++ +    IN ULONG  ReportLength)
++++++++ +  {
++++++++ +      UNIMPLEMENTED
++++++++ +      ASSERT(FALSE);
++++++++ +      return STATUS_NOT_IMPLEMENTED;
++++++++ +  }
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_GetExtendedAttributes(
++++++++ +    IN HIDP_REPORT_TYPE  ReportType,
++++++++ +    IN USHORT  DataIndex,
++++++++ +    IN PHIDP_PREPARSED_DATA  PreparsedData,
++++++++ +    OUT PHIDP_EXTENDED_ATTRIBUTES  Attributes,
++++++++ +    IN OUT PULONG  LengthAttributes)
++++++++ +  {
++++++++ +      UNIMPLEMENTED
++++++++ +      ASSERT(FALSE);
++++++++ +      return STATUS_NOT_IMPLEMENTED;
++++++++ +  }
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_GetLinkCollectionNodes(
++++++++ +      OUT PHIDP_LINK_COLLECTION_NODE  LinkCollectionNodes,
++++++++ +      IN OUT PULONG  LinkCollectionNodesLength,
++++++++ +      IN PHIDP_PREPARSED_DATA  PreparsedData)
++++++++ +  {
++++++++ +      UNIMPLEMENTED
++++++++ +      ASSERT(FALSE);
++++++++ +      return STATUS_NOT_IMPLEMENTED;
++++++++ +  }
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_GetUsageValue(
++++++++ +    IN HIDP_REPORT_TYPE  ReportType,
++++++++ +    IN USAGE  UsagePage,
++++++++ +    IN USHORT  LinkCollection,
++++++++ +    IN USAGE  Usage,
++++++++ +    OUT PULONG  UsageValue,
++++++++ +    IN PHIDP_PREPARSED_DATA  PreparsedData,
++++++++ +    IN PCHAR  Report,
++++++++ +    IN ULONG  ReportLength)
++++++++ +  {
++++++++ +      UNIMPLEMENTED
++++++++ +      ASSERT(FALSE);
++++++++ +      return STATUS_NOT_IMPLEMENTED;
++++++++ +  }
++++++++ +  
++++++++ +  
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_SysPowerEvent (
++++++++ +      IN PCHAR HidPacket,
++++++++ +      IN USHORT HidPacketLength,
++++++++ +      IN PHIDP_PREPARSED_DATA Ppd,
++++++++ +      OUT PULONG OutputBuffer)
++++++++ +  {
++++++++ +      UNIMPLEMENTED
++++++++ +      ASSERT(FALSE);
++++++++ +      return STATUS_NOT_IMPLEMENTED;
++++++++ +  }
++++++++ +  
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_SysPowerCaps (
++++++++ +      IN PHIDP_PREPARSED_DATA Ppd,
++++++++ +      OUT PULONG OutputBuffer)
++++++++ +  {
++++++++ +      UNIMPLEMENTED
++++++++ +      ASSERT(FALSE);
++++++++ +      return STATUS_NOT_IMPLEMENTED;
++++++++ +  }
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_GetUsageValueArray(
++++++++ +    IN HIDP_REPORT_TYPE  ReportType,
++++++++ +    IN USAGE  UsagePage,
++++++++ +    IN USHORT  LinkCollection  OPTIONAL,
++++++++ +    IN USAGE  Usage,
++++++++ +    OUT PCHAR  UsageValue,
++++++++ +    IN USHORT  UsageValueByteLength,
++++++++ +    IN PHIDP_PREPARSED_DATA  PreparsedData,
++++++++ +    IN PCHAR  Report,
++++++++ +    IN ULONG  ReportLength)
++++++++ +  {
++++++++ +      UNIMPLEMENTED
++++++++ +      ASSERT(FALSE);
++++++++ +      return STATUS_NOT_IMPLEMENTED;
++++++++ +  }
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_UnsetUsages(
++++++++ +    IN HIDP_REPORT_TYPE  ReportType,
++++++++ +    IN USAGE  UsagePage,
++++++++ +    IN USHORT  LinkCollection,
++++++++ +    IN PUSAGE  UsageList,
++++++++ +    IN OUT PULONG  UsageLength,
++++++++ +    IN PHIDP_PREPARSED_DATA  PreparsedData,
++++++++ +    IN OUT PCHAR  Report,
++++++++ +    IN ULONG  ReportLength)
++++++++ +  {
++++++++ +      UNIMPLEMENTED
++++++++ +      ASSERT(FALSE);
++++++++ +      return STATUS_NOT_IMPLEMENTED;
++++++++ +  }
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_TranslateUsagesToI8042ScanCodes(
++++++++ +    IN PUSAGE  ChangedUsageList,
++++++++ +    IN ULONG  UsageListLength,
++++++++ +    IN HIDP_KEYBOARD_DIRECTION  KeyAction,
++++++++ +    IN OUT PHIDP_KEYBOARD_MODIFIER_STATE  ModifierState,
++++++++ +    IN PHIDP_INSERT_SCANCODES  InsertCodesProcedure,
++++++++ +    IN PVOID  InsertCodesContext)
++++++++ +  {
++++++++ +      UNIMPLEMENTED
++++++++ +      ASSERT(FALSE);
++++++++ +      return STATUS_NOT_IMPLEMENTED;
++++++++ +  }
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_SetUsages(
++++++++ +    IN HIDP_REPORT_TYPE  ReportType,
++++++++ +    IN USAGE  UsagePage,
++++++++ +    IN USHORT  LinkCollection,
++++++++ +    IN PUSAGE  UsageList,
++++++++ +    IN OUT PULONG  UsageLength,
++++++++ +    IN PHIDP_PREPARSED_DATA  PreparsedData,
++++++++ +    IN OUT PCHAR  Report,
++++++++ +    IN ULONG  ReportLength)
++++++++ +  {
++++++++ +      UNIMPLEMENTED
++++++++ +      ASSERT(FALSE);
++++++++ +      return STATUS_NOT_IMPLEMENTED;
++++++++ +  }
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_SetUsageValueArray(
++++++++ +    IN HIDP_REPORT_TYPE  ReportType,
++++++++ +    IN USAGE  UsagePage,
++++++++ +    IN USHORT  LinkCollection  OPTIONAL,
++++++++ +    IN USAGE  Usage,
++++++++ +    IN PCHAR  UsageValue,
++++++++ +    IN USHORT  UsageValueByteLength,
++++++++ +    IN PHIDP_PREPARSED_DATA  PreparsedData,
++++++++ +    OUT PCHAR  Report,
++++++++ +    IN ULONG  ReportLength)
++++++++ +  {
++++++++ +      UNIMPLEMENTED
++++++++ +      ASSERT(FALSE);
++++++++ +      return STATUS_NOT_IMPLEMENTED;
++++++++ +  }
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_SetUsageValue(
++++++++ +    IN HIDP_REPORT_TYPE  ReportType,
++++++++ +    IN USAGE  UsagePage,
++++++++ +    IN USHORT  LinkCollection,
++++++++ +    IN USAGE  Usage,
++++++++ +    IN ULONG  UsageValue,
++++++++ +    IN PHIDP_PREPARSED_DATA  PreparsedData,
++++++++ +    IN OUT PCHAR  Report,
++++++++ +    IN ULONG  ReportLength)
++++++++ +  {
++++++++ +      UNIMPLEMENTED
++++++++ +      ASSERT(FALSE);
++++++++ +      return STATUS_NOT_IMPLEMENTED;
++++++++ +  }
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_SetScaledUsageValue(
++++++++ +    IN HIDP_REPORT_TYPE  ReportType,
++++++++ +    IN USAGE  UsagePage,
++++++++ +    IN USHORT  LinkCollection  OPTIONAL,
++++++++ +    IN USAGE  Usage,
++++++++ +    IN LONG  UsageValue,
++++++++ +    IN PHIDP_PREPARSED_DATA  PreparsedData,
++++++++ +    IN OUT PCHAR  Report,
++++++++ +    IN ULONG  ReportLength)
++++++++ +  {
++++++++ +      UNIMPLEMENTED
++++++++ +      ASSERT(FALSE);
++++++++ +      return STATUS_NOT_IMPLEMENTED;
++++++++ +  }
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_SetData(
++++++++ +    IN HIDP_REPORT_TYPE  ReportType,
++++++++ +    IN PHIDP_DATA  DataList,
++++++++ +    IN OUT PULONG  DataLength,
++++++++ +    IN PHIDP_PREPARSED_DATA  PreparsedData,
++++++++ +    IN OUT PCHAR  Report,
++++++++ +    IN ULONG  ReportLength)
++++++++ +  {
++++++++ +      UNIMPLEMENTED
++++++++ +      ASSERT(FALSE);
++++++++ +      return STATUS_NOT_IMPLEMENTED;
++++++++ +  }
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  ULONG
++++++++ +  NTAPI
++++++++ +  HidParser_MaxDataListLength(
++++++++ +    IN HIDP_REPORT_TYPE  ReportType,
++++++++ +    IN PHIDP_PREPARSED_DATA  PreparsedData)
++++++++ +  {
++++++++ +      UNIMPLEMENTED
++++++++ +      ASSERT(FALSE);
++++++++ +      return STATUS_NOT_IMPLEMENTED;
++++++++ +  }
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_InitializeReportForID(
++++++++ +    IN HIDP_REPORT_TYPE  ReportType,
++++++++ +    IN UCHAR  ReportID,
++++++++ +    IN PHIDP_PREPARSED_DATA  PreparsedData,
++++++++ +    IN OUT PCHAR  Report,
++++++++ +    IN ULONG  ReportLength)
++++++++ +  {
++++++++ +      UNIMPLEMENTED
++++++++ +      ASSERT(FALSE);
++++++++ +      return STATUS_NOT_IMPLEMENTED;
++++++++ +  }
++++++++ +  
++++++++ +  #undef HidParser_GetValueCaps
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_GetValueCaps(
++++++++ +    HIDP_REPORT_TYPE ReportType,
++++++++ +    PHIDP_VALUE_CAPS ValueCaps,
++++++++ +    PULONG ValueCapsLength,
++++++++ +    PHIDP_PREPARSED_DATA PreparsedData)
++++++++ +  {
++++++++ +      UNIMPLEMENTED
++++++++ +      ASSERT(FALSE);
++++++++ +      return STATUS_NOT_IMPLEMENTED;
++++++++ +  }
index 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000,f305c22,0000000,f305c22,f305c22..104ceee
mode 000000,000000,000000,000000,000000,000000,000000,000000,100644,000000,100644,100644..100644
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
--- /dev/null
@@@@@@@@@@@@@ -1,0 -1,0 -1,0 -1,0 -1,0 -1,0 -1,0 -1,0 -1,427 -1,0 -1,427 -1,427 +1,428 @@@@@@@@@@@@@
        - --    HIDPARSER_STATUS_USAGE_NOT_FOUND = 8
++++++++ +  /*
++++++++ +   * PROJECT:     ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
++++++++ +   * LICENSE:     GPL - See COPYING in the top level directory
++++++++ +   * FILE:        lib/drivers/hidparser/hidparser.c
++++++++ +   * PURPOSE:     HID Parser
++++++++ +   * PROGRAMMERS:
++++++++ +   *              Michael Martin (michael.martin@reactos.org)
++++++++ +   *              Johannes Anderwald (johannes.anderwald@reactos.org)
++++++++ +   */
++++++++ +  
++++++++ +  #pragma once
++++++++ +  
++++++++ +  #define _HIDPI_
++++++++ +  #define _HIDPI_NO_FUNCTION_MACROS_
++++++++ +  #include <ntddk.h>
++++++++ +  #include <hidpddi.h>
++++++++ +  #include <hidpi.h>
++++++++ +  #include <debug.h>
++++++++ +  
++++++++ +  //
++++++++ +  // function prototypes
++++++++ +  //
++++++++ +  typedef PVOID (NTAPI *PHIDPARSER_ALLOC_FUNCTION)(ULONG Size);
++++++++ +  typedef VOID (NTAPI *PHIDPARSER_FREE_FUNCTION)(PVOID Item);
++++++++ +  typedef VOID (NTAPI *PHIDPARSER_ZERO_FUNCTION)(PVOID Item, ULONG Size);
++++++++ +  typedef VOID (NTAPI *PHIDPARSER_COPY_FUNCTION)(PVOID Target, PVOID Source, ULONG Size);
++++++++ +  typedef VOID (NTAPI *PHIDPARSER_DEBUG_FUNCTION)(LPCSTR Src, ...);
++++++++ +  
++++++++ +  //
++++++++ +  // status code
++++++++ +  //
++++++++ +  typedef long HIDPARSER_STATUS;
++++++++ +  
++++++++ +  //
++++++++ +  // result codes
++++++++ +  //
++++++++ +  typedef enum
++++++++ +  {
++++++++ +      HIDPARSER_STATUS_SUCCESS = 0,
++++++++ +      HIDPARSER_STATUS_INSUFFICIENT_RESOURCES = -1,
++++++++ +      HIDPARSER_STATUS_NOT_IMPLEMENTED = -2,
++++++++ +      HIDPARSER_STATUS_REPORT_NOT_FOUND = -3,
++++++++ +      HIDPARSER_STATUS_COLLECTION_NOT_FOUND = -4,
++++++++ +      HIDPARSER_STATUS_INVALID_REPORT_LENGTH = -5,
++++++++ +      HIDPARSER_STATUS_INVALID_REPORT_TYPE = -6,
++++++++ +      HIDPARSER_STATUS_BUFFER_TOO_SMALL = -7,
++++++++++++    HIDPARSER_STATUS_USAGE_NOT_FOUND = -8,
++++++++++++    HIDPARSER_STATUS_I8042_TRANS_UNKNOWN = -9
++++++++ +  }HIDPARSER_STATUS_CODES;
++++++++ +  
++++++++ +  typedef struct
++++++++ +  {
++++++++ +      //
++++++++ +      // size of struct
++++++++ +      //
++++++++ +      unsigned long Size;
++++++++ +  
++++++++ +      //
++++++++ +      // allocation function
++++++++ +      //
++++++++ +      PHIDPARSER_ALLOC_FUNCTION Alloc;
++++++++ +  
++++++++ +      //
++++++++ +      // free function
++++++++ +      //
++++++++ +      PFREE_FUNCTION Free;
++++++++ +  
++++++++ +      //
++++++++ +      // zero function
++++++++ +      //
++++++++ +      PHIDPARSER_ZERO_FUNCTION Zero;
++++++++ +  
++++++++ +      //
++++++++ +      // copy function
++++++++ +      //
++++++++ +      PHIDPARSER_COPY_FUNCTION Copy;
++++++++ +  
++++++++ +      //
++++++++ +      // debug function
++++++++ +      //
++++++++ +      PHIDPARSER_DEBUG_FUNCTION Debug;
++++++++ +  
++++++++ +      //
++++++++ +      // parser context
++++++++ +      //
++++++++ +      void * ParserContext;
++++++++ +  
++++++++ +  }HID_PARSER, *PHID_PARSER;
++++++++ +  
++++++++ +  HIDPARSER_STATUS
++++++++ +  HidParser_AllocateParser(
++++++++ +      IN PHIDPARSER_ALLOC_FUNCTION AllocFunction,
++++++++ +      IN PHIDPARSER_FREE_FUNCTION FreeFunction,
++++++++ +      IN PHIDPARSER_ZERO_FUNCTION ZeroFunction,
++++++++ +      IN PHIDPARSER_COPY_FUNCTION CopyFunction,
++++++++ +      IN PHIDPARSER_DEBUG_FUNCTION DebugFunction,
++++++++ +      OUT PHID_PARSER *OutParser);
++++++++ +  
++++++++ +  VOID
++++++++ +  HidParser_InitParser(
++++++++ +      IN PHIDPARSER_ALLOC_FUNCTION AllocFunction,
++++++++ +      IN PHIDPARSER_FREE_FUNCTION FreeFunction,
++++++++ +      IN PHIDPARSER_ZERO_FUNCTION ZeroFunction,
++++++++ +      IN PHIDPARSER_COPY_FUNCTION CopyFunction,
++++++++ +      IN PHIDPARSER_DEBUG_FUNCTION DebugFunction,
++++++++ +      IN PVOID ParserContext,
++++++++ +      OUT PHID_PARSER Parser);
++++++++ +  
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_GetCollectionDescription(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      IN PHIDP_REPORT_DESCRIPTOR ReportDesc,
++++++++ +      IN ULONG DescLength,
++++++++ +      IN POOL_TYPE PoolType,
++++++++ +      OUT PHIDP_DEVICE_DESC DeviceDescription);
++++++++ +  
++++++++ +  VOID
++++++++ +  NTAPI
++++++++ +  HidParser_FreeCollectionDescription(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      IN PHIDP_DEVICE_DESC   DeviceDescription);
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_GetCaps(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      OUT PHIDP_CAPS  Capabilities);
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_GetSpecificValueCaps(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      IN HIDP_REPORT_TYPE  ReportType,
++++++++ +      IN USAGE  UsagePage,
++++++++ +      IN USHORT  LinkCollection,
++++++++ +      IN USAGE  Usage,
++++++++ +      OUT PHIDP_VALUE_CAPS  ValueCaps,
++++++++ +      IN OUT PULONG  ValueCapsLength);
++++++++ +  
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_GetButtonCaps(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      HIDP_REPORT_TYPE ReportType,
++++++++ +      PHIDP_BUTTON_CAPS ButtonCaps,
++++++++ +      PUSHORT ButtonCapsLength);
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_GetSpecificButtonCaps(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      IN HIDP_REPORT_TYPE  ReportType,
++++++++ +      IN USAGE  UsagePage,
++++++++ +      IN USHORT  LinkCollection,
++++++++ +      IN USAGE  Usage,
++++++++ +      OUT PHIDP_BUTTON_CAPS  ButtonCaps,
++++++++ +      IN OUT PULONG  ButtonCapsLength);
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_GetScaledUsageValue(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      IN HIDP_REPORT_TYPE  ReportType,
++++++++ +      IN USAGE  UsagePage,
++++++++ +      IN USHORT  LinkCollection  OPTIONAL,
++++++++ +      IN USAGE  Usage,
++++++++ +      OUT PLONG  UsageValue,
++++++++ +      IN PCHAR  Report,
++++++++ +      IN ULONG  ReportLength);
++++++++ +  
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_GetData(
++++++++ +    IN HIDP_REPORT_TYPE  ReportType,
++++++++ +    OUT PHIDP_DATA  DataList,
++++++++ +    IN OUT PULONG  DataLength,
++++++++ +    IN PHIDP_PREPARSED_DATA  PreparsedData,
++++++++ +    IN PCHAR  Report,
++++++++ +    IN ULONG  ReportLength);
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_GetExtendedAttributes(
++++++++ +    IN HIDP_REPORT_TYPE  ReportType,
++++++++ +    IN USHORT  DataIndex,
++++++++ +    IN PHIDP_PREPARSED_DATA  PreparsedData,
++++++++ +    OUT PHIDP_EXTENDED_ATTRIBUTES  Attributes,
++++++++ +    IN OUT PULONG  LengthAttributes);
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_GetLinkCollectionNodes(
++++++++ +      OUT PHIDP_LINK_COLLECTION_NODE  LinkCollectionNodes,
++++++++ +      IN OUT PULONG  LinkCollectionNodesLength,
++++++++ +      IN PHIDP_PREPARSED_DATA  PreparsedData);
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_GetUsageValue(
++++++++ +    IN HIDP_REPORT_TYPE  ReportType,
++++++++ +    IN USAGE  UsagePage,
++++++++ +    IN USHORT  LinkCollection,
++++++++ +    IN USAGE  Usage,
++++++++ +    OUT PULONG  UsageValue,
++++++++ +    IN PHIDP_PREPARSED_DATA  PreparsedData,
++++++++ +    IN PCHAR  Report,
++++++++ +    IN ULONG  ReportLength);
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_UsageListDifference(
++++++++ +    IN PUSAGE  PreviousUsageList,
++++++++ +    IN PUSAGE  CurrentUsageList,
++++++++ +    OUT PUSAGE  BreakUsageList,
++++++++ +    OUT PUSAGE  MakeUsageList,
++++++++ +    IN ULONG  UsageListLength);
++++++++ +  
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  ULONG
++++++++ +  NTAPI
++++++++ +  HidParser_MaxUsageListLength(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      IN HIDP_REPORT_TYPE  ReportType,
++++++++ +      IN USAGE  UsagePage  OPTIONAL);
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_GetUsages(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      IN HIDP_REPORT_TYPE  ReportType,
++++++++ +      IN USAGE  UsagePage,
++++++++ +      IN USHORT  LinkCollection  OPTIONAL,
++++++++ +      OUT USAGE  *UsageList,
++++++++ +      IN OUT ULONG  *UsageLength,
++++++++ +      IN PCHAR  Report,
++++++++ +      IN ULONG  ReportLength);
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_GetUsagesEx(
++++++++ +      IN PHID_PARSER Parser,
++++++++ +      IN HIDP_REPORT_TYPE  ReportType,
++++++++ +      IN USHORT  LinkCollection,
++++++++ +      OUT PUSAGE_AND_PAGE  ButtonList,
++++++++ +      IN OUT ULONG  *UsageLength,
++++++++ +      IN PCHAR  Report,
++++++++ +      IN ULONG  ReportLength);
++++++++ +  
++++++++ +  
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_SysPowerEvent (
++++++++ +      IN PCHAR HidPacket,
++++++++ +      IN USHORT HidPacketLength,
++++++++ +      IN PHIDP_PREPARSED_DATA Ppd,
++++++++ +      OUT PULONG OutputBuffer);
++++++++ +  
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_SysPowerCaps (
++++++++ +      IN PHIDP_PREPARSED_DATA Ppd,
++++++++ +      OUT PULONG OutputBuffer);
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_GetUsageValueArray(
++++++++ +    IN HIDP_REPORT_TYPE  ReportType,
++++++++ +    IN USAGE  UsagePage,
++++++++ +    IN USHORT  LinkCollection  OPTIONAL,
++++++++ +    IN USAGE  Usage,
++++++++ +    OUT PCHAR  UsageValue,
++++++++ +    IN USHORT  UsageValueByteLength,
++++++++ +    IN PHIDP_PREPARSED_DATA  PreparsedData,
++++++++ +    IN PCHAR  Report,
++++++++ +    IN ULONG  ReportLength);
++++++++ +  
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_UsageAndPageListDifference(
++++++++ +     IN PUSAGE_AND_PAGE  PreviousUsageList,
++++++++ +     IN PUSAGE_AND_PAGE  CurrentUsageList,
++++++++ +     OUT PUSAGE_AND_PAGE  BreakUsageList,
++++++++ +     OUT PUSAGE_AND_PAGE  MakeUsageList,
++++++++ +     IN ULONG  UsageListLength);
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_UnsetUsages(
++++++++ +    IN HIDP_REPORT_TYPE  ReportType,
++++++++ +    IN USAGE  UsagePage,
++++++++ +    IN USHORT  LinkCollection,
++++++++ +    IN PUSAGE  UsageList,
++++++++ +    IN OUT PULONG  UsageLength,
++++++++ +    IN PHIDP_PREPARSED_DATA  PreparsedData,
++++++++ +    IN OUT PCHAR  Report,
++++++++ +    IN ULONG  ReportLength);
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_TranslateUsagesToI8042ScanCodes(
++++++++ +    IN PUSAGE  ChangedUsageList,
++++++++ +    IN ULONG  UsageListLength,
++++++++ +    IN HIDP_KEYBOARD_DIRECTION  KeyAction,
++++++++ +    IN OUT PHIDP_KEYBOARD_MODIFIER_STATE  ModifierState,
++++++++ +    IN PHIDP_INSERT_SCANCODES  InsertCodesProcedure,
++++++++ +    IN PVOID  InsertCodesContext);
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_TranslateUsageAndPagesToI8042ScanCodes(
++++++++ +     IN PUSAGE_AND_PAGE  ChangedUsageList,
++++++++ +     IN ULONG  UsageListLength,
++++++++ +     IN HIDP_KEYBOARD_DIRECTION  KeyAction,
++++++++ +     IN OUT PHIDP_KEYBOARD_MODIFIER_STATE  ModifierState,
++++++++ +     IN PHIDP_INSERT_SCANCODES  InsertCodesProcedure,
++++++++ +     IN PVOID  InsertCodesContext);
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_SetUsages(
++++++++ +    IN HIDP_REPORT_TYPE  ReportType,
++++++++ +    IN USAGE  UsagePage,
++++++++ +    IN USHORT  LinkCollection,
++++++++ +    IN PUSAGE  UsageList,
++++++++ +    IN OUT PULONG  UsageLength,
++++++++ +    IN PHIDP_PREPARSED_DATA  PreparsedData,
++++++++ +    IN OUT PCHAR  Report,
++++++++ +    IN ULONG  ReportLength);
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_SetUsageValueArray(
++++++++ +    IN HIDP_REPORT_TYPE  ReportType,
++++++++ +    IN USAGE  UsagePage,
++++++++ +    IN USHORT  LinkCollection  OPTIONAL,
++++++++ +    IN USAGE  Usage,
++++++++ +    IN PCHAR  UsageValue,
++++++++ +    IN USHORT  UsageValueByteLength,
++++++++ +    IN PHIDP_PREPARSED_DATA  PreparsedData,
++++++++ +    OUT PCHAR  Report,
++++++++ +    IN ULONG  ReportLength);
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_SetUsageValue(
++++++++ +    IN HIDP_REPORT_TYPE  ReportType,
++++++++ +    IN USAGE  UsagePage,
++++++++ +    IN USHORT  LinkCollection,
++++++++ +    IN USAGE  Usage,
++++++++ +    IN ULONG  UsageValue,
++++++++ +    IN PHIDP_PREPARSED_DATA  PreparsedData,
++++++++ +    IN OUT PCHAR  Report,
++++++++ +    IN ULONG  ReportLength);
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_SetScaledUsageValue(
++++++++ +    IN HIDP_REPORT_TYPE  ReportType,
++++++++ +    IN USAGE  UsagePage,
++++++++ +    IN USHORT  LinkCollection  OPTIONAL,
++++++++ +    IN USAGE  Usage,
++++++++ +    IN LONG  UsageValue,
++++++++ +    IN PHIDP_PREPARSED_DATA  PreparsedData,
++++++++ +    IN OUT PCHAR  Report,
++++++++ +    IN ULONG  ReportLength);
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_SetData(
++++++++ +    IN HIDP_REPORT_TYPE  ReportType,
++++++++ +    IN PHIDP_DATA  DataList,
++++++++ +    IN OUT PULONG  DataLength,
++++++++ +    IN PHIDP_PREPARSED_DATA  PreparsedData,
++++++++ +    IN OUT PCHAR  Report,
++++++++ +    IN ULONG  ReportLength);
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  ULONG
++++++++ +  NTAPI
++++++++ +  HidParser_MaxDataListLength(
++++++++ +    IN HIDP_REPORT_TYPE  ReportType,
++++++++ +    IN PHIDP_PREPARSED_DATA  PreparsedData);
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_InitializeReportForID(
++++++++ +    IN HIDP_REPORT_TYPE  ReportType,
++++++++ +    IN UCHAR  ReportID,
++++++++ +    IN PHIDP_PREPARSED_DATA  PreparsedData,
++++++++ +    IN OUT PCHAR  Report,
++++++++ +    IN ULONG  ReportLength);
++++++++ +  
++++++++ +  HIDAPI
++++++++ +  NTSTATUS
++++++++ +  NTAPI
++++++++ +  HidParser_GetValueCaps(
++++++++ +    HIDP_REPORT_TYPE ReportType,
++++++++ +    PHIDP_VALUE_CAPS ValueCaps,
++++++++ +    PULONG ValueCapsLength,
++++++++ +    PHIDP_PREPARSED_DATA PreparsedData);
@@@@@@@@@@@@@ -9,8 -8,7 -8,7 -8,7 -8,7 -8,7 -8,7 -8,7 -8,8 -8,7 -8,7 -8,8 +9,9 @@@@@@@@@@@@@ list(APPEND INF_FILE
                display.inf
                fdc.inf
                font.inf
 +++++++++++    hal.inf
                hdc.inf
++++++++ ++     input.inf
                intl.inf
                keyboard.inf
                ks.inf
@@@@@@@@@@@@@ -16,12 -16,9 -16,9 -16,9 -16,9 -16,9 -16,9 -16,9 -16,10 -16,9 -16,9 -16,10 +16,13 @@@@@@@@@@@@@ ClassGUID={00000000-0000-0000-0000-0000
            ; we use a separate one to keep things clean\r
            battery.inf\r
            cdrom.inf\r
 +++++++++++cpu.inf\r
 +++++++++++disk.inf\r
            display.inf\r
            fdc.inf\r
 +++++++++++hal.inf\r
            hdc.inf\r
++++++++ ++ input.inf\r
            keyboard.inf\r
            machine.inf\r
            msmouse.inf\r
@@@@@@@@@@@@@ -1205,7 -1160,8 -1160,8 -1160,8 -1160,8 -1160,8 -1160,8 -1160,8 -1160,8 -1160,8 -1160,8 -1160,8 +1205,33 @@@@@@@@@@@@@ ObQueryDeviceMapInformation(IN PEPROCES
                              ObSystemDeviceMap->DriveType,
                              sizeof(ObSystemDeviceMap->DriveType));
            
 -----------    /* FIXME: Release the DeviceMap Spinlock */
 -----------    // KeReleasepinLock(DeviceMap->Lock, OldIrql);
 +++++++++++    KeReleaseGuardedMutex(&ObpDeviceMapLock);
 +++++++++++}
 +++++++++++
++++++++++++NTSTATUS
++++++++++++NTAPI
++++++++++++ObIsDosDeviceLocallyMapped(
++++++++++++    IN ULONG Index,
++++++++++++    OUT PUCHAR DosDeviceState)
++++++++++++{
++++++++++++    /* check parameters */
++++++++++++    if (Index < 1 || Index > 26)
++++++++++++    {
++++++++++++        /* invalid index */
++++++++++++        return STATUS_INVALID_PARAMETER;
++++++++++++    }
++++++++++++
++++++++++++    /* acquire lock */
++++++++++++    KeAcquireGuardedMutex(&ObpDeviceMapLock);
++++++++++++
++++++++++++    /* get drive mapping status */
++++++++++++    *DosDeviceState = (ObSystemDeviceMap->DriveMap & (1 << Index)) != 0;
++++++++++++
++++++++++++    /* release lock */
++++++++++++    KeReleaseGuardedMutex(&ObpDeviceMapLock);
++++++++++++
++++++++++++    /* done */
++++++++++++    return STATUS_SUCCESS;
+           }
+           
            /* EOF */