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