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
DumpDescriptorData(const usb_generic_descriptor * descriptor)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
DumpEndpointSSCompanionDescriptor(const usb_endpoint_ss_companion_descriptor * descriptor)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
DumpDescriptor(const usb_generic_descriptor * descriptor,int classNum,int subclass)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
DumpInterface(const BUSBInterface * interface)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
DumpConfiguration(const BUSBConfiguration * configuration)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
DumpInfo(BUSBDevice & device,bool verbose)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:
DumpRoster(bool verbose)240 DumpRoster(bool verbose)
241 : fVerbose(verbose)
242 {
243 }
244
245
DeviceAdded(BUSBDevice * device)246 virtual status_t DeviceAdded(BUSBDevice* device)
247 {
248 DumpInfo(*device, fVerbose);
249 return B_OK;
250 }
251
252
DeviceRemoved(BUSBDevice * device)253 virtual void DeviceRemoved(BUSBDevice* device)
254 {
255 }
256
257 private:
258 bool fVerbose;
259 };
260
261
262
263 int
main(int argc,char * argv[])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