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