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 private static final boolean DEBUG = false; 35 36 public static final int USBSPEC_1_0 = 0x0100; 37 public static final int USBSPEC_1_1 = 0x0110; 38 public static final int USBSPEC_2_0 = 0x0200; 39 40 private int mSpec; // 2:2 bcdUSB 2 BCD USB Specification Number - BCD 41 private int mDevClass; // 4:1 class code 42 private int mDevSubClass; // 5:1 subclass code 43 private int mProtocol; // 6:1 protocol 44 private byte mPacketSize; // 7:1 Maximum Packet Size for Zero Endpoint. 45 // Valid Sizes are 8, 16, 32, 64 46 private int mVendorID; // 8:2 vendor ID 47 private int mProductID; // 10:2 product ID 48 private int mDeviceRelease; // 12:2 Device Release number - BCD 49 private byte mMfgIndex; // 14:1 Index of Manufacturer String Descriptor 50 private byte mProductIndex; // 15:1 Index of Product String Descriptor 51 private byte mSerialIndex; // 16:1 Index of Serial Number String Descriptor 52 private byte mNumConfigs; // 17:1 Number of Possible Configurations 53 54 private ArrayList<UsbConfigDescriptor> mConfigDescriptors = 55 new ArrayList<UsbConfigDescriptor>(); 56 UsbDeviceDescriptor(int length, byte type)57 UsbDeviceDescriptor(int length, byte type) { 58 super(length, type); 59 mHierarchyLevel = 1; 60 } 61 getSpec()62 public int getSpec() { 63 return mSpec; 64 } 65 getDevClass()66 public int getDevClass() { 67 return mDevClass; 68 } 69 getDevSubClass()70 public int getDevSubClass() { 71 return mDevSubClass; 72 } 73 getProtocol()74 public int getProtocol() { 75 return mProtocol; 76 } 77 getPacketSize()78 public byte getPacketSize() { 79 return mPacketSize; 80 } 81 getVendorID()82 public int getVendorID() { 83 return mVendorID; 84 } 85 getProductID()86 public int getProductID() { 87 return mProductID; 88 } 89 getDeviceRelease()90 public int getDeviceRelease() { 91 return mDeviceRelease; 92 } 93 94 // mDeviceRelease is binary-coded decimal, format DD.DD getDeviceReleaseString()95 public String getDeviceReleaseString() { 96 int hundredths = mDeviceRelease & 0xF; 97 int tenths = (mDeviceRelease & 0xF0) >> 4; 98 int ones = (mDeviceRelease & 0xF00) >> 8; 99 int tens = (mDeviceRelease & 0xF000) >> 12; 100 return String.format("%d.%d%d", tens * 10 + ones, tenths, hundredths); 101 } 102 getMfgIndex()103 public byte getMfgIndex() { 104 return mMfgIndex; 105 } 106 getMfgString(UsbDescriptorParser p)107 public String getMfgString(UsbDescriptorParser p) { 108 return p.getDescriptorString(mMfgIndex); 109 } 110 getProductIndex()111 public byte getProductIndex() { 112 return mProductIndex; 113 } 114 getProductString(UsbDescriptorParser p)115 public String getProductString(UsbDescriptorParser p) { 116 return p.getDescriptorString(mProductIndex); 117 } 118 getSerialIndex()119 public byte getSerialIndex() { 120 return mSerialIndex; 121 } 122 getSerialString(UsbDescriptorParser p)123 public String getSerialString(UsbDescriptorParser p) { 124 return p.getDescriptorString(mSerialIndex); 125 } 126 getNumConfigs()127 public byte getNumConfigs() { 128 return mNumConfigs; 129 } 130 addConfigDescriptor(UsbConfigDescriptor config)131 void addConfigDescriptor(UsbConfigDescriptor config) { 132 mConfigDescriptors.add(config); 133 } 134 135 /** 136 * @hide 137 */ toAndroid(UsbDescriptorParser parser)138 public UsbDevice.Builder toAndroid(UsbDescriptorParser parser) { 139 if (DEBUG) { 140 Log.d(TAG, "toAndroid()"); 141 } 142 143 String mfgName = getMfgString(parser); 144 String prodName = getProductString(parser); 145 if (DEBUG) { 146 Log.d(TAG, " mfgName:" + mfgName + " prodName:" + prodName); 147 } 148 149 String versionString = getDeviceReleaseString(); 150 String serialStr = getSerialString(parser); 151 if (DEBUG) { 152 Log.d(TAG, " versionString:" + versionString + " serialStr:" + serialStr); 153 } 154 155 UsbConfiguration[] configs = new UsbConfiguration[mConfigDescriptors.size()]; 156 Log.d(TAG, " " + configs.length + " configs"); 157 for (int index = 0; index < mConfigDescriptors.size(); index++) { 158 configs[index] = mConfigDescriptors.get(index).toAndroid(parser); 159 } 160 UsbDevice.Builder device = new UsbDevice.Builder(parser.getDeviceAddr(), mVendorID, 161 mProductID, mDevClass, mDevSubClass, mProtocol, mfgName, prodName, versionString, 162 configs, serialStr); 163 164 return device; 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