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