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
18void
19DumpAudioCSInterfaceDescriptorHeader(
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
38void
39DumpChannelConfig(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
86static const char*
87TerminalTypeName(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
139void
140DumpAudioCSInterfaceDescriptorInputTerminal(
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
167void
168DumpAudioCSInterfaceDescriptorOutputTerminal(
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
189void
190DumpAudioCSInterfaceDescriptorMixerUnit(
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
229void
230DumpAudioCSInterfaceDescriptorSelectorUnit(
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
251void
252DumpBMAControl(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
284void
285DumpAudioCSInterfaceDescriptorFeatureUnit(
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
329void
330DumpAudioCSInterfaceDescriptorAssociated(
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
347void
348DumpAudioControlCSInterfaceDescriptor(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
385void
386DumpGeneralASInterfaceDescriptor(
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
400uint32
401GetSamplingFrequency(const usb_audio_sampling_freq& freq)
402{
403	return freq.bytes[0] | freq.bytes[1] << 8 | freq.bytes[2] << 16;
404}
405
406
407void
408DumpSamplingFrequencies(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
423void
424DumpASFormatTypeI(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
442void
443DumpASFormatTypeIII(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
461void
462DumpASFormatTypeII(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
478void
479DumpASFmtType(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
499void
500DumpMPEGCapabilities(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
540void
541DumpMPEGFeatures(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
565void
566DumpASFmtSpecificMPEG(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
581void
582DumpAC_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
620void
621DumpASFmtSpecificAC_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
635void
636DumpASFmtSpecific(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
659void
660DumpAudioStreamCSInterfaceDescriptor(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
682void
683DumpAudioStreamCSEndpointDescriptor(
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
725void
726DumpMidiInterfaceHeaderDescriptor(
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
740void
741DumpMidiInJackDescriptor(
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
769void
770DumpMidiOutJackDescriptor(
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
801void
802DumpMidiStreamCSInterfaceDescriptor(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
829void
830DumpMidiStreamCSEndpointDescriptor(
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
846void
847DumpAudioStreamInterfaceDescriptor(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
866void
867DumpAudioDescriptor(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