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.UsbEndpoint;
     19 import android.util.Log;
     20 
     21 import com.android.server.usb.descriptors.report.ReportCanvas;
     22 
     23 /**
     24  * @hide
     25  * A Usb Endpoint Descriptor.
     26  * see usb11.pdf section 9.6.4
     27  */
     28 public class UsbEndpointDescriptor extends UsbDescriptor {
     29     private static final String TAG = "UsbEndpointDescriptor";
     30     private static final boolean DEBUG = false;
     31 
     32     public static final int MASK_ENDPOINT_ADDRESS = 0b000000000001111;
     33     public static final int MASK_ENDPOINT_DIRECTION = (byte) 0b0000000010000000;
     34     public static final int DIRECTION_OUTPUT = 0x0000;
     35     public static final int DIRECTION_INPUT = (byte) 0x0080;
     36 
     37     public static final int MASK_ATTRIBS_TRANSTYPE = 0b00000011;
     38     public static final int TRANSTYPE_CONTROL = 0x00;
     39     public static final int TRANSTYPE_ISO = 0x01;
     40     public static final int TRANSTYPE_BULK = 0x02;
     41     public static final int TRANSTYPE_INTERRUPT = 0x03;
     42 
     43     public static final byte MASK_ATTRIBS_SYNCTYPE = 0b00001100;
     44     public static final byte SYNCTYPE_NONE = 0b00000000;
     45     public static final byte SYNCTYPE_ASYNC = 0b00000100;
     46     public static final byte SYNCTYPE_ADAPTSYNC = 0b00001000;
     47     public static final byte SYNCTYPE_RESERVED = 0b00001100;
     48 
     49     public static final int MASK_ATTRIBS_USEAGE = 0b00110000;
     50     public static final int USEAGE_DATA = 0b00000000;
     51     public static final int USEAGE_FEEDBACK = 0b00010000;
     52     public static final int USEAGE_EXPLICIT = 0b00100000;
     53     public static final int USEAGE_RESERVED = 0b00110000;
     54 
     55     private int mEndpointAddress;   // 2:1 Endpoint Address
     56                                     // Bits 0..3b Endpoint Number.
     57                                     // Bits 4..6b Reserved. Set to Zero
     58                                     // Bits 7 Direction 0 = Out, 1 = In
     59                                     // (Ignored for Control Endpoints)
     60     private int mAttributes;    // 3:1 Various flags
     61                                 // Bits 0..1 Transfer Type:
     62                                 //     00 = Control, 01 = Isochronous, 10 = Bulk, 11 = Interrupt
     63                                 // Bits 2..7 are reserved. If Isochronous endpoint,
     64                                 // Bits 3..2 = Synchronisation Type (Iso Mode)
     65                                 //  00 = No Synchonisation
     66                                 //  01 = Asynchronous
     67                                 //  10 = Adaptive
     68                                 //  11 = Synchronous
     69                                 // Bits 5..4 = Usage Type (Iso Mode)
     70                                 //  00: Data Endpoint
     71                                 //  01:Feedback Endpoint 10
     72                                 //  Explicit Feedback Data Endpoint
     73                                 //  11: Reserved
     74     private int mPacketSize;    // 4:2 Maximum Packet Size this endpoint is capable of
     75                                 // sending or receiving
     76     private int mInterval;      // 6:1 Interval for polling endpoint data transfers. Value in
     77                                 // frame counts.
     78                                 // Ignored for Bulk & Control Endpoints. Isochronous must equal
     79                                 // 1 and field may range from 1 to 255 for interrupt endpoints.
     80     private byte mRefresh;
     81     private byte mSyncAddress;
     82 
     83     public UsbEndpointDescriptor(int length, byte type) {
     84         super(length, type);
     85         mHierarchyLevel = 4;
     86     }
     87 
     88     public int getEndpointAddress() {
     89         return mEndpointAddress;
     90     }
     91 
     92     public int getAttributes() {
     93         return mAttributes;
     94     }
     95 
     96     public int getPacketSize() {
     97         return mPacketSize;
     98     }
     99 
    100     public int getInterval() {
    101         return mInterval;
    102     }
    103 
    104     public byte getRefresh() {
    105         return mRefresh;
    106     }
    107 
    108     public byte getSyncAddress() {
    109         return mSyncAddress;
    110     }
    111 
    112     /* package */ UsbEndpoint toAndroid(UsbDescriptorParser parser) {
    113         if (DEBUG) {
    114             Log.d(TAG, "toAndroid() type:"
    115                     + Integer.toHexString(mAttributes & MASK_ATTRIBS_TRANSTYPE)
    116                     + " sync:" + Integer.toHexString(mAttributes & MASK_ATTRIBS_SYNCTYPE)
    117                     + " usage:" + Integer.toHexString(mAttributes & MASK_ATTRIBS_USEAGE));
    118         }
    119         return new UsbEndpoint(mEndpointAddress, mAttributes, mPacketSize, mInterval);
    120     }
    121 
    122     @Override
    123     public int parseRawDescriptors(ByteStream stream) {
    124         mEndpointAddress = stream.getUnsignedByte();
    125         mAttributes = stream.getUnsignedByte();
    126         mPacketSize = stream.unpackUsbShort();
    127         mInterval = stream.getUnsignedByte();
    128         if (mLength == 9) {
    129             mRefresh = stream.getByte();
    130             mSyncAddress = stream.getByte();
    131         }
    132         return mLength;
    133     }
    134 
    135     @Override
    136     public void report(ReportCanvas canvas) {
    137         super.report(canvas);
    138 
    139         canvas.openList();
    140 
    141         int address = getEndpointAddress();
    142         canvas.writeListItem("Address: "
    143                 + ReportCanvas.getHexString(address & UsbEndpointDescriptor.MASK_ENDPOINT_ADDRESS)
    144                 + ((address & UsbEndpointDescriptor.MASK_ENDPOINT_DIRECTION)
    145                 == UsbEndpointDescriptor.DIRECTION_OUTPUT ? " [out]" : " [in]"));
    146 
    147         int attributes = getAttributes();
    148         canvas.openListItem();
    149         canvas.write("Attributes: " + ReportCanvas.getHexString(attributes) + " ");
    150         switch (attributes & UsbEndpointDescriptor.MASK_ATTRIBS_TRANSTYPE) {
    151             case UsbEndpointDescriptor.TRANSTYPE_CONTROL:
    152                 canvas.write("Control");
    153                 break;
    154             case UsbEndpointDescriptor.TRANSTYPE_ISO:
    155                 canvas.write("Iso");
    156                 break;
    157             case UsbEndpointDescriptor.TRANSTYPE_BULK:
    158                 canvas.write("Bulk");
    159                 break;
    160             case UsbEndpointDescriptor.TRANSTYPE_INTERRUPT:
    161                 canvas.write("Interrupt");
    162                 break;
    163         }
    164         canvas.closeListItem();
    165 
    166         // These flags are only relevant for ISO transfer type
    167         if ((attributes & UsbEndpointDescriptor.MASK_ATTRIBS_TRANSTYPE)
    168                 == UsbEndpointDescriptor.TRANSTYPE_ISO) {
    169             canvas.openListItem();
    170             canvas.write("Aync: ");
    171             switch (attributes & UsbEndpointDescriptor.MASK_ATTRIBS_SYNCTYPE) {
    172                 case UsbEndpointDescriptor.SYNCTYPE_NONE:
    173                     canvas.write("NONE");
    174                     break;
    175                 case UsbEndpointDescriptor.SYNCTYPE_ASYNC:
    176                     canvas.write("ASYNC");
    177                     break;
    178                 case UsbEndpointDescriptor.SYNCTYPE_ADAPTSYNC:
    179                     canvas.write("ADAPTIVE ASYNC");
    180                     break;
    181             }
    182             canvas.closeListItem();
    183 
    184             canvas.openListItem();
    185             canvas.write("Useage: ");
    186             switch (attributes & UsbEndpointDescriptor.MASK_ATTRIBS_USEAGE) {
    187                 case UsbEndpointDescriptor.USEAGE_DATA:
    188                     canvas.write("DATA");
    189                     break;
    190                 case UsbEndpointDescriptor.USEAGE_FEEDBACK:
    191                     canvas.write("FEEDBACK");
    192                     break;
    193                 case UsbEndpointDescriptor.USEAGE_EXPLICIT:
    194                     canvas.write("EXPLICIT FEEDBACK");
    195                     break;
    196                 case UsbEndpointDescriptor.USEAGE_RESERVED:
    197                     canvas.write("RESERVED");
    198                     break;
    199             }
    200             canvas.closeListItem();
    201         }
    202         canvas.writeListItem("Package Size: " + getPacketSize());
    203         canvas.writeListItem("Interval: " + getInterval());
    204         canvas.closeList();
    205     }
    206 }
    207