1 /* 2 * Copyright 2006-2012, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Jérôme Duval 7 */ 8 9 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 #include <unistd.h> 14 15 #include <drivers/device_manager.h> 16 #include <drivers/module.h> 17 #include <drivers/PCI.h> 18 #include <drivers/bus/PCI.h> 19 #include <drivers/bus/SCSI.h> 20 #include <drivers/bus/USB.h> 21 22 extern "C" { 23 #include "dm_wrapper.h" 24 #include "pcihdr.h" 25 #include "pci-utils.h" 26 #include "usb-utils.h" 27 } 28 29 30 extern const char *__progname; 31 32 #define DUMP_MODE 0 33 #define USER_MODE 1 34 int gMode = USER_MODE; 35 36 #define BUS_ISA 1 37 #define BUS_PCI 2 38 #define BUS_SCSI 3 39 #define BUS_USB 4 40 41 42 static const char * 43 get_scsi_device_type(uint8 type) 44 { 45 switch (type) { 46 case 0x0: return "Direct Access"; 47 case 0x1: return "Sequential Access"; 48 case 0x2: return "Printer"; 49 case 0x3: return "Processor"; 50 case 0x4: return "WORM"; 51 case 0x5: return "CDROM"; 52 case 0x6: return "Scanner"; 53 case 0x7: return "Optical memory"; 54 case 0x8: return "Medium changer"; 55 case 0x9: return "Communication"; 56 case 0xc: return "Storage array controller"; 57 case 0xd: return "Enclosure services"; 58 case 0xe: return "Simplified Direct Access"; 59 default: return ""; 60 } 61 } 62 63 64 static void 65 usage() 66 { 67 fprintf(stderr, "usage: %s [-d]\n", __progname); 68 fprintf(stderr, "Displays devices in a user friendly way\n"); 69 fprintf(stderr, "-d : dumps the tree\n"); 70 exit(0); 71 } 72 73 74 static void 75 put_level(int32 level) 76 { 77 while (level-- > 0) 78 printf(" "); 79 } 80 81 82 static void 83 dump_attribute(struct device_attr_info *attr, int32 level) 84 { 85 if (attr == NULL) 86 return; 87 88 put_level(level); 89 printf("\"%s\" : ", attr->name); 90 switch (attr->type) { 91 case B_STRING_TYPE: 92 printf("string : \"%s\"", attr->value.string); 93 break; 94 case B_UINT8_TYPE: 95 printf("uint8 : %" B_PRIu8 " (%#" B_PRIx8 ")", attr->value.ui8, 96 attr->value.ui8); 97 break; 98 case B_UINT16_TYPE: 99 printf("uint16 : %" B_PRIu16 " (%#" B_PRIx16 ")", attr->value.ui16, 100 attr->value.ui16); 101 break; 102 case B_UINT32_TYPE: 103 printf("uint32 : %" B_PRIu32 " (%#" B_PRIx32 ")", attr->value.ui32, 104 attr->value.ui32); 105 break; 106 case B_UINT64_TYPE: 107 printf("uint64 : %" B_PRIu64 " (%#" B_PRIx64 ")", attr->value.ui64, 108 attr->value.ui64); 109 break; 110 default: 111 printf("raw data"); 112 } 113 printf("\n"); 114 } 115 116 117 static void 118 dump_device(device_node_cookie *node, uint8 level) 119 { 120 char data[256]; 121 struct device_attr_info attr; 122 attr.cookie = 0; 123 attr.node_cookie = *node; 124 attr.value.raw.data = data; 125 attr.value.raw.length = sizeof(data); 126 127 put_level(level); 128 printf("(%d)\n", level); 129 while (dm_get_next_attr(&attr) == B_OK) { 130 dump_attribute(&attr, level); 131 } 132 } 133 134 135 static void 136 dump_nodes(device_node_cookie *node, uint8 level) 137 { 138 status_t err; 139 device_node_cookie child = *node; 140 dump_device(node, level); 141 142 if (get_child(&child) != B_OK) 143 return; 144 145 do { 146 dump_nodes(&child, level + 1); 147 } while ((err = get_next_child(&child)) == B_OK); 148 149 } 150 151 152 static int32 153 display_device(device_node_cookie *node, uint8 level) 154 { 155 uint8 new_level = level; 156 157 char data[256]; 158 struct device_attr_info attr; 159 160 // BUS attributes 161 char device_bus[64]; 162 uint8 scsi_path_id = 255; 163 int bus = 0; 164 uint16 vendor_id = 0; 165 uint16 device_id = 0; 166 167 // PCI attributes 168 uint8 pci_class_base_id = 0; 169 uint8 pci_class_sub_id = 0; 170 uint8 pci_class_api_id = 0; 171 uint16 pci_subsystem_vendor_id = 0; 172 uint16 pci_subsystem_id = 0; 173 174 // SCSI attributes 175 uint8 scsi_target_lun = 0; 176 uint8 scsi_target_id = 0; 177 uint8 scsi_type = 255; 178 char scsi_vendor[64]; 179 char scsi_product[64]; 180 181 // USB attributes 182 uint8 usb_class_base_id = 0; 183 uint8 usb_class_sub_id = 0; 184 uint8 usb_class_proto_id = 0; 185 186 attr.cookie = 0; 187 attr.node_cookie = *node; 188 attr.value.raw.data = data; 189 attr.value.raw.length = sizeof(data); 190 191 while (dm_get_next_attr(&attr) == B_OK) { 192 if (!strcmp(attr.name, B_DEVICE_BUS) 193 && attr.type == B_STRING_TYPE) { 194 strlcpy(device_bus, attr.value.string, 64); 195 } else if (!strcmp(attr.name, "scsi/path_id") 196 && attr.type == B_UINT8_TYPE) { 197 scsi_path_id = attr.value.ui8; 198 } else if (!strcmp(attr.name, B_DEVICE_TYPE) 199 && attr.type == B_UINT16_TYPE) 200 pci_class_base_id = attr.value.ui8; 201 else if (!strcmp(attr.name, B_DEVICE_SUB_TYPE) 202 && attr.type == B_UINT16_TYPE) 203 pci_class_sub_id = attr.value.ui8; 204 else if (!strcmp(attr.name, B_DEVICE_INTERFACE) 205 && attr.type == B_UINT16_TYPE) 206 pci_class_api_id = attr.value.ui8; 207 else if (!strcmp(attr.name, B_DEVICE_VENDOR_ID) 208 && attr.type == B_UINT16_TYPE) 209 vendor_id = attr.value.ui16; 210 else if (!strcmp(attr.name, B_DEVICE_ID) 211 && attr.type == B_UINT16_TYPE) 212 device_id = attr.value.ui16; 213 else if (!strcmp(attr.name, SCSI_DEVICE_TARGET_LUN_ITEM) 214 && attr.type == B_UINT8_TYPE) 215 scsi_target_lun = attr.value.ui8; 216 else if (!strcmp(attr.name, SCSI_DEVICE_TARGET_ID_ITEM) 217 && attr.type == B_UINT8_TYPE) 218 scsi_target_id = attr.value.ui8; 219 else if (!strcmp(attr.name, SCSI_DEVICE_TYPE_ITEM) 220 && attr.type == B_UINT8_TYPE) 221 scsi_type = attr.value.ui8; 222 else if (!strcmp(attr.name, SCSI_DEVICE_VENDOR_ITEM) 223 && attr.type == B_STRING_TYPE) 224 strlcpy(scsi_vendor, attr.value.string, 64); 225 else if (!strcmp(attr.name, SCSI_DEVICE_PRODUCT_ITEM) 226 && attr.type == B_STRING_TYPE) 227 strlcpy(scsi_product, attr.value.string, 64); 228 else if (!strcmp(attr.name, USB_DEVICE_CLASS) 229 && attr.type == B_UINT8_TYPE) 230 usb_class_base_id = attr.value.ui8; 231 else if (!strcmp(attr.name, USB_DEVICE_SUBCLASS) 232 && attr.type == B_UINT8_TYPE) 233 usb_class_sub_id = attr.value.ui8; 234 else if (!strcmp(attr.name, USB_DEVICE_PROTOCOL) 235 && attr.type == B_UINT8_TYPE) 236 usb_class_proto_id = attr.value.ui8; 237 238 if (!strcmp(device_bus, "isa")) 239 bus = BUS_ISA; 240 else if (!strcmp(device_bus, "pci")) 241 bus = BUS_PCI; 242 else if (!strcmp(device_bus, "usb")) 243 bus = BUS_USB; 244 else if (scsi_path_id < 255) 245 bus = BUS_SCSI; 246 247 /*else if (!strcmp(attr.name, PCI_DEVICE_SUBVENDOR_ID_ITEM) 248 && attr.type == B_UINT16_TYPE) 249 pci_subsystem_vendor_id = attr.value.ui16; 250 else if (!strcmp(attr.name, PCI_DEVICE_SUBSYSTEM_ID_ITEM) 251 && attr.type == B_UINT16_TYPE) 252 pci_subsystem_id = attr.value.ui16;*/ 253 254 attr.value.raw.data = data; 255 attr.value.raw.length = sizeof(data); 256 } 257 258 switch (bus) { 259 case BUS_ISA: 260 new_level = level + 1; 261 break; 262 case BUS_PCI: 263 printf("\n"); 264 { 265 char classInfo[128]; 266 get_class_info(pci_class_base_id, pci_class_sub_id, 267 pci_class_api_id, classInfo, 64); 268 put_level(level); 269 printf("device %s [%x|%x|%x]\n", classInfo, pci_class_base_id, 270 pci_class_sub_id, pci_class_api_id); 271 } 272 273 put_level(level); 274 printf(" "); 275 const char *venShort; 276 const char *venFull; 277 const char *devShort; 278 const char *devFull; 279 280 get_vendor_info(vendor_id, &venShort, &venFull); 281 if (!venShort && !venFull) { 282 printf("vendor %04x: Unknown\n", vendor_id); 283 } else if (venShort && venFull) { 284 printf("vendor %04x: %s - %s\n", vendor_id, 285 venShort, venFull); 286 } else { 287 printf("vendor %04x: %s\n", vendor_id, 288 venShort ? venShort : venFull); 289 } 290 291 put_level(level); 292 printf(" "); 293 get_device_info(vendor_id, device_id, pci_subsystem_vendor_id, pci_subsystem_id, 294 &devShort, &devFull); 295 if (!devShort && !devFull) { 296 printf("device %04x: Unknown\n", device_id); 297 } else if (devShort && devFull) { 298 printf("device %04x: %s (%s)\n", device_id, 299 devShort, devFull); 300 } else { 301 printf("device %04x: %s\n", device_id, 302 devShort ? devShort : devFull); 303 } 304 new_level = level + 1; 305 break; 306 case BUS_SCSI: 307 if (scsi_type == 255) 308 break; 309 put_level(level); 310 printf(" device [%x|%x]\n", scsi_target_id, scsi_target_lun); 311 put_level(level); 312 printf(" vendor %15s\tmodel %15s\ttype %s\n", scsi_vendor, 313 scsi_product, get_scsi_device_type(scsi_type)); 314 315 new_level = level + 1; 316 break; 317 318 case BUS_USB: 319 { 320 printf("\n"); 321 char classInfo[128]; 322 usb_get_class_info(usb_class_base_id, usb_class_sub_id, usb_class_proto_id, 323 classInfo, sizeof(classInfo)); 324 put_level(level); 325 printf("device %s [%x|%x|%x]\n", classInfo, usb_class_base_id, 326 usb_class_sub_id, usb_class_proto_id); 327 328 put_level(level); 329 printf(" "); 330 const char* vendorName = NULL; 331 const char* deviceName = NULL; 332 usb_get_vendor_info(vendor_id, &vendorName); 333 usb_get_device_info(vendor_id, device_id, &deviceName); 334 printf("vendor %04x: %s\n", vendor_id, vendorName != NULL ? vendorName : "Unknown"); 335 put_level(level); 336 printf(" "); 337 printf("device %04x: %s\n", device_id, deviceName != NULL ? deviceName : "Unknown"); 338 new_level = level + 1; 339 break; 340 } 341 } 342 343 return new_level; 344 } 345 346 347 static void 348 display_nodes(device_node_cookie *node, uint8 level) 349 { 350 status_t err; 351 device_node_cookie child = *node; 352 level = display_device(node, level); 353 354 if (get_child(&child) != B_OK) 355 return; 356 357 do { 358 display_nodes(&child, level); 359 } while ((err = get_next_child(&child)) == B_OK); 360 } 361 362 363 int 364 main(int argc, char **argv) 365 { 366 status_t error; 367 device_node_cookie root; 368 369 if ((error = init_dm_wrapper()) < 0) { 370 printf("Error initializing device manager (%s)\n", strerror(error)); 371 return error; 372 } 373 374 if (argc > 2) 375 usage(); 376 377 if (argc == 2) { 378 if (!strcmp(argv[1], "-d")) { 379 gMode = DUMP_MODE; 380 } else { 381 usage(); 382 } 383 } 384 385 if (gMode == DUMP_MODE) { 386 get_root(&root); 387 dump_nodes(&root, 0); 388 } else { 389 get_root(&root); 390 display_nodes(&root, 0); 391 } 392 393 uninit_dm_wrapper(); 394 395 return 0; 396 } 397