xref: /haiku/src/bin/listusb/usb_audio.cpp (revision 5e7964b0a929555415798dea3373db9ac4611caa)
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 
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;
318 		}
319 	}
320 
321 	usb_generic_descriptor* generic = (usb_generic_descriptor*)descriptor;
322 	printf("                    Feature ........... %u\n",
323 			(uint8)generic->data[descriptor->length - 3]);
324 }
325 
326 
327 void
328 DumpAudioCSInterfaceDescriptorAssociated(
329 	const usb_generic_descriptor* descriptor)
330 {
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]);
337 
338 	printf("                    Data .............. ");
339 	for (uint8 i = 0; i < descriptor->length - 2; i++)
340 		printf("%02x ", descriptor->data[i]);
341 	printf("\n");
342 }
343 
344 
345 void
346 DumpAudioControlCSInterfaceDescriptor(const usb_generic_descriptor* descriptor)
347 {
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);
379 	}
380 }
381 
382 
383 void
384 DumpGeneralASInterfaceDescriptor(
385 	const usb_audio_streaming_interface_descriptor* descriptor)
386 {
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);
395 }
396 
397 
398 uint32
399 GetSamplingFrequency(const usb_audio_sampling_freq& freq)
400 {
401 	return freq.bytes[0] | freq.bytes[1] << 8 | freq.bytes[2] << 16;
402 }
403 
404 
405 void
406 DumpSamplingFrequencies(uint8 type, const usb_audio_sampling_freq* freqs)
407 {
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]));
417 	}
418 }
419 
420 
421 void
422 DumpASFormatTypeI(const usb_audio_format_descriptor* descriptor)
423 {
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);
434 
435 	DumpSamplingFrequencies(descriptor->typeI.sam_freq_type,
436 			descriptor->typeI.sam_freqs);
437 }
438 
439 
440 void
441 DumpASFormatTypeIII(const usb_audio_format_descriptor* descriptor)
442 {
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);
453 
454 	DumpSamplingFrequencies(descriptor->typeIII.sam_freq_type,
455 			descriptor->typeIII.sam_freqs);
456 }
457 
458 
459 void
460 DumpASFormatTypeII(const usb_audio_format_descriptor* descriptor)
461 {
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);
470 
471 	DumpSamplingFrequencies(descriptor->typeII.sam_freq_type,
472 			descriptor->typeII.sam_freqs);
473 }
474 
475 
476 void
477 DumpASFmtType(const usb_audio_format_descriptor* descriptor)
478 {
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;
493 	}
494 }
495 
496 
497 void
498 DumpMPEGCapabilities(uint16 capabilities)
499 {
500 	const char* MPEGCapabilities[] = {
501 		"Layer I",
502 		"Layer II",
503 		"Layer III",
504 
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"
510 	};
511 
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;
518 	}
519 
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;
534 	}
535 }
536 
537 
538 void
539 DumpMPEGFeatures(uint8 features)
540 {
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;
559 	}
560 }
561 
562 
563 void
564 DumpASFmtSpecificMPEG(const usb_generic_descriptor* descriptor)
565 {
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]);
576 }
577 
578 
579 void
580 DumpAC_3Features(uint8 features)
581 {
582 	const char* featuresStr[] = {
583 		"RF mode",
584 		"Line mode",
585 		"Custom0 mode",
586 		"Custom1 mode"
587 	};
588 
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;
594 	}
595 
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;
614 	}
615 }
616 
617 
618 void
619 DumpASFmtSpecificAC_3(const usb_generic_descriptor* descriptor)
620 {
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]);
630 }
631 
632 
633 void
634 DumpASFmtSpecific(const usb_generic_descriptor* descriptor)
635 {
636 	enum {
637 		TYPE_II_UNDEFINED = 0x1000,
638 		MPEG =				0x1001,
639 		AC_3 =				0x1002
640 	};
641 
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;
653 	}
654 }
655 
656 
657 void
658 DumpAudioStreamCSInterfaceDescriptor(const usb_generic_descriptor* descriptor)
659 {
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;
676 	}
677 }
678 
679 
680 void
681 DumpAudioStreamCSEndpointDescriptor(
682 	const usb_audio_streaming_endpoint_descriptor* descriptor)
683 {
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);
690 
691 	const char* attributes[] = {
692 		"Sampling Frequency",
693 		"Pitch",
694 		"", "", "", "", "",
695 		"Max Packet Only"
696 	};
697 
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;
703 	}
704 	printf("\n");
705 
706 	const char* aUnits[] = {
707 		"Undefined",
708 		"Milliseconds",
709 		"Decoded PCM samples",
710 		"Unknown (%u)"
711 	};
712 
713 	const char* units = descriptor->lock_delay_units >= 4
714 		? aUnits[3] : aUnits[descriptor->lock_delay_units];
715 
716 	printf("                    Lock Delay Units .. %u (%s)\n",
717 		descriptor->lock_delay_units, units);
718 	printf("                    Lock Delay ........ %u\n",
719 		descriptor->lock_delay);
720 }
721 
722 
723 void
724 DumpMidiInterfaceHeaderDescriptor(
725 	const usb_midi_interface_header_descriptor* descriptor)
726 {
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);
735 }
736 
737 
738 void
739 DumpMidiInJackDescriptor(
740 	const usb_midi_in_jack_descriptor* descriptor)
741 {
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);
751 
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;
763 	}
764 }
765 
766 
767 void
768 DumpMidiOutJackDescriptor(
769 	const usb_midi_out_jack_descriptor* descriptor)
770 {
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);
777 
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;
789 	}
790 
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);
795 	}
796 }
797 
798 
799 void
800 DumpMidiStreamCSInterfaceDescriptor(const usb_generic_descriptor* descriptor)
801 {
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;
823 	}
824 }
825 
826 
827 void
828 DumpMidiStreamCSEndpointDescriptor(
829 	const usb_midi_endpoint_descriptor* descriptor)
830 {
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 ............. ");
836 
837 	for (int i = 0; i < descriptor->jacks_count; i++)
838 		printf("%d, ", descriptor->jacks_id[i]);
839 
840 	printf("\n");
841 }
842 
843 
844 void
845 DumpAudioStreamInterfaceDescriptor(const usb_interface_descriptor* descriptor)
846 {
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);
861 }
862 
863 
864 void
865 DumpAudioDescriptor(const usb_generic_descriptor* descriptor, int subclass)
866 {
867 	const uint8 USB_AUDIO_INTERFACE = 0x04;
868 
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;
878 			}
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;
896 			}
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;
910 			}
911 			break;
912 		default:
913 			DumpDescriptorData(descriptor);
914 			break;
915 	}
916 }
917