Source file: /~heha/hs/usbview.zip/src/disphid.c

#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