xref: /haiku/src/bin/listusb/usb_audio.cpp (revision 13581b3d2a71545960b98fefebc5225b5bf29072)
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-2016, Haiku Inc. All rights reserved.
7  */
8 
9 #include <MediaDefs.h>
10 #include <USBKit.h>
11 #include <stdio.h>
12 
13 #include <usb/USB_audio.h>
14 #include <usb/USB_midi.h>
15 
16 #include "listusb.h"
17 
18 void
19 DumpAudioCSInterfaceDescriptorHeader(
20 	const usb_audiocontrol_header_descriptor* descriptor)
21 {
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 ........ ");
31 
32 	for (uint8 i = 0; i < descriptor->r1.in_collection; i++)
33 		printf("%u, ", descriptor->r1.interface_numbers[i]);
34 	printf("\n");
35 }
36 
37 
38 void
39 DumpChannelConfig(uint32 wChannelConfig)
40 {
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 }
58 	};
59 
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 }
71 	};
72 
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");
81 		}
82 	}
83 }
84 
85 
86 static const char*
87 TerminalTypeName(uint16 terminalType)
88 {
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";
96 
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";
115 
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";
132 
133 		default:
134 			return "Unknown";
135 	}
136 }
137 
138 
139 void
140 DumpAudioCSInterfaceDescriptorInputTerminal(
141 	const usb_audio_input_terminal_descriptor* descriptor)
142 {
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);
159 
160 	printf("                    Channel Names ..... %u\n",
161 		descriptor->r1.channel_names);
162 	printf("                    Terminal .......... %u\n",
163 		descriptor->r1.terminal);
164 }
165 
166 
167 void
168 DumpAudioCSInterfaceDescriptorOutputTerminal(
169 	const usb_audio_output_terminal_descriptor* descriptor)
170 {
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);
186 }
187 
188 
189 void
190 DumpAudioCSInterfaceDescriptorMixerUnit(
191 	const usb_audio_mixer_unit_descriptor* descriptor)
192 {
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);
199 
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");
204 
205 	usb_audio_output_channels_descriptor_r1* channels
206 		= (usb_audio_output_channels_descriptor_r1*)
207 			&descriptor->input_pins[descriptor->num_input_pins];
208 
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);
216 
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");
223 
224 	printf("                    Mixer ............. %u\n",
225 			generic->data[generic->length - 3]);
226 }
227 
228 
229 void
230 DumpAudioCSInterfaceDescriptorSelectorUnit(
231 	const usb_audio_selector_unit_descriptor* descriptor)
232 {
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);
239 
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");
244 
245 	usb_generic_descriptor* generic = (usb_generic_descriptor*)descriptor;
246 	printf("                    Selector .......... %u\n",
247 		(uint8)generic->data[descriptor->num_input_pins + 2]);
248 }
249 
250 
251 void
252 DumpBMAControl(uint8 channel, uint32 bma)
253 {
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"
265 	};
266 
267 	if (bma == 0)
268 		return;
269 
270 	if (channel == 0)
271 		printf("                       Master Channel . ");
272 	else
273 		printf("                       Channel %u ...... ", channel);
274 
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");
281 }
282 
283 
284 void
285 DumpAudioCSInterfaceDescriptorFeatureUnit(
286 	const usb_audio_feature_unit_descriptor* descriptor)
287 {
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);
296 
297 	printf("                    Control Size ...... %u\n",
298 			descriptor->r1.control_size);
299 
300 	uint8 channels = 0;
301 	if (descriptor->r1.control_size > 0)
302 		channels = (descriptor->length - 6) / descriptor->r1.control_size;
303 	for (uint8 i = 0; i < channels; i++) {
304 		switch (descriptor->r1.control_size) {
305 			case 1:
306 				DumpBMAControl(i, descriptor->r1.bma_controls[i]);
307 				break;
308 			case 2:
309 				DumpBMAControl(i, *(uint16*)&descriptor->r1.bma_controls[i * 2]);
310 				break;
311 			case 4:
312 				DumpBMAControl(i, *(uint32*)&descriptor->r1.bma_controls[i * 4]);
313 				break;
314 			default:
315 				printf("                    BMA Channel %u ... ", i);
316 				for (uint8 j = 0; j < descriptor->r1.control_size; j++)
317 					printf("%02x ", descriptor->r1.bma_controls[i + j]);
318 				printf("\n");
319 				break;
320 		}
321 	}
322 
323 	usb_generic_descriptor* generic = (usb_generic_descriptor*)descriptor;
324 	printf("                    Feature ........... %u\n",
325 			(uint8)generic->data[descriptor->length - 3]);
326 }
327 
328 
329 void
330 DumpAudioCSInterfaceDescriptorAssociated(
331 	const usb_generic_descriptor* descriptor)
332 {
333 	printf("                    Type .............. 0x%02x\n",
334 		descriptor->descriptor_type);
335 	printf("                    Subtype ........... 0x%02x (Associate Interface)\n",
336 		(uint8)descriptor->data[0]);
337 	printf("                    Interface ......... %u\n",
338 		(uint8)descriptor->data[1]);
339 
340 	printf("                    Data .............. ");
341 	for (uint8 i = 0; i < descriptor->length - 2; i++)
342 		printf("%02x ", descriptor->data[i]);
343 	printf("\n");
344 }
345 
346 
347 void
348 DumpAudioControlCSInterfaceDescriptor(const usb_generic_descriptor* descriptor)
349 {
350 	uint8 descriptorSubtype = descriptor->data[0];
351 	switch (descriptorSubtype) {
352 		case USB_AUDIO_AC_HEADER:
353 			DumpAudioCSInterfaceDescriptorHeader(
354 				(usb_audiocontrol_header_descriptor*)descriptor);
355 			break;
356 		case USB_AUDIO_AC_INPUT_TERMINAL:
357 			DumpAudioCSInterfaceDescriptorInputTerminal(
358 				(usb_audio_input_terminal_descriptor*)descriptor);
359 			break;
360 		case USB_AUDIO_AC_OUTPUT_TERMINAL:
361 			DumpAudioCSInterfaceDescriptorOutputTerminal(
362 				(usb_audio_output_terminal_descriptor*)descriptor);
363 			break;
364 		case USB_AUDIO_AC_MIXER_UNIT:
365 			DumpAudioCSInterfaceDescriptorMixerUnit(
366 				(usb_audio_mixer_unit_descriptor*)descriptor);
367 			break;
368 		case USB_AUDIO_AC_SELECTOR_UNIT:
369 			DumpAudioCSInterfaceDescriptorSelectorUnit(
370 				(usb_audio_selector_unit_descriptor*)descriptor);
371 			break;
372 		case USB_AUDIO_AC_FEATURE_UNIT:
373 			DumpAudioCSInterfaceDescriptorFeatureUnit(
374 				(usb_audio_feature_unit_descriptor*)descriptor);
375 			break;
376 		case USB_AUDIO_AC_EXTENSION_UNIT:
377 			DumpAudioCSInterfaceDescriptorAssociated(descriptor);
378 			break;
379 		default:
380 			DumpDescriptorData(descriptor);
381 	}
382 }
383 
384 
385 void
386 DumpGeneralASInterfaceDescriptor(
387 	const usb_audio_streaming_interface_descriptor* descriptor)
388 {
389 	printf("                    Subtype ........... %u (AS_GENERAL)\n",
390 		descriptor->descriptor_subtype);
391 	printf("                    Terminal link ..... %u\n",
392 		descriptor->terminal_link);
393 	printf("                    Delay ............. %u\n",
394 		descriptor->r1.delay);
395 	printf("                    Format tag ........ %u\n",
396 		descriptor->r1.format_tag);
397 }
398 
399 
400 uint32
401 GetSamplingFrequency(const usb_audio_sampling_freq& freq)
402 {
403 	return freq.bytes[0] | freq.bytes[1] << 8 | freq.bytes[2] << 16;
404 }
405 
406 
407 void
408 DumpSamplingFrequencies(uint8 type, const usb_audio_sampling_freq* freqs)
409 {
410 	if (type > 0) {
411 		printf("                    Sampling Freq ..... ");
412 		for (uint8 i = 0; i < type; i++)
413 			printf("%" B_PRIu32 ", ", GetSamplingFrequency(freqs[i]));
414 		printf("\n");
415 	} else {
416 		printf("                    Sampling Freq ..... %" B_PRIu32 " to %"
417 			B_PRIu32 "\n", GetSamplingFrequency(freqs[0]),
418 			GetSamplingFrequency(freqs[1]));
419 	}
420 }
421 
422 
423 void
424 DumpASFormatTypeI(const usb_audio_format_descriptor* descriptor)
425 {
426 	printf("                    Subtype ........... %u (FORMAT_TYPE)\n",
427 		descriptor->descriptor_subtype);
428 	printf("                    Format Type ....... %u (FORMAT_TYPE_I)\n",
429 		descriptor->format_type);
430 	printf("                    Channels .......... %u\n",
431 		descriptor->typeI.nr_channels);
432 	printf("                    Subframe size ..... %u\n",
433 		descriptor->typeI.subframe_size);
434 	printf("                    Bit resolution .... %u\n",
435 		descriptor->typeI.bit_resolution);
436 
437 	DumpSamplingFrequencies(descriptor->typeI.sam_freq_type,
438 			descriptor->typeI.sam_freqs);
439 }
440 
441 
442 void
443 DumpASFormatTypeIII(const usb_audio_format_descriptor* descriptor)
444 {
445 	printf("                    Subtype ........... %u (FORMAT_TYPE)\n",
446 		descriptor->descriptor_subtype);
447 	printf("                    Format Type ....... %u (FORMAT_TYPE_III)\n",
448 		descriptor->format_type);
449 	printf("                    Channels .......... %u\n",
450 		descriptor->typeIII.nr_channels);
451 	printf("                    Subframe size ..... %u\n",
452 		descriptor->typeIII.subframe_size);
453 	printf("                    Bit resolution .... %u\n",
454 		descriptor->typeIII.bit_resolution);
455 
456 	DumpSamplingFrequencies(descriptor->typeIII.sam_freq_type,
457 			descriptor->typeIII.sam_freqs);
458 }
459 
460 
461 void
462 DumpASFormatTypeII(const usb_audio_format_descriptor* descriptor)
463 {
464 	printf("                    Subtype ........... %u (FORMAT_TYPE)\n",
465 		descriptor->descriptor_subtype);
466 	printf("                    Format Type ....... %u (FORMAT_TYPE_II)\n",
467 		descriptor->format_type);
468 	printf("                    Max Bitrate ....... %u\n",
469 		descriptor->typeII.max_bit_rate);
470 	printf("                    Samples per Frame . %u\n",
471 		descriptor->typeII.samples_per_frame);
472 
473 	DumpSamplingFrequencies(descriptor->typeII.sam_freq_type,
474 			descriptor->typeII.sam_freqs);
475 }
476 
477 
478 void
479 DumpASFmtType(const usb_audio_format_descriptor* descriptor)
480 {
481 	uint8 format = descriptor->format_type;
482 	switch (format) {
483 		case USB_AUDIO_FORMAT_TYPE_I:
484 			DumpASFormatTypeI(descriptor);
485 			break;
486 		case USB_AUDIO_FORMAT_TYPE_II:
487 			DumpASFormatTypeII(descriptor);
488 			break;
489 		case USB_AUDIO_FORMAT_TYPE_III:
490 			DumpASFormatTypeIII(descriptor);
491 			break;
492 		default:
493 			DumpDescriptorData((usb_generic_descriptor*)descriptor);
494 			break;
495 	}
496 }
497 
498 
499 void
500 DumpMPEGCapabilities(uint16 capabilities)
501 {
502 	const char* MPEGCapabilities[] = {
503 		"Layer I",
504 		"Layer II",
505 		"Layer III",
506 
507 		"MPEG-1 only",
508 		"MPEG-1 dual-channel",
509 		"MPEG-2 second stereo",
510 		"MPEG-2 7.1 channel augumentation",
511 		"Adaptive multi-channel predicion"
512 	};
513 
514 	uint16 mask = 1;
515 	for (uint8 i = 0;
516 			i < sizeof(MPEGCapabilities) / sizeof(MPEGCapabilities[0]); i++) {
517 		if (capabilities & mask)
518 			printf("                         %s\n", MPEGCapabilities[i]);
519 		mask <<= 1;
520 	}
521 
522 	mask = 0x300; // bits 8 and 9
523 	uint16 multilingualSupport = (capabilities & mask) >> 8;
524 	switch (multilingualSupport) {
525 		case 0:
526 			printf("                         No Multilingual support\n");
527 			break;
528 		case 1:
529 			printf("                         Supported at Fs\n");
530 			break;
531 		case 3:
532 			printf("                         Supported at Fs and 1/2Fs\n");
533 			break;
534 		default:
535 			break;
536 	}
537 }
538 
539 
540 void
541 DumpMPEGFeatures(uint8 features)
542 {
543 	uint8 mask = 0x30; // bits 4 and 5
544 	uint8 dynRangeControl = (features & mask) >> 4;
545 	switch (dynRangeControl) {
546 		case 0:
547 			printf("                         Not supported\n");
548 			break;
549 		case 1:
550 			printf("                         Supported, not scalable\n");
551 			break;
552 		case 2:
553 			printf("                         Scalable, common boost, "
554 				"cut scaling value\n");
555 			break;
556 		case 3:
557 			printf("                         Scalable, separate boost, "
558 				"cut scaling value\n");
559 		default:
560 			break;
561 	}
562 }
563 
564 
565 void
566 DumpASFmtSpecificMPEG(const usb_generic_descriptor* descriptor)
567 {
568 	printf("                    Subtype ........... %u (FORMAT_SPECIFIC)\n",
569 		descriptor->data[0]);
570 	printf("                    Format Tag ........ %u\n",
571 		*(uint16*)&descriptor->data[1]);
572 	printf("                    MPEG Capabilities . %u\n",
573 		*(uint16*)&descriptor->data[3]);
574 	DumpMPEGCapabilities(*(uint16*)&descriptor->data[3]);
575 	printf("                    MPEG Features ..... %u\n",
576 		descriptor->data[5]);
577 	DumpMPEGFeatures(descriptor->data[5]);
578 }
579 
580 
581 void
582 DumpAC_3Features(uint8 features)
583 {
584 	const char* featuresStr[] = {
585 		"RF mode",
586 		"Line mode",
587 		"Custom0 mode",
588 		"Custom1 mode"
589 	};
590 
591 	uint8 mask = 1;
592 	for (uint8 i = 0; i < sizeof(featuresStr) / sizeof(const char*); i++) {
593 		if (features & mask)
594 			printf("                         %s\n", featuresStr[i]);
595 		mask <<= 1;
596 	}
597 
598 	mask = 0x30; // bits 4 and 5
599 	uint8 dynRangeControl = (features & mask) >> 4;
600 	switch (dynRangeControl) {
601 		case 0:
602 			printf("                         Not supported\n");
603 			break;
604 		case 1:
605 			printf("                         Supported, not scalable\n");
606 			break;
607 		case 2:
608 			printf("                         Scalable, common boost, "
609 				"cut scaling value\n");
610 			break;
611 		case 3:
612 			printf("                         Scalable, separate boost, "
613 				"cut scaling value\n");
614 		default:
615 			break;
616 	}
617 }
618 
619 
620 void
621 DumpASFmtSpecificAC_3(const usb_generic_descriptor* descriptor)
622 {
623 	printf("                    Subtype ........... %u (FORMAT_TYPE)\n",
624 		descriptor->data[0]);
625 	printf("                    Format Tag ........ %u\n",
626 		*(uint16*)&descriptor->data[1]);
627 	printf("                    BSID .............. %" B_PRIx32 "\n",
628 		*(uint32*)&descriptor->data[2]);
629 	printf("                    AC3 Features ...... %u\n",
630 		descriptor->data[6]);
631 	DumpAC_3Features(descriptor->data[6]);
632 }
633 
634 
635 void
636 DumpASFmtSpecific(const usb_generic_descriptor* descriptor)
637 {
638 	enum {
639 		TYPE_II_UNDEFINED = 0x1000,
640 		MPEG =				0x1001,
641 		AC_3 =				0x1002
642 	};
643 
644 	uint16 formatTag = *(uint16*)&descriptor->data[1];
645 	switch (formatTag) {
646 		case MPEG:
647 			DumpASFmtSpecificMPEG(descriptor);
648 			break;
649 		case AC_3:
650 			DumpASFmtSpecificAC_3(descriptor);
651 			break;
652 		default:
653 			DumpDescriptorData(descriptor);
654 			break;
655 	}
656 }
657 
658 
659 void
660 DumpAudioStreamCSInterfaceDescriptor(const usb_generic_descriptor* descriptor)
661 {
662 	uint8 subtype = descriptor->data[0];
663 	switch (subtype) {
664 		case USB_AUDIO_AS_GENERAL:
665 			DumpGeneralASInterfaceDescriptor(
666 				(usb_audio_streaming_interface_descriptor*)descriptor);
667 			break;
668 		case USB_AUDIO_AS_FORMAT_TYPE:
669 			DumpASFmtType(
670 				(usb_audio_format_descriptor*)descriptor);
671 			break;
672 		case USB_AUDIO_AS_FORMAT_SPECIFIC:
673 			DumpASFmtSpecific(descriptor);
674 			break;
675 		default:
676 			DumpDescriptorData(descriptor);
677 			break;
678 	}
679 }
680 
681 
682 void
683 DumpAudioStreamCSEndpointDescriptor(
684 	const usb_audio_streaming_endpoint_descriptor* descriptor)
685 {
686 	printf("                    Type .............. 0x%02x (CS_ENDPOINT)\n",
687 		descriptor->descriptor_type);
688 	printf("                    Subtype ........... 0x%02x (EP_GENERAL)\n",
689 		descriptor->descriptor_subtype);
690 	printf("                    Attributes ........ 0x%02x ",
691 		descriptor->attributes);
692 
693 	const char* attributes[] = {
694 		"Sampling Frequency",
695 		"Pitch",
696 		"", "", "", "", "",
697 		"Max Packet Only"
698 	};
699 
700 	uint8 mask = 1;
701 	for (uint8 i = 0; i < sizeof(attributes) / sizeof(attributes[0]); i++) {
702 		if ((descriptor->attributes & mask) != 0)
703 			printf("%s ", attributes[i]);
704 		mask <<= 1;
705 	}
706 	printf("\n");
707 
708 	const char* aUnits[] = {
709 		"Undefined",
710 		"Milliseconds",
711 		"Decoded PCM samples",
712 		"Unknown (%u)"
713 	};
714 
715 	const char* units = descriptor->lock_delay_units >= 4
716 		? aUnits[3] : aUnits[descriptor->lock_delay_units];
717 
718 	printf("                    Lock Delay Units .. %u (%s)\n",
719 		descriptor->lock_delay_units, units);
720 	printf("                    Lock Delay ........ %u\n",
721 		descriptor->lock_delay);
722 }
723 
724 
725 void
726 DumpMidiInterfaceHeaderDescriptor(
727 	const usb_midi_interface_header_descriptor* descriptor)
728 {
729 	printf("                    Type .............. 0x%02x (CS_ENDPOINT)\n",
730 		descriptor->descriptor_type);
731 	printf("                    Subtype ........... 0x%02x (MS_HEADER)\n",
732 		descriptor->descriptor_subtype);
733 	printf("                    MSC Version ....... 0x%04x\n",
734 		descriptor->ms_version);
735 	printf("                    Length ............ 0x%04x\n",
736 		descriptor->total_length);
737 }
738 
739 
740 void
741 DumpMidiInJackDescriptor(
742 	const usb_midi_in_jack_descriptor* descriptor)
743 {
744 	printf("                    Type .............. 0x%02x (CS_INTERFACE)\n",
745 		descriptor->descriptor_type);
746 	printf("                    Subtype ........... 0x%02x (MIDI_IN_JACK)\n",
747 		descriptor->descriptor_subtype);
748 	printf("                    Jack ID ........... 0x%02x\n",
749 		descriptor->id);
750 	// TODO can we get the string?
751 	printf("                    String ............ 0x%02x\n",
752 		descriptor->string_descriptor);
753 
754 	switch (descriptor->type) {
755 		case USB_MIDI_EMBEDDED_JACK:
756 			printf("                    Jack Type ......... Embedded\n");
757 			break;
758 		case USB_MIDI_EXTERNAL_JACK:
759 			printf("                    Jack Type ......... External\n");
760 			break;
761 		default:
762 			printf("                    Jack Type ......... 0x%02x (unknown)\n",
763 				descriptor->type);
764 			break;
765 	}
766 }
767 
768 
769 void
770 DumpMidiOutJackDescriptor(
771 	const usb_midi_out_jack_descriptor* descriptor)
772 {
773 	printf("                    Type .............. 0x%02x (CS_INTERFACE)\n",
774 		descriptor->descriptor_type);
775 	printf("                    Subtype ........... 0x%02x (MIDI_OUT_JACK)\n",
776 		descriptor->descriptor_subtype);
777 	printf("                    Jack ID ........... 0x%02x\n",
778 		descriptor->id);
779 
780 	switch (descriptor->type) {
781 		case USB_MIDI_EMBEDDED_JACK:
782 			printf("                    Jack Type ......... Embedded\n");
783 			break;
784 		case USB_MIDI_EXTERNAL_JACK:
785 			printf("                    Jack Type ......... External\n");
786 			break;
787 		default:
788 			printf("                    Jack Type ......... 0x%02x (unknown)\n",
789 				descriptor->type);
790 			break;
791 	}
792 
793 	for (int i = 0; i < descriptor->inputs_count; i++) {
794 		printf("                    Pin %02d ............ (%d,%d)\n", i,
795 			descriptor->input_source[i].source_id,
796 			descriptor->input_source[i].source_pin);
797 	}
798 }
799 
800 
801 void
802 DumpMidiStreamCSInterfaceDescriptor(const usb_generic_descriptor* descriptor)
803 {
804 	uint8 subtype = descriptor->data[0];
805 	switch (subtype) {
806 		case USB_MS_HEADER_DESCRIPTOR:
807 			DumpMidiInterfaceHeaderDescriptor(
808 				(usb_midi_interface_header_descriptor*)descriptor);
809 			break;
810 		case USB_MS_MIDI_IN_JACK_DESCRIPTOR:
811 			DumpMidiInJackDescriptor(
812 				(usb_midi_in_jack_descriptor*)descriptor);
813 			break;
814 		case USB_MS_MIDI_OUT_JACK_DESCRIPTOR:
815 			DumpMidiOutJackDescriptor(
816 				(usb_midi_out_jack_descriptor*)descriptor);
817 			break;
818 		case USB_MS_ELEMENT_DESCRIPTOR:
819 			// TODO
820 			DumpDescriptorData(descriptor);
821 			break;
822 		default:
823 			DumpDescriptorData(descriptor);
824 			break;
825 	}
826 }
827 
828 
829 void
830 DumpMidiStreamCSEndpointDescriptor(
831 	const usb_midi_endpoint_descriptor* descriptor)
832 {
833 	printf("                    Type .............. 0x%02x (CS_ENDPOINT)\n",
834 		descriptor->descriptor_type);
835 	printf("                    Subtype ........... 0x%02x (MS_GENERAL)\n",
836 		descriptor->descriptor_subtype);
837 	printf("                    Jacks ............. ");
838 
839 	for (int i = 0; i < descriptor->jacks_count; i++)
840 		printf("%d, ", descriptor->jacks_id[i]);
841 
842 	printf("\n");
843 }
844 
845 
846 void
847 DumpAudioStreamInterfaceDescriptor(const usb_interface_descriptor* descriptor)
848 {
849 	printf("                    Type .............. %u (INTERFACE)\n",
850 		descriptor->descriptor_type);
851 	printf("                    Interface ........... %u\n",
852 		descriptor->interface_number);
853 	printf("                    Alternate setting ... %u\n",
854 		descriptor->alternate_setting);
855 	printf("                    Endpoints ........... %u\n",
856 		descriptor->num_endpoints);
857 	printf("                    Interface class ..... %u (AUDIO)\n",
858 		descriptor->interface_class);
859 	printf("                    Interface subclass .. %u (AUDIO_STREAMING)\n",
860 		descriptor->interface_subclass);
861 	printf("                    Interface ........... %u\n",
862 		descriptor->interface);
863 }
864 
865 
866 void
867 DumpAudioDescriptor(const usb_generic_descriptor* descriptor, int subclass)
868 {
869 	const uint8 USB_AUDIO_INTERFACE = 0x04;
870 
871 	switch (subclass) {
872 		case USB_AUDIO_INTERFACE_AUDIOCONTROL_SUBCLASS:
873 			switch (descriptor->descriptor_type) {
874 				case USB_AUDIO_CS_INTERFACE:
875 					DumpAudioControlCSInterfaceDescriptor(descriptor);
876 					break;
877 				default:
878 					DumpDescriptorData(descriptor);
879 					break;
880 			}
881 			break;
882 		case USB_AUDIO_INTERFACE_AUDIOSTREAMING_SUBCLASS:
883 			switch (descriptor->descriptor_type) {
884 				case USB_AUDIO_INTERFACE:
885 					DumpAudioStreamInterfaceDescriptor(
886 						(const usb_interface_descriptor*)descriptor);
887 					break;
888 				case USB_AUDIO_CS_INTERFACE:
889 					DumpAudioStreamCSInterfaceDescriptor(descriptor);
890 					break;
891 				case USB_AUDIO_CS_ENDPOINT:
892 					DumpAudioStreamCSEndpointDescriptor(
893 						(const usb_audio_streaming_endpoint_descriptor*)descriptor);
894 					break;
895 				default:
896 					DumpDescriptorData(descriptor);
897 					break;
898 			}
899 			break;
900 		case USB_AUDIO_INTERFACE_MIDISTREAMING_SUBCLASS:
901 			switch (descriptor->descriptor_type) {
902 				case USB_AUDIO_CS_INTERFACE:
903 					DumpMidiStreamCSInterfaceDescriptor(descriptor);
904 					break;
905 				case USB_AUDIO_CS_ENDPOINT:
906 					DumpMidiStreamCSEndpointDescriptor(
907 						(const usb_midi_endpoint_descriptor*)descriptor);
908 					break;
909 				default:
910 					DumpDescriptorData(descriptor);
911 					break;
912 			}
913 			break;
914 		default:
915 			DumpDescriptorData(descriptor);
916 			break;
917 	}
918 }
919