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