xref: /haiku/src/bin/listusb/usb_audio.cpp (revision 8251b2c8f6c7bffe42318b2251bd1163d3c86326)
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, Michael Lotz and Greg Crain.
6  * Copyright 2007-2024, 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 
19 void
DumpClockSource(uint8 attributes)20 DumpClockSource(uint8 attributes)
21 {
22 	switch (attributes & 0x3){
23 	case 0:
24 		printf("  External clock.");
25 		break;
26 	case 1:
27 		printf("  Internal fixed clock.");
28 		break;
29 	case 2:
30 		printf("  Internal variable clock.");
31 		break;
32 	case 3:
33 		printf("  Internal programmable clock.");
34 		break;
35 	}
36 	if (attributes & 0x4){
37 		printf("  Clock synchronized to SOF.");
38 	}
39 	printf("\n");
40 }
41 
42 
43 void
DumpAudioCSInterfaceDescriptorClockSourceUnit(const usb_audio_clocksource_descriptor * descriptor)44 DumpAudioCSInterfaceDescriptorClockSourceUnit(
45 	const usb_audio_clocksource_descriptor* descriptor)
46 {
47 	printf("                    Length............. 0x%02x\n", descriptor->length);
48 	printf("                    Type .............. 0x%02x\n", descriptor->descriptor_type);
49 	printf("                    Subtype ........... 0x%02x (Clock Source)\n",
50 		descriptor->descriptor_subtype);
51 	printf("                    Clock ID .......... 0x%02x\n", descriptor->clock_id);
52 	printf("                    Attributes......... 0x%02x", descriptor->bm_attributes);
53 	DumpClockSource(descriptor->bm_attributes);
54 	printf("                    bm controls ....... 0x%02x", descriptor->bm_controls);
55 	if (descriptor->bm_controls & 0x3)
56 	 printf("  Clock Valid.");
57 	printf("\n");
58 	printf("                    Assoc Term ........ 0x%02x\n", descriptor->assoc_terminal);
59 	printf("                    Clock Src Idx ..... 0x%02x\n", descriptor->clock_source_idx);
60 }
61 
62 
63 void
DumpAudioCSInterfaceDescriptorClockSelectorUnit(const usb_audio_clockselector_descriptor * descriptor)64 DumpAudioCSInterfaceDescriptorClockSelectorUnit(
65 	const usb_audio_clockselector_descriptor* descriptor)
66 {
67 	printf("                    Length ............ 0x%02x\n", descriptor->length);
68 	printf("                    Type .............. 0x%02x\n", descriptor->descriptor_type);
69 	printf("                    Subtype ........... 0x%02x (Clock Selector)\n",
70 		descriptor->descriptor_subtype);
71 	printf("                    Clock ID .......... 0x%02x\n", descriptor->clock_id);
72 	printf("                    Num Of Input Pins .. 0x%02x\n", descriptor->nrinpins);
73 	printf("                    Clock Src Entity ... 0x%02x\n", descriptor->Csourceid[0]);
74 	printf("                    Controls ........... 0x%02x\n", descriptor->bm_controls);
75 	printf("                    Clock Selector...... 0x%02x\n", descriptor->clockselector);
76 }
77 
78 
79 void
DumpAudioCSInterfaceDescriptorClockMultiplier(const usb_audio_clockmultiplier_descriptor * descriptor)80 DumpAudioCSInterfaceDescriptorClockMultiplier(
81 	const usb_audio_clockmultiplier_descriptor* descriptor)
82 {
83 	printf("                    Length ............ 0x%02x\n", descriptor->length);
84 	printf("                    Type .............. 0x%02x\n", descriptor->descriptor_type);
85 	printf("                    Subtype ........... 0x%02x (Clock Multiplier)\n",
86 		descriptor->descriptor_subtype);
87 	printf("                    Clock ID .......... 0x%02x\n", descriptor->clockid);
88 	printf("                    Clock Src Entity ... 0x%02x\n", descriptor->clksourceid);
89 	printf("                    bm_controls ........ 0x%02x\n", descriptor->bm_controls);
90 	printf("                    Clock Multipler .... 0x%02x\n", descriptor->clockmultiplier);
91 }
92 
93 uint16
DumpAudioCSInterfaceDescriptorHeader(const usb_audiocontrol_header_descriptor * descriptor)94 DumpAudioCSInterfaceDescriptorHeader(
95 	const usb_audiocontrol_header_descriptor* descriptor)
96 {
97 	printf("                    Type .............. 0x%02x\n",
98 		descriptor->descriptor_type);
99 	printf("                    Subtype ........... 0x%02x (Header)\n",
100 		descriptor->descriptor_subtype);
101 	printf("                    Audio codec version .. %d.%d\n",
102 		descriptor->bcd_release_no >> 8, descriptor->bcd_release_no & 0xFF);
103 
104 	if (descriptor->bcd_release_no < USB_AUDIO_CLASS_VERSION_2) {
105 		printf("                    Total Length ...... %u\n",
106 			descriptor->r1.total_length);
107 		printf("                    Interfaces ........ ");
108 
109 		for (uint8 i = 0; i < descriptor->r1.in_collection; i++)
110 			printf("%u, ", descriptor->r1.interface_numbers[i]);
111 		printf("\n");
112 	} else {
113 		// Audio 2.0
114 		printf("                    Function Category...... %u\n", descriptor->r2.function_category);
115 		printf("                    Total Length ...........%d\n", descriptor->r2.total_length);
116 		printf("                    bm Controls ............0x%02x\n", descriptor->r2.bm_controls);
117 	}
118 
119 	return descriptor->bcd_release_no;
120 }
121 
122 
123 void
DumpChannelConfig(uint32 wChannelConfig)124 DumpChannelConfig(uint32 wChannelConfig)
125 {
126 	struct _Entry {
127 		const char* name;
128 		uint32 mask;
129 	} aClusters[] = {
130 		{ "Front .......... ", B_CHANNEL_LEFT | B_CHANNEL_RIGHT
131 			| B_CHANNEL_CENTER },
132 		{ "L.F.E .......... ", B_CHANNEL_SUB },
133 		{ "Back ........... ", B_CHANNEL_REARLEFT | B_CHANNEL_REARRIGHT
134 			| B_CHANNEL_BACK_CENTER },
135 		{ "Center ......... ", B_CHANNEL_FRONT_LEFT_CENTER
136 			| B_CHANNEL_FRONT_RIGHT_CENTER },
137 		{ "Side ........... ", B_CHANNEL_SIDE_LEFT | B_CHANNEL_SIDE_RIGHT },
138 		{ "Top ............ ", B_CHANNEL_TOP_CENTER },
139 		{ "Top Front ...... ", B_CHANNEL_TOP_FRONT_LEFT
140 			| B_CHANNEL_TOP_FRONT_CENTER | B_CHANNEL_TOP_FRONT_RIGHT },
141 		{ "Top Back ....... ", B_CHANNEL_TOP_BACK_LEFT
142 			| B_CHANNEL_TOP_BACK_CENTER | B_CHANNEL_TOP_BACK_RIGHT }
143 	};
144 
145 	struct _Entry aChannels[] = {
146 		{ "Left", B_CHANNEL_LEFT | B_CHANNEL_FRONT_LEFT_CENTER
147 			| B_CHANNEL_REARLEFT | B_CHANNEL_SIDE_LEFT | B_CHANNEL_TOP_BACK_LEFT
148 			| B_CHANNEL_TOP_FRONT_LEFT },
149 		{ "Right", B_CHANNEL_FRONT_RIGHT_CENTER | B_CHANNEL_TOP_FRONT_RIGHT
150 			| B_CHANNEL_REARRIGHT | B_CHANNEL_RIGHT | B_CHANNEL_SIDE_RIGHT
151 			| B_CHANNEL_TOP_BACK_RIGHT },
152 		{ "Center", B_CHANNEL_BACK_CENTER | B_CHANNEL_CENTER
153 			| B_CHANNEL_TOP_BACK_CENTER | B_CHANNEL_TOP_CENTER
154 			| B_CHANNEL_TOP_FRONT_CENTER },
155 		{ "L.F.E.", B_CHANNEL_SUB }
156 	};
157 
158 	for (size_t i = 0; i < sizeof(aClusters) / sizeof(aClusters[0]); i++) {
159 		uint32 mask = aClusters[i].mask & wChannelConfig;
160 		if (mask != 0) {
161 			printf("                       %s", aClusters[i].name);
162 			for (size_t j = 0; j < sizeof(aChannels) / sizeof(aChannels[0]); j++)
163 				if ((aChannels[j].mask & mask) != 0)
164 					printf("%s ", aChannels[j].name);
165 			printf("\n");
166 		}
167 	}
168 }
169 
170 
171 static const char*
TerminalTypeName(uint16 terminalType)172 TerminalTypeName(uint16 terminalType)
173 {
174 	switch (terminalType) {
175 		case USB_AUDIO_UNDEFINED_USB_IO:
176 			return "USB Undefined";
177 		case USB_AUDIO_STREAMING_USB_IO:
178 			return "USB Streaming";
179 		case USB_AUDIO_VENDOR_USB_IO:
180 			return "USB vendor specific";
181 
182 		case USB_AUDIO_UNDEFINED_IN:
183 			return "Undefined";
184 		case USB_AUDIO_MICROPHONE_IN:
185 			return "Microphone";
186 		case USB_AUDIO_DESKTOPMIC_IN:
187 			return "Desktop microphone";
188 		case USB_AUDIO_PERSONALMIC_IN:
189 			return "Personal microphone";
190 		case USB_AUDIO_OMNI_MIC_IN:
191 			return "Omni-directional microphone";
192 		case USB_AUDIO_MICS_ARRAY_IN:
193 			return "Microphone array";
194 		case USB_AUDIO_PROC_MICS_ARRAY_IN:
195 			return "Processing microphone array";
196 		case USB_AUDIO_LINE_CONNECTOR_IO:
197 			return "Line I/O";
198 		case USB_AUDIO_SPDIF_INTERFACE_IO:
199 			return "S/PDIF";
200 
201 		case USB_AUDIO_UNDEFINED_OUT:
202 			return "Undefined";
203 		case USB_AUDIO_SPEAKER_OUT:
204 			return "Speaker";
205 		case USB_AUDIO_HEAD_PHONES_OUT:
206 			return "Headphones";
207 		case USB_AUDIO_HMD_AUDIO_OUT:
208 			return "Head Mounted Display Audio";
209 		case USB_AUDIO_DESKTOP_SPEAKER:
210 			return "Desktop speaker";
211 		case USB_AUDIO_ROOM_SPEAKER:
212 			return "Room speaker";
213 		case USB_AUDIO_COMM_SPEAKER:
214 			return "Communication speaker";
215 		case USB_AUDIO_LFE_SPEAKER:
216 			return "Low frequency effects speaker";
217 
218 		default:
219 			return "Unknown";
220 	}
221 }
222 
223 
224 void
DumpAudioCSInterfaceDescriptorInputTerminal(const usb_audio_input_terminal_descriptor * descriptor,uint16 bcd_release_no)225 DumpAudioCSInterfaceDescriptorInputTerminal(
226 	const usb_audio_input_terminal_descriptor* descriptor,
227 	 uint16 bcd_release_no)
228 {
229 	printf("                    Length............. %u\n", descriptor->length);
230 	printf("                    Type .............. 0x%02x\n",
231 		descriptor->descriptor_type);
232 	printf("                    Subtype ........... 0x%02x (Input Terminal)\n",
233 		descriptor->descriptor_subtype);
234 	printf("                    Terminal ID ....... %u\n",
235 		descriptor->terminal_id);
236 	printf("                    Terminal Type ..... 0x%04x (%s)\n",
237 		descriptor->terminal_type,
238 			TerminalTypeName(descriptor->terminal_type));
239 	printf("                    Associated Terminal %u\n",
240 		descriptor->assoc_terminal);
241 
242 	if (bcd_release_no < USB_AUDIO_CLASS_VERSION_2){
243 		printf("                    Nr Channels ....... %u\n", descriptor->r1.num_channels);
244 		printf("                    Channel Config .... 0x%x\n", descriptor->r1.channel_config);
245 		DumpChannelConfig(descriptor->r1.channel_config);
246 		printf("                    Channel Names ..... %u\n", descriptor->r1.channel_names);
247 		printf("                    Terminal .......... %u\n", descriptor->r1.terminal);
248 	} else {
249 		// Audio 2.0
250 		printf("                    Clock Source ID.....0x%02x\n", descriptor->r2.clock_source_id);
251 		printf("                    Nr Channels ....... %u\n", descriptor->r2.num_channels);
252 		printf("                    Channel Config .... 0x%08" B_PRIx32 "\n",
253 			descriptor->r2.channel_config);
254 		DumpChannelConfig(descriptor->r2.channel_config);
255 		printf("                    Channel Names ..... %u\n", descriptor->r2.channel_names);
256 		printf("                    bm_controls.........0x%04x\n", descriptor->r2.bm_controls);
257 		printf("                    Terminal .......... %u\n", descriptor->r2.terminal);
258 	}
259 }
260 
261 
262 void
DumpAudioCSInterfaceDescriptorOutputTerminal(const usb_audio_output_terminal_descriptor * descriptor,uint16 bcd_release_no)263 DumpAudioCSInterfaceDescriptorOutputTerminal(
264 	const usb_audio_output_terminal_descriptor* descriptor,
265 	 uint16 bcd_release_no)
266 {
267 	printf("                    Length............. %u\n", descriptor->length);
268 	printf("                    Type .............. 0x%02x\n",
269 		descriptor->descriptor_type);
270 	printf("                    Subtype ........... 0x%02x (Output Terminal)\n",
271 		descriptor->descriptor_subtype);
272 	printf("                    Terminal ID ....... %u\n",
273 		descriptor->terminal_id);
274 	printf("                    Terminal Type ..... 0x%04x (%s)\n",
275 		descriptor->terminal_type,
276 			TerminalTypeName(descriptor->terminal_type));
277 	printf("                    Associated Terminal %u\n",
278 		descriptor->assoc_terminal);
279 	printf("                    Source ID ......... 0x%02x\n", descriptor->source_id);
280 
281 	if (bcd_release_no < USB_AUDIO_CLASS_VERSION_2) {
282 		printf("                    Terminal .......... %u\n", descriptor->r1.terminal);
283 	} else {
284 		// Audio 2.0
285 		printf("                    Clock Source ID.....0x%02x\n", descriptor->r2.clock_source_id);
286 		printf("                    bm_controls.........0x%04x\n", descriptor->r2.bm_controls);
287 		printf("                    Terminal .......... %u\n", descriptor->r2.terminal);
288 	}
289 }
290 
291 
292 void
DumpAudioCSInterfaceDescriptorMixerUnit(const usb_audio_mixer_unit_descriptor * descriptor)293 DumpAudioCSInterfaceDescriptorMixerUnit(
294 	const usb_audio_mixer_unit_descriptor* descriptor)
295 {
296 	printf("                    Length............. %u\n", descriptor->length);
297 	printf("                    Type .............. 0x%02x\n",
298 		descriptor->descriptor_type);
299 	printf("                    Subtype ........... 0x%02x (Mixer Unit)\n",
300 		descriptor->descriptor_subtype);
301 	printf("                    Unit ID ........... %u\n",
302 		descriptor->unit_id);
303 
304 	printf("                    Source IDs ........ ");
305 	for (uint8 i = 0; i < descriptor->num_input_pins; i++)
306 		printf("%u, ", descriptor->input_pins[i]);
307 	printf("\n");
308 
309 	usb_audio_output_channels_descriptor_r1* channels
310 		= (usb_audio_output_channels_descriptor_r1*)
311 			&descriptor->input_pins[descriptor->num_input_pins];
312 
313 	printf("                    Channels .......... %u\n",
314 		channels->num_output_pins);
315 	printf("                    Channel Config .... 0x%x\n",
316 			channels->channel_config);
317 	DumpChannelConfig(channels->channel_config);
318 	printf("                    Channel Names ..... %u\n",
319 		channels->channel_names);
320 
321 	usb_generic_descriptor* generic = (usb_generic_descriptor*)descriptor;
322 	uint8 idx = 7 + descriptor->num_input_pins;
323 		printf("                    Bitmap Control .... 0x");
324 	for (uint i = 1; idx < descriptor->length - 3; idx++, i++)
325 		printf("%02x ", (uint8)generic->data[idx]);
326 	printf("\n");
327 
328 	printf("                    Mixer ............. %u\n",
329 			generic->data[generic->length - 3]);
330 }
331 
332 
333 void
DumpAudioCSInterfaceDescriptorSelectorUnit(const usb_audio_selector_unit_descriptor * descriptor)334 DumpAudioCSInterfaceDescriptorSelectorUnit(
335 	const usb_audio_selector_unit_descriptor* descriptor)
336 {
337 	printf("                    Type .............. 0x%02x\n",
338 		descriptor->descriptor_type);
339 	printf("                    Subtype ........... 0x%02x (Selector Unit)\n",
340 		descriptor->descriptor_subtype);
341 	printf("                    Unit ID ........... %u\n",
342 		descriptor->unit_id);
343 
344 	printf("                    Source IDs ........ ");
345 	for (uint8 i = 0; i < descriptor->num_input_pins; i++)
346 		printf("%u, ", descriptor->input_pins[i]);
347 	printf("\n");
348 
349 	usb_generic_descriptor* generic = (usb_generic_descriptor*)descriptor;
350 	printf("                    Selector .......... %u\n",
351 		(uint8)generic->data[descriptor->num_input_pins + 2]);
352 }
353 
354 
355 void
DumpBMAControl(uint8 channel,uint32 bma,uint16 bcd_release_no)356 DumpBMAControl(uint8 channel, uint32 bma, uint16 bcd_release_no)
357 {
358 	const char* BMAControls[] = {
359 		"Mute",
360 		"Volume",
361 		"Bass",
362 		"Mid",
363 		"Treble",
364 		"Graphic Equalizer",
365 		"Automatic Gain",
366 		"Delay",
367 		"Bass Boost",
368 		"Loudness"
369 	};
370 
371 	if (bma == 0)
372 		return;
373 
374 	if (channel == 0)
375 		printf("                       Master Channel . ");
376 	else
377 		printf("                       Channel %u ...... ", channel);
378 
379 	int mask = 1;
380 	if (bcd_release_no < USB_AUDIO_CLASS_VERSION_2) {
381 	for (uint8 i = 0;
382 			i < sizeof(BMAControls) / sizeof(BMAControls[0]); i++, mask <<= 1)
383 		if (bma & mask)
384 			printf("%s ", BMAControls[i]);
385 	} else {
386 		// Audio 2.0
387 		mask = 0x3;
388 		for (uint8 i = 0; i < sizeof(BMAControls) / sizeof(BMAControls[0]); i++, mask <<= 2) {
389 			if (bma & mask) {
390 				printf("%s ", BMAControls[i]);
391 			}
392 		}
393 	}
394 	printf("\n");
395 }
396 
397 
398 void
DumpAudioCSInterfaceDescriptorFeatureUnit(const usb_audio_feature_unit_descriptor * descriptor,uint16 bcd_release_no)399 DumpAudioCSInterfaceDescriptorFeatureUnit(
400 	const usb_audio_feature_unit_descriptor* descriptor,
401 	uint16 bcd_release_no)
402 {
403 	printf("                    Length............. %u\n", descriptor->length);
404 	printf("                    Type .............. 0x%02x\n",
405 		descriptor->descriptor_type);
406 	printf("                    Subtype ........... 0x%02x (Feature Unit)\n",
407 		descriptor->descriptor_subtype);
408 	printf("                    Unit ID ........... %u\n",
409 			descriptor->unit_id);
410 	printf("                    Source ID ......... 0x%02x\n", descriptor->source_id);
411 
412 	if (bcd_release_no < USB_AUDIO_CLASS_VERSION_2) {
413 		printf("                    Control Size ...... %u\n", descriptor->r1.control_size);
414 		uint8 channels = 0;
415 		if (descriptor->r1.control_size > 0)
416 			channels = (descriptor->length - 6) / descriptor->r1.control_size;
417 		for (uint8 i = 0; i < channels; i++) {
418 			switch (descriptor->r1.control_size) {
419 				case 1:
420 					DumpBMAControl(i, descriptor->r1.bma_controls[i], bcd_release_no);
421 					break;
422 				case 2:
423 					DumpBMAControl(i, *(uint16*)&descriptor->r1.bma_controls[i * 2],
424 						bcd_release_no);
425 					break;
426 				case 4:
427 					DumpBMAControl(i, *(uint32*)&descriptor->r1.bma_controls[i * 4],
428 						bcd_release_no);
429 					break;
430 				default:
431 					printf("                    BMA Channel %u ... ", i);
432 					for (uint8 j = 0; j < descriptor->r1.control_size; j++)
433 						printf("%02x ", descriptor->r1.bma_controls[i + j]);
434 					printf("\n");
435 					break;
436 			}
437 			//	usb_generic_descriptor* generic = (usb_generic_descriptor*)descriptor;
438 			//	printf("                    Feature ........... %u\n",
439 			//			(uint8)generic->data[descriptor->length - 3]);
440 		}
441 	} else {
442 			// Audio 2.0
443 			printf("                    BMA Controls ....... 0x%08" B_PRIx32 "\n",
444 				descriptor->r2.bma_controls[0]);
445 			DumpBMAControl(0, descriptor->r2.bma_controls[0], bcd_release_no);
446 		}
447 }
448 
449 void
DumpAudioCSInterfaceDescriptorAssociated(const usb_generic_descriptor * descriptor)450 DumpAudioCSInterfaceDescriptorAssociated(
451 	const usb_generic_descriptor* descriptor)
452 {
453 	printf("                    Type .............. 0x%02x\n",
454 		descriptor->descriptor_type);
455 	printf("                    Subtype ........... 0x%02x (Associate Interface)\n",
456 		(uint8)descriptor->data[0]);
457 	printf("                    Interface ......... %u\n",
458 		(uint8)descriptor->data[1]);
459 
460 	printf("                    Data .............. ");
461 	for (uint8 i = 0; i < descriptor->length - 2; i++)
462 		printf("%02x ", descriptor->data[i]);
463 	printf("\n");
464 }
465 
466 
467 void
DumpAudioControlCSInterfaceDescriptor(const usb_generic_descriptor * descriptor)468 DumpAudioControlCSInterfaceDescriptor(const usb_generic_descriptor* descriptor)
469 {
470 	uint8 descriptorSubtype = descriptor->data[0];
471 	static uint16 bcd_release_no;
472 
473 	switch (descriptorSubtype) {
474 		case USB_AUDIO_AC_HEADER:
475 			bcd_release_no = DumpAudioCSInterfaceDescriptorHeader(
476 				(usb_audiocontrol_header_descriptor*)descriptor);
477 			break;
478 		case USB_AUDIO_AC_INPUT_TERMINAL:
479 			DumpAudioCSInterfaceDescriptorInputTerminal(
480 				(usb_audio_input_terminal_descriptor*)descriptor, bcd_release_no);
481 			break;
482 		case USB_AUDIO_AC_OUTPUT_TERMINAL:
483 			DumpAudioCSInterfaceDescriptorOutputTerminal(
484 				(usb_audio_output_terminal_descriptor*)descriptor, bcd_release_no);
485 			break;
486 		case USB_AUDIO_AC_MIXER_UNIT:
487 			DumpAudioCSInterfaceDescriptorMixerUnit(
488 				(usb_audio_mixer_unit_descriptor*)descriptor);
489 			break;
490 		case USB_AUDIO_AC_SELECTOR_UNIT:
491 			DumpAudioCSInterfaceDescriptorSelectorUnit(
492 				(usb_audio_selector_unit_descriptor*)descriptor);
493 			break;
494 		case USB_AUDIO_AC_FEATURE_UNIT:
495 			DumpAudioCSInterfaceDescriptorFeatureUnit(
496 				(usb_audio_feature_unit_descriptor*)descriptor, bcd_release_no);
497 			break;
498 		case USB_AUDIO_AC_EXTENSION_UNIT:
499 			// USB_AUDIO_AC_PROCESSING_UNIT_R2 == USB_AUDIO_AC_EXTENSION_UNIT
500 			if (bcd_release_no < USB_AUDIO_CLASS_VERSION_2)
501 				DumpAudioCSInterfaceDescriptorAssociated(descriptor);
502 			break;
503 		case USB_AUDIO_AC_PROCESSING_UNIT:
504 			// USB_AUDIO_AC_EFFECT_UNIT_R2 == USB_AUDIO_AC_PROCESSING_UNIT
505 			break;
506 		case USB_AUDIO_AC_EXTENSION_UNIT_R2:
507 			break;
508 		case USB_AUDIO_AC_CLOCK_SOURCE_R2:
509 			DumpAudioCSInterfaceDescriptorClockSourceUnit(
510 				(usb_audio_clocksource_descriptor*)descriptor);
511 			break;
512 		case USB_AUDIO_AC_CLOCK_SELECTOR_R2:
513 			DumpAudioCSInterfaceDescriptorClockSelectorUnit(
514 				(usb_audio_clockselector_descriptor*)descriptor);
515 			break;
516 		case USB_AUDIO_AC_CLOCK_MULTIPLIER_R2:
517 			DumpAudioCSInterfaceDescriptorClockMultiplier(
518 			(usb_audio_clockmultiplier_descriptor*)descriptor);
519 			break;
520 		case USB_AUDIO_AC_SAMPLE_RATE_CONVERTER_R2:
521 			break;
522 
523 		default:
524 			DumpDescriptorData(descriptor);
525 	}
526 }
527 
528 
529 void
DumpGeneralASInterfaceDescriptor(const usb_audio_streaming_interface_descriptor * descriptor)530 DumpGeneralASInterfaceDescriptor(
531 	const usb_audio_streaming_interface_descriptor* descriptor)
532 {
533 	printf("                    Subtype ........... %u (AS_GENERAL)\n",
534 		descriptor->descriptor_subtype);
535 	printf("                    Terminal link ..... %u\n",
536 		descriptor->terminal_link);
537 	printf("                    Delay ............. %u\n",
538 		descriptor->r1.delay);
539 	printf("                    Format tag ........ %u\n",
540 		descriptor->r1.format_tag);
541 }
542 
543 
544 uint32
GetSamplingFrequency(const usb_audio_sampling_freq & freq)545 GetSamplingFrequency(const usb_audio_sampling_freq& freq)
546 {
547 	return freq.bytes[0] | freq.bytes[1] << 8 | freq.bytes[2] << 16;
548 }
549 
550 
551 void
DumpSamplingFrequencies(uint8 type,const usb_audio_sampling_freq * freqs)552 DumpSamplingFrequencies(uint8 type, const usb_audio_sampling_freq* freqs)
553 {
554 	if (type > 0) {
555 		printf("                    Sampling Freq ..... ");
556 		for (uint8 i = 0; i < type; i++)
557 			printf("%" B_PRIu32 ", ", GetSamplingFrequency(freqs[i]));
558 		printf("\n");
559 	} else {
560 		printf("                    Sampling Freq ..... %" B_PRIu32 " to %"
561 			B_PRIu32 "\n", GetSamplingFrequency(freqs[0]),
562 			GetSamplingFrequency(freqs[1]));
563 	}
564 }
565 
566 
567 void
DumpASFormatTypeI(const usb_audio_format_descriptor * descriptor)568 DumpASFormatTypeI(const usb_audio_format_descriptor* descriptor)
569 {
570 	printf("                    Subtype ........... %u (FORMAT_TYPE)\n",
571 		descriptor->descriptor_subtype);
572 	printf("                    Format Type ....... %u (FORMAT_TYPE_I)\n",
573 		descriptor->format_type);
574 	printf("                    Channels .......... %u\n",
575 		descriptor->typeI.nr_channels);
576 	printf("                    Subframe size ..... %u\n",
577 		descriptor->typeI.subframe_size);
578 	printf("                    Bit resolution .... %u\n",
579 		descriptor->typeI.bit_resolution);
580 
581 	DumpSamplingFrequencies(descriptor->typeI.sam_freq_type,
582 			descriptor->typeI.sam_freqs);
583 }
584 
585 
586 void
DumpASFormatTypeIII(const usb_audio_format_descriptor * descriptor)587 DumpASFormatTypeIII(const usb_audio_format_descriptor* descriptor)
588 {
589 	printf("                    Subtype ........... %u (FORMAT_TYPE)\n",
590 		descriptor->descriptor_subtype);
591 	printf("                    Format Type ....... %u (FORMAT_TYPE_III)\n",
592 		descriptor->format_type);
593 	printf("                    Channels .......... %u\n",
594 		descriptor->typeIII.nr_channels);
595 	printf("                    Subframe size ..... %u\n",
596 		descriptor->typeIII.subframe_size);
597 	printf("                    Bit resolution .... %u\n",
598 		descriptor->typeIII.bit_resolution);
599 
600 	DumpSamplingFrequencies(descriptor->typeIII.sam_freq_type,
601 			descriptor->typeIII.sam_freqs);
602 }
603 
604 
605 void
DumpASFormatTypeII(const usb_audio_format_descriptor * descriptor)606 DumpASFormatTypeII(const usb_audio_format_descriptor* descriptor)
607 {
608 	printf("                    Subtype ........... %u (FORMAT_TYPE)\n",
609 		descriptor->descriptor_subtype);
610 	printf("                    Format Type ....... %u (FORMAT_TYPE_II)\n",
611 		descriptor->format_type);
612 	printf("                    Max Bitrate ....... %u\n",
613 		descriptor->typeII.max_bit_rate);
614 	printf("                    Samples per Frame . %u\n",
615 		descriptor->typeII.samples_per_frame);
616 
617 	DumpSamplingFrequencies(descriptor->typeII.sam_freq_type,
618 			descriptor->typeII.sam_freqs);
619 }
620 
621 
622 void
DumpASFmtType(const usb_audio_format_descriptor * descriptor)623 DumpASFmtType(const usb_audio_format_descriptor* descriptor)
624 {
625 	uint8 format = descriptor->format_type;
626 	switch (format) {
627 		case USB_AUDIO_FORMAT_TYPE_I:
628 			DumpASFormatTypeI(descriptor);
629 			break;
630 		case USB_AUDIO_FORMAT_TYPE_II:
631 			DumpASFormatTypeII(descriptor);
632 			break;
633 		case USB_AUDIO_FORMAT_TYPE_III:
634 			DumpASFormatTypeIII(descriptor);
635 			break;
636 		default:
637 			DumpDescriptorData((usb_generic_descriptor*)descriptor);
638 			break;
639 	}
640 }
641 
642 
643 void
DumpMPEGCapabilities(uint16 capabilities)644 DumpMPEGCapabilities(uint16 capabilities)
645 {
646 	const char* MPEGCapabilities[] = {
647 		"Layer I",
648 		"Layer II",
649 		"Layer III",
650 
651 		"MPEG-1 only",
652 		"MPEG-1 dual-channel",
653 		"MPEG-2 second stereo",
654 		"MPEG-2 7.1 channel augumentation",
655 		"Adaptive multi-channel predicion"
656 	};
657 
658 	uint16 mask = 1;
659 	for (uint8 i = 0;
660 			i < sizeof(MPEGCapabilities) / sizeof(MPEGCapabilities[0]); i++) {
661 		if (capabilities & mask)
662 			printf("                         %s\n", MPEGCapabilities[i]);
663 		mask <<= 1;
664 	}
665 
666 	mask = 0x300; // bits 8 and 9
667 	uint16 multilingualSupport = (capabilities & mask) >> 8;
668 	switch (multilingualSupport) {
669 		case 0:
670 			printf("                         No Multilingual support\n");
671 			break;
672 		case 1:
673 			printf("                         Supported at Fs\n");
674 			break;
675 		case 3:
676 			printf("                         Supported at Fs and 1/2Fs\n");
677 			break;
678 		default:
679 			break;
680 	}
681 }
682 
683 
684 void
DumpMPEGFeatures(uint8 features)685 DumpMPEGFeatures(uint8 features)
686 {
687 	uint8 mask = 0x30; // bits 4 and 5
688 	uint8 dynRangeControl = (features & mask) >> 4;
689 	switch (dynRangeControl) {
690 		case 0:
691 			printf("                         Not supported\n");
692 			break;
693 		case 1:
694 			printf("                         Supported, not scalable\n");
695 			break;
696 		case 2:
697 			printf("                         Scalable, common boost, "
698 				"cut scaling value\n");
699 			break;
700 		case 3:
701 			printf("                         Scalable, separate boost, "
702 				"cut scaling value\n");
703 		default:
704 			break;
705 	}
706 }
707 
708 
709 void
DumpASFmtSpecificMPEG(const usb_generic_descriptor * descriptor)710 DumpASFmtSpecificMPEG(const usb_generic_descriptor* descriptor)
711 {
712 	printf("                    Subtype ........... %u (FORMAT_SPECIFIC)\n",
713 		descriptor->data[0]);
714 	printf("                    Format Tag ........ %u\n",
715 		*(uint16*)&descriptor->data[1]);
716 	printf("                    MPEG Capabilities . %u\n",
717 		*(uint16*)&descriptor->data[3]);
718 	DumpMPEGCapabilities(*(uint16*)&descriptor->data[3]);
719 	printf("                    MPEG Features ..... %u\n",
720 		descriptor->data[5]);
721 	DumpMPEGFeatures(descriptor->data[5]);
722 }
723 
724 
725 void
DumpAC_3Features(uint8 features)726 DumpAC_3Features(uint8 features)
727 {
728 	const char* featuresStr[] = {
729 		"RF mode",
730 		"Line mode",
731 		"Custom0 mode",
732 		"Custom1 mode"
733 	};
734 
735 	uint8 mask = 1;
736 	for (uint8 i = 0; i < sizeof(featuresStr) / sizeof(const char*); i++) {
737 		if (features & mask)
738 			printf("                         %s\n", featuresStr[i]);
739 		mask <<= 1;
740 	}
741 
742 	mask = 0x30; // bits 4 and 5
743 	uint8 dynRangeControl = (features & mask) >> 4;
744 	switch (dynRangeControl) {
745 		case 0:
746 			printf("                         Not supported\n");
747 			break;
748 		case 1:
749 			printf("                         Supported, not scalable\n");
750 			break;
751 		case 2:
752 			printf("                         Scalable, common boost, "
753 				"cut scaling value\n");
754 			break;
755 		case 3:
756 			printf("                         Scalable, separate boost, "
757 				"cut scaling value\n");
758 		default:
759 			break;
760 	}
761 }
762 
763 
764 void
DumpASFmtSpecificAC_3(const usb_generic_descriptor * descriptor)765 DumpASFmtSpecificAC_3(const usb_generic_descriptor* descriptor)
766 {
767 	printf("                    Subtype ........... %u (FORMAT_TYPE)\n",
768 		descriptor->data[0]);
769 	printf("                    Format Tag ........ %u\n",
770 		*(uint16*)&descriptor->data[1]);
771 	printf("                    BSID .............. %" B_PRIx32 "\n",
772 		*(uint32*)&descriptor->data[2]);
773 	printf("                    AC3 Features ...... %u\n",
774 		descriptor->data[6]);
775 	DumpAC_3Features(descriptor->data[6]);
776 }
777 
778 
779 void
DumpASFmtSpecific(const usb_generic_descriptor * descriptor)780 DumpASFmtSpecific(const usb_generic_descriptor* descriptor)
781 {
782 	enum {
783 		TYPE_II_UNDEFINED = 0x1000,
784 		MPEG =				0x1001,
785 		AC_3 =				0x1002
786 	};
787 
788 	uint16 formatTag = *(uint16*)&descriptor->data[1];
789 	switch (formatTag) {
790 		case MPEG:
791 			DumpASFmtSpecificMPEG(descriptor);
792 			break;
793 		case AC_3:
794 			DumpASFmtSpecificAC_3(descriptor);
795 			break;
796 		default:
797 			DumpDescriptorData(descriptor);
798 			break;
799 	}
800 }
801 
802 
803 void
DumpAudioStreamCSInterfaceDescriptor(const usb_generic_descriptor * descriptor)804 DumpAudioStreamCSInterfaceDescriptor(const usb_generic_descriptor* descriptor)
805 {
806 	uint8 subtype = descriptor->data[0];
807 	switch (subtype) {
808 		case USB_AUDIO_AS_GENERAL:
809 			DumpGeneralASInterfaceDescriptor(
810 				(usb_audio_streaming_interface_descriptor*)descriptor);
811 			break;
812 		case USB_AUDIO_AS_FORMAT_TYPE:
813 			DumpASFmtType(
814 				(usb_audio_format_descriptor*)descriptor);
815 			break;
816 		case USB_AUDIO_AS_FORMAT_SPECIFIC:
817 			DumpASFmtSpecific(descriptor);
818 			break;
819 		default:
820 			DumpDescriptorData(descriptor);
821 			break;
822 	}
823 }
824 
825 
826 void
DumpAudioStreamCSEndpointDescriptor(const usb_audio_streaming_endpoint_descriptor * descriptor)827 DumpAudioStreamCSEndpointDescriptor(
828 	const usb_audio_streaming_endpoint_descriptor* descriptor)
829 {
830 	printf("                    Type .............. 0x%02x (CS_ENDPOINT)\n",
831 		descriptor->descriptor_type);
832 	printf("                    Subtype ........... 0x%02x (EP_GENERAL)\n",
833 		descriptor->descriptor_subtype);
834 	printf("                    Attributes ........ 0x%02x ",
835 		descriptor->attributes);
836 
837 	const char* attributes[] = {
838 		"Sampling Frequency",
839 		"Pitch",
840 		"", "", "", "", "",
841 		"Max Packet Only"
842 	};
843 
844 	uint8 mask = 1;
845 	for (uint8 i = 0; i < sizeof(attributes) / sizeof(attributes[0]); i++) {
846 		if ((descriptor->attributes & mask) != 0)
847 			printf("%s ", attributes[i]);
848 		mask <<= 1;
849 	}
850 	printf("\n");
851 
852 	const char* aUnits[] = {
853 		"Undefined",
854 		"Milliseconds",
855 		"Decoded PCM samples",
856 		"Unknown (%u)"
857 	};
858 
859 	const char* units = descriptor->lock_delay_units >= 4
860 		? aUnits[3] : aUnits[descriptor->lock_delay_units];
861 
862 	printf("                    Lock Delay Units .. %u (%s)\n",
863 		descriptor->lock_delay_units, units);
864 	printf("                    Lock Delay ........ %u\n",
865 		descriptor->lock_delay);
866 }
867 
868 
869 void
DumpMidiInterfaceHeaderDescriptor(const usb_midi_interface_header_descriptor * descriptor)870 DumpMidiInterfaceHeaderDescriptor(
871 	const usb_midi_interface_header_descriptor* descriptor)
872 {
873 	printf("                    Type .............. 0x%02x (CS_ENDPOINT)\n",
874 		descriptor->descriptor_type);
875 	printf("                    Subtype ........... 0x%02x (MS_HEADER)\n",
876 		descriptor->descriptor_subtype);
877 	printf("                    MSC Version ....... 0x%04x\n",
878 		descriptor->ms_version);
879 	printf("                    Length ............ 0x%04x\n",
880 		descriptor->total_length);
881 }
882 
883 
884 void
DumpMidiInJackDescriptor(const usb_midi_in_jack_descriptor * descriptor)885 DumpMidiInJackDescriptor(
886 	const usb_midi_in_jack_descriptor* descriptor)
887 {
888 	printf("                    Type .............. 0x%02x (CS_INTERFACE)\n",
889 		descriptor->descriptor_type);
890 	printf("                    Subtype ........... 0x%02x (MIDI_IN_JACK)\n",
891 		descriptor->descriptor_subtype);
892 	printf("                    Jack ID ........... 0x%02x\n",
893 		descriptor->id);
894 	// TODO can we get the string?
895 	printf("                    String ............ 0x%02x\n",
896 		descriptor->string_descriptor);
897 
898 	switch (descriptor->type) {
899 		case USB_MIDI_EMBEDDED_JACK:
900 			printf("                    Jack Type ......... Embedded\n");
901 			break;
902 		case USB_MIDI_EXTERNAL_JACK:
903 			printf("                    Jack Type ......... External\n");
904 			break;
905 		default:
906 			printf("                    Jack Type ......... 0x%02x (unknown)\n",
907 				descriptor->type);
908 			break;
909 	}
910 }
911 
912 
913 void
DumpMidiOutJackDescriptor(const usb_midi_out_jack_descriptor * descriptor)914 DumpMidiOutJackDescriptor(
915 	const usb_midi_out_jack_descriptor* descriptor)
916 {
917 	printf("                    Type .............. 0x%02x (CS_INTERFACE)\n",
918 		descriptor->descriptor_type);
919 	printf("                    Subtype ........... 0x%02x (MIDI_OUT_JACK)\n",
920 		descriptor->descriptor_subtype);
921 	printf("                    Jack ID ........... 0x%02x\n",
922 		descriptor->id);
923 
924 	switch (descriptor->type) {
925 		case USB_MIDI_EMBEDDED_JACK:
926 			printf("                    Jack Type ......... Embedded\n");
927 			break;
928 		case USB_MIDI_EXTERNAL_JACK:
929 			printf("                    Jack Type ......... External\n");
930 			break;
931 		default:
932 			printf("                    Jack Type ......... 0x%02x (unknown)\n",
933 				descriptor->type);
934 			break;
935 	}
936 
937 	for (int i = 0; i < descriptor->inputs_count; i++) {
938 		printf("                    Pin %02d ............ (%d,%d)\n", i,
939 			descriptor->input_source[i].source_id,
940 			descriptor->input_source[i].source_pin);
941 	}
942 }
943 
944 
945 void
DumpMidiStreamCSInterfaceDescriptor(const usb_generic_descriptor * descriptor)946 DumpMidiStreamCSInterfaceDescriptor(const usb_generic_descriptor* descriptor)
947 {
948 	uint8 subtype = descriptor->data[0];
949 	switch (subtype) {
950 		case USB_MS_HEADER_DESCRIPTOR:
951 			DumpMidiInterfaceHeaderDescriptor(
952 				(usb_midi_interface_header_descriptor*)descriptor);
953 			break;
954 		case USB_MS_MIDI_IN_JACK_DESCRIPTOR:
955 			DumpMidiInJackDescriptor(
956 				(usb_midi_in_jack_descriptor*)descriptor);
957 			break;
958 		case USB_MS_MIDI_OUT_JACK_DESCRIPTOR:
959 			DumpMidiOutJackDescriptor(
960 				(usb_midi_out_jack_descriptor*)descriptor);
961 			break;
962 		case USB_MS_ELEMENT_DESCRIPTOR:
963 			// TODO
964 			DumpDescriptorData(descriptor);
965 			break;
966 		default:
967 			DumpDescriptorData(descriptor);
968 			break;
969 	}
970 }
971 
972 
973 void
DumpMidiStreamCSEndpointDescriptor(const usb_midi_endpoint_descriptor * descriptor)974 DumpMidiStreamCSEndpointDescriptor(
975 	const usb_midi_endpoint_descriptor* descriptor)
976 {
977 	printf("                    Type .............. 0x%02x (CS_ENDPOINT)\n",
978 		descriptor->descriptor_type);
979 	printf("                    Subtype ........... 0x%02x (MS_GENERAL)\n",
980 		descriptor->descriptor_subtype);
981 	printf("                    Jacks ............. ");
982 
983 	for (int i = 0; i < descriptor->jacks_count; i++)
984 		printf("%d, ", descriptor->jacks_id[i]);
985 
986 	printf("\n");
987 }
988 
989 
990 void
DumpAudioStreamInterfaceDescriptor(const usb_interface_descriptor * descriptor)991 DumpAudioStreamInterfaceDescriptor(const usb_interface_descriptor* descriptor)
992 {
993 	printf("                    Type .............. %u (INTERFACE)\n",
994 		descriptor->descriptor_type);
995 	printf("                    Interface ........... %u\n",
996 		descriptor->interface_number);
997 	printf("                    Alternate setting ... %u\n",
998 		descriptor->alternate_setting);
999 	printf("                    Endpoints ........... %u\n",
1000 		descriptor->num_endpoints);
1001 	printf("                    Interface class ..... %u (AUDIO)\n",
1002 		descriptor->interface_class);
1003 	printf("                    Interface subclass .. %u (AUDIO_STREAMING)\n",
1004 		descriptor->interface_subclass);
1005 	printf("                    Interface ........... %u\n",
1006 		descriptor->interface);
1007 }
1008 
1009 
1010 void
DumpAudioDescriptor(const usb_generic_descriptor * descriptor,int subclass)1011 DumpAudioDescriptor(const usb_generic_descriptor* descriptor, int subclass)
1012 {
1013 	const uint8 USB_AUDIO_INTERFACE = 0x04;
1014 
1015 	switch (subclass) {
1016 		case USB_AUDIO_INTERFACE_AUDIOCONTROL_SUBCLASS:
1017 			switch (descriptor->descriptor_type) {
1018 				case USB_AUDIO_CS_INTERFACE:
1019 					DumpAudioControlCSInterfaceDescriptor(descriptor);
1020 					break;
1021 				default:
1022 					DumpDescriptorData(descriptor);
1023 					break;
1024 			}
1025 			break;
1026 		case USB_AUDIO_INTERFACE_AUDIOSTREAMING_SUBCLASS:
1027 			switch (descriptor->descriptor_type) {
1028 				case USB_AUDIO_INTERFACE:
1029 					DumpAudioStreamInterfaceDescriptor(
1030 						(const usb_interface_descriptor*)descriptor);
1031 					break;
1032 				case USB_AUDIO_CS_INTERFACE:
1033 					DumpAudioStreamCSInterfaceDescriptor(descriptor);
1034 					break;
1035 				case USB_AUDIO_CS_ENDPOINT:
1036 					DumpAudioStreamCSEndpointDescriptor(
1037 						(const usb_audio_streaming_endpoint_descriptor*)descriptor);
1038 					break;
1039 				default:
1040 					DumpDescriptorData(descriptor);
1041 					break;
1042 			}
1043 			break;
1044 		case USB_AUDIO_INTERFACE_MIDISTREAMING_SUBCLASS:
1045 			switch (descriptor->descriptor_type) {
1046 				case USB_AUDIO_CS_INTERFACE:
1047 					DumpMidiStreamCSInterfaceDescriptor(descriptor);
1048 					break;
1049 				case USB_AUDIO_CS_ENDPOINT:
1050 					DumpMidiStreamCSEndpointDescriptor(
1051 						(const usb_midi_endpoint_descriptor*)descriptor);
1052 					break;
1053 				default:
1054 					DumpDescriptorData(descriptor);
1055 					break;
1056 			}
1057 			break;
1058 		default:
1059 			DumpDescriptorData(descriptor);
1060 			break;
1061 	}
1062 }
1063