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.UsbConfiguration; 19 import android.hardware.usb.UsbDevice; 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 USB Device Descriptor. 30 * see usb11.pdf section 9.6.1 31 */ 32 public final class UsbDeviceDescriptor extends UsbDescriptor { 33 private static final String TAG = "UsbDeviceDescriptor"; 34 35 public static final int USBSPEC_1_0 = 0x0100; 36 public static final int USBSPEC_1_1 = 0x0110; 37 public static final int USBSPEC_2_0 = 0x0200; 38 39 private int mSpec; // 2:2 bcdUSB 2 BCD USB Specification Number - BCD 40 private int mDevClass; // 4:1 class code 41 private int mDevSubClass; // 5:1 subclass code 42 private int mProtocol; // 6:1 protocol 43 private byte mPacketSize; // 7:1 Maximum Packet Size for Zero Endpoint. 44 // Valid Sizes are 8, 16, 32, 64 45 private int mVendorID; // 8:2 vendor ID 46 private int mProductID; // 10:2 product ID 47 private int mDeviceRelease; // 12:2 Device Release number - BCD 48 private byte mMfgIndex; // 14:1 Index of Manufacturer String Descriptor 49 private byte mProductIndex; // 15:1 Index of Product String Descriptor 50 private byte mSerialIndex; // 16:1 Index of Serial Number String Descriptor 51 private byte mNumConfigs; // 17:1 Number of Possible Configurations 52 53 private ArrayList<UsbConfigDescriptor> mConfigDescriptors = 54 new ArrayList<UsbConfigDescriptor>(); 55 UsbDeviceDescriptor(int length, byte type)56 UsbDeviceDescriptor(int length, byte type) { 57 super(length, type); 58 mHierarchyLevel = 1; 59 } 60 getSpec()61 public int getSpec() { 62 return mSpec; 63 } 64 getDevClass()65 public int getDevClass() { 66 return mDevClass; 67 } 68 getDevSubClass()69 public int getDevSubClass() { 70 return mDevSubClass; 71 } 72 getProtocol()73 public int getProtocol() { 74 return mProtocol; 75 } 76 getPacketSize()77 public byte getPacketSize() { 78 return mPacketSize; 79 } 80 getVendorID()81 public int getVendorID() { 82 return mVendorID; 83 } 84 getProductID()85 public int getProductID() { 86 return mProductID; 87 } 88 getDeviceRelease()89 public int getDeviceRelease() { 90 return mDeviceRelease; 91 } 92 93 // mDeviceRelease is binary-coded decimal, format DD.DD getDeviceReleaseString()94 public String getDeviceReleaseString() { 95 int hundredths = mDeviceRelease & 0xF; 96 int tenths = (mDeviceRelease & 0xF0) >> 4; 97 int ones = (mDeviceRelease & 0xF00) >> 8; 98 int tens = (mDeviceRelease & 0xF000) >> 12; 99 return String.format("%d.%d%d", tens * 10 + ones, tenths, hundredths); 100 } 101 getMfgIndex()102 public byte getMfgIndex() { 103 return mMfgIndex; 104 } 105 getMfgString(UsbDescriptorParser p)106 public String getMfgString(UsbDescriptorParser p) { 107 return p.getDescriptorString(mMfgIndex); 108 } 109 getProductIndex()110 public byte getProductIndex() { 111 return mProductIndex; 112 } 113 getProductString(UsbDescriptorParser p)114 public String getProductString(UsbDescriptorParser p) { 115 return p.getDescriptorString(mProductIndex); 116 } 117 getSerialIndex()118 public byte getSerialIndex() { 119 return mSerialIndex; 120 } 121 getSerialString(UsbDescriptorParser p)122 public String getSerialString(UsbDescriptorParser p) { 123 return p.getDescriptorString(mSerialIndex); 124 } 125 getNumConfigs()126 public byte getNumConfigs() { 127 return mNumConfigs; 128 } 129 addConfigDescriptor(UsbConfigDescriptor config)130 void addConfigDescriptor(UsbConfigDescriptor config) { 131 mConfigDescriptors.add(config); 132 } 133 134 /** 135 * @hide 136 */ toAndroid(UsbDescriptorParser parser)137 public UsbDevice.Builder toAndroid(UsbDescriptorParser parser) { 138 if (UsbDescriptorParser.DEBUG) { 139 Log.d(TAG, "toAndroid()"); 140 } 141 142 String mfgName = getMfgString(parser); 143 String prodName = getProductString(parser); 144 if (UsbDescriptorParser.DEBUG) { 145 Log.d(TAG, " mfgName:" + mfgName + " prodName:" + prodName); 146 } 147 148 String versionString = getDeviceReleaseString(); 149 String serialStr = getSerialString(parser); 150 if (UsbDescriptorParser.DEBUG) { 151 Log.d(TAG, " versionString:" + versionString + " serialStr:" + serialStr); 152 } 153 154 UsbConfiguration[] configs = new UsbConfiguration[mConfigDescriptors.size()]; 155 Log.d(TAG, " " + configs.length + " configs"); 156 for (int index = 0; index < mConfigDescriptors.size(); index++) { 157 configs[index] = mConfigDescriptors.get(index).toAndroid(parser); 158 } 159 160 return new UsbDevice.Builder(parser.getDeviceAddr(), mVendorID, 161 mProductID, mDevClass, mDevSubClass, mProtocol, mfgName, prodName, versionString, 162 configs, serialStr, parser.hasAudioPlayback(), parser.hasAudioCapture(), 163 parser.hasMIDIInterface(), 164 parser.hasVideoPlayback(), parser.hasVideoCapture()); 165 } 166 167 @Override parseRawDescriptors(ByteStream stream)168 public int parseRawDescriptors(ByteStream stream) { 169 mSpec = stream.unpackUsbShort(); 170 mDevClass = stream.getUnsignedByte(); 171 mDevSubClass = stream.getUnsignedByte(); 172 mProtocol = stream.getUnsignedByte(); 173 mPacketSize = stream.getByte(); 174 mVendorID = stream.unpackUsbShort(); 175 mProductID = stream.unpackUsbShort(); 176 mDeviceRelease = stream.unpackUsbShort(); 177 mMfgIndex = stream.getByte(); 178 mProductIndex = stream.getByte(); 179 mSerialIndex = stream.getByte(); 180 mNumConfigs = stream.getByte(); 181 182 return mLength; 183 } 184 185 @Override report(ReportCanvas canvas)186 public void report(ReportCanvas canvas) { 187 super.report(canvas); 188 189 canvas.openList(); 190 191 int spec = getSpec(); 192 canvas.writeListItem("Spec: " + ReportCanvas.getBCDString(spec)); 193 194 int devClass = getDevClass(); 195 String classStr = UsbStrings.getClassName(devClass); 196 int devSubClass = getDevSubClass(); 197 String subClasStr = UsbStrings.getClassName(devSubClass); 198 canvas.writeListItem("Class " + devClass + ": " + classStr + " Subclass" 199 + devSubClass + ": " + subClasStr); 200 canvas.writeListItem("Vendor ID: " + ReportCanvas.getHexString(getVendorID()) 201 + " Product ID: " + ReportCanvas.getHexString(getProductID()) 202 + " Product Release: " + ReportCanvas.getBCDString(getDeviceRelease())); 203 204 UsbDescriptorParser parser = canvas.getParser(); 205 byte mfgIndex = getMfgIndex(); 206 String manufacturer = parser.getDescriptorString(mfgIndex); 207 byte productIndex = getProductIndex(); 208 String product = parser.getDescriptorString(productIndex); 209 210 canvas.writeListItem("Manufacturer " + mfgIndex + ": " + manufacturer 211 + " Product " + productIndex + ": " + product); 212 canvas.closeList(); 213 } 214 } 215