Home | History | Annotate | Download | only in descriptors
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.android.server.usb.descriptors;
     17 
     18 import android.util.Log;
     19 
     20 import com.android.server.usb.descriptors.report.ReportCanvas;
     21 import com.android.server.usb.descriptors.report.UsbStrings;
     22 
     23 /**
     24  * @hide
     25  * An audio class-specific Interface.
     26  * see audio10.pdf section 4.3.2
     27  */
     28 public abstract class UsbACInterface extends UsbDescriptor {
     29     private static final String TAG = "UsbACInterface";
     30 
     31     // Audio Control Subtypes
     32     public static final byte ACI_UNDEFINED = 0;
     33     public static final byte ACI_HEADER = 1;
     34     public static final byte ACI_INPUT_TERMINAL = 2;
     35     public static final byte ACI_OUTPUT_TERMINAL = 3;
     36     public static final byte ACI_MIXER_UNIT = 4;
     37     public static final byte ACI_SELECTOR_UNIT = 5;
     38     public static final byte ACI_FEATURE_UNIT = 6;
     39     public static final byte ACI_PROCESSING_UNIT = 7;
     40     public static final byte ACI_EXTENSION_UNIT = 8;
     41     // Not handled yet
     42     public static final byte ACI_CLOCK_SOURCE = 0x0A;
     43     public static final byte ACI_CLOCK_SELECTOR = 0x0B;
     44     public static final byte ACI_CLOCK_MULTIPLIER = 0x0C;
     45     public static final byte ACI_SAMPLE_RATE_CONVERTER =  0x0D;
     46 
     47     // Audio Streaming Subtypes
     48     public static final byte ASI_UNDEFINED = 0;
     49     public static final byte ASI_GENERAL = 1;
     50     public static final byte ASI_FORMAT_TYPE = 2;
     51     public static final byte ASI_FORMAT_SPECIFIC = 3;
     52 
     53     // MIDI Streaming Subtypes
     54     public static final byte MSI_UNDEFINED = 0;
     55     public static final byte MSI_HEADER = 1;
     56     public static final byte MSI_IN_JACK = 2;
     57     public static final byte MSI_OUT_JACK = 3;
     58     public static final byte MSI_ELEMENT = 4;
     59 
     60     // Sample format IDs (encodings)
     61     // FORMAT_I
     62     public static final int FORMAT_I_UNDEFINED     = 0x0000;
     63     public static final int FORMAT_I_PCM           = 0x0001;
     64     public static final int FORMAT_I_PCM8          = 0x0002;
     65     public static final int FORMAT_I_IEEE_FLOAT    = 0x0003;
     66     public static final int FORMAT_I_ALAW          = 0x0004;
     67     public static final int FORMAT_I_MULAW         = 0x0005;
     68     // FORMAT_II
     69     public static final int FORMAT_II_UNDEFINED    = 0x1000;
     70     public static final int FORMAT_II_MPEG         = 0x1001;
     71     public static final int FORMAT_II_AC3          = 0x1002;
     72     // FORMAT_III
     73     public static final int FORMAT_III_UNDEFINED              = 0x2000;
     74     public static final int FORMAT_III_IEC1937AC3             = 0x2001;
     75     public static final int FORMAT_III_IEC1937_MPEG1_Layer1   = 0x2002;
     76     public static final int FORMAT_III_IEC1937_MPEG1_Layer2   = 0x2003;
     77     public static final int FORMAT_III_IEC1937_MPEG2_EXT      = 0x2004;
     78     public static final int FORMAT_III_IEC1937_MPEG2_Layer1LS = 0x2005;
     79 
     80     protected final byte mSubtype;  // 2:1 HEADER descriptor subtype
     81     protected final int mSubclass;  // from the mSubclass member of the
     82                                     // "enclosing" Interface Descriptor
     83 
     84     public UsbACInterface(int length, byte type, byte subtype, int subclass) {
     85         super(length, type);
     86         mSubtype = subtype;
     87         mSubclass = subclass;
     88     }
     89 
     90     public byte getSubtype() {
     91         return mSubtype;
     92     }
     93 
     94     public int getSubclass() {
     95         return mSubclass;
     96     }
     97 
     98     private static UsbDescriptor allocAudioControlDescriptor(UsbDescriptorParser parser,
     99             ByteStream stream, int length, byte type, byte subtype, int subClass) {
    100         switch (subtype) {
    101             case ACI_HEADER:
    102             {
    103                 int acInterfaceSpec = stream.unpackUsbShort();
    104                 parser.setACInterfaceSpec(acInterfaceSpec);
    105                 if (acInterfaceSpec == UsbDeviceDescriptor.USBSPEC_2_0) {
    106                     return new Usb20ACHeader(length, type, subtype, subClass, acInterfaceSpec);
    107                 } else {
    108                     return new Usb10ACHeader(length, type, subtype, subClass, acInterfaceSpec);
    109                 }
    110             }
    111 
    112             case ACI_INPUT_TERMINAL:
    113             {
    114                 int acInterfaceSpec = parser.getACInterfaceSpec();
    115                 if (acInterfaceSpec == UsbDeviceDescriptor.USBSPEC_2_0) {
    116                     return new Usb20ACInputTerminal(length, type, subtype, subClass);
    117                 } else {
    118                     return new Usb10ACInputTerminal(length, type, subtype, subClass);
    119                 }
    120             }
    121 
    122             case ACI_OUTPUT_TERMINAL:
    123             {
    124                 int acInterfaceSpec = parser.getACInterfaceSpec();
    125                 if (acInterfaceSpec == UsbDeviceDescriptor.USBSPEC_2_0) {
    126                     return new Usb20ACOutputTerminal(length, type, subtype, subClass);
    127                 } else {
    128                     return new Usb10ACOutputTerminal(length, type, subtype, subClass);
    129                 }
    130             }
    131 
    132             case ACI_SELECTOR_UNIT:
    133                 return new UsbACSelectorUnit(length, type, subtype, subClass);
    134 
    135             case ACI_FEATURE_UNIT:
    136                 return new UsbACFeatureUnit(length, type, subtype, subClass);
    137 
    138             case ACI_MIXER_UNIT:
    139             {
    140                 int acInterfaceSpec = parser.getACInterfaceSpec();
    141                 if (acInterfaceSpec == UsbDeviceDescriptor.USBSPEC_2_0) {
    142                     return new Usb20ACMixerUnit(length, type, subtype, subClass);
    143                 } else {
    144                     return new Usb10ACMixerUnit(length, type, subtype, subClass);
    145                 }
    146             }
    147 
    148             case ACI_PROCESSING_UNIT:
    149             case ACI_EXTENSION_UNIT:
    150             case ACI_UNDEFINED:
    151                 // break; Fall through until we implement this descriptor
    152             default:
    153                 Log.w(TAG, "Unknown Audio Class Interface subtype:0x"
    154                         + Integer.toHexString(subtype));
    155                 return new UsbACInterfaceUnparsed(length, type, subtype, subClass);
    156         }
    157     }
    158 
    159     private static UsbDescriptor allocAudioStreamingDescriptor(UsbDescriptorParser parser,
    160             ByteStream stream, int length, byte type, byte subtype, int subClass) {
    161         //int spec = parser.getUsbSpec();
    162         int acInterfaceSpec = parser.getACInterfaceSpec();
    163         switch (subtype) {
    164             case ASI_GENERAL:
    165                 if (acInterfaceSpec == UsbDeviceDescriptor.USBSPEC_2_0) {
    166                     return new Usb20ASGeneral(length, type, subtype, subClass);
    167                 } else {
    168                     return new Usb10ASGeneral(length, type, subtype, subClass);
    169                 }
    170 
    171             case ASI_FORMAT_TYPE:
    172                 return UsbASFormat.allocDescriptor(parser, stream, length, type, subtype, subClass);
    173 
    174             case ASI_FORMAT_SPECIFIC:
    175             case ASI_UNDEFINED:
    176                 // break; Fall through until we implement this descriptor
    177             default:
    178                 Log.w(TAG, "Unknown Audio Streaming Interface subtype:0x"
    179                         + Integer.toHexString(subtype));
    180                 return null;
    181         }
    182     }
    183 
    184     private static UsbDescriptor allocMidiStreamingDescriptor(int length, byte type,
    185             byte subtype, int subClass) {
    186         switch (subtype) {
    187             case MSI_HEADER:
    188                 return new UsbMSMidiHeader(length, type, subtype, subClass);
    189 
    190             case MSI_IN_JACK:
    191                 return new UsbMSMidiInputJack(length, type, subtype, subClass);
    192 
    193             case MSI_OUT_JACK:
    194                 return new UsbMSMidiOutputJack(length, type, subtype, subClass);
    195 
    196             case MSI_ELEMENT:
    197                 // break;
    198                 // Fall through until we implement that descriptor
    199 
    200             case MSI_UNDEFINED:
    201             default:
    202                 Log.w(TAG, "Unknown MIDI Streaming Interface subtype:0x"
    203                         + Integer.toHexString(subtype));
    204                 return null;
    205         }
    206     }
    207 
    208     /**
    209      * Allocates an audio class interface subtype based on subtype and subclass.
    210      */
    211     public static UsbDescriptor allocDescriptor(UsbDescriptorParser parser, ByteStream stream,
    212             int length, byte type) {
    213         byte subtype = stream.getByte();
    214         UsbInterfaceDescriptor interfaceDesc = parser.getCurInterface();
    215         int subClass = interfaceDesc.getUsbSubclass();
    216         switch (subClass) {
    217             case AUDIO_AUDIOCONTROL:
    218                 return allocAudioControlDescriptor(
    219                         parser, stream, length, type, subtype, subClass);
    220 
    221             case AUDIO_AUDIOSTREAMING:
    222                 return allocAudioStreamingDescriptor(
    223                         parser, stream, length, type, subtype, subClass);
    224 
    225             case AUDIO_MIDISTREAMING:
    226                 return allocMidiStreamingDescriptor(length, type, subtype, subClass);
    227 
    228             default:
    229                 Log.w(TAG, "Unknown Audio Class Interface Subclass: 0x"
    230                         + Integer.toHexString(subClass));
    231                 return null;
    232         }
    233     }
    234 
    235     @Override
    236     public void report(ReportCanvas canvas) {
    237         super.report(canvas);
    238 
    239         int subClass = getSubclass();
    240         String subClassName = UsbStrings.getACInterfaceSubclassName(subClass);
    241 
    242         byte subtype = getSubtype();
    243         String subTypeName = UsbStrings.getACControlInterfaceName(subtype);
    244 
    245         canvas.openList();
    246         canvas.writeListItem("Subclass: " + ReportCanvas.getHexString(subClass)
    247                 + " " + subClassName);
    248         canvas.writeListItem("Subtype: " + ReportCanvas.getHexString(subtype) + " " + subTypeName);
    249         canvas.closeList();
    250     }
    251 }
    252