xref: /haiku/src/bin/listusb/listusb.cpp (revision 01dc1ea4cfb70a5499b7d90f91fede60e50c468f)
1 /*
2  * Originally released under the Be Sample Code License.
3  * Copyright 2000, Be Incorporated. All rights reserved.
4  *
5  * Modified for Haiku by François Revol and Michael Lotz.
6  * Copyright 2007-2008, Haiku Inc. All rights reserved.
7  */
8 
9 #include <Directory.h>
10 #include <Entry.h>
11 #include <Path.h>
12 #include <String.h>
13 #include <stdio.h>
14 
15 #include <usb/USB_audio.h>
16 #include <usb/USB_cdc.h>
17 #include <usb/USB_video.h>
18 
19 #include "usbspec_private.h"
20 #include "usb-utils.h"
21 
22 #include "listusb.h"
23 
24 
25 void
26 DumpDescriptorData(const usb_generic_descriptor* descriptor)
27 {
28 	printf("                    Length............ 0x%02x\n",
29 		descriptor->length);
30 	printf("                    Type ............. 0x%02x\n",
31 		descriptor->descriptor_type);
32 
33 	printf("                    Data ............. ");
34 	// len includes len and descriptor_type field
35 	for (int32 i = 0; i < descriptor->length - 2; i++)
36 		printf("%02x ", descriptor->data[i]);
37 	printf("\n");
38 }
39 
40 
41 void
42 DumpEndpointSSCompanionDescriptor(
43 	const usb_endpoint_ss_companion_descriptor* descriptor)
44 {
45 	printf("                    Type .............. 0x%02x Endpoint SuperSpeed Companion\n",
46 		descriptor->descriptor_type);
47 	printf("                    MaxBurst .......... 0x%02x\n",
48 		descriptor->max_burst);
49 	printf("                    Attributes ........ 0x%02x\n",
50 		descriptor->attributes);
51 	printf("                    Bytes per Interval  0x%02x\n",
52 		descriptor->bytes_per_interval);
53 }
54 
55 
56 void
57 DumpDescriptor(const usb_generic_descriptor* descriptor,
58 	int classNum, int subclass)
59 {
60 	if (descriptor->descriptor_type == USB_DESCRIPTOR_ENDPOINT_SS_COMPANION) {
61 		DumpEndpointSSCompanionDescriptor((const usb_endpoint_ss_companion_descriptor*)descriptor);
62 		return;
63 	}
64 
65 	switch (classNum) {
66 		case USB_AUDIO_DEVICE_CLASS:
67 			DumpAudioDescriptor(descriptor, subclass);
68 			break;
69 		case USB_VIDEO_DEVICE_CLASS:
70 			DumpVideoDescriptor(descriptor, subclass);
71 			break;
72 		case USB_COMMUNICATION_DEVICE_CLASS:
73 		case USB_COMMUNICATION_WIRELESS_DEVICE_CLASS:
74 			DumpCDCDescriptor(descriptor, subclass);
75 			break;
76 		default:
77 			DumpDescriptorData(descriptor);
78 			break;
79 	}
80 }
81 
82 
83 static void
84 DumpInterface(const BUSBInterface* interface)
85 {
86 	if (!interface)
87 		return;
88 
89 	char classInfo[128];
90 	usb_get_class_info(interface->Class(), 0, 0, classInfo, sizeof(classInfo));
91 	printf("                Class .............. 0x%02x %s\n",
92 		interface->Class(), classInfo);
93 	usb_get_class_info(interface->Class(), interface->Subclass(), 0, classInfo, sizeof(classInfo));
94 	printf("                Subclass ........... 0x%02x %s\n",
95 		interface->Subclass(), classInfo);
96 	usb_get_class_info(interface->Class(), interface->Subclass(), interface->Protocol(), classInfo,
97 		sizeof(classInfo));
98 	printf("                Protocol ........... 0x%02x %s\n",
99 		interface->Protocol(), classInfo);
100 	printf("                Interface String ... \"%s\"\n",
101 		interface->InterfaceString());
102 
103 	for (uint32 i = 0; i < interface->CountEndpoints(); i++) {
104 		const BUSBEndpoint* endpoint = interface->EndpointAt(i);
105 		if (!endpoint)
106 			continue;
107 
108 		printf("                [Endpoint %" B_PRIu32 "]\n", i);
109 		printf("                    MaxPacketSize .... %dx %d bytes\n",
110 			((endpoint->MaxPacketSize() >> 11) & 0x3) + 1, endpoint->MaxPacketSize() & 0x7ff);
111 		printf("                    Interval ......... %d\n",
112 			endpoint->Interval());
113 
114 		if (endpoint->IsControl())
115 			printf("                    Type ............. Control\n");
116 		else if (endpoint->IsBulk())
117 			printf("                    Type ............. Bulk\n");
118 		else if (endpoint->IsIsochronous())
119 			printf("                    Type ............. Isochronous\n");
120 		else if (endpoint->IsInterrupt())
121 			printf("                    Type ............. Interrupt\n");
122 
123 		if (endpoint->IsInput())
124 			printf("                    Direction ........ Input\n");
125 		else
126 			printf("                    Direction ........ Output\n");
127 	}
128 
129 	char buffer[256];
130 	usb_descriptor* generic = (usb_descriptor*)buffer;
131 	for (uint32 i = 0;
132 			interface->OtherDescriptorAt(i, generic, 256) == B_OK; i++) {
133 		printf("                [Descriptor %" B_PRIu32 "]\n", i);
134 		DumpDescriptor(&generic->generic, interface->Class(), interface->Subclass());
135 	}
136 }
137 
138 
139 static void
140 DumpConfiguration(const BUSBConfiguration* configuration)
141 {
142 	if (!configuration)
143 		return;
144 
145 	printf("        Configuration String . \"%s\"\n",
146 		configuration->ConfigurationString());
147 	for (uint32 i = 0; i < configuration->CountInterfaces(); i++) {
148 		printf("        [Interface %" B_PRIu32 "]\n", i);
149 		const BUSBInterface* interface = configuration->InterfaceAt(i);
150 
151 		for (uint32 j = 0; j < interface->CountAlternates(); j++) {
152 			const BUSBInterface* alternate = interface->AlternateAt(j);
153 			printf("            [Alternate %" B_PRIu32 "%s]\n", j,
154 				j == interface->AlternateIndex() ? " active" : "");
155 			DumpInterface(alternate);
156 		}
157 	}
158 }
159 
160 
161 static void
162 DumpInfo(BUSBDevice& device, bool verbose)
163 {
164 	const char* vendorName = NULL;
165 	const char* deviceName = NULL;
166 	usb_get_vendor_info(device.VendorID(), &vendorName);
167 	usb_get_device_info(device.VendorID(), device.ProductID(), &deviceName);
168 
169 	if (!verbose) {
170 		printf("%04x:%04x /dev/bus/usb%s \"%s\" \"%s\" ver. %04x\n",
171 			device.VendorID(), device.ProductID(), device.Location(),
172 			vendorName ? vendorName : device.ManufacturerString(),
173 			deviceName ? deviceName : device.ProductString(),
174 			device.Version());
175 		return;
176 	}
177 
178 	char classInfo[128];
179 	printf("[Device /dev/bus/usb%s]\n", device.Location());
180 	usb_get_class_info(device.Class(), 0, 0, classInfo, sizeof(classInfo));
181 	printf("    Class .................. 0x%02x %s\n", device.Class(), classInfo);
182 	usb_get_class_info(device.Class(), device.Subclass(), 0, classInfo, sizeof(classInfo));
183 	printf("    Subclass ............... 0x%02x %s\n", device.Subclass(), classInfo);
184 	usb_get_class_info(device.Class(), device.Subclass(), device.Protocol(), classInfo,
185 		sizeof(classInfo));
186 	printf("    Protocol ............... 0x%02x %s\n", device.Protocol(), classInfo);
187 	printf("    Max Endpoint 0 Packet .. %d\n", device.MaxEndpoint0PacketSize());
188 	uint32_t version = device.USBVersion();
189 	printf("    USB Version ............ %d.%d\n", version >> 8, version & 0xFF);
190 	printf("    Vendor ID .............. 0x%04x", device.VendorID());
191 	if (vendorName != NULL)
192 		printf(" (%s)", vendorName);
193 	printf("\n    Product ID ............. 0x%04x", device.ProductID());
194 	if (deviceName != NULL)
195 		printf(" (%s)", deviceName);
196 	printf("\n    Product Version ........ 0x%04x\n", device.Version());
197 	printf("    Manufacturer String .... \"%s\"\n", device.ManufacturerString());
198 	printf("    Product String ......... \"%s\"\n", device.ProductString());
199 	printf("    Serial Number .......... \"%s\"\n", device.SerialNumberString());
200 
201 	for (uint32 i = 0; i < device.CountConfigurations(); i++) {
202 		printf("    [Configuration %" B_PRIu32 "]\n", i);
203 		DumpConfiguration(device.ConfigurationAt(i));
204 	}
205 
206 	if (device.Class() != 0x09)
207 		return;
208 
209 	usb_hub_descriptor hubDescriptor;
210 	size_t size = device.GetDescriptor(USB_DESCRIPTOR_HUB, 0, 0,
211 		(void*)&hubDescriptor, sizeof(usb_hub_descriptor));
212 	if (size == sizeof(usb_hub_descriptor)) {
213 		printf("    Hub ports count......... %d\n", hubDescriptor.num_ports);
214 		printf("    Hub Controller Current.. %dmA\n", hubDescriptor.max_power);
215 
216 		for (int index = 1; index <= hubDescriptor.num_ports; index++) {
217 			usb_port_status portStatus;
218 			size_t actualLength = device.ControlTransfer(USB_REQTYPE_CLASS
219 				| USB_REQTYPE_OTHER_IN, USB_REQUEST_GET_STATUS, 0,
220 				index, sizeof(portStatus), (void*)&portStatus);
221 			if (actualLength != sizeof(portStatus))
222 				continue;
223 			printf("      Port %d status....... %04x.%04x%s%s%s%s%s%s%s%s\n",
224 				index, portStatus.status, portStatus.change,
225 				portStatus.status & PORT_STATUS_CONNECTION ? " Connect": "",
226 				portStatus.status & PORT_STATUS_ENABLE ? " Enable": "",
227 				portStatus.status & PORT_STATUS_SUSPEND ? " Suspend": "",
228 				portStatus.status & PORT_STATUS_OVER_CURRENT ? " Overcurrent": "",
229 				portStatus.status & PORT_STATUS_RESET ? " Reset": "",
230 				portStatus.status & PORT_STATUS_POWER ? " Power": "",
231 				portStatus.status & PORT_STATUS_TEST ? " Test": "",
232 				portStatus.status & PORT_STATUS_INDICATOR ? " Indicator": "");
233 		}
234 	}
235 }
236 
237 
238 class DumpRoster : public BUSBRoster {
239 public:
240 					DumpRoster(bool verbose)
241 						:	fVerbose(verbose)
242 					{
243 					}
244 
245 
246 virtual	status_t	DeviceAdded(BUSBDevice* device)
247 					{
248 						DumpInfo(*device, fVerbose);
249 						return B_OK;
250 					}
251 
252 
253 virtual	void		DeviceRemoved(BUSBDevice* device)
254 					{
255 					}
256 
257 private:
258 		bool		fVerbose;
259 };
260 
261 
262 
263 int
264 main(int argc, char* argv[])
265 {
266 	bool verbose = false;
267 	BString devname = "";
268 	for (int i = 1; i < argc; i++) {
269 		if (argv[i][0] == '-') {
270 			if (argv[i][1] == 'v')
271 				verbose = true;
272 			else {
273 				printf("Usage: listusb [-v] [device]\n\n");
274 				printf("-v: Show more detailed information including "
275 					"interfaces, configurations, etc.\n\n");
276 				printf("If a device is not specified, "
277 					"all devices found on the bus will be listed\n");
278 				return 1;
279 			}
280 		} else
281 			devname = argv[i];
282 	}
283 
284 	if (devname.Length() > 0) {
285 		BUSBDevice device(devname.String());
286 		if (device.InitCheck() < B_OK) {
287 			printf("Cannot open USB device: %s\n", devname.String());
288 			return 1;
289 		} else {
290 				DumpInfo(device, verbose);
291 				return 0;
292 		}
293 	} else {
294 		DumpRoster roster(verbose);
295 		roster.Start();
296 		roster.Stop();
297 	}
298 
299 	return 0;
300 }
301