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 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 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 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 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 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 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* 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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