vfs: check userland buffers before reading them.
[haiku.git] / src / bin / listusb / listusb.cpp
blob2c21ef0e579609dc30711d61d3623a663e909844
1 /*
2 * Originally released under the Be Sample Code License.
3 * Copyright 2000, Be Incorporated. All rights reserved.
5 * Modified for Haiku by François Revol and Michael Lotz.
6 * Copyright 2007-2008, Haiku Inc. All rights reserved.
7 */
9 #include <Directory.h>
10 #include <Entry.h>
11 #include <Path.h>
12 #include <String.h>
13 #include <stdio.h>
14 #include <usb/USB_audio.h>
15 #include <usb/USB_video.h>
17 #include "usbspec_private.h"
18 #include "usb-utils.h"
20 #include "listusb.h"
23 const char*
24 ClassName(int classNumber) {
25 switch (classNumber) {
26 case 0:
27 return "Per-interface classes";
28 case USB_AUDIO_DEVICE_CLASS:
29 return "Audio";
30 case 2:
31 return "Communication";
32 case 3:
33 return "HID";
34 case 5:
35 return "Physical";
36 case 6:
37 return "Image";
38 case 7:
39 return "Printer";
40 case 8:
41 return "Mass storage";
42 case 9:
43 return "Hub";
44 case 10:
45 return "CDC-Data";
46 case 11:
47 return "Smart card";
48 case 13:
49 return "Content security";
50 case USB_VIDEO_DEVICE_CLASS:
51 return "Video";
52 case 15:
53 return "Personal Healthcare";
54 case 0xDC:
55 return "Diagnostic device";
56 case 0xE0:
57 return "Wireless controller";
58 case 0xEF:
59 return "Miscellaneous";
60 case 0xFE:
61 return "Application specific";
62 case 0xFF:
63 return "Vendor specific";
66 return "Unknown";
70 const char*
71 SubclassName(int classNumber, int subclass)
73 if (classNumber == 0xEF) {
74 if (subclass == 0x02)
75 return " (Common)";
78 if (classNumber == USB_VIDEO_DEVICE_CLASS) {
79 switch (subclass) {
80 case USB_VIDEO_INTERFACE_UNDEFINED_SUBCLASS:
81 return " (Undefined)";
82 case USB_VIDEO_INTERFACE_VIDEOCONTROL_SUBCLASS:
83 return " (Control)";
84 case USB_VIDEO_INTERFACE_VIDEOSTREAMING_SUBCLASS:
85 return " (Streaming)";
86 case USB_VIDEO_INTERFACE_COLLECTION_SUBCLASS:
87 return " (Collection)";
90 return "";
94 const char*
95 ProtocolName(int classNumber, int subclass, int protocol)
97 switch (classNumber) {
98 case 0x09:
99 if (subclass == 0x00)
101 switch (protocol) {
102 case 0x00:
103 return " (Full speed)";
104 case 0x01:
105 return " (Hi-speed, single TT)";
106 case 0x02:
107 return " (Hi-speed, multiple TT)";
108 case 0x03:
109 return " (Super speed)";
112 case 0xE0:
113 if (subclass == 0x01 && protocol == 0x01)
114 return " (Bluetooth)";
115 case 0xEF:
116 if (subclass == 0x02 && protocol == 0x01)
117 return " (Interface Association)";
118 break;
120 return "";
124 void
125 DumpDescriptorData(const usb_generic_descriptor* descriptor)
127 printf(" Type ............. 0x%02x\n",
128 descriptor->descriptor_type);
130 printf(" Data ............. ");
131 // len includes len and descriptor_type field
132 for (int32 i = 0; i < descriptor->length - 2; i++)
133 printf("%02x ", descriptor->data[i]);
134 printf("\n");
138 void
139 DumpDescriptor(const usb_generic_descriptor* descriptor,
140 int classNum, int subclass)
142 switch (classNum) {
143 case USB_AUDIO_DEVICE_CLASS:
144 DumpAudioDescriptor(descriptor, subclass);
145 break;
146 case USB_VIDEO_DEVICE_CLASS:
147 DumpVideoDescriptor(descriptor, subclass);
148 break;
149 default:
150 DumpDescriptorData(descriptor);
151 break;
156 static void
157 DumpInterface(const BUSBInterface* interface)
159 if (!interface)
160 return;
162 printf(" Class .............. 0x%02x (%s)\n",
163 interface->Class(), ClassName(interface->Class()));
164 printf(" Subclass ........... 0x%02x%s\n",
165 interface->Subclass(),
166 SubclassName(interface->Class(), interface->Subclass()));
167 printf(" Protocol ........... 0x%02x%s\n",
168 interface->Protocol(), ProtocolName(interface->Class(),
169 interface->Subclass(), interface->Protocol()));
170 printf(" Interface String ... \"%s\"\n",
171 interface->InterfaceString());
173 for (uint32 i = 0; i < interface->CountEndpoints(); i++) {
174 const BUSBEndpoint* endpoint = interface->EndpointAt(i);
175 if (!endpoint)
176 continue;
178 printf(" [Endpoint %" B_PRIu32 "]\n", i);
179 printf(" MaxPacketSize .... %d\n",
180 endpoint->MaxPacketSize());
181 printf(" Interval ......... %d\n",
182 endpoint->Interval());
184 if (endpoint->IsControl())
185 printf(" Type ............. Control\n");
186 else if (endpoint->IsBulk())
187 printf(" Type ............. Bulk\n");
188 else if (endpoint->IsIsochronous())
189 printf(" Type ............. Isochronous\n");
190 else if (endpoint->IsInterrupt())
191 printf(" Type ............. Interrupt\n");
193 if (endpoint->IsInput())
194 printf(" Direction ........ Input\n");
195 else
196 printf(" Direction ........ Output\n");
199 char buffer[256];
200 usb_descriptor* generic = (usb_descriptor*)buffer;
201 for (uint32 i = 0;
202 interface->OtherDescriptorAt(i, generic, 256) == B_OK; i++) {
203 printf(" [Descriptor %" B_PRIu32 "]\n", i);
204 DumpDescriptor(&generic->generic, interface->Class(), interface->Subclass());
209 static void
210 DumpConfiguration(const BUSBConfiguration* configuration)
212 if (!configuration)
213 return;
215 printf(" Configuration String . \"%s\"\n",
216 configuration->ConfigurationString());
217 for (uint32 i = 0; i < configuration->CountInterfaces(); i++) {
218 printf(" [Interface %" B_PRIu32 "]\n", i);
219 const BUSBInterface* interface = configuration->InterfaceAt(i);
221 for (uint32 j = 0; j < interface->CountAlternates(); j++) {
222 const BUSBInterface* alternate = interface->AlternateAt(j);
223 printf(" [Alternate %" B_PRIu32 "%s]\n", j,
224 j == interface->AlternateIndex() ? " active" : "");
225 DumpInterface(alternate);
231 static void
232 DumpInfo(BUSBDevice& device, bool verbose)
234 const char* vendorName = NULL;
235 const char* deviceName = NULL;
236 usb_get_vendor_info(device.VendorID(), &vendorName);
237 usb_get_device_info(device.VendorID(), device.ProductID(), &deviceName);
239 if (!verbose) {
240 printf("%04x:%04x /dev/bus/usb%s \"%s\" \"%s\" ver. %04x\n",
241 device.VendorID(), device.ProductID(), device.Location(),
242 vendorName ? vendorName : device.ManufacturerString(),
243 deviceName ? deviceName : device.ProductString(),
244 device.Version());
245 return;
248 printf("[Device /dev/bus/usb%s]\n", device.Location());
249 printf(" Class .................. 0x%02x (%s)\n", device.Class(),
250 ClassName(device.Class()));
251 printf(" Subclass ............... 0x%02x%s\n", device.Subclass(),
252 SubclassName(device.Class(), device.Subclass()));
253 printf(" Protocol ............... 0x%02x%s\n", device.Protocol(),
254 ProtocolName(device.Class(), device.Subclass(), device.Protocol()));
255 printf(" Max Endpoint 0 Packet .. %d\n", device.MaxEndpoint0PacketSize());
256 uint32_t version = device.USBVersion();
257 printf(" USB Version ............ %d.%d\n", version >> 8, version & 0xFF);
258 printf(" Vendor ID .............. 0x%04x", device.VendorID());
259 if (vendorName != NULL)
260 printf(" (%s)", vendorName);
261 printf("\n Product ID ............. 0x%04x", device.ProductID());
262 if (deviceName != NULL)
263 printf(" (%s)", deviceName);
264 printf("\n Product Version ........ 0x%04x\n", device.Version());
265 printf(" Manufacturer String .... \"%s\"\n", device.ManufacturerString());
266 printf(" Product String ......... \"%s\"\n", device.ProductString());
267 printf(" Serial Number .......... \"%s\"\n", device.SerialNumberString());
269 for (uint32 i = 0; i < device.CountConfigurations(); i++) {
270 printf(" [Configuration %" B_PRIu32 "]\n", i);
271 DumpConfiguration(device.ConfigurationAt(i));
274 if (device.Class() != 0x09)
275 return;
277 usb_hub_descriptor hubDescriptor;
278 size_t size = device.GetDescriptor(USB_DESCRIPTOR_HUB, 0, 0,
279 (void*)&hubDescriptor, sizeof(usb_hub_descriptor));
280 if (size == sizeof(usb_hub_descriptor)) {
281 printf(" Hub ports count......... %d\n", hubDescriptor.num_ports);
282 printf(" Hub Controller Current.. %dmA\n", hubDescriptor.max_power);
284 for (int index = 1; index <= hubDescriptor.num_ports; index++) {
285 usb_port_status portStatus;
286 size_t actualLength = device.ControlTransfer(USB_REQTYPE_CLASS
287 | USB_REQTYPE_OTHER_IN, USB_REQUEST_GET_STATUS, 0,
288 index, sizeof(portStatus), (void*)&portStatus);
289 if (actualLength != sizeof(portStatus))
290 continue;
291 printf(" Port %d status....... %04x.%04x%s%s%s%s%s%s%s%s%s\n",
292 index, portStatus.status, portStatus.change,
293 portStatus.status & PORT_STATUS_CONNECTION ? " Connect": "",
294 portStatus.status & PORT_STATUS_ENABLE ? " Enable": "",
295 portStatus.status & PORT_STATUS_SUSPEND ? " Suspend": "",
296 portStatus.status & PORT_STATUS_OVER_CURRENT ? " Overcurrent": "",
297 portStatus.status & PORT_STATUS_RESET ? " Reset": "",
298 portStatus.status & PORT_STATUS_POWER ? " Power": "",
299 portStatus.status & PORT_STATUS_CONNECTION
300 ? (portStatus.status & PORT_STATUS_LOW_SPEED ? " Lowspeed"
301 : (portStatus.status & PORT_STATUS_HIGH_SPEED ? " Highspeed"
302 : " Fullspeed")) : "",
303 portStatus.status & PORT_STATUS_TEST ? " Test": "",
304 portStatus.status & PORT_STATUS_INDICATOR ? " Indicator": "");
310 class DumpRoster : public BUSBRoster {
311 public:
312 DumpRoster(bool verbose)
313 : fVerbose(verbose)
318 virtual status_t DeviceAdded(BUSBDevice* device)
320 DumpInfo(*device, fVerbose);
321 return B_OK;
325 virtual void DeviceRemoved(BUSBDevice* device)
329 private:
330 bool fVerbose;
336 main(int argc, char* argv[])
338 bool verbose = false;
339 BString devname = "";
340 for (int i = 1; i < argc; i++) {
341 if (argv[i][0] == '-') {
342 if (argv[i][1] == 'v')
343 verbose = true;
344 else {
345 printf("Usage: listusb [-v] [device]\n\n");
346 printf("-v: Show more detailed information including "
347 "interfaces, configurations, etc.\n\n");
348 printf("If a device is not specified, "
349 "all devices found on the bus will be listed\n");
350 return 1;
352 } else
353 devname = argv[i];
356 if (devname.Length() > 0) {
357 BUSBDevice device(devname.String());
358 if (device.InitCheck() < B_OK) {
359 printf("Cannot open USB device: %s\n", devname.String());
360 return 1;
361 } else {
362 DumpInfo(device, verbose);
363 return 0;
365 } else {
366 DumpRoster roster(verbose);
367 roster.Start();
368 roster.Stop();
371 return 0;