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