#include <windows.h>
#include <shlwapi.h>
#include "usbview.h"
//*****************************************************************************
// Display HID descriptor and report/physical descriptors
//*****************************************************************************
// Calculate length of descriptor item, including the first byte
static int DecodeLength(const BYTE *data) {
BYTE b=*data;
if (b==0xFE) return data[1]+3; // long item (6.2.2.3)
else switch (b&=3) { // short item (6.2.2.2)
case 3: return 5;
default: return b+1;
}
}
static void AppendHidReportDesc(const BYTE *data, int l) {
int indent=0;
int upage=-1;
while (l>0) {
int i,ll=DecodeLength(data);
BYTE b=*data&0xFC;
long iarg=0;
DWORD uarg=0;
const char *p;
char buf[64],b2[64];
switch (ll) {
case 2: iarg=(char)data[1]; uarg=data[1]; break;
case 3: iarg=*(short*)(data+1); uarg=*(WORD*)(data+1); break;
case 5: iarg=*(long*)(data+1); uarg=*(DWORD*)(data+1); break;
}
if (ll>l) ll=l;
if (b==0x04) upage=uarg;
if (b==0xC0 && indent) indent--;
for (i=-3; i<indent; i++) AppendTextBuffer(" ");
p = Lookup('R',b,-1,-1);
buf[0]=0;
if (p) {
const char* t="%s";
const char *q,*r;
switch (b) {
case 0x04: { // usage page
q=Lookup('UH',uarg,-1,-1);
if (q) t="%s (%s)";
else t="%s (0x%02X)", q=(const char*)uarg;
}break;
case 0x08:
case 0x18:
case 0x28: if (ll>3) { // long usage
q=Lookup('UH',HIWORD(uarg),-1,-1);
if (q) {
r=Lookup('UH',HIWORD(uarg),LOWORD(uarg),-1);
if (r) t="%s (%s:%s)";
else t="%s (%s:0x%02X)", r=(const char*)LOWORD(uarg);
}else t="%s (0x%02X:0x%02X)", q=(const char*)HIWORD(uarg), r=(const char*)LOWORD(uarg);
}else{ // short (normal) usage
q=Lookup('UH',upage,uarg,-1);
if (q) t="%s (%s)";
else t="%s (0x%02X)", q=(const char*)uarg;
}break;
case 0xA0: {
static const char *coll[]={"Physical","Application","Logical","Report","Named Array","Usage Switch","Usage Modifier"};
if (uarg<elemof(coll)) t="%s (%s)", q=coll[uarg];
else t="%s (0x%02X)", q=(const char*)uarg;
}break;
case 0x14:
case 0x24:
case 0x34:
case 0x44: t="%s (%d)", q=(const char*)iarg; break;
case 0x38:
case 0x48:
case 0x58:
case 0xA8:
case 0x74:
case 0x94: t="%s (%u)", q=(const char*)uarg; break;
case 0x78:
case 0x88:
case 0x98:
case 0x54:
case 0x64:
case 0x84: t="%s (0x%02X)", q=(const char*)uarg; break;
case 0x80:
case 0x90:
case 0xB0: {
static const char *bits[]={"Const","Var","Rel","Wrap","Nonlinear","PrefState","NullState","Volatile","BuffBytes"};
int i;
char *r=b2;
q="Array";
t="%s (%s)";
for (i=0; i<elemof(bits); i++) if (uarg>>i&1) {
if (r!=b2) *r++=',';
lstrcpynA(r,bits[i],(int)(b2+elemof(b2)-r));
r+=lstrlenA(r);
}
if (r!=b2) q=b2;
}break;
}
wnsprintfA(buf,sizeof(buf),t,p,q,r);
}
AppendTextBuffer(
#ifdef UNICODE
"%-40S"
#else
"%-40s"
#endif
,buf);
AppendHexDump(data,ll);
if (b==0xA0) indent++;
data+=ll;
l-=ll;
}
}
static void AppendHidPhysDesc(const BYTE *data, int l) {
AppendHexDump(data,l);
}
extern void DisplayHidDescriptor(const USB_HID_DESCRIPTOR*HidDesc, const BYTE*data) {
UCHAR i;
BYTE lenPhys0=0; // set to !=0 when first physical descriptor is detected
const char *p;
AppendTextBuffer("\r\nHID Descriptor:\r\n");
AppendTextBuffer(" bcdHID: 0x%04X\r\n", HidDesc->bcdHID);
AppendTextBuffer(" bCountryCode: 0x%02X", HidDesc->bCountryCode);
p = Lookup('CH',HidDesc->bCountryCode,-1,-1);
if (p) AppendTextBuffer(" (" ASTR ")",p);
AppendTextBuffer("\r\n");
AppendTextBuffer(" bNumDescriptors: 0x%02X\r\n", HidDesc->bNumDescriptors);
for (i=0; i<HidDesc->bNumDescriptors; i++) {
int l=HidDesc->OptionalDescriptors[i].wDescriptorLength;
if (HidDesc->OptionalDescriptors[i].bDescriptorType==0x23 && !lenPhys0) {
lenPhys0=data?*data++:1;
if (!lenPhys0) OOPS();
AppendTextBuffer(" (automatic Physical Descriptor 0 length %d)\r\n",lenPhys0);
if (data) {
AppendHexDump(data,lenPhys0);
data+=lenPhys0;
}
}
AppendTextBuffer(" bDescriptorType: 0x%02X", HidDesc->OptionalDescriptors[i].bDescriptorType);
p = Lookup('IH',HidDesc->OptionalDescriptors[i].bDescriptorType,-1,-1);
if (p) AppendTextBuffer(" (" ASTR ")",p);
AppendTextBuffer("\r\n");
AppendTextBuffer(" wDescriptorLength: 0x%04X (%d bytes)\r\n", l,l);
if (data) {
switch (HidDesc->OptionalDescriptors[i].bDescriptorType) {
case 0x22: AppendHidReportDesc(data,l); break;
case 0x23: AppendHidPhysDesc(data,l); break;
default: AppendHexDump(data,l);
}
data+=l;
}
}
}
Detected encoding: ASCII (7 bit) | 2
|