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.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 
     57     UsbDeviceDescriptor(int length, byte type) {
     58         super(length, type);
     59         mHierarchyLevel = 1;
     60     }
     61 
     62     public int getSpec() {
     63         return mSpec;
     64     }
     65 
     66     public int getDevClass() {
     67         return mDevClass;
     68     }
     69 
     70     public int getDevSubClass() {
     71         return mDevSubClass;
     72     }
     73 
     74     public int getProtocol() {
     75         return mProtocol;
     76     }
     77 
     78     public byte getPacketSize() {
     79         return mPacketSize;
     80     }
     81 
     82     public int getVendorID() {
     83         return mVendorID;
     84     }
     85 
     86     public int getProductID() {
     87         return mProductID;
     88     }
     89 
     90     public int getDeviceRelease() {
     91         return mDeviceRelease;
     92     }
     93 
     94     // mDeviceRelease is binary-coded decimal, format DD.DD
     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 
    103     public byte getMfgIndex() {
    104         return mMfgIndex;
    105     }
    106 
    107     public String getMfgString(UsbDescriptorParser p) {
    108         return p.getDescriptorString(mMfgIndex);
    109     }
    110 
    111     public byte getProductIndex() {
    112         return mProductIndex;
    113     }
    114 
    115     public String getProductString(UsbDescriptorParser p) {
    116         return p.getDescriptorString(mProductIndex);
    117     }
    118 
    119     public byte getSerialIndex() {
    120         return mSerialIndex;
    121     }
    122 
    123     public String getSerialString(UsbDescriptorParser p) {
    124         return p.getDescriptorString(mSerialIndex);
    125     }
    126 
    127     public byte getNumConfigs() {
    128         return mNumConfigs;
    129     }
    130 
    131     void addConfigDescriptor(UsbConfigDescriptor config) {
    132         mConfigDescriptors.add(config);
    133     }
    134 
    135     /**
    136      * @hide
    137      */
    138     public UsbDevice 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         UsbDevice device = new UsbDevice(parser.getDeviceAddr(), mVendorID, mProductID,
    156                 mDevClass, mDevSubClass,
    157                 mProtocol, mfgName, prodName,
    158                 versionString, serialStr);
    159         UsbConfiguration[] configs = new UsbConfiguration[mConfigDescriptors.size()];
    160         Log.d(TAG, "  " + configs.length + " configs");
    161         for (int index = 0; index < mConfigDescriptors.size(); index++) {
    162             configs[index] = mConfigDescriptors.get(index).toAndroid(parser);
    163         }
    164         device.setConfigurations(configs);
    165 
    166         return device;
    167     }
    168 
    169     @Override
    170     public int parseRawDescriptors(ByteStream stream) {
    171         mSpec = stream.unpackUsbShort();
    172         mDevClass = stream.getUnsignedByte();
    173         mDevSubClass = stream.getUnsignedByte();
    174         mProtocol = stream.getUnsignedByte();
    175         mPacketSize = stream.getByte();
    176         mVendorID = stream.unpackUsbShort();
    177         mProductID = stream.unpackUsbShort();
    178         mDeviceRelease = stream.unpackUsbShort();
    179         mMfgIndex = stream.getByte();
    180         mProductIndex = stream.getByte();
    181         mSerialIndex = stream.getByte();
    182         mNumConfigs = stream.getByte();
    183 
    184         return mLength;
    185     }
    186 
    187     @Override
    188     public void report(ReportCanvas canvas) {
    189         super.report(canvas);
    190 
    191         canvas.openList();
    192 
    193         int spec = getSpec();
    194         canvas.writeListItem("Spec: " + ReportCanvas.getBCDString(spec));
    195 
    196         int devClass = getDevClass();
    197         String classStr = UsbStrings.getClassName(devClass);
    198         int devSubClass = getDevSubClass();
    199         String subClasStr = UsbStrings.getClassName(devSubClass);
    200         canvas.writeListItem("Class " + devClass + ": " + classStr + " Subclass"
    201                 + devSubClass + ": " + subClasStr);
    202         canvas.writeListItem("Vendor ID: " + ReportCanvas.getHexString(getVendorID())
    203                 + " Product ID: " + ReportCanvas.getHexString(getProductID())
    204                 + " Product Release: " + ReportCanvas.getBCDString(getDeviceRelease()));
    205 
    206         UsbDescriptorParser parser = canvas.getParser();
    207         byte mfgIndex = getMfgIndex();
    208         String manufacturer = parser.getDescriptorString(mfgIndex);
    209         byte productIndex = getProductIndex();
    210         String product = parser.getDescriptorString(productIndex);
    211 
    212         canvas.writeListItem("Manufacturer " + mfgIndex + ": " + manufacturer
    213                 + " Product " + productIndex + ": " + product);
    214         canvas.closeList();
    215     }
    216 }
    217