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