vfs: check userland buffers before reading them.
[haiku.git] / src / bin / listusb / usb_audio.cpp
blob71025020be79822eb113e7b1d6924c67b6dcf57f
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-2016, Haiku Inc. All rights reserved.
7 */
9 #include <MediaDefs.h>
10 #include <USBKit.h>
11 #include <stdio.h>
13 #include <usb/USB_audio.h>
14 #include <usb/USB_midi.h>
16 #include "listusb.h"
18 void
19 DumpAudioCSInterfaceDescriptorHeader(
20 const usb_audiocontrol_header_descriptor* descriptor)
22 printf(" Type .............. 0x%02x\n",
23 descriptor->descriptor_type);
24 printf(" Subtype ........... 0x%02x (Header)\n",
25 descriptor->descriptor_subtype);
26 printf(" ADC Release ....... %d.%d\n",
27 descriptor->bcd_release_no >> 8, descriptor->bcd_release_no & 0xFF);
28 printf(" Total Length ...... %u\n",
29 descriptor->r1.total_length);
30 printf(" Interfaces ........ ");
32 for (uint8 i = 0; i < descriptor->r1.in_collection; i++)
33 printf("%u, ", descriptor->r1.interface_numbers[i]);
34 printf("\n");
38 void
39 DumpChannelConfig(uint32 wChannelConfig)
41 struct _Entry {
42 const char* name;
43 uint32 mask;
44 } aClusters[] = {
45 { "Front .......... ", B_CHANNEL_LEFT | B_CHANNEL_RIGHT
46 | B_CHANNEL_CENTER },
47 { "L.F.E .......... ", B_CHANNEL_SUB },
48 { "Back ........... ", B_CHANNEL_REARLEFT | B_CHANNEL_REARRIGHT
49 | B_CHANNEL_BACK_CENTER },
50 { "Center ......... ", B_CHANNEL_FRONT_LEFT_CENTER
51 | B_CHANNEL_FRONT_RIGHT_CENTER },
52 { "Side ........... ", B_CHANNEL_SIDE_LEFT | B_CHANNEL_SIDE_RIGHT },
53 { "Top ............ ", B_CHANNEL_TOP_CENTER },
54 { "Top Front ...... ", B_CHANNEL_TOP_FRONT_LEFT
55 | B_CHANNEL_TOP_FRONT_CENTER | B_CHANNEL_TOP_FRONT_RIGHT },
56 { "Top Back ....... ", B_CHANNEL_TOP_BACK_LEFT
57 | B_CHANNEL_TOP_BACK_CENTER | B_CHANNEL_TOP_BACK_RIGHT }
60 struct _Entry aChannels[] = {
61 { "Left", B_CHANNEL_LEFT | B_CHANNEL_FRONT_LEFT_CENTER
62 | B_CHANNEL_REARLEFT | B_CHANNEL_SIDE_LEFT | B_CHANNEL_TOP_BACK_LEFT
63 | B_CHANNEL_TOP_FRONT_LEFT },
64 { "Right", B_CHANNEL_FRONT_RIGHT_CENTER | B_CHANNEL_TOP_FRONT_RIGHT
65 | B_CHANNEL_REARRIGHT | B_CHANNEL_RIGHT | B_CHANNEL_SIDE_RIGHT
66 | B_CHANNEL_TOP_BACK_RIGHT },
67 { "Center", B_CHANNEL_BACK_CENTER | B_CHANNEL_CENTER
68 | B_CHANNEL_TOP_BACK_CENTER | B_CHANNEL_TOP_CENTER
69 | B_CHANNEL_TOP_FRONT_CENTER },
70 { "L.F.E.", B_CHANNEL_SUB }
73 for (size_t i = 0; i < sizeof(aClusters) / sizeof(aClusters[0]); i++) {
74 uint32 mask = aClusters[i].mask & wChannelConfig;
75 if (mask != 0) {
76 printf(" %s", aClusters[i].name);
77 for (size_t j = 0; j < sizeof(aChannels) / sizeof(aChannels[0]); j++)
78 if ((aChannels[j].mask & mask) != 0)
79 printf("%s ", aChannels[j].name);
80 printf("\n");
86 static const char*
87 TerminalTypeName(uint16 terminalType)
89 switch (terminalType) {
90 case USB_AUDIO_UNDEFINED_USB_IO:
91 return "USB Undefined";
92 case USB_AUDIO_STREAMING_USB_IO:
93 return "USB Streaming";
94 case USB_AUDIO_VENDOR_USB_IO:
95 return "USB vendor specific";
97 case USB_AUDIO_UNDEFINED_IN:
98 return "Undefined";
99 case USB_AUDIO_MICROPHONE_IN:
100 return "Microphone";
101 case USB_AUDIO_DESKTOPMIC_IN:
102 return "Desktop microphone";
103 case USB_AUDIO_PERSONALMIC_IN:
104 return "Personal microphone";
105 case USB_AUDIO_OMNI_MIC_IN:
106 return "Omni-directional microphone";
107 case USB_AUDIO_MICS_ARRAY_IN:
108 return "Microphone array";
109 case USB_AUDIO_PROC_MICS_ARRAY_IN:
110 return "Processing microphone array";
111 case USB_AUDIO_LINE_CONNECTOR_IO:
112 return "Line I/O";
113 case USB_AUDIO_SPDIF_INTERFACE_IO:
114 return "S/PDIF";
116 case USB_AUDIO_UNDEFINED_OUT:
117 return "Undefined";
118 case USB_AUDIO_SPEAKER_OUT:
119 return "Speaker";
120 case USB_AUDIO_HEAD_PHONES_OUT:
121 return "Headphones";
122 case USB_AUDIO_HMD_AUDIO_OUT:
123 return "Head Mounted Display Audio";
124 case USB_AUDIO_DESKTOP_SPEAKER:
125 return "Desktop speaker";
126 case USB_AUDIO_ROOM_SPEAKER:
127 return "Room speaker";
128 case USB_AUDIO_COMM_SPEAKER:
129 return "Communication speaker";
130 case USB_AUDIO_LFE_SPEAKER:
131 return "Low frequency effects speaker";
133 default:
134 return "Unknown";
139 void
140 DumpAudioCSInterfaceDescriptorInputTerminal(
141 const usb_audio_input_terminal_descriptor* descriptor)
143 printf(" Type .............. 0x%02x\n",
144 descriptor->descriptor_type);
145 printf(" Subtype ........... 0x%02x (Input Terminal)\n",
146 descriptor->descriptor_subtype);
147 printf(" Terminal ID ....... %u\n",
148 descriptor->terminal_id);
149 printf(" Terminal Type ..... 0x%04x (%s)\n",
150 descriptor->terminal_type,
151 TerminalTypeName(descriptor->terminal_type));
152 printf(" Associated Terminal %u\n",
153 descriptor->assoc_terminal);
154 printf(" Nr Channels ....... %u\n",
155 descriptor->r1.num_channels);
156 printf(" Channel Config .... 0x%x\n",
157 descriptor->r1.channel_config);
158 DumpChannelConfig(descriptor->r1.channel_config);
160 printf(" Channel Names ..... %u\n",
161 descriptor->r1.channel_names);
162 printf(" Terminal .......... %u\n",
163 descriptor->r1.terminal);
167 void
168 DumpAudioCSInterfaceDescriptorOutputTerminal(
169 const usb_audio_output_terminal_descriptor* descriptor)
171 printf(" Type .............. 0x%02x\n",
172 descriptor->descriptor_type);
173 printf(" Subtype ........... 0x%02x (Output Terminal)\n",
174 descriptor->descriptor_subtype);
175 printf(" Terminal ID ....... %u\n",
176 descriptor->terminal_id);
177 printf(" Terminal Type ..... 0x%04x (%s)\n",
178 descriptor->terminal_type,
179 TerminalTypeName(descriptor->terminal_type));
180 printf(" Associated Terminal %u\n",
181 descriptor->assoc_terminal);
182 printf(" Source ID ......... %u\n",
183 descriptor->source_id);
184 printf(" Terminal .......... %u\n",
185 descriptor->r1.terminal);
189 void
190 DumpAudioCSInterfaceDescriptorMixerUnit(
191 const usb_audio_mixer_unit_descriptor* descriptor)
193 printf(" Type .............. 0x%02x\n",
194 descriptor->descriptor_type);
195 printf(" Subtype ........... 0x%02x (Mixer Unit)\n",
196 descriptor->descriptor_subtype);
197 printf(" Unit ID ........... %u\n",
198 descriptor->unit_id);
200 printf(" Source IDs ........ ");
201 for (uint8 i = 0; i < descriptor->num_input_pins; i++)
202 printf("%u, ", descriptor->input_pins[i]);
203 printf("\n");
205 usb_audio_output_channels_descriptor_r1* channels
206 = (usb_audio_output_channels_descriptor_r1*)
207 &descriptor->input_pins[descriptor->num_input_pins];
209 printf(" Channels .......... %u\n",
210 channels->num_output_pins);
211 printf(" Channel Config .... 0x%x\n",
212 channels->channel_config);
213 DumpChannelConfig(channels->channel_config);
214 printf(" Channel Names ..... %u\n",
215 channels->channel_names);
217 usb_generic_descriptor* generic = (usb_generic_descriptor*)descriptor;
218 uint8 idx = 7 + descriptor->num_input_pins;
219 printf(" Bitmap Control .... 0x");
220 for (uint i = 1; idx < descriptor->length - 3; idx++, i++)
221 printf("%02x ", (uint8)generic->data[idx]);
222 printf("\n");
224 printf(" Mixer ............. %u\n",
225 generic->data[generic->length - 3]);
229 void
230 DumpAudioCSInterfaceDescriptorSelectorUnit(
231 const usb_audio_selector_unit_descriptor* descriptor)
233 printf(" Type .............. 0x%02x\n",
234 descriptor->descriptor_type);
235 printf(" Subtype ........... 0x%02x (Selector Unit)\n",
236 descriptor->descriptor_subtype);
237 printf(" Unit ID ........... %u\n",
238 descriptor->unit_id);
240 printf(" Source IDs ........ ");
241 for (uint8 i = 0; i < descriptor->num_input_pins; i++)
242 printf("%u, ", descriptor->input_pins[i]);
243 printf("\n");
245 usb_generic_descriptor* generic = (usb_generic_descriptor*)descriptor;
246 printf(" Selector .......... %u\n",
247 (uint8)generic->data[descriptor->num_input_pins + 2]);
251 void
252 DumpBMAControl(uint8 channel, uint32 bma)
254 const char* BMAControls[] = {
255 "Mute",
256 "Volume",
257 "Bass",
258 "Mid",
259 "Treble",
260 "Graphic Equalizer",
261 "Automatic Gain",
262 "Delay",
263 "Bass Boost",
264 "Loudness"
267 if (bma == 0)
268 return;
270 if (channel == 0)
271 printf(" Master Channel . ");
272 else
273 printf(" Channel %u ...... ", channel);
275 int mask = 1;
276 for (uint8 i = 0;
277 i < sizeof(BMAControls) / sizeof(BMAControls[0]); i++, mask <<= 1)
278 if (bma & mask)
279 printf("%s ", BMAControls[i]);
280 printf("\n");
284 void
285 DumpAudioCSInterfaceDescriptorFeatureUnit(
286 const usb_audio_feature_unit_descriptor* descriptor)
288 printf(" Type .............. 0x%02x\n",
289 descriptor->descriptor_type);
290 printf(" Subtype ........... 0x%02x (Feature Unit)\n",
291 descriptor->descriptor_subtype);
292 printf(" Unit ID ........... %u\n",
293 descriptor->unit_id);
294 printf(" Source ID ......... %u\n",
295 descriptor->source_id);
297 printf(" Control Size ...... %u\n",
298 descriptor->r1.control_size);
301 uint8 channels = (descriptor->length - 6) / descriptor->r1.control_size;
302 for (uint8 i = 0; i < channels; i++) {
303 switch (descriptor->r1.control_size) {
304 case 1:
305 DumpBMAControl(i, descriptor->r1.bma_controls[i]);
306 break;
307 case 2:
308 DumpBMAControl(i, *(uint16*)&descriptor->r1.bma_controls[i * 2]);
309 break;
310 case 4:
311 DumpBMAControl(i, *(uint32*)&descriptor->r1.bma_controls[i * 4]);
312 break;
313 default:
314 printf(" BMA Channel %u ... ", i);
315 for (uint8 j = 0; j < descriptor->r1.control_size; j++)
316 printf("%02x ", descriptor->r1.bma_controls[i + j]);
317 break;
321 usb_generic_descriptor* generic = (usb_generic_descriptor*)descriptor;
322 printf(" Feature ........... %u\n",
323 (uint8)generic->data[descriptor->length - 3]);
327 void
328 DumpAudioCSInterfaceDescriptorAssociated(
329 const usb_generic_descriptor* descriptor)
331 printf(" Type .............. 0x%02x\n",
332 descriptor->descriptor_type);
333 printf(" Subtype ........... 0x%02x (Associate Interface)\n",
334 (uint8)descriptor->data[0]);
335 printf(" Interface ......... %u\n",
336 (uint8)descriptor->data[1]);
338 printf(" Data .............. ");
339 for (uint8 i = 0; i < descriptor->length - 2; i++)
340 printf("%02x ", descriptor->data[i]);
341 printf("\n");
345 void
346 DumpAudioControlCSInterfaceDescriptor(const usb_generic_descriptor* descriptor)
348 uint8 descriptorSubtype = descriptor->data[0];
349 switch (descriptorSubtype) {
350 case USB_AUDIO_AC_HEADER:
351 DumpAudioCSInterfaceDescriptorHeader(
352 (usb_audiocontrol_header_descriptor*)descriptor);
353 break;
354 case USB_AUDIO_AC_INPUT_TERMINAL:
355 DumpAudioCSInterfaceDescriptorInputTerminal(
356 (usb_audio_input_terminal_descriptor*)descriptor);
357 break;
358 case USB_AUDIO_AC_OUTPUT_TERMINAL:
359 DumpAudioCSInterfaceDescriptorOutputTerminal(
360 (usb_audio_output_terminal_descriptor*)descriptor);
361 break;
362 case USB_AUDIO_AC_MIXER_UNIT:
363 DumpAudioCSInterfaceDescriptorMixerUnit(
364 (usb_audio_mixer_unit_descriptor*)descriptor);
365 break;
366 case USB_AUDIO_AC_SELECTOR_UNIT:
367 DumpAudioCSInterfaceDescriptorSelectorUnit(
368 (usb_audio_selector_unit_descriptor*)descriptor);
369 break;
370 case USB_AUDIO_AC_FEATURE_UNIT:
371 DumpAudioCSInterfaceDescriptorFeatureUnit(
372 (usb_audio_feature_unit_descriptor*)descriptor);
373 break;
374 case USB_AUDIO_AC_EXTENSION_UNIT:
375 DumpAudioCSInterfaceDescriptorAssociated(descriptor);
376 break;
377 default:
378 DumpDescriptorData(descriptor);
383 void
384 DumpGeneralASInterfaceDescriptor(
385 const usb_audio_streaming_interface_descriptor* descriptor)
387 printf(" Subtype ........... %u (AS_GENERAL)\n",
388 descriptor->descriptor_subtype);
389 printf(" Terminal link ..... %u\n",
390 descriptor->terminal_link);
391 printf(" Delay ............. %u\n",
392 descriptor->r1.delay);
393 printf(" Format tag ........ %u\n",
394 descriptor->r1.format_tag);
398 uint32
399 GetSamplingFrequency(const usb_audio_sampling_freq& freq)
401 return freq.bytes[0] | freq.bytes[1] << 8 | freq.bytes[2] << 16;
405 void
406 DumpSamplingFrequencies(uint8 type, const usb_audio_sampling_freq* freqs)
408 if (type > 0) {
409 printf(" Sampling Freq ..... ");
410 for (uint8 i = 0; i < type; i++)
411 printf("%" B_PRIu32 ", ", GetSamplingFrequency(freqs[i]));
412 printf("\n");
413 } else {
414 printf(" Sampling Freq ..... %" B_PRIu32 " to %"
415 B_PRIu32 "\n", GetSamplingFrequency(freqs[0]),
416 GetSamplingFrequency(freqs[1]));
421 void
422 DumpASFormatTypeI(const usb_audio_format_descriptor* descriptor)
424 printf(" Subtype ........... %u (FORMAT_TYPE)\n",
425 descriptor->descriptor_subtype);
426 printf(" Format Type ....... %u (FORMAT_TYPE_I)\n",
427 descriptor->format_type);
428 printf(" Channels .......... %u\n",
429 descriptor->typeI.nr_channels);
430 printf(" Subframe size ..... %u\n",
431 descriptor->typeI.subframe_size);
432 printf(" Bit resoultion .... %u\n",
433 descriptor->typeI.bit_resolution);
435 DumpSamplingFrequencies(descriptor->typeI.sam_freq_type,
436 descriptor->typeI.sam_freqs);
440 void
441 DumpASFormatTypeIII(const usb_audio_format_descriptor* descriptor)
443 printf(" Subtype ........... %u (FORMAT_TYPE)\n",
444 descriptor->descriptor_subtype);
445 printf(" Format Type ....... %u (FORMAT_TYPE_III)\n",
446 descriptor->format_type);
447 printf(" Channels .......... %u\n",
448 descriptor->typeIII.nr_channels);
449 printf(" Subframe size ..... %u\n",
450 descriptor->typeIII.subframe_size);
451 printf(" Bit resoultion .... %u\n",
452 descriptor->typeIII.bit_resolution);
454 DumpSamplingFrequencies(descriptor->typeIII.sam_freq_type,
455 descriptor->typeIII.sam_freqs);
459 void
460 DumpASFormatTypeII(const usb_audio_format_descriptor* descriptor)
462 printf(" Subtype ........... %u (FORMAT_TYPE)\n",
463 descriptor->descriptor_subtype);
464 printf(" Format Type ....... %u (FORMAT_TYPE_II)\n",
465 descriptor->format_type);
466 printf(" Max Bitrate ....... %u\n",
467 descriptor->typeII.max_bit_rate);
468 printf(" Samples per Frame . %u\n",
469 descriptor->typeII.samples_per_frame);
471 DumpSamplingFrequencies(descriptor->typeII.sam_freq_type,
472 descriptor->typeII.sam_freqs);
476 void
477 DumpASFmtType(const usb_audio_format_descriptor* descriptor)
479 uint8 format = descriptor->format_type;
480 switch (format) {
481 case USB_AUDIO_FORMAT_TYPE_I:
482 DumpASFormatTypeI(descriptor);
483 break;
484 case USB_AUDIO_FORMAT_TYPE_II:
485 DumpASFormatTypeII(descriptor);
486 break;
487 case USB_AUDIO_FORMAT_TYPE_III:
488 DumpASFormatTypeIII(descriptor);
489 break;
490 default:
491 DumpDescriptorData((usb_generic_descriptor*)descriptor);
492 break;
497 void
498 DumpMPEGCapabilities(uint16 capabilities)
500 const char* MPEGCapabilities[] = {
501 "Layer I",
502 "Layer II",
503 "Layer III",
505 "MPEG-1 only",
506 "MPEG-1 dual-channel",
507 "MPEG-2 second stereo",
508 "MPEG-2 7.1 channel augumentation",
509 "Adaptive multi-channel predicion"
512 uint16 mask = 1;
513 for (uint8 i = 0;
514 i < sizeof(MPEGCapabilities) / sizeof(MPEGCapabilities[0]); i++) {
515 if (capabilities & mask)
516 printf(" %s\n", MPEGCapabilities[i]);
517 mask <<= 1;
520 mask = 0x300; // bits 8 and 9
521 uint16 multilingualSupport = (capabilities & mask) >> 8;
522 switch (multilingualSupport) {
523 case 0:
524 printf(" No Multilingual support\n");
525 break;
526 case 1:
527 printf(" Supported at Fs\n");
528 break;
529 case 3:
530 printf(" Supported at Fs and 1/2Fs\n");
531 break;
532 default:
533 break;
538 void
539 DumpMPEGFeatures(uint8 features)
541 uint8 mask = 0x30; // bits 4 and 5
542 uint8 dynRangeControl = (features & mask) >> 4;
543 switch (dynRangeControl) {
544 case 0:
545 printf(" Not supported\n");
546 break;
547 case 1:
548 printf(" Supported, not scalable\n");
549 break;
550 case 2:
551 printf(" Scalable, common boost, "
552 "cut scaling value\n");
553 break;
554 case 3:
555 printf(" Scalable, separate boost, "
556 "cut scaling value\n");
557 default:
558 break;
563 void
564 DumpASFmtSpecificMPEG(const usb_generic_descriptor* descriptor)
566 printf(" Subtype ........... %u (FORMAT_SPECIFIC)\n",
567 descriptor->data[0]);
568 printf(" Format Tag ........ %u\n",
569 *(uint16*)&descriptor->data[1]);
570 printf(" MPEG Capabilities . %u\n",
571 *(uint16*)&descriptor->data[3]);
572 DumpMPEGCapabilities(*(uint16*)&descriptor->data[3]);
573 printf(" MPEG Features ..... %u\n",
574 descriptor->data[5]);
575 DumpMPEGFeatures(descriptor->data[5]);
579 void
580 DumpAC_3Features(uint8 features)
582 const char* featuresStr[] = {
583 "RF mode",
584 "Line mode",
585 "Custom0 mode",
586 "Custom1 mode"
589 uint8 mask = 1;
590 for (uint8 i = 0; i < sizeof(featuresStr) / sizeof(const char*); i++) {
591 if (features & mask)
592 printf(" %s\n", featuresStr[i]);
593 mask <<= 1;
596 mask = 0x30; // bits 4 and 5
597 uint8 dynRangeControl = (features & mask) >> 4;
598 switch (dynRangeControl) {
599 case 0:
600 printf(" Not supported\n");
601 break;
602 case 1:
603 printf(" Supported, not scalable\n");
604 break;
605 case 2:
606 printf(" Scalable, common boost, "
607 "cut scaling value\n");
608 break;
609 case 3:
610 printf(" Scalable, separate boost, "
611 "cut scaling value\n");
612 default:
613 break;
618 void
619 DumpASFmtSpecificAC_3(const usb_generic_descriptor* descriptor)
621 printf(" Subtype ........... %u (FORMAT_TYPE)\n",
622 descriptor->data[0]);
623 printf(" Format Tag ........ %u\n",
624 *(uint16*)&descriptor->data[1]);
625 printf(" BSID .............. %" B_PRIx32 "\n",
626 *(uint32*)&descriptor->data[2]);
627 printf(" AC3 Features ...... %u\n",
628 descriptor->data[6]);
629 DumpAC_3Features(descriptor->data[6]);
633 void
634 DumpASFmtSpecific(const usb_generic_descriptor* descriptor)
636 enum {
637 TYPE_II_UNDEFINED = 0x1000,
638 MPEG = 0x1001,
639 AC_3 = 0x1002
642 uint16 formatTag = *(uint16*)&descriptor->data[1];
643 switch (formatTag) {
644 case MPEG:
645 DumpASFmtSpecificMPEG(descriptor);
646 break;
647 case AC_3:
648 DumpASFmtSpecificAC_3(descriptor);
649 break;
650 default:
651 DumpDescriptorData(descriptor);
652 break;
657 void
658 DumpAudioStreamCSInterfaceDescriptor(const usb_generic_descriptor* descriptor)
660 uint8 subtype = descriptor->data[0];
661 switch (subtype) {
662 case USB_AUDIO_AS_GENERAL:
663 DumpGeneralASInterfaceDescriptor(
664 (usb_audio_streaming_interface_descriptor*)descriptor);
665 break;
666 case USB_AUDIO_AS_FORMAT_TYPE:
667 DumpASFmtType(
668 (usb_audio_format_descriptor*)descriptor);
669 break;
670 case USB_AUDIO_AS_FORMAT_SPECIFIC:
671 DumpASFmtSpecific(descriptor);
672 break;
673 default:
674 DumpDescriptorData(descriptor);
675 break;
680 void
681 DumpAudioStreamCSEndpointDescriptor(
682 const usb_audio_streaming_endpoint_descriptor* descriptor)
684 printf(" Type .............. 0x%02x (CS_ENDPOINT)\n",
685 descriptor->descriptor_type);
686 printf(" Subtype ........... 0x%02x (EP_GENERAL)\n",
687 descriptor->descriptor_subtype);
688 printf(" Attributes ........ 0x%02x ",
689 descriptor->attributes);
691 const char* attributes[] = {
692 "Sampling Frequency",
693 "Pitch",
694 "", "", "", "", "",
695 "Max Packet Only"
698 uint8 mask = 1;
699 for (uint8 i = 0; i < sizeof(attributes) / sizeof(attributes[0]); i++) {
700 if ((descriptor->attributes & mask) != 0)
701 printf("%s ", attributes[i]);
702 mask <<= 1;
704 printf("\n");
706 const char* aUnits[] = {
707 "Undefined",
708 "Milliseconds",
709 "Decoded PCM samples",
710 "Unknown (%u)"
713 const char* units = descriptor->lock_delay_units >= 4
714 ? aUnits[3] : aUnits[descriptor->lock_delay_units];
716 printf(" Lock Delay Units .. %u (%s)\n",
717 descriptor->lock_delay_units, units);
718 printf(" Lock Delay ........ %u\n",
719 descriptor->lock_delay);
723 void
724 DumpMidiInterfaceHeaderDescriptor(
725 const usb_midi_interface_header_descriptor* descriptor)
727 printf(" Type .............. 0x%02x (CS_ENDPOINT)\n",
728 descriptor->descriptor_type);
729 printf(" Subtype ........... 0x%02x (MS_HEADER)\n",
730 descriptor->descriptor_subtype);
731 printf(" MSC Version ....... 0x%04x\n",
732 descriptor->ms_version);
733 printf(" Length ............ 0x%04x\n",
734 descriptor->total_length);
738 void
739 DumpMidiInJackDescriptor(
740 const usb_midi_in_jack_descriptor* descriptor)
742 printf(" Type .............. 0x%02x (CS_INTERFACE)\n",
743 descriptor->descriptor_type);
744 printf(" Subtype ........... 0x%02x (MIDI_IN_JACK)\n",
745 descriptor->descriptor_subtype);
746 printf(" Jack ID ........... 0x%02x\n",
747 descriptor->id);
748 // TODO can we get the string?
749 printf(" String ............ 0x%02x\n",
750 descriptor->string_descriptor);
752 switch (descriptor->type) {
753 case USB_MIDI_EMBEDDED_JACK:
754 printf(" Jack Type ......... Embedded\n");
755 break;
756 case USB_MIDI_EXTERNAL_JACK:
757 printf(" Jack Type ......... External\n");
758 break;
759 default:
760 printf(" Jack Type ......... 0x%02x (unknown)\n",
761 descriptor->type);
762 break;
767 void
768 DumpMidiOutJackDescriptor(
769 const usb_midi_out_jack_descriptor* descriptor)
771 printf(" Type .............. 0x%02x (CS_INTERFACE)\n",
772 descriptor->descriptor_type);
773 printf(" Subtype ........... 0x%02x (MIDI_OUT_JACK)\n",
774 descriptor->descriptor_subtype);
775 printf(" Jack ID ........... 0x%02x\n",
776 descriptor->id);
778 switch (descriptor->type) {
779 case USB_MIDI_EMBEDDED_JACK:
780 printf(" Jack Type ......... Embedded\n");
781 break;
782 case USB_MIDI_EXTERNAL_JACK:
783 printf(" Jack Type ......... External\n");
784 break;
785 default:
786 printf(" Jack Type ......... 0x%02x (unknown)\n",
787 descriptor->type);
788 break;
791 for (int i = 0; i < descriptor->inputs_count; i++) {
792 printf(" Pin %02d ............ (%d,%d)\n", i,
793 descriptor->input_source[i].source_id,
794 descriptor->input_source[i].source_pin);
799 void
800 DumpMidiStreamCSInterfaceDescriptor(const usb_generic_descriptor* descriptor)
802 uint8 subtype = descriptor->data[0];
803 switch (subtype) {
804 case USB_MS_HEADER_DESCRIPTOR:
805 DumpMidiInterfaceHeaderDescriptor(
806 (usb_midi_interface_header_descriptor*)descriptor);
807 break;
808 case USB_MS_MIDI_IN_JACK_DESCRIPTOR:
809 DumpMidiInJackDescriptor(
810 (usb_midi_in_jack_descriptor*)descriptor);
811 break;
812 case USB_MS_MIDI_OUT_JACK_DESCRIPTOR:
813 DumpMidiOutJackDescriptor(
814 (usb_midi_out_jack_descriptor*)descriptor);
815 break;
816 case USB_MS_ELEMENT_DESCRIPTOR:
817 // TODO
818 DumpDescriptorData(descriptor);
819 break;
820 default:
821 DumpDescriptorData(descriptor);
822 break;
827 void
828 DumpMidiStreamCSEndpointDescriptor(
829 const usb_midi_endpoint_descriptor* descriptor)
831 printf(" Type .............. 0x%02x (CS_ENDPOINT)\n",
832 descriptor->descriptor_type);
833 printf(" Subtype ........... 0x%02x (MS_GENERAL)\n",
834 descriptor->descriptor_subtype);
835 printf(" Jacks ............. ");
837 for (int i = 0; i < descriptor->jacks_count; i++)
838 printf("%d, ", descriptor->jacks_id[i]);
840 printf("\n");
844 void
845 DumpAudioStreamInterfaceDescriptor(const usb_interface_descriptor* descriptor)
847 printf(" Type .............. %u (INTERFACE)\n",
848 descriptor->descriptor_type);
849 printf(" Interface ........... %u\n",
850 descriptor->interface_number);
851 printf(" Alternate setting ... %u\n",
852 descriptor->alternate_setting);
853 printf(" Endpoints ........... %u\n",
854 descriptor->num_endpoints);
855 printf(" Interface class ..... %u (AUDIO)\n",
856 descriptor->interface_class);
857 printf(" Interface subclass .. %u (AUDIO_STREAMING)\n",
858 descriptor->interface_subclass);
859 printf(" Interface ........... %u\n",
860 descriptor->interface);
864 void
865 DumpAudioDescriptor(const usb_generic_descriptor* descriptor, int subclass)
867 const uint8 USB_AUDIO_INTERFACE = 0x04;
869 switch (subclass) {
870 case USB_AUDIO_INTERFACE_AUDIOCONTROL_SUBCLASS:
871 switch (descriptor->descriptor_type) {
872 case USB_AUDIO_CS_INTERFACE:
873 DumpAudioControlCSInterfaceDescriptor(descriptor);
874 break;
875 default:
876 DumpDescriptorData(descriptor);
877 break;
879 break;
880 case USB_AUDIO_INTERFACE_AUDIOSTREAMING_SUBCLASS:
881 switch (descriptor->descriptor_type) {
882 case USB_AUDIO_INTERFACE:
883 DumpAudioStreamInterfaceDescriptor(
884 (const usb_interface_descriptor*)descriptor);
885 break;
886 case USB_AUDIO_CS_INTERFACE:
887 DumpAudioStreamCSInterfaceDescriptor(descriptor);
888 break;
889 case USB_AUDIO_CS_ENDPOINT:
890 DumpAudioStreamCSEndpointDescriptor(
891 (const usb_audio_streaming_endpoint_descriptor*)descriptor);
892 break;
893 default:
894 DumpDescriptorData(descriptor);
895 break;
897 break;
898 case USB_AUDIO_INTERFACE_MIDISTREAMING_SUBCLASS:
899 switch (descriptor->descriptor_type) {
900 case USB_AUDIO_CS_INTERFACE:
901 DumpMidiStreamCSInterfaceDescriptor(descriptor);
902 break;
903 case USB_AUDIO_CS_ENDPOINT:
904 DumpMidiStreamCSEndpointDescriptor(
905 (const usb_midi_endpoint_descriptor*)descriptor);
906 break;
907 default:
908 DumpDescriptorData(descriptor);
909 break;
911 break;
912 default:
913 DumpDescriptorData(descriptor);
914 break;