|
|
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
HID.c
Abstract:
WinDbg Extension Api
Author:
Kenneth D. Ray (kenray) June 1997
Environment:
User Mode.
Revision History:
--*/
#include "precomp.h"
typedef union _HID_PPD_FLAGS { struct { ULONG InputChannels : 1; ULONG OutputChannels : 1; ULONG FeatureChannels : 1; ULONG LinkCollections : 1; ULONG FullChannelListing : 1; ULONG ReportLocation : 1; ULONG Reserved : 25; ULONG IgnoreSignature : 1; }; ULONG64 Flags; } HID_PPD_FLAGS;
typedef union _HID_FLAGS { struct { ULONG FullListing : 1; ULONG PowerListing : 1; ULONG HidPDeviceDesc : 1; ULONG FileListing : 1; ULONG Reserved : 27; }; ULONG64 Flags; } HID_FLAGS;
#define PRINT_FLAGS(value, flag) \
if ((value) & (flag)) { \ dprintf (#flag " "); \ }
//
// Local function declarations
//
VOID HID_DumpPpd (ULONG64 Ppd, HID_PPD_FLAGS Flags); VOID HID_DumpFDOExt (ULONG64 Fdo); VOID HID_DumpPDOExt (ULONG64 Pdo);
DECLARE_API( hidppd )
/*++
Routine Description:
Dumps a HID Preparsed Data blob
Arguments:
args - Address flags
Return Value:
None
--*/
{ ULONG64 memLoc=0; ULONG result; ULONG size; HID_PPD_FLAGS flags; ULONG InSize;
flags.Flags = 0;
if (!*args) { dprintf ("hidppd <address> [flags]\n"); } else { if (GetExpressionEx(args, &memLoc, &args)) { GetExpressionEx(args, &(flags.Flags), &args); } }
dprintf ("Dump Ppd %p %x \n", memLoc, (ULONG)flags.Flags);
//
// Get the preparsed data
//
if (GetFieldValue (memLoc, "hidparse!_HIDP_PREPARSED_DATA", "Input.Size", InSize)) { dprintf ("Could not read hidparse!_HIDP_PREPARSED_DATA @%p\n", memLoc); return E_INVALIDARG; }
InitTypeRead(memLoc, hidparse!_HIDP_PREPARSED_DATA); size = GetTypeSize ("hidparse!_HIDP_PREPARSED_DATA") + (GetTypeSize ("hidparse!_HIDP_CHANNEL_DESC") * ((ULONG) ReadField(Input.Size) + (ULONG) ReadField(Output.Size) + (ULONG) ReadField(Feature.Size))) + (GetTypeSize ("hidparse!_HIDP_LINK_COLLECTION_NODE") * (ULONG) ReadField(LinkCollectionArrayLength));
dprintf ("TOT Size: %x\n", size);
HID_DumpPpd (memLoc, flags);
return S_OK; }
VOID HID_DumpChannel ( ULONG64 Channel, HID_PPD_FLAGS Flags ) { InitTypeRead(Channel, hidparse!_HIDP_CHANNEL_DESC);
dprintf ("-------CHANNEL---------\n"); dprintf ("P %x ID %x Col %x Sz %x Cnt %x UMin %x UMax %x ", (ULONG) ReadField(UsagePage), (ULONG) ReadField(ReportID), (ULONG) ReadField(LinkCollection), (ULONG) ReadField(ReportSize), (ULONG) ReadField(ReportCount), (ULONG) ReadField(Range.UsageMin), (ULONG) ReadField(Range.UsageMax));
if (ReadField(MoreChannels)) { dprintf ("MoreChannels "); } if (ReadField(IsConst)) { dprintf ("Const "); } if (ReadField(IsButton)) { dprintf ("Button "); } else { dprintf ("Value "); } if (ReadField(IsAbsolute)) { dprintf ("Absolute "); } if (ReadField(IsAlias)) { dprintf ("ALIAS! "); }
dprintf ("\n");
if (Flags.FullChannelListing) { dprintf ("LinkUP %x LinkU %x SMin %x SMax %x " "DMin %x DMax %x IndexMin %x IndexMax %x\n", (ULONG) ReadField(LinkUsagePage), (ULONG) ReadField(LinkUsage), (ULONG) ReadField(Range.StringMin), (ULONG) ReadField(Range.StringMax), (ULONG) ReadField(Range.DesignatorMin), (ULONG) ReadField(Range.DesignatorMax), (ULONG) ReadField(Range.DataIndexMin), (ULONG) ReadField(Range.DataIndexMax));
if (!ReadField(IsButton)) { if (ReadField(Data.HasNull)) { dprintf ("Has Null "); } dprintf ("LMin %x LMax %x PMin %x PMax %x \n", (ULONG) ReadField(Data.LogicalMin), (ULONG) ReadField(Data.LogicalMax), (ULONG) ReadField(Data.PhysicalMin), (ULONG) ReadField(Data.PhysicalMax)); } }
if (Flags.ReportLocation) { dprintf ("ByteOffset %x BitOffset %x BitLength %x ByteEnd %x\n", (ULONG) ReadField(ByteOffset), (ULONG) ReadField(BitOffset), (ULONG) ReadField(BitLength), (ULONG) ReadField(ByteEnd)); } }
VOID HID_DumpLink ( ULONG LinkNo, ULONG64 Node ) { InitTypeRead(Node, hidparse!_HIDP_LINK_COLLECTION_NODE);
dprintf ("Link %x: U %x P %x Par %p #C %x NxSib %p 1stC %p ", LinkNo, (ULONG) ReadField(LinkUsage), (ULONG) ReadField(LinkUsagePage), ReadField(Parent), (ULONG) ReadField(NumberOfChildren), ReadField(NextSibling), ReadField(FirstChild));
if (ReadField(IsAlias)) { dprintf (" ALIAS\n"); } else { dprintf ("\n"); } }
VOID HID_DumpPpd ( ULONG64 Ppd, HID_PPD_FLAGS Flags ) { ULONG i; ULONG64 channel; ULONG64 node; ULONG SizeOfChannels, DataOff;
if (InitTypeRead(Ppd, hidparse!_HIDP_PREPARSED_DATA)) { dprintf("Cannot read type hidparse!_HIDP_PREPARSED_DATA at %p\n", Ppd); return; }
if (!Flags.IgnoreSignature) { if ((HIDP_PREPARSED_DATA_SIGNATURE1 != (ULONG) ReadField(Signature1)) || (HIDP_PREPARSED_DATA_SIGNATURE2 != (ULONG) ReadField(Signature2))) {
dprintf("Preparsed Data signature does not match, probably aint\n"); return; } }
SizeOfChannels = GetTypeSize("hidparse!_HIDP_CHANNEL_DESC"); GetFieldOffset("hidparse!_HIDP_CHANNEL_DESC", "Data", &DataOff);
if (Flags.InputChannels) { dprintf ("\n========== Input Channels =========\n"); for (i = (ULONG) ReadField(Input.Offset); i < (ULONG) ReadField(Input.Index); i++) { channel = Ppd + DataOff + SizeOfChannels * i; HID_DumpChannel (channel, Flags); } } else { dprintf ("Input channels: off %x sz %x indx %x bytelen %x\n", (ULONG) ReadField(Input.Offset), (ULONG) ReadField(Input.Size), (ULONG) ReadField(Input.Index), (ULONG) ReadField(Input.ByteLen)); }
if (Flags.OutputChannels) { dprintf ("\n========== Output Channels =========\n"); for (i = (ULONG) ReadField(Output.Offset); i < (ULONG) ReadField(Output.Index); i++) { channel = Ppd + DataOff + SizeOfChannels * i; HID_DumpChannel (channel, Flags); } } else { dprintf ("Output channels: off %x sz %x indx %x bytelen %x\n", (ULONG) ReadField(Output.Offset), (ULONG) ReadField(Output.Size), (ULONG) ReadField(Output.Index), (ULONG) ReadField(Output.ByteLen)); }
if (Flags.FeatureChannels) { dprintf ("\n========== Feature Channels =========\n"); for (i = (ULONG) ReadField(Feature.Offset); i < (ULONG) ReadField(Feature.Index); i++) { channel = Ppd + DataOff + SizeOfChannels * i; HID_DumpChannel (channel, Flags); }
} else { dprintf ("Feature channels: off %x sz %x indx %x bytelen %x\n", (ULONG) ReadField(Feature.Offset), (ULONG) ReadField(Feature.Size), (ULONG) ReadField(Feature.Index), (ULONG) ReadField(Feature.ByteLen)); }
if (Flags.LinkCollections) { ULONG NodeSize;
dprintf ("\n========== Link Collections =========\n"); node = (ReadField(RawBytes) + ReadField(LinkCollectionArrayOffset)); NodeSize = GetTypeSize("hidparse!_HIDP_LINK_COLLECTION_NODE");
for (i = 0; i < (ULONG) ReadField(LinkCollectionArrayLength); i++, node+=NodeSize) { HID_DumpLink (i, node); }
} else { dprintf ("Link Collections: %x \n", (ULONG) ReadField(LinkCollectionArrayLength)); } dprintf ("\n"); }
VOID HID_DumpHidPDeviceDesc ( ULONG64 Desc, HID_FLAGS Flags ) { HID_PPD_FLAGS ppdFlags; ULONG result; ULONG i; ULONG size; PVOID col; PVOID rep; ULONG CollectionDescLength, ReportIDsLength; ULONG64 ReportIDs, CollectionDesc; ULONG SizeofDesc, SizeofRep;
UNREFERENCED_PARAMETER (Flags);
dprintf ("\n*** HID Device Descripton ***\n");
InitTypeRead(Desc, hidparse!_HIDP_DEVICE_DESC); CollectionDesc = ReadField(CollectionDesc); ReportIDs = ReadField(ReportIDs); CollectionDescLength = (ULONG) ReadField(CollectionDescLength); ReportIDsLength = (ULONG) ReadField(ReportIDsLength);
dprintf ("Col len: %x Report ID Len: %x\n", CollectionDescLength, ReportIDsLength);
SizeofDesc = GetTypeSize("hidparse!_HIDP_COLLECTION_DESC"); if (!SizeofDesc) { dprintf("Cannot find type hidparse!_HIDP_COLLECTION_DESC.\n"); return; }
SizeofRep = GetTypeSize("hidparse!_HIDP_REPORT_IDS"); if (!SizeofRep) { dprintf("Cannot find type hidparse!_HIDP_REPORT_IDS.\n"); return; }
size = CollectionDescLength * SizeofDesc; col = LocalAlloc (LPTR, size); if (NULL == col) { dprintf ("Could not allocate the memory\n"); return; }
if (!ReadMemory (CollectionDesc, col, size, &result)) { dprintf ("Could not read Ppd\n"); LocalFree (col); return; }
size = ReportIDsLength * SizeofRep; rep = LocalAlloc (LPTR, size); if (NULL == rep) { dprintf ("Could not allocate the memory\n"); LocalFree (col); return; }
if (!ReadMemory (ReportIDs, rep, size, &result)) { dprintf ("Could not read Ppd\n"); LocalFree (col); LocalFree (rep); return; } LocalFree (col); LocalFree (rep);
dprintf ("--- Top Collections -----\n"); for (i=0; i < CollectionDescLength; i++) { InitTypeRead(CollectionDesc + i*SizeofDesc, hidparse!_HIDP_COLLECTION_DESC);
dprintf ("%x: U %x UP %x ColNum %x In %x Out %x Fea %x Ppd %x\n", i, (ULONG) ReadField(.Usage), (ULONG) ReadField(.UsagePage), (ULONG) ReadField(.CollectionNumber), (ULONG) ReadField(.InputLength), (ULONG) ReadField(.OutputLength), (ULONG) ReadField(.FeatureLength), (ULONG) ReadField(.PreparsedData)); }
dprintf ("--- Report IDs -----\n"); for (i=0; i < ReportIDsLength; i++) { InitTypeRead(ReportIDs + i*SizeofRep, hidparse!_HIDP_REPORT_IDS);
dprintf ("%x: ID %x ColNum %x In %x Out %x Fea %x\n", i, (ULONG) ReadField(.ReportID), (ULONG) ReadField(.CollectionNumber), (ULONG) ReadField(.InputLength), (ULONG) ReadField(.OutputLength), (ULONG) ReadField(.FeatureLength)); } return; }
VOID HID_DumpPDOExt ( ULONG64 Pdo ) { InitTypeRead(Pdo, hidparse!_HIDCLASS_DEVICE_EXTENSION); dprintf("\n"); dprintf ("Collection Num %x Collection Index %x PDO %x Name %x \n" "Fdo Extension %x\n", (ULONG) ReadField(pdoExt.collectionNum), (ULONG) ReadField(pdoExt.collectionIndex), (ULONG) ReadField(pdoExt.pdo), (ULONG) ReadField(pdoExt.name), (ULONG) ReadField(pdoExt.deviceFdoExt)); dprintf ("\n"); }
VOID HID_DumpFDOExt ( ULONG64 Fdo ) { ULONG64 object; ULONG64 fdoExt; ULONG size; ULONG i; ULONG result; ULONG64 loc; ULONG64 startLoc; HID_FLAGS Flags; ULONG FdoExtOffset; PVOID collection; ULONG PtrSize; ULONG SizeOfClassColl; ULONG CollectionDescLength; ULONG64 classCollectionArray, deviceRelations; ULONG fileExtListOff, fileListOff; ULONG devCapOff;
InitTypeRead(Fdo, hidparse!_HIDCLASS_DEVICE_EXTENSION);
dprintf("\n"); dprintf("Fdo %p => PDO: %p NextDO %p \n" "MiniDeviceExt %p DriveExt %p\n", ReadField(fdoExt.fdo), ReadField(hidExt.PhysicalDeviceObject), ReadField(hidExt.NextDeviceObject), ReadField(hidExt.MiniDeviceExtension), ReadField(fdoExt.driverExt));
switch ((ULONG) ReadField(fdoExt.state)) { case DEVICE_STATE_INITIALIZED: dprintf ("DEVICE_STATE_INITIALIZED: \n"); break; case DEVICE_STATE_STARTING: dprintf ("DEVICE_STATE_STARTING: \n"); break; case DEVICE_STATE_START_SUCCESS: dprintf ("DEVICE_STATE_START_SUCCESS: \n"); break; case DEVICE_STATE_START_FAILURE: dprintf ("DEVICE_STATE_START_FAILURE: \n"); break; case DEVICE_STATE_STOPPED: dprintf ("DEVICE_STATE_STOPPED: \n"); break; case DEVICE_STATE_REMOVING: dprintf ("DEVICE_STATE_REMOVING: \n"); break; case DEVICE_STATE_REMOVED: dprintf ("DEVICE_STATE_REMOVED: \n"); break; case DEVICE_STATE_SUSPENDED: dprintf ("DEVICE_STATE_SUSPENDED: \n"); break; }
dprintf("\nHidDescriptor:: len %x bcd %x numDesc %x repleng %x \n", (ULONG) ReadField(fdoExt.hidDescriptor.bLength), (ULONG) ReadField(fdoExt.hidDescriptor.bcdHID), (ULONG) ReadField(fdoExt.hidDescriptor.bNumDescriptors), (ULONG) ReadField(fdoExt.hidDescriptor.DescriptorList[0].wReportLength));
dprintf("Raw Desriptor: %x length: %x \n", (ULONG) ReadField(fdoExt.rawReportDescription), (ULONG) ReadField(fdoExt.rawReportDescriptionLength));
dprintf("HIDP_DEVICE_DESC: %x\n", (ULONG) ReadField(fdoExt.deviceDesc)); dprintf("Collections: %x Report IDs: %x\n", (CollectionDescLength = (ULONG) ReadField(fdoExt.deviceDesc.CollectionDescLength)), (ULONG) ReadField(fdoExt.deviceDesc.ReportIDsLength));
dprintf("Device Relations Array: %p\n", (deviceRelations = ReadField(fdoExt.deviceRelations))); dprintf("Class Collection Array: %p\n", (classCollectionArray = ReadField(fdoExt.classCollectionArray)));
Flags.Flags = 0x0F;
HID_DumpHidPDeviceDesc (ReadField(fdoExt.deviceDesc), Flags);
PtrSize = DBG_PTR_SIZE; SizeOfClassColl = GetTypeSize ("HIDCLASS_COLLECTION"); size = (CollectionDescLength) * SizeOfClassColl;
collection = LocalAlloc (0, size); if (!collection) { dprintf ("Could not allocate the memory\n"); return; } //
// Read entire array so that its cached for each element
//
if (!ReadMemory (classCollectionArray, collection, size, &result)) { dprintf ("Could not read Collection array\n"); LocalFree (collection); return; }
size = (CollectionDescLength + 1)* PtrSize;
GetFieldOffset("HIDCLASS_COLLECTION", "FileExtensionList", &fileExtListOff); GetFieldOffset("HIDCLASS_FILE_EXTENSION", "FileList", &fileListOff);
dprintf ("------ Children -----\n"); for (i = 0; i < CollectionDescLength; i++) { ULONG64 objAddr;
ReadPointer(deviceRelations + i* PtrSize, &objAddr);
InitTypeRead(classCollectionArray + i*SizeOfClassColl, hidparse!_HIDCLASS_COLLECTION);
dprintf ("DO: %p: ColNum %x ColIndx %x DevExt %x\n" " # Opens %x, FileExtList.Flink %p \n" " PollInterval ms %x, PolledDeviceReadQueue.Flink %p\n" " SymLinName %x Ppd %x PowerIrp %x\n", objAddr, (ULONG) ReadField(CollectionNumber), (ULONG) ReadField(CollectionIndex), (ULONG) ReadField(DeviceExtension), (ULONG) ReadField(NumOpens), ReadField(FileExtensionList.Flink), (ULONG) ReadField(PollInterval_msec), ReadField(polledDeviceReadQueue.Flink), (ULONG) ReadField(SymbolicLinkName.Buffer), (ULONG) ReadField(phidDescriptor), (ULONG) ReadField(powerEventIrp));
dprintf (" DescSize %x polled %x VID %x PID %x Version %x\n", (ULONG) ReadField(hidCollectionInfo.DescriptorSize), (ULONG) ReadField(hidCollectionInfo.Polled), (ULONG) ReadField(hidCollectionInfo.VendorID), (ULONG) ReadField(hidCollectionInfo.ProductID), (ULONG) ReadField(hidCollectionInfo.VersionNumber));
loc = ReadField(FileExtensionList.Flink); startLoc = classCollectionArray + fileExtListOff;
dprintf (" File List %x\n", startLoc);
i=0; while ((loc != startLoc) && (i++ < 100)) { ULONG64 Flink;
loc = (loc - fileListOff);
if (GetFieldValue(loc, "hidparse!_HIDCLASS_FILE_EXTENSION", "FileList.Flink", Flink)) { dprintf ("could not read hidparse!_HIDCLASS_FILE_EXTENSION at %p\n", loc); LocalFree (collection); return; }
InitTypeRead(loc, hidparse!_HIDCLASS_COLLECTION); dprintf (" FileExt %p ColNum %x fdoExt %x\n" " PendingIrp.Flink %x Reports.Flink %x\n" " FILE %x Closing? %x \n", loc, (ULONG) ReadField(CollectionNumber), (ULONG) ReadField(fdoExt), (ULONG) ReadField(PendingIrpList.Flink), (ULONG) ReadField(ReportList.Flink), (ULONG) ReadField(FileObject), (ULONG) ReadField(Closing));
loc = Flink; } } GetFieldOffset("hidparse!_HIDCLASS_DEVICE_EXTENSION", "fdoExt.deviceCapabilities", &devCapOff); DumpDeviceCapabilities (Fdo + devCapOff);
LocalFree (collection); dprintf ("\n");
return; }
VOID DevExtHID( ULONG64 MemLocPtr ) /*++
Routine Description:
Dump a HID Device extension.
Arguments:
Extension Address of the extension to be dumped.
Return Value:
None.
--*/ { ULONG isClientPdo, Signature; ULONG64 MemLoc = MemLocPtr;
dprintf ("Dump HID Extension: %p\n", MemLoc);
if (GetFieldValue (MemLoc, "HIDCLASS_DEVICE_EXTENSION", "isClientPdo", isClientPdo)) { dprintf ("Could not read HID Extension\n"); }
GetFieldValue (MemLoc, "HIDCLASS_DEVICE_EXTENSION", "Signature", Signature); if (HID_DEVICE_EXTENSION_SIG != Signature) {
dprintf("HID Extension Signature does not match, probably aint\n"); return; }
if (isClientPdo) { HID_DumpPDOExt(MemLoc); } else { HID_DumpFDOExt(MemLoc); }
return; }
|