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 *
get_scsi_device_type(uint8 type)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
usage()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
put_level(int32 level)75 put_level(int32 level)
76 {
77 while (level-- > 0)
78 printf(" ");
79 }
80
81
82 static void
dump_attribute(struct device_attr_info * attr,int32 level)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
dump_device(device_node_cookie * node,uint8 level)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
dump_nodes(device_node_cookie * node,uint8 level)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
display_device(device_node_cookie * node,uint8 level)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
display_nodes(device_node_cookie * node,uint8 level)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
main(int argc,char ** argv)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