+
+static const char *class_names[] = {
+ "unknown",
+ "mass storage controller",
+ "network controller",
+ "display controller",
+ "multimedia device",
+ "memory controller",
+ "bridge device",
+ "simple communication controller",
+ "base system peripheral",
+ "input device",
+ "docking station",
+ "processor",
+ "serial bus controller",
+ "wireless controller",
+ "intelligent I/O controller",
+ "satellite communication controller",
+ "encryption/decryption controller",
+ "data acquisition & signal processing controller"
+};
+
+static const char *class_mass_names[] = {
+ "SCSI bus controller",
+ "IDE controller",
+ "floppy disk controller",
+ "IPI bus controller",
+ "RAID controller"
+};
+
+static const char *class_net_names[] = {
+ "ethernet controller",
+ "token ring controller",
+ "FDDI controller",
+ "ATM controller",
+ "ISDN controller"
+};
+
+static const char *class_disp_names[] = {
+ "VGA-compatible controller",
+ "XGA controller",
+ "3D controller"
+};
+
+static const char *class_mm_names[] = {
+ "video device",
+ "audio device",
+ "telephony device"
+};
+
+static const char *class_bridge_names[] = {
+ "host bridge",
+ "ISA bridge",
+ "EISA bridge",
+ "MCA bridge",
+ "PCI-to-PCI bridge",
+ "Subtractive decode PCI-to-PCI bridge",
+ "PCMCIA bridge",
+ "NuBus bridge",
+ "CardBus bridge",
+ "RACEway bridge"
+};
+
+static const char *class_comm_names[] = {
+ "serial controller",
+ "parallel/IEEE1284",
+ "multiport serial controller",
+ "modem"
+};
+
+static const char *class_base_names[] = {
+ "interrupt controller",
+ "DMA controller",
+ "timer",
+ "RTC",
+ "PCI hot-plug controller"
+};
+
+static const char *class_input_names[] = {
+ "keyboard controller",
+ "digitizer",
+ "mouse controller",
+ "scanner controller",
+ "gameport controller"
+};
+
+static const char *class_ser_names[] = {
+ "firewire",
+ "ACCESS.bus",
+ "SSA",
+ "USB",
+ "Fibre Channel",
+ "SMBus"
+};
+
+static const char *class_sat_names[] = {
+ "TV",
+ "audio",
+ "voice",
+ "data"
+};
+
+
+static const char *class_str(int cc)
+{
+ if(cc == 0xff) {
+ return "other";
+ }
+ if(cc >= 0x12) {
+ return "unknown";
+ }
+ return class_names[cc];
+}
+
+static const char *subclass_str(int cc, int sub)
+{
+ if(sub == 0x80) return "other";
+
+ switch(cc) {
+ case 0:
+ if(sub == 1) return "VGA-compatible device";
+ return "unknown";
+
+ case 1:
+ if(sub > 4) return "unknown";
+ return class_mass_names[sub];
+
+ case 2:
+ if(sub > 4) return "unknown";
+ return class_net_names[sub];
+
+ case 3:
+ if(sub > 2) return "unknown";
+ return class_disp_names[sub];
+
+ case 4:
+ if(sub > 2) return "unknown";
+ return class_mm_names[sub];
+
+ case 5:
+ if(sub == 0) return "RAM";
+ if(sub == 1) return "flash";
+ return "unknown";
+
+ case 6:
+ if(sub > 8) return "unknown";
+ return class_bridge_names[sub];
+
+ case 7:
+ if(sub > 3) return "unknown";
+ return class_comm_names[sub];
+
+ case 8:
+ if(sub > 4) return "unknown";
+ return class_base_names[sub];
+
+ case 9:
+ if(sub > 4) return "unknown";
+ return class_input_names[sub];
+
+ case 10:
+ if(sub == 0) return "generic docking station";
+ return "unknown";
+
+ case 11:
+ switch(sub) {
+ case 0: return "386";
+ case 1: return "486";
+ case 2: return "pentium";
+ case 0x10: return "alpha";
+ case 0x20: return "powerpc";
+ case 0x30: return "mips";
+ case 0x40: return "co-processor";
+ default:
+ break;
+ }
+ return "unknown";
+
+ case 12:
+ if(sub > 5) return "unknown";
+ return class_ser_names[sub];
+
+ case 13:
+ if(sub == 0) return "irda controller";
+ if(sub == 1) return "IR controller";
+ if(sub == 0x10) return "RF controller";
+ return "unknonw";
+
+ case 15:
+ if(sub > 4) return "unknown";
+ return class_sat_names[sub];
+
+ case 16:
+ if(sub == 0) return "network & computing crypto";
+ if(sub == 1) return "entertainment crypto";
+ return "unknown";
+
+ case 17:
+ if(sub == 0) return "DPIO module";
+ return "unknown";
+
+ default:
+ break;
+ }
+ return "unknown";
+}