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.hardware.usb.UsbEndpoint;
19 import android.hardware.usb.UsbInterface;
20 import android.util.Log;
21 
22 import com.android.server.usb.descriptors.report.ReportCanvas;
23 import com.android.server.usb.descriptors.report.UsbStrings;
24 
25 import java.util.ArrayList;
26 
27 /**
28  * @hide
29  * A common super-class for all USB Interface Descritor subtypes.
30  * see usb11.pdf section 9.6.3
31  */
32 public class UsbInterfaceDescriptor extends UsbDescriptor {
33     private static final String TAG = "UsbInterfaceDescriptor";
34     protected int mInterfaceNumber;   // 2:1 Number of Interface
35     protected byte mAlternateSetting; // 3:1 Value used to select alternative setting
36     protected byte mNumEndpoints;     // 4:1 Number of Endpoints used for this interface
37     protected int mUsbClass;          // 5:1 Class Code
38     protected int mUsbSubclass;       // 6:1 Subclass Code
39     protected int mProtocol;          // 7:1 Protocol Code
40     protected byte mDescrIndex;       // 8:1 Index of String Descriptor Describing this interface
41 
42     private ArrayList<UsbEndpointDescriptor> mEndpointDescriptors =
43             new ArrayList<UsbEndpointDescriptor>();
44 
45     // Used for MIDI only.
46     private UsbDescriptor mMidiHeaderInterfaceDescriptor;
47 
UsbInterfaceDescriptor(int length, byte type)48     UsbInterfaceDescriptor(int length, byte type) {
49         super(length, type);
50         mHierarchyLevel = 3;
51     }
52 
53     @Override
parseRawDescriptors(ByteStream stream)54     public int parseRawDescriptors(ByteStream stream) {
55         mInterfaceNumber = stream.getUnsignedByte();
56         mAlternateSetting = stream.getByte();
57         mNumEndpoints = stream.getByte();
58         mUsbClass = stream.getUnsignedByte();
59         mUsbSubclass = stream.getUnsignedByte();
60         mProtocol = stream.getUnsignedByte();
61         mDescrIndex = stream.getByte();
62 
63         return mLength;
64     }
65 
getInterfaceNumber()66     public int getInterfaceNumber() {
67         return mInterfaceNumber;
68     }
69 
getAlternateSetting()70     public byte getAlternateSetting() {
71         return mAlternateSetting;
72     }
73 
getNumEndpoints()74     public byte getNumEndpoints() {
75         return mNumEndpoints;
76     }
77 
78     /**
79      * @param index Index of desired UsbEndpointDescriptor.
80      * @return the UsbEndpointDescriptor descriptor at the specified index, or
81      *  null if an invalid index.
82      */
getEndpointDescriptor(int index)83     public UsbEndpointDescriptor getEndpointDescriptor(int index) {
84         if (index < 0 || index >= mEndpointDescriptors.size()) {
85             return null;
86         }
87 
88         return mEndpointDescriptors.get(index);
89     }
90 
getUsbClass()91     public int getUsbClass() {
92         return mUsbClass;
93     }
94 
getUsbSubclass()95     public int getUsbSubclass() {
96         return mUsbSubclass;
97     }
98 
getProtocol()99     public int getProtocol() {
100         return mProtocol;
101     }
102 
getDescrIndex()103     public byte getDescrIndex() {
104         return mDescrIndex;
105     }
106 
addEndpointDescriptor(UsbEndpointDescriptor endpoint)107     void addEndpointDescriptor(UsbEndpointDescriptor endpoint) {
108         mEndpointDescriptors.add(endpoint);
109     }
110 
setMidiHeaderInterfaceDescriptor(UsbDescriptor descriptor)111     public void setMidiHeaderInterfaceDescriptor(UsbDescriptor descriptor) {
112         mMidiHeaderInterfaceDescriptor = descriptor;
113     }
114 
getMidiHeaderInterfaceDescriptor()115     public UsbDescriptor getMidiHeaderInterfaceDescriptor() {
116         return mMidiHeaderInterfaceDescriptor;
117     }
118 
119     /**
120     * Returns a UsbInterface that this UsbInterfaceDescriptor is describing.
121     */
toAndroid(UsbDescriptorParser parser)122     public UsbInterface toAndroid(UsbDescriptorParser parser) {
123         if (UsbDescriptorParser.DEBUG) {
124             Log.d(TAG, "toAndroid() class:" + Integer.toHexString(mUsbClass)
125                     + " subclass:" + Integer.toHexString(mUsbSubclass)
126                     + " " + mEndpointDescriptors.size() + " endpoints.");
127         }
128         String name = parser.getDescriptorString(mDescrIndex);
129         UsbInterface ntrface = new UsbInterface(
130                 mInterfaceNumber, mAlternateSetting, name, mUsbClass, mUsbSubclass, mProtocol);
131         UsbEndpoint[] endpoints = new UsbEndpoint[mEndpointDescriptors.size()];
132         for (int index = 0; index < mEndpointDescriptors.size(); index++) {
133             endpoints[index] = mEndpointDescriptors.get(index).toAndroid(parser);
134         }
135         ntrface.setEndpoints(endpoints);
136         return ntrface;
137     }
138 
139     @Override
report(ReportCanvas canvas)140     public void report(ReportCanvas canvas) {
141         super.report(canvas);
142 
143         int usbClass = getUsbClass();
144         int usbSubclass = getUsbSubclass();
145         int protocol = getProtocol();
146         String className = UsbStrings.getClassName(usbClass);
147         String subclassName = "";
148         if (usbClass == UsbDescriptor.CLASSID_AUDIO) {
149             subclassName = UsbStrings.getAudioSubclassName(usbSubclass);
150         }
151 
152         canvas.openList();
153         canvas.writeListItem("Interface #" + getInterfaceNumber());
154         canvas.writeListItem("Class: " + ReportCanvas.getHexString(usbClass) + ": " + className);
155         canvas.writeListItem("Subclass: "
156                 + ReportCanvas.getHexString(usbSubclass) + ": " + subclassName);
157         canvas.writeListItem("Protocol: " + protocol + ": " + ReportCanvas.getHexString(protocol));
158         canvas.writeListItem("Endpoints: " + getNumEndpoints());
159         canvas.closeList();
160     }
161 }
162