Assorted whitespace cleanup and typo fixes.
[haiku.git] / src / bin / listusb.cpp
blobf0d20b69aa2bf3ad47576325fcec10a9b79f2370
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 <MediaDefs.h>
12 #include <Path.h>
13 #include <String.h>
14 #include <USBKit.h>
15 #include <stdio.h>
16 #include <usb/USB_audio.h>
17 #include <usb/USB_midi.h>
19 #include "usbspec_private.h"
20 #include "usb-utils.h"
23 const char*
24 ClassName(int classNumber) {
25 switch (classNumber) {
26 case 0:
27 return "Per-interface classes";
28 case 1:
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 14:
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 void
71 DumpDescriptorData(const usb_generic_descriptor* descriptor)
73 printf(" Type ............. 0x%02x\n",
74 descriptor->descriptor_type);
76 printf(" Data ............. ");
77 // len includes len and descriptor_type field
78 for (int32 i = 0; i < descriptor->length - 2; i++)
79 printf("%02x ", descriptor->data[i]);
80 printf("\n");
84 void
85 DumpAudioCSInterfaceDescriptorHeader(
86 const usb_audiocontrol_header_descriptor* descriptor)
88 printf(" Subtype ........... 0x%02x (Header)\n",
89 descriptor->descriptor_subtype);
90 printf(" bcdADC Release date 0x%04x\n",
91 descriptor->bcd_release_no);
92 printf(" Total Length ...... %u\n",
93 descriptor->r1.total_length);
94 printf(" Interfaces ........ ");
96 for (uint8 i = 0; i < descriptor->r1.in_collection; i++)
97 printf("%u, ", descriptor->r1.interface_numbers[i]);
98 printf("\n");
102 void
103 DumpChannelConfig(uint32 wChannelConfig)
105 struct _Entry {
106 const char* name;
107 uint32 mask;
108 } aClusters[] = {
109 { "Front .......... ", B_CHANNEL_LEFT | B_CHANNEL_RIGHT
110 | B_CHANNEL_CENTER },
111 { "L.F.E .......... ", B_CHANNEL_SUB },
112 { "Back ........... ", B_CHANNEL_REARLEFT | B_CHANNEL_REARRIGHT
113 | B_CHANNEL_BACK_CENTER },
114 { "Center ......... ", B_CHANNEL_FRONT_LEFT_CENTER
115 | B_CHANNEL_FRONT_RIGHT_CENTER },
116 { "Side ........... ", B_CHANNEL_SIDE_LEFT | B_CHANNEL_SIDE_RIGHT },
117 { "Top ............ ", B_CHANNEL_TOP_CENTER },
118 { "Top Front ...... ", B_CHANNEL_TOP_FRONT_LEFT
119 | B_CHANNEL_TOP_FRONT_CENTER | B_CHANNEL_TOP_FRONT_RIGHT },
120 { "Top Back ....... ", B_CHANNEL_TOP_BACK_LEFT
121 | B_CHANNEL_TOP_BACK_CENTER | B_CHANNEL_TOP_BACK_RIGHT }
124 struct _Entry aChannels[] = {
125 { "Left", B_CHANNEL_LEFT | B_CHANNEL_FRONT_LEFT_CENTER
126 | B_CHANNEL_REARLEFT | B_CHANNEL_SIDE_LEFT | B_CHANNEL_TOP_BACK_LEFT
127 | B_CHANNEL_TOP_FRONT_LEFT },
128 { "Right", B_CHANNEL_FRONT_RIGHT_CENTER | B_CHANNEL_TOP_FRONT_RIGHT
129 | B_CHANNEL_REARRIGHT | B_CHANNEL_RIGHT | B_CHANNEL_SIDE_RIGHT
130 | B_CHANNEL_TOP_BACK_RIGHT },
131 { "Center", B_CHANNEL_BACK_CENTER | B_CHANNEL_CENTER
132 | B_CHANNEL_TOP_BACK_CENTER | B_CHANNEL_TOP_CENTER
133 | B_CHANNEL_TOP_FRONT_CENTER },
134 { "L.F.E.", B_CHANNEL_SUB }
137 for (size_t i = 0; i < sizeof(aClusters) / sizeof(aClusters[0]); i++) {
138 uint32 mask = aClusters[i].mask & wChannelConfig;
139 if (mask != 0) {
140 printf(" %s", aClusters[i].name);
141 for (size_t j = 0; j < sizeof(aChannels) / sizeof(aChannels[0]); j++)
142 if ((aChannels[j].mask & mask) != 0)
143 printf("%s ", aChannels[j].name);
144 printf("\n");
150 const char*
151 TerminalTypeName(uint16 terminalType)
153 switch (terminalType) {
154 case USB_AUDIO_UNDEFINED_USB_IO:
155 return "USB Undefined";
156 case USB_AUDIO_STREAMING_USB_IO:
157 return "USB Streaming";
158 case USB_AUDIO_VENDOR_USB_IO:
159 return "USB vendor specific";
161 case USB_AUDIO_UNDEFINED_IN:
162 return "Undefined";
163 case USB_AUDIO_MICROPHONE_IN:
164 return "Microphone";
165 case USB_AUDIO_DESKTOPMIC_IN:
166 return "Desktop microphone";
167 case USB_AUDIO_PERSONALMIC_IN:
168 return "Personal microphone";
169 case USB_AUDIO_OMNI_MIC_IN:
170 return "Omni-directional microphone";
171 case USB_AUDIO_MICS_ARRAY_IN:
172 return "Microphone array";
173 case USB_AUDIO_PROC_MICS_ARRAY_IN:
174 return "Processing microphone array";
175 case USB_AUDIO_LINE_CONNECTOR_IO:
176 return "Line I/O";
177 case USB_AUDIO_SPDIF_INTERFACE_IO:
178 return "S/PDIF";
180 case USB_AUDIO_UNDEFINED_OUT:
181 return "Undefined";
182 case USB_AUDIO_SPEAKER_OUT:
183 return "Speaker";
184 case USB_AUDIO_HEAD_PHONES_OUT:
185 return "Headphones";
186 case USB_AUDIO_HMD_AUDIO_OUT:
187 return "Head Mounted Display Audio";
188 case USB_AUDIO_DESKTOP_SPEAKER:
189 return "Desktop speaker";
190 case USB_AUDIO_ROOM_SPEAKER:
191 return "Room speaker";
192 case USB_AUDIO_COMM_SPEAKER:
193 return "Communication speaker";
194 case USB_AUDIO_LFE_SPEAKER:
195 return "Low frequency effects speaker";
197 default:
198 return "Unknown";
203 void
204 DumpAudioCSInterfaceDescriptorInputTerminal(
205 const usb_audio_input_terminal_descriptor* descriptor)
207 printf(" Subtype ........... 0x%02x (Input Terminal)\n",
208 descriptor->descriptor_subtype);
209 printf(" Terminal ID ....... %u\n",
210 descriptor->terminal_id);
211 printf(" Terminal Type ..... 0x%04x (%s)\n",
212 descriptor->terminal_type,
213 TerminalTypeName(descriptor->terminal_type));
214 printf(" Associated Terminal %u\n",
215 descriptor->assoc_terminal);
216 printf(" Nr Channels ....... %u\n",
217 descriptor->r1.num_channels);
218 printf(" Channel Config .... 0x%x\n",
219 descriptor->r1.channel_config);
220 DumpChannelConfig(descriptor->r1.channel_config);
222 printf(" Channel Names ..... %u\n",
223 descriptor->r1.channel_names);
224 printf(" Terminal .......... %u\n",
225 descriptor->r1.terminal);
229 void
230 DumpAudioCSInterfaceDescriptorOutputTerminal(
231 const usb_audio_output_terminal_descriptor* descriptor)
233 printf(" Subtype ........... 0x%02x (Output Terminal)\n",
234 descriptor->descriptor_subtype);
235 printf(" Terminal ID ....... %u\n",
236 descriptor->terminal_id);
237 printf(" Terminal Type ..... 0x%04x (%s)\n",
238 descriptor->terminal_type,
239 TerminalTypeName(descriptor->terminal_type));
240 printf(" Associated Terminal %u\n",
241 descriptor->assoc_terminal);
242 printf(" Source ID ......... %u\n",
243 descriptor->source_id);
244 printf(" Terminal .......... %u\n",
245 descriptor->r1.terminal);
249 void
250 DumpAudioCSInterfaceDescriptorMixerUnit(
251 const usb_audio_mixer_unit_descriptor* descriptor)
253 printf(" Subtype ........... 0x%02x (Mixer Unit)\n",
254 descriptor->descriptor_subtype);
255 printf(" Unit ID ........... %u\n",
256 descriptor->unit_id);
258 printf(" Source IDs ........ ");
259 for (uint8 i = 0; i < descriptor->num_input_pins; i++)
260 printf("%u, ", descriptor->input_pins[i]);
261 printf("\n");
263 usb_audio_output_channels_descriptor_r1* channels
264 = (usb_audio_output_channels_descriptor_r1*)
265 &descriptor->input_pins[descriptor->num_input_pins];
267 printf(" Channels .......... %u\n",
268 channels->num_output_pins);
269 printf(" Channel Config .... 0x%x\n",
270 channels->channel_config);
271 DumpChannelConfig(channels->channel_config);
272 printf(" Channel Names ..... %u\n",
273 channels->channel_names);
275 usb_generic_descriptor* generic = (usb_generic_descriptor*)descriptor;
276 uint8 idx = 7 + descriptor->num_input_pins;
277 printf(" Bitmap Control .... 0x");
278 for (uint i = 1; idx < descriptor->length - 3; idx++, i++)
279 printf("%02x ", (uint8)generic->data[idx]);
280 printf("\n");
282 printf(" Mixer ............. %u\n",
283 generic->data[generic->length - 3]);
287 void
288 DumpAudioCSInterfaceDescriptorSelectorUnit(
289 const usb_audio_selector_unit_descriptor* descriptor)
291 printf(" Subtype ........... 0x%02x (Selector Unit)\n",
292 descriptor->descriptor_subtype);
293 printf(" Unit ID ........... %u\n",
294 descriptor->unit_id);
296 printf(" Source IDs ........ ");
297 for (uint8 i = 0; i < descriptor->num_input_pins; i++)
298 printf("%u, ", descriptor->input_pins[i]);
299 printf("\n");
301 usb_generic_descriptor* generic = (usb_generic_descriptor*)descriptor;
302 printf(" Selector .......... %u\n",
303 (uint8)generic->data[descriptor->num_input_pins + 2]);
307 void
308 DumpBMAControl(uint8 channel, uint32 bma)
310 const char* BMAControls[] = {
311 "Mute",
312 "Volume",
313 "Bass",
314 "Mid",
315 "Treble",
316 "Graphic Equalizer",
317 "Automatic Gain",
318 "Delay",
319 "Bass Boost",
320 "Loudness"
323 if (bma == 0)
324 return;
326 if (channel == 0)
327 printf(" Master Channel . ");
328 else
329 printf(" Channel %u ...... ", channel);
331 int mask = 1;
332 for (uint8 i = 0;
333 i < sizeof(BMAControls) / sizeof(BMAControls[0]); i++, mask <<= 1)
334 if (bma & mask)
335 printf("%s ", BMAControls[i]);
336 printf("\n");
340 void
341 DumpAudioCSInterfaceDescriptorFeatureUnit(
342 const usb_audio_feature_unit_descriptor* descriptor)
344 printf(" Subtype ........... 0x%02x (Feature Unit)\n",
345 descriptor->descriptor_subtype);
346 printf(" Unit ID ........... %u\n",
347 descriptor->unit_id);
348 printf(" Source ID ......... %u\n",
349 descriptor->source_id);
351 printf(" Control Size ...... %u\n",
352 descriptor->r1.control_size);
355 uint8 channels = (descriptor->length - 6) / descriptor->r1.control_size;
356 for (uint8 i = 0; i < channels; i++) {
357 switch (descriptor->r1.control_size) {
358 case 1:
359 DumpBMAControl(i, descriptor->r1.bma_controls[i]);
360 break;
361 case 2:
362 DumpBMAControl(i, *(uint16*)&descriptor->r1.bma_controls[i * 2]);
363 break;
364 case 4:
365 DumpBMAControl(i, *(uint32*)&descriptor->r1.bma_controls[i * 4]);
366 break;
367 default:
368 printf(" BMA Channel %u ... ", i);
369 for (uint8 j = 0; j < descriptor->r1.control_size; j++)
370 printf("%02x ", descriptor->r1.bma_controls[i + j]);
371 break;
375 usb_generic_descriptor* generic = (usb_generic_descriptor*)descriptor;
376 printf(" Feature ........... %u\n",
377 (uint8)generic->data[descriptor->length - 3]);
381 void
382 DumpAudioCSInterfaceDescriptorAssociated(
383 const usb_generic_descriptor* descriptor)
385 printf(" Subtype ........... 0x%02x (Associate Interface)\n",
386 (uint8)descriptor->data[0]);
387 printf(" Interface ......... %u\n",
388 (uint8)descriptor->data[1]);
390 printf(" Data .............. ");
391 for (uint8 i = 0; i < descriptor->length - 2; i++)
392 printf("%02x ", descriptor->data[i]);
396 void
397 DumpAudioControlCSInterfaceDescriptor(const usb_generic_descriptor* descriptor)
399 uint8 descriptorSubtype = descriptor->data[0];
400 switch (descriptorSubtype) {
401 case USB_AUDIO_AC_HEADER:
402 DumpAudioCSInterfaceDescriptorHeader(
403 (usb_audiocontrol_header_descriptor*)descriptor);
404 break;
405 case USB_AUDIO_AC_INPUT_TERMINAL:
406 DumpAudioCSInterfaceDescriptorInputTerminal(
407 (usb_audio_input_terminal_descriptor*)descriptor);
408 break;
409 case USB_AUDIO_AC_OUTPUT_TERMINAL:
410 DumpAudioCSInterfaceDescriptorOutputTerminal(
411 (usb_audio_output_terminal_descriptor*)descriptor);
412 break;
413 case USB_AUDIO_AC_MIXER_UNIT:
414 DumpAudioCSInterfaceDescriptorMixerUnit(
415 (usb_audio_mixer_unit_descriptor*)descriptor);
416 break;
417 case USB_AUDIO_AC_SELECTOR_UNIT:
418 DumpAudioCSInterfaceDescriptorSelectorUnit(
419 (usb_audio_selector_unit_descriptor*)descriptor);
420 break;
421 case USB_AUDIO_AC_FEATURE_UNIT:
422 DumpAudioCSInterfaceDescriptorFeatureUnit(
423 (usb_audio_feature_unit_descriptor*)descriptor);
424 break;
425 case USB_AUDIO_AC_EXTENSION_UNIT:
426 DumpAudioCSInterfaceDescriptorAssociated(descriptor);
427 break;
428 default:
429 DumpDescriptorData(descriptor);
434 void
435 DumpGeneralASInterfaceDescriptor(
436 const usb_audio_streaming_interface_descriptor* descriptor)
438 printf(" Subtype ........... %u (AS_GENERAL)\n",
439 descriptor->descriptor_subtype);
440 printf(" Terminal link ..... %u\n",
441 descriptor->terminal_link);
442 printf(" Delay ............. %u\n",
443 descriptor->r1.delay);
444 printf(" Format tag ........ %u\n",
445 descriptor->r1.format_tag);
449 uint32
450 GetSamplingFrequency(const usb_audio_sampling_freq& freq)
452 return freq.bytes[0] | freq.bytes[1] << 8 | freq.bytes[2] << 16;
456 void
457 DumpSamplingFrequencies(uint8 type, const usb_audio_sampling_freq* freqs)
459 if (type > 0) {
460 printf(" Sampling Freq ..... ");
461 for (uint8 i = 0; i < type; i++)
462 printf("%lu, ", GetSamplingFrequency(freqs[i]));
463 printf("\n");
464 } else
465 printf(" Sampling Freq ..... %lu to %lu\n",
466 GetSamplingFrequency(freqs[0]), GetSamplingFrequency(freqs[1]));
470 void
471 DumpASFormatTypeI(const usb_audio_format_descriptor* descriptor)
473 printf(" Subtype ........... %u (FORMAT_TYPE)\n",
474 descriptor->descriptor_subtype);
475 printf(" Format Type ....... %u (FORMAT_TYPE_I)\n",
476 descriptor->format_type);
477 printf(" Channels .......... %u\n",
478 descriptor->typeI.nr_channels);
479 printf(" Subframe size ..... %u\n",
480 descriptor->typeI.subframe_size);
481 printf(" Bit resoultion .... %u\n",
482 descriptor->typeI.bit_resolution);
484 DumpSamplingFrequencies(descriptor->typeI.sam_freq_type,
485 descriptor->typeI.sam_freqs);
489 void
490 DumpASFormatTypeIII(const usb_audio_format_descriptor* descriptor)
492 printf(" Subtype ........... %u (FORMAT_TYPE)\n",
493 descriptor->descriptor_subtype);
494 printf(" Format Type ....... %u (FORMAT_TYPE_III)\n",
495 descriptor->format_type);
496 printf(" Channels .......... %u\n",
497 descriptor->typeIII.nr_channels);
498 printf(" Subframe size ..... %u\n",
499 descriptor->typeIII.subframe_size);
500 printf(" Bit resoultion .... %u\n",
501 descriptor->typeIII.bit_resolution);
503 DumpSamplingFrequencies(descriptor->typeIII.sam_freq_type,
504 descriptor->typeIII.sam_freqs);
508 void
509 DumpASFormatTypeII(const usb_audio_format_descriptor* descriptor)
511 printf(" Subtype ........... %u (FORMAT_TYPE)\n",
512 descriptor->descriptor_subtype);
513 printf(" Format Type ....... %u (FORMAT_TYPE_II)\n",
514 descriptor->format_type);
515 printf(" Max Bitrate ....... %u\n",
516 descriptor->typeII.max_bit_rate);
517 printf(" Samples per Frame . %u\n",
518 descriptor->typeII.samples_per_frame);
520 DumpSamplingFrequencies(descriptor->typeII.sam_freq_type,
521 descriptor->typeII.sam_freqs);
525 void
526 DumpASFmtType(const usb_audio_format_descriptor* descriptor)
528 uint8 format = descriptor->format_type;
529 switch (format) {
530 case USB_AUDIO_FORMAT_TYPE_I:
531 DumpASFormatTypeI(descriptor);
532 break;
533 case USB_AUDIO_FORMAT_TYPE_II:
534 DumpASFormatTypeII(descriptor);
535 break;
536 case USB_AUDIO_FORMAT_TYPE_III:
537 DumpASFormatTypeIII(descriptor);
538 break;
539 default:
540 DumpDescriptorData((usb_generic_descriptor*)descriptor);
541 break;
546 void
547 DumpMPEGCapabilities(uint16 capabilities)
549 const char* MPEGCapabilities[] = {
550 "Layer I",
551 "Layer II",
552 "Layer III",
554 "MPEG-1 only",
555 "MPEG-1 dual-channel",
556 "MPEG-2 second stereo",
557 "MPEG-2 7.1 channel augumentation",
558 "Adaptive multi-channel predicion"
561 uint16 mask = 1;
562 for (uint8 i = 0;
563 i < sizeof(MPEGCapabilities) / sizeof(MPEGCapabilities[0]); i++) {
564 if (capabilities & mask)
565 printf(" %s\n", MPEGCapabilities[i]);
566 mask <<= 1;
569 mask = 0x300; // bits 8 and 9
570 uint16 multilingualSupport = (capabilities & mask) >> 8;
571 switch (multilingualSupport) {
572 case 0:
573 printf(" No Multilingual support\n");
574 break;
575 case 1:
576 printf(" Supported at Fs\n");
577 break;
578 case 3:
579 printf(" Supported at Fs and 1/2Fs\n");
580 break;
581 default:
582 break;
587 void
588 DumpMPEGFeatures(uint8 features)
590 uint8 mask = 0x30; // bits 4 and 5
591 uint8 dynRangeControl = (features & mask) >> 4;
592 switch (dynRangeControl) {
593 case 0:
594 printf(" Not supported\n");
595 break;
596 case 1:
597 printf(" Supported, not scalable\n");
598 break;
599 case 2:
600 printf(" Scalable, common boost, "
601 "cut scaling value\n");
602 break;
603 case 3:
604 printf(" Scalable, separate boost, "
605 "cut scaling value\n");
606 default:
607 break;
612 void
613 DumpASFmtSpecificMPEG(const usb_generic_descriptor* descriptor)
615 printf(" Subtype ........... %u (FORMAT_SPECIFIC)\n",
616 descriptor->data[0]);
617 printf(" Format Tag ........ %u\n",
618 *(uint16*)&descriptor->data[1]);
619 printf(" MPEG Capabilities . %u\n",
620 *(uint16*)&descriptor->data[3]);
621 DumpMPEGCapabilities(*(uint16*)&descriptor->data[3]);
622 printf(" MPEG Features ..... %u\n",
623 descriptor->data[5]);
624 DumpMPEGFeatures(descriptor->data[5]);
628 void
629 DumpAC_3Features(uint8 features)
631 const char* featuresStr[] = {
632 "RF mode",
633 "Line mode",
634 "Custom0 mode",
635 "Custom1 mode"
638 uint8 mask = 1;
639 for (uint8 i = 0; i < sizeof(featuresStr) / sizeof(const char*); i++) {
640 if (features & mask)
641 printf(" %s\n", featuresStr[i]);
642 mask <<= 1;
645 mask = 0x30; // bits 4 and 5
646 uint8 dynRangeControl = (features & mask) >> 4;
647 switch (dynRangeControl) {
648 case 0:
649 printf(" Not supported\n");
650 break;
651 case 1:
652 printf(" Supported, not scalable\n");
653 break;
654 case 2:
655 printf(" Scalable, common boost, "
656 "cut scaling value\n");
657 break;
658 case 3:
659 printf(" Scalable, separate boost, "
660 "cut scaling value\n");
661 default:
662 break;
667 void
668 DumpASFmtSpecificAC_3(const usb_generic_descriptor* descriptor)
670 printf(" Subtype ........... %u (FORMAT_TYPE)\n",
671 descriptor->data[0]);
672 printf(" Format Tag ........ %u\n",
673 *(uint16*)&descriptor->data[1]);
674 printf(" BSID .............. %lx\n",
675 *(uint32*)&descriptor->data[2]);
676 printf(" AC3 Features ...... %u\n",
677 descriptor->data[6]);
678 DumpAC_3Features(descriptor->data[6]);
682 void
683 DumpASFmtSpecific(const usb_generic_descriptor* descriptor)
685 enum {
686 TYPE_II_UNDEFINED = 0x1000,
687 MPEG = 0x1001,
688 AC_3 = 0x1002
691 uint16 formatTag = *(uint16*)&descriptor->data[1];
692 switch (formatTag) {
693 case MPEG:
694 DumpASFmtSpecificMPEG(descriptor);
695 break;
696 case AC_3:
697 DumpASFmtSpecificAC_3(descriptor);
698 break;
699 default:
700 DumpDescriptorData(descriptor);
701 break;
706 void
707 DumpAudioStreamCSInterfaceDescriptor(const usb_generic_descriptor* descriptor)
709 uint8 subtype = descriptor->data[0];
710 switch (subtype) {
711 case USB_AUDIO_AS_GENERAL:
712 DumpGeneralASInterfaceDescriptor(
713 (usb_audio_streaming_interface_descriptor*)descriptor);
714 break;
715 case USB_AUDIO_AS_FORMAT_TYPE:
716 DumpASFmtType(
717 (usb_audio_format_descriptor*)descriptor);
718 break;
719 case USB_AUDIO_AS_FORMAT_SPECIFIC:
720 DumpASFmtSpecific(descriptor);
721 break;
722 default:
723 DumpDescriptorData(descriptor);
724 break;
729 void
730 DumpAudioStreamCSEndpointDescriptor(
731 const usb_audio_streaming_endpoint_descriptor* descriptor)
733 printf(" Type .............. 0x%02x (CS_ENDPOINT)\n",
734 descriptor->descriptor_type);
735 printf(" Subtype ........... 0x%02x (EP_GENERAL)\n",
736 descriptor->descriptor_subtype);
737 printf(" Attributes ........ 0x%02x ",
738 descriptor->attributes);
740 const char* attributes[] = {
741 "Sampling Frequency",
742 "Pitch",
743 "", "", "", "", "",
744 "Max Packet Only"
747 uint8 mask = 1;
748 for (uint8 i = 0; i < sizeof(attributes) / sizeof(attributes[0]); i++) {
749 if ((descriptor->attributes & mask) != 0)
750 printf("%s ", attributes[i]);
751 mask <<= 1;
753 printf("\n");
755 const char* aUnits[] = {
756 "Undefined",
757 "Milliseconds",
758 "Decoded PCM samples",
759 "Unknown (%u)"
762 const char* units = descriptor->lock_delay_units >= 4
763 ? aUnits[3] : aUnits[descriptor->lock_delay_units];
765 printf(" Lock Delay Units .. %u (%s)\n",
766 descriptor->lock_delay_units, units);
767 printf(" Lock Delay ........ %u\n",
768 descriptor->lock_delay);
772 void
773 DumpMidiInterfaceHeaderDescriptor(
774 const usb_midi_interface_header_descriptor* descriptor)
776 printf(" Type .............. 0x%02x (CS_ENDPOINT)\n",
777 descriptor->descriptor_type);
778 printf(" Subtype ........... 0x%02x (MS_HEADER)\n",
779 descriptor->descriptor_subtype);
780 printf(" MSC Version ....... 0x%04x\n",
781 descriptor->ms_version);
782 printf(" Length ............ 0x%04x\n",
783 descriptor->total_length);
787 void
788 DumpMidiInJackDescriptor(
789 const usb_midi_in_jack_descriptor* descriptor)
791 printf(" Type .............. 0x%02x (CS_INTERFACE)\n",
792 descriptor->descriptor_type);
793 printf(" Subtype ........... 0x%02x (MIDI_IN_JACK)\n",
794 descriptor->descriptor_subtype);
795 printf(" Jack ID ........... 0x%02x\n",
796 descriptor->id);
797 // TODO can we get the string?
798 printf(" String ............ 0x%02x\n",
799 descriptor->string_descriptor);
801 switch (descriptor->type) {
802 case USB_MIDI_EMBEDDED_JACK:
803 printf(" Jack Type ......... Embedded\n");
804 break;
805 case USB_MIDI_EXTERNAL_JACK:
806 printf(" Jack Type ......... External\n");
807 break;
808 default:
809 printf(" Jack Type ......... 0x%02x (unknown)\n",
810 descriptor->type);
811 break;
816 void
817 DumpMidiOutJackDescriptor(
818 const usb_midi_out_jack_descriptor* descriptor)
820 printf(" Type .............. 0x%02x (CS_INTERFACE)\n",
821 descriptor->descriptor_type);
822 printf(" Subtype ........... 0x%02x (MIDI_OUT_JACK)\n",
823 descriptor->descriptor_subtype);
824 printf(" Jack ID ........... 0x%02x\n",
825 descriptor->id);
827 switch (descriptor->type) {
828 case USB_MIDI_EMBEDDED_JACK:
829 printf(" Jack Type ......... Embedded\n");
830 break;
831 case USB_MIDI_EXTERNAL_JACK:
832 printf(" Jack Type ......... External\n");
833 break;
834 default:
835 printf(" Jack Type ......... 0x%02x (unknown)\n",
836 descriptor->type);
837 break;
840 for (int i = 0; i < descriptor->inputs_count; i++) {
841 printf(" Pin %02d ............ (%d,%d)\n", i,
842 descriptor->input_source[i].source_id,
843 descriptor->input_source[i].source_pin);
848 void
849 DumpMidiStreamCSInterfaceDescriptor(const usb_generic_descriptor* descriptor)
851 uint8 subtype = descriptor->data[0];
852 switch (subtype) {
853 case USB_MS_HEADER_DESCRIPTOR:
854 DumpMidiInterfaceHeaderDescriptor(
855 (usb_midi_interface_header_descriptor*)descriptor);
856 break;
857 case USB_MS_MIDI_IN_JACK_DESCRIPTOR:
858 DumpMidiInJackDescriptor(
859 (usb_midi_in_jack_descriptor*)descriptor);
860 break;
861 case USB_MS_MIDI_OUT_JACK_DESCRIPTOR:
862 DumpMidiOutJackDescriptor(
863 (usb_midi_out_jack_descriptor*)descriptor);
864 break;
865 case USB_MS_ELEMENT_DESCRIPTOR:
866 // TODO
867 DumpDescriptorData(descriptor);
868 break;
869 default:
870 DumpDescriptorData(descriptor);
871 break;
876 void
877 DumpMidiStreamCSEndpointDescriptor(
878 const usb_midi_endpoint_descriptor* descriptor)
880 printf(" Type .............. 0x%02x (CS_ENDPOINT)\n",
881 descriptor->descriptor_type);
882 printf(" Subtype ........... 0x%02x (MS_GENERAL)\n",
883 descriptor->descriptor_subtype);
884 printf(" Jacks ............. ");
886 for (int i = 0; i < descriptor->jacks_count; i++)
887 printf("%d, ", descriptor->jacks_id[i]);
889 printf("\n");
893 void
894 DumpAudioStreamInterfaceDescriptor(const usb_interface_descriptor* descriptor)
896 printf(" Type .............. %u (INTERFACE)\n",
897 descriptor->descriptor_type);
898 printf(" Interface ........... %u\n",
899 descriptor->interface_number);
900 printf(" Alternate setting ... %u\n",
901 descriptor->alternate_setting);
902 printf(" Endpoints ........... %u\n",
903 descriptor->num_endpoints);
904 printf(" Interface class ..... %u (AUDIO)\n",
905 descriptor->interface_class);
906 printf(" Interface subclass .. %u (AUDIO_STREAMING)\n",
907 descriptor->interface_subclass);
908 printf(" Interface ........... %u\n",
909 descriptor->interface);
913 void
914 DumpAudioDescriptor(const usb_generic_descriptor* descriptor, int subclass)
916 const uint8 USB_AUDIO_INTERFACE = 0x04;
918 switch (subclass) {
919 case USB_AUDIO_INTERFACE_AUDIOCONTROL_SUBCLASS:
920 switch (descriptor->descriptor_type) {
921 case USB_AUDIO_CS_INTERFACE:
922 DumpAudioControlCSInterfaceDescriptor(descriptor);
923 break;
924 default:
925 DumpDescriptorData(descriptor);
926 break;
928 break;
929 case USB_AUDIO_INTERFACE_AUDIOSTREAMING_SUBCLASS:
930 switch (descriptor->descriptor_type) {
931 case USB_AUDIO_INTERFACE:
932 DumpAudioStreamInterfaceDescriptor(
933 (const usb_interface_descriptor*)descriptor);
934 break;
935 case USB_AUDIO_CS_INTERFACE:
936 DumpAudioStreamCSInterfaceDescriptor(descriptor);
937 break;
938 case USB_AUDIO_CS_ENDPOINT:
939 DumpAudioStreamCSEndpointDescriptor(
940 (const usb_audio_streaming_endpoint_descriptor*)descriptor);
941 break;
942 default:
943 DumpDescriptorData(descriptor);
944 break;
946 break;
947 case USB_AUDIO_INTERFACE_MIDISTREAMING_SUBCLASS:
948 switch (descriptor->descriptor_type) {
949 case USB_AUDIO_CS_INTERFACE:
950 DumpMidiStreamCSInterfaceDescriptor(descriptor);
951 break;
952 case USB_AUDIO_CS_ENDPOINT:
953 DumpMidiStreamCSEndpointDescriptor(
954 (const usb_midi_endpoint_descriptor*)descriptor);
955 break;
956 default:
957 DumpDescriptorData(descriptor);
958 break;
960 break;
961 default:
962 DumpDescriptorData(descriptor);
963 break;
968 void
969 DumpDescriptor(const usb_generic_descriptor* descriptor,
970 int classNum, int subclass)
972 switch (classNum) {
973 case USB_AUDIO_DEVICE_CLASS:
974 DumpAudioDescriptor(descriptor, subclass);
975 break;
976 default:
977 DumpDescriptorData(descriptor);
978 break;
983 static void
984 DumpInterface(const BUSBInterface* interface)
986 if (!interface)
987 return;
989 printf(" Class .............. 0x%02x (%s)\n",
990 interface->Class(), ClassName(interface->Class()));
991 printf(" Subclass ........... 0x%02x\n",
992 interface->Subclass());
993 printf(" Protocol ........... 0x%02x\n",
994 interface->Protocol());
995 printf(" Interface String ... \"%s\"\n",
996 interface->InterfaceString());
998 for (uint32 i = 0; i < interface->CountEndpoints(); i++) {
999 const BUSBEndpoint* endpoint = interface->EndpointAt(i);
1000 if (!endpoint)
1001 continue;
1003 printf(" [Endpoint %lu]\n", i);
1004 printf(" MaxPacketSize .... %d\n",
1005 endpoint->MaxPacketSize());
1006 printf(" Interval ......... %d\n",
1007 endpoint->Interval());
1009 if (endpoint->IsControl())
1010 printf(" Type ............. Control\n");
1011 else if (endpoint->IsBulk())
1012 printf(" Type ............. Bulk\n");
1013 else if (endpoint->IsIsochronous())
1014 printf(" Type ............. Isochronous\n");
1015 else if (endpoint->IsInterrupt())
1016 printf(" Type ............. Interrupt\n");
1018 if (endpoint->IsInput())
1019 printf(" Direction ........ Input\n");
1020 else
1021 printf(" Direction ........ Output\n");
1024 char buffer[256];
1025 usb_descriptor* generic = (usb_descriptor*)buffer;
1026 for (uint32 i = 0;
1027 interface->OtherDescriptorAt(i, generic, 256) == B_OK; i++) {
1028 printf(" [Descriptor %lu]\n", i);
1029 DumpDescriptor(&generic->generic, interface->Class(), interface->Subclass());
1034 static void
1035 DumpConfiguration(const BUSBConfiguration* configuration)
1037 if (!configuration)
1038 return;
1040 printf(" Configuration String . \"%s\"\n",
1041 configuration->ConfigurationString());
1042 for (uint32 i = 0; i < configuration->CountInterfaces(); i++) {
1043 printf(" [Interface %lu]\n", i);
1044 const BUSBInterface* interface = configuration->InterfaceAt(i);
1046 for (uint32 j = 0; j < interface->CountAlternates(); j++) {
1047 const BUSBInterface* alternate = interface->AlternateAt(j);
1048 printf(" [Alternate %lu%s]\n", j,
1049 j == interface->AlternateIndex() ? " active" : "");
1050 DumpInterface(alternate);
1056 static void
1057 DumpInfo(BUSBDevice& device, bool verbose)
1059 const char* vendorName = NULL;
1060 const char* deviceName = NULL;
1061 usb_get_vendor_info(device.VendorID(), &vendorName);
1062 usb_get_device_info(device.VendorID(), device.ProductID(), &deviceName);
1064 if (!verbose) {
1065 printf("%04x:%04x /dev/bus/usb%s \"%s\" \"%s\" ver. %04x\n",
1066 device.VendorID(), device.ProductID(), device.Location(),
1067 vendorName ? vendorName : device.ManufacturerString(),
1068 deviceName ? deviceName : device.ProductString(),
1069 device.Version());
1070 return;
1073 printf("[Device /dev/bus/usb%s]\n", device.Location());
1074 printf(" Class .................. 0x%02x (%s)\n", device.Class(),
1075 ClassName(device.Class()));
1076 printf(" Subclass ............... 0x%02x\n", device.Subclass());
1077 printf(" Protocol ............... 0x%02x\n", device.Protocol());
1078 printf(" Max Endpoint 0 Packet .. %d\n", device.MaxEndpoint0PacketSize());
1079 printf(" USB Version ............ 0x%04x\n", device.USBVersion());
1080 printf(" Vendor ID .............. 0x%04x", device.VendorID());
1081 if (vendorName != NULL)
1082 printf(" (%s)", vendorName);
1083 printf("\n Product ID ............. 0x%04x", device.ProductID());
1084 if (deviceName != NULL)
1085 printf(" (%s)", deviceName);
1086 printf("\n Product Version ........ 0x%04x\n", device.Version());
1087 printf(" Manufacturer String .... \"%s\"\n", device.ManufacturerString());
1088 printf(" Product String ......... \"%s\"\n", device.ProductString());
1089 printf(" Serial Number .......... \"%s\"\n", device.SerialNumberString());
1091 for (uint32 i = 0; i < device.CountConfigurations(); i++) {
1092 printf(" [Configuration %lu]\n", i);
1093 DumpConfiguration(device.ConfigurationAt(i));
1096 if (device.Class() != 0x09)
1097 return;
1099 usb_hub_descriptor hubDescriptor;
1100 size_t size = device.GetDescriptor(USB_DESCRIPTOR_HUB, 0, 0,
1101 (void*)&hubDescriptor, sizeof(usb_hub_descriptor));
1102 if (size == sizeof(usb_hub_descriptor)) {
1103 printf(" Hub ports count......... %d\n", hubDescriptor.num_ports);
1104 printf(" Hub Controller Current.. %dmA\n", hubDescriptor.max_power);
1106 for (int index = 1; index <= hubDescriptor.num_ports; index++) {
1107 usb_port_status portStatus;
1108 size_t actualLength = device.ControlTransfer(USB_REQTYPE_CLASS
1109 | USB_REQTYPE_OTHER_IN, USB_REQUEST_GET_STATUS, 0,
1110 index, sizeof(portStatus), (void*)&portStatus);
1111 if (actualLength != sizeof(portStatus))
1112 continue;
1113 printf(" Port %d status....... %04x.%04x%s%s%s%s%s%s%s%s%s\n",
1114 index, portStatus.status, portStatus.change,
1115 portStatus.status & PORT_STATUS_CONNECTION ? " Connect": "",
1116 portStatus.status & PORT_STATUS_ENABLE ? " Enable": "",
1117 portStatus.status & PORT_STATUS_SUSPEND ? " Suspend": "",
1118 portStatus.status & PORT_STATUS_OVER_CURRENT ? " Overcurrent": "",
1119 portStatus.status & PORT_STATUS_RESET ? " Reset": "",
1120 portStatus.status & PORT_STATUS_POWER ? " Power": "",
1121 portStatus.status & PORT_STATUS_CONNECTION
1122 ? (portStatus.status & PORT_STATUS_LOW_SPEED ? " Lowspeed"
1123 : (portStatus.status & PORT_STATUS_HIGH_SPEED ? " Highspeed"
1124 : " Fullspeed")) : "",
1125 portStatus.status & PORT_STATUS_TEST ? " Test": "",
1126 portStatus.status & PORT_STATUS_INDICATOR ? " Indicator": "");
1132 class DumpRoster : public BUSBRoster {
1133 public:
1134 DumpRoster(bool verbose)
1135 : fVerbose(verbose)
1140 virtual status_t DeviceAdded(BUSBDevice* device)
1142 DumpInfo(*device, fVerbose);
1143 return B_OK;
1147 virtual void DeviceRemoved(BUSBDevice* device)
1151 private:
1152 bool fVerbose;
1158 main(int argc, char* argv[])
1160 bool verbose = false;
1161 BString devname = "";
1162 for (int i = 1; i < argc; i++) {
1163 if (argv[i][0] == '-') {
1164 if (argv[i][1] == 'v')
1165 verbose = true;
1166 else {
1167 printf("Usage: listusb [-v] [device]\n\n");
1168 printf("-v: Show more detailed information including "
1169 "interfaces, configurations, etc.\n\n");
1170 printf("If a device is not specified, "
1171 "all devices found on the bus will be listed\n");
1172 return 1;
1174 } else
1175 devname = argv[i];
1178 if (devname.Length() > 0) {
1179 BUSBDevice device(devname.String());
1180 if (device.InitCheck() < B_OK) {
1181 printf("Cannot open USB device: %s\n", devname.String());
1182 return 1;
1183 } else {
1184 DumpInfo(device, verbose);
1185 return 0;
1187 } else {
1188 DumpRoster roster(verbose);
1189 roster.Start();
1190 roster.Stop();
1193 return 0;