418 | | switch (descriptor->descriptor_type) { |
419 | | case USB_AUDIO_CS_INTERFACE: |
420 | | DumpAudioCSInterfaceDescriptor(descriptor); |
| 419 | printf(" Type .............. %u (CS_INTERFACE)\n", |
| 420 | descriptor->descriptor_type); |
| 421 | printf(" Subtype ........... %u (AS_GENERAL)\n", |
| 422 | descriptor->descriptor_subtype); |
| 423 | printf(" Terminal link ..... %u\n", |
| 424 | descriptor->terminal_link); |
| 425 | printf(" Delay ............. %u\n", |
| 426 | descriptor->r1.delay); |
| 427 | printf(" Format tag ........ %u\n", |
| 428 | descriptor->r1.format_tag); |
| 429 | } |
| 430 | |
| 431 | |
| 432 | void |
| 433 | DumpASFormatTypeI(const usb_generic_descriptor* descriptor) |
| 434 | { |
| 435 | printf(" Type .............. %u (CS_INTERFACE)\n", |
| 436 | descriptor->descriptor_type); |
| 437 | printf(" Subtype ........... %u (FORMAT_TYPE)\n", |
| 438 | descriptor->data[0]); |
| 439 | printf(" Format Type ....... %u (FORMAT_TYPE_I)\n", |
| 440 | descriptor->data[1]); |
| 441 | printf(" Channels .......... %u\n", |
| 442 | descriptor->data[2]); |
| 443 | printf(" Subframe size ..... %u\n", |
| 444 | descriptor->data[3]); |
| 445 | printf(" Bit resoultion .... %u\n", |
| 446 | descriptor->data[4]); |
| 447 | |
| 448 | uint8 samFreqType = descriptor->data[5]; |
| 449 | printf(" Sample Freq Type .. %u\n", |
| 450 | samFreqType); |
| 451 | |
| 452 | if (samFreqType == 0) { |
| 453 | printf(" Lower Sample Freq . %02x %02x %02x\n", |
| 454 | descriptor->data[6], descriptor->data[7], descriptor->data[8]); |
| 455 | printf(" Upper Sample Freq . %02x %02x %02x\n", |
| 456 | descriptor->data[9], descriptor->data[10], descriptor->data[11]); |
| 457 | } else { |
| 458 | for (uint8 i = 0; i < samFreqType; i++) |
| 459 | printf(" Sample Freq %u .... %02x %02x %02x\n", |
| 460 | i + 1, descriptor->data[6 + i * 3], |
| 461 | descriptor->data[6 + i * 3 + 1], |
| 462 | descriptor->data[6 + i * 3 + 2]); |
| 463 | } |
| 464 | } |
| 465 | |
| 466 | |
| 467 | void |
| 468 | DumpASFormatTypeIII(const usb_generic_descriptor* descriptor) |
| 469 | { |
| 470 | printf(" Type .............. %u (CS_INTERFACE)\n", |
| 471 | descriptor->descriptor_type); |
| 472 | printf(" Subtype ........... %u (FORMAT_TYPE)\n", |
| 473 | descriptor->data[0]); |
| 474 | printf(" Format Type ....... %u (FORMAT_TYPE_III)\n", |
| 475 | descriptor->data[1]); |
| 476 | printf(" Channels .......... %u\n", |
| 477 | descriptor->data[2]); |
| 478 | printf(" Subframe size ..... %u\n", |
| 479 | descriptor->data[3]); |
| 480 | printf(" Bit resoultion .... %u\n", |
| 481 | descriptor->data[4]); |
| 482 | |
| 483 | uint8 samFreqType = descriptor->data[5]; |
| 484 | printf(" Sample Freq Type .. %u\n", |
| 485 | samFreqType); |
| 486 | |
| 487 | if (samFreqType == 0) { |
| 488 | printf(" Lower Sample Freq . %02x %02x %02x\n", |
| 489 | descriptor->data[6], descriptor->data[7], descriptor->data[8]); |
| 490 | printf(" Upper Sample Freq . %02x %02x %02x\n", |
| 491 | descriptor->data[9], descriptor->data[10], descriptor->data[11]); |
| 492 | } else { |
| 493 | for (uint8 i = 0; i < samFreqType; i++) |
| 494 | printf(" Sample Freq %u .... %02x %02x %02x\n", |
| 495 | i + 1, descriptor->data[6 + i * 3], |
| 496 | descriptor->data[6 + i * 3 + 1], |
| 497 | descriptor->data[6 + i * 3 + 2]); |
| 498 | } |
| 499 | } |
| 500 | |
| 501 | |
| 502 | void |
| 503 | DumpASFormatTypeII(const usb_generic_descriptor* descriptor) |
| 504 | { |
| 505 | printf(" Type .............. %u (CS_INTERFACE)\n", |
| 506 | descriptor->descriptor_type); |
| 507 | printf(" Subtype ........... %u (FORMAT_TYPE)\n", |
| 508 | descriptor->data[0]); |
| 509 | printf(" Format Type ....... %u (FORMAT_TYPE_II)\n", |
| 510 | descriptor->data[1]); |
| 511 | printf(" Max Bitrate ....... %u\n", |
| 512 | *(uint16*)&descriptor->data[2]); |
| 513 | printf(" Samples per Frame . %u\n", |
| 514 | *(uint16*)&descriptor->data[4]); |
| 515 | |
| 516 | uint8 samFreqType = descriptor->data[6]; |
| 517 | printf(" Sample Freq type .. %u\n", |
| 518 | samFreqType); |
| 519 | |
| 520 | if (samFreqType == 0) { |
| 521 | printf(" Lower Sample Freq . %02x %02x %02x\n", |
| 522 | descriptor->data[7], descriptor->data[8], descriptor->data[9]); |
| 523 | printf(" Upper Sample Freq . %02x %02x %02x\n", |
| 524 | descriptor->data[10], descriptor->data[11], descriptor->data[12]); |
| 525 | } else { |
| 526 | for (uint8 i = 0; i < samFreqType; i++) |
| 527 | printf(" Sample Freq %u .... %02x %02x %02x\n", |
| 528 | i + 1, descriptor->data[7 + i * 3], |
| 529 | descriptor->data[7 + i * 3 + 1], |
| 530 | descriptor->data[7 + i * 3 + 2]); |
| 531 | } |
| 532 | } |
| 533 | |
| 534 | |
| 535 | void |
| 536 | DumpASFmtType(const usb_generic_descriptor* descriptor) |
| 537 | { |
| 538 | enum { |
| 539 | FORMAT_TYPE_UNDEFINED = 0x00, |
| 540 | FORMAT_TYPE_I = 0x01, |
| 541 | FORMAT_TYPE_II = 0x02, |
| 542 | FORMAT_TYPE_III = 0x03 |
| 543 | }; |
| 544 | |
| 545 | uint8 format = descriptor->data[1]; |
| 546 | switch (format) { |
| 547 | case FORMAT_TYPE_I: |
| 548 | DumpASFormatTypeI(descriptor); |
| 549 | break; |
| 550 | case FORMAT_TYPE_II: |
| 551 | DumpASFormatTypeII(descriptor); |
| 552 | break; |
| 553 | case FORMAT_TYPE_III: |
| 554 | DumpASFormatTypeIII(descriptor); |
433 | | DumpAudioDescriptor(descriptor); |
| 591 | printf(" Supported at Fs\n"); |
| 592 | break; |
| 593 | case 3: |
| 594 | printf(" Supported at Fs and 1/2Fs\n"); |
| 595 | |
| 596 | } |
| 597 | } |
| 598 | |
| 599 | |
| 600 | void |
| 601 | DumpMPEGFeatures(uint8 features) |
| 602 | { |
| 603 | uint8 mask = 0x30; //bits 4 and 5 |
| 604 | uint8 dynRangeControl = (features & mask) >> 4; |
| 605 | switch (dynRangeControl) { |
| 606 | case 0: |
| 607 | printf(" Not supported\n"); |
| 608 | break; |
| 609 | case 1: |
| 610 | printf(" Supported, not scaleable\n"); |
| 611 | break; |
| 612 | case 2: |
| 613 | printf(" Scaleable, common boost, " |
| 614 | "cut scaling value\n"); |
| 615 | break; |
| 616 | case 3: |
| 617 | printf(" Scaleable, separate boost, " |
| 618 | "cut scaling value\n"); |
| 619 | |
| 620 | } |
| 621 | } |
| 622 | |
| 623 | |
| 624 | void |
| 625 | DumpASFmtSpecificMPEG(const usb_generic_descriptor* descriptor) |
| 626 | { |
| 627 | printf(" Type .............. %u (CS_INTERFACE)\n", |
| 628 | descriptor->descriptor_type); |
| 629 | printf(" Subtype ........... %u (FORMAT_SPECIFIC)\n", |
| 630 | descriptor->data[0]); |
| 631 | printf(" Format Tag ........ %u\n", |
| 632 | *(uint16*)&descriptor->data[1]); |
| 633 | printf(" MPEG Capabilities . %u\n", |
| 634 | *(uint16*)&descriptor->data[3]); |
| 635 | DumpMPEGCapabilities(*(uint16*)&descriptor->data[3]); |
| 636 | printf(" MPEG Features ..... %u\n", |
| 637 | descriptor->data[5]); |
| 638 | DumpMPEGFeatures(descriptor->data[5]); |
| 639 | } |
| 640 | |
| 641 | |
| 642 | void |
| 643 | DumpAC_3Features(uint8 features) |
| 644 | { |
| 645 | const char* featuresStr[] = { |
| 646 | "RF mode", |
| 647 | "Line mode", |
| 648 | "Custom0 mode", |
| 649 | "Custom1 mode", |
| 650 | }; |
| 651 | |
| 652 | uint8 mask = 1; |
| 653 | for (uint8 i = 0; i < sizeof(featuresStr) / sizeof(const char*); i++) { |
| 654 | if(features & mask) |
| 655 | printf(" %s\n", featuresStr[i]); |
| 656 | mask <<= 1; |
| 657 | } |
| 658 | |
| 659 | mask = 0x30; //bits 4 and 5 |
| 660 | uint8 dynRangeControl = (features & mask) >> 4; |
| 661 | switch (dynRangeControl) { |
| 662 | case 0: |
| 663 | printf(" Not supported\n"); |
| 664 | break; |
| 665 | case 1: |
| 666 | printf(" Supported, not scaleable\n"); |
| 667 | break; |
| 668 | case 2: |
| 669 | printf(" Scaleable, common boost, " |
| 670 | "cut scaling value\n"); |
| 671 | case 3: |
| 672 | printf(" Scaleable, separate boost, " |
| 673 | "cut scaling value\n"); |
| 674 | |
| 675 | } |
| 676 | } |
| 677 | |
| 678 | |
| 679 | void |
| 680 | DumpASFmtSpecificAC_3(const usb_generic_descriptor* descriptor) |
| 681 | { |
| 682 | printf(" Type .............. %u (CS_INTERFACE)\n", |
| 683 | descriptor->descriptor_type); |
| 684 | printf(" Subtype ........... %u (FORMAT_TYPE)\n", |
| 685 | descriptor->data[0]); |
| 686 | printf(" Format Tag ........ %u\n", |
| 687 | *(uint16*)&descriptor->data[1]); |
| 688 | printf(" BSID .............. %xl\n", |
| 689 | *(uint32*)&descriptor->data[2]); |
| 690 | printf(" AC3 Features ...... %u\n", |
| 691 | descriptor->data[6]); |
| 692 | DumpAC_3Features(descriptor->data[6]); |
| 693 | } |
| 694 | |
| 695 | |
| 696 | void |
| 697 | DumpASFmtSpecific(const usb_generic_descriptor* descriptor) |
| 698 | { |
| 699 | enum { |
| 700 | TYPE_II_UNDEFINED = 0x1000, |
| 701 | MPEG = 0x1001, |
| 702 | AC_3 = 0x1002 |
| 703 | }; |
| 704 | |
| 705 | uint16 formatTag = *(uint16*)&descriptor->data[1]; |
| 706 | switch (formatTag) { |
| 707 | case MPEG: |
| 708 | DumpASFmtSpecificMPEG(descriptor); |
| 709 | break; |
| 710 | case AC_3: |
| 711 | DumpASFmtSpecificAC_3(descriptor); |
| 712 | break; |
| 713 | default: |
| 714 | DumpDescriptorData(descriptor); |
| 715 | } |
| 716 | } |
| 717 | |
| 718 | |
| 719 | void |
| 720 | DumpAudioStreamCSInterfaceDescriptor(const usb_generic_descriptor* descriptor) |
| 721 | { |
| 722 | uint8 subtype = descriptor->data[0]; |
| 723 | switch (subtype) { |
| 724 | case USB_AUDIO_AS_GENERAL: |
| 725 | DumpGeneralASInterfaceDescriptor( |
| 726 | (usb_audio_streaming_interface_descriptor*)descriptor); |
| 727 | break; |
| 728 | case USB_AUDIO_AS_FORMAT_TYPE: |
| 729 | DumpASFmtType(descriptor); |
| 730 | break; |
| 731 | case USB_AUDIO_AS_FORMAT_SPECIFIC: |
| 732 | DumpASFmtSpecific(descriptor); |
| 733 | break; |
| 734 | default: |
| 735 | DumpDescriptorData(descriptor); |
| 736 | } |
| 737 | } |
| 738 | |
| 739 | |
| 740 | void |
| 741 | DumpAudioStreamInterfaceDescriptor(const usb_generic_descriptor* descriptor) |
| 742 | { |
| 743 | printf(" Type .............. %u (INTERFACE)\n", |
| 744 | descriptor->descriptor_type); |
| 745 | printf(" Interface ........... %u\n", |
| 746 | descriptor->data[0]); |
| 747 | printf(" Alternate setting ... %u\n", |
| 748 | descriptor->data[1]); |
| 749 | printf(" Endpoints ........... %u\n", |
| 750 | descriptor->data[2]); |
| 751 | printf(" Interface class ..... %u (AUDIO)\n", |
| 752 | descriptor->data[3]); |
| 753 | printf(" Interface subclass .. %u (AUDIO_STREAMING)\n", |
| 754 | descriptor->data[4]); |
| 755 | printf(" Interface ........... %u\n", |
| 756 | descriptor->data[6]); |
| 757 | } |
| 758 | |
| 759 | |
| 760 | void |
| 761 | DumpAudioDescriptor(const usb_generic_descriptor* descriptor, int subclass) |
| 762 | { |
| 763 | const uint8 USB_AUDIO_INTERFACE = 0x04; |
| 764 | |
| 765 | switch (subclass) { |
| 766 | case USB_AUDIO_INTERFACE_AUDIOCONTROL_SUBCLASS: |
| 767 | switch (descriptor->descriptor_type) { |
| 768 | case USB_AUDIO_CS_INTERFACE: |
| 769 | DumpAudioControlCSInterfaceDescriptor(descriptor); |
| 770 | break; |
| 771 | default: |
| 772 | DumpDescriptorData(descriptor); |
| 773 | } |
| 774 | break; |
| 775 | case USB_AUDIO_INTERFACE_AUDIOSTREAMING_SUBCLASS: |
| 776 | switch (descriptor->descriptor_type) { |
| 777 | case USB_AUDIO_INTERFACE: |
| 778 | DumpAudioStreamInterfaceDescriptor(descriptor); |
| 779 | break; |
| 780 | case USB_AUDIO_CS_INTERFACE: |
| 781 | DumpAudioStreamCSInterfaceDescriptor(descriptor); |
| 782 | break; |
| 783 | default: |
| 784 | DumpDescriptorData(descriptor); |
| 785 | } |
| 786 | break; |
| 787 | } |
| 788 | } |
| 789 | |
| 790 | |
| 791 | void |
| 792 | DumpDescriptor(const usb_generic_descriptor* descriptor, int classNum, int subclass) |
| 793 | { |
| 794 | switch (classNum) { |
| 795 | case USB_AUDIO_DEVICE_CLASS: |
| 796 | DumpAudioDescriptor(descriptor, subclass); |