blob: 4da31ea469c392521c7f92bb049a6e3896e78498 [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.usb.descriptors;
import android.hardware.usb.UsbEndpoint;
import android.util.Log;
import com.android.server.usb.descriptors.report.ReportCanvas;
/**
* @hide
* A Usb Endpoint Descriptor.
* see usb11.pdf section 9.6.4
*/
public class UsbEndpointDescriptor extends UsbDescriptor {
private static final String TAG = "UsbEndpointDescriptor";
private static final boolean DEBUG = false;
public static final int MASK_ENDPOINT_ADDRESS = 0b000000000001111;
public static final int MASK_ENDPOINT_DIRECTION = (byte) 0b0000000010000000;
public static final int DIRECTION_OUTPUT = 0x0000;
public static final int DIRECTION_INPUT = (byte) 0x0080;
public static final int MASK_ATTRIBS_TRANSTYPE = 0b00000011;
public static final int TRANSTYPE_CONTROL = 0x00;
public static final int TRANSTYPE_ISO = 0x01;
public static final int TRANSTYPE_BULK = 0x02;
public static final int TRANSTYPE_INTERRUPT = 0x03;
public static final byte MASK_ATTRIBS_SYNCTYPE = 0b00001100;
public static final byte SYNCTYPE_NONE = 0b00000000;
public static final byte SYNCTYPE_ASYNC = 0b00000100;
public static final byte SYNCTYPE_ADAPTSYNC = 0b00001000;
public static final byte SYNCTYPE_RESERVED = 0b00001100;
public static final int MASK_ATTRIBS_USEAGE = 0b00110000;
public static final int USEAGE_DATA = 0b00000000;
public static final int USEAGE_FEEDBACK = 0b00010000;
public static final int USEAGE_EXPLICIT = 0b00100000;
public static final int USEAGE_RESERVED = 0b00110000;
private int mEndpointAddress; // 2:1 Endpoint Address
// Bits 0..3b Endpoint Number.
// Bits 4..6b Reserved. Set to Zero
// Bits 7 Direction 0 = Out, 1 = In
// (Ignored for Control Endpoints)
private int mAttributes; // 3:1 Various flags
// Bits 0..1 Transfer Type:
// 00 = Control, 01 = Isochronous, 10 = Bulk, 11 = Interrupt
// Bits 2..7 are reserved. If Isochronous endpoint,
// Bits 3..2 = Synchronisation Type (Iso Mode)
// 00 = No Synchonisation
// 01 = Asynchronous
// 10 = Adaptive
// 11 = Synchronous
// Bits 5..4 = Usage Type (Iso Mode)
// 00: Data Endpoint
// 01:Feedback Endpoint 10
// Explicit Feedback Data Endpoint
// 11: Reserved
private int mPacketSize; // 4:2 Maximum Packet Size this endpoint is capable of
// sending or receiving
private int mInterval; // 6:1 Interval for polling endpoint data transfers. Value in
// frame counts.
// Ignored for Bulk & Control Endpoints. Isochronous must equal
// 1 and field may range from 1 to 255 for interrupt endpoints.
private byte mRefresh;
private byte mSyncAddress;
public UsbEndpointDescriptor(int length, byte type) {
super(length, type);
mHierarchyLevel = 4;
}
public int getEndpointAddress() {
return mEndpointAddress;
}
public int getAttributes() {
return mAttributes;
}
public int getPacketSize() {
return mPacketSize;
}
public int getInterval() {
return mInterval;
}
public byte getRefresh() {
return mRefresh;
}
public byte getSyncAddress() {
return mSyncAddress;
}
/* package */ UsbEndpoint toAndroid(UsbDescriptorParser parser) {
if (DEBUG) {
Log.d(TAG, "toAndroid() type:"
+ Integer.toHexString(mAttributes & MASK_ATTRIBS_TRANSTYPE)
+ " sync:" + Integer.toHexString(mAttributes & MASK_ATTRIBS_SYNCTYPE)
+ " usage:" + Integer.toHexString(mAttributes & MASK_ATTRIBS_USEAGE));
}
return new UsbEndpoint(mEndpointAddress, mAttributes, mPacketSize, mInterval);
}
@Override
public int parseRawDescriptors(ByteStream stream) {
mEndpointAddress = stream.getUnsignedByte();
mAttributes = stream.getUnsignedByte();
mPacketSize = stream.unpackUsbShort();
mInterval = stream.getUnsignedByte();
if (mLength == 9) {
mRefresh = stream.getByte();
mSyncAddress = stream.getByte();
}
return mLength;
}
@Override
public void report(ReportCanvas canvas) {
super.report(canvas);
canvas.openList();
int address = getEndpointAddress();
canvas.writeListItem("Address: "
+ ReportCanvas.getHexString(address & UsbEndpointDescriptor.MASK_ENDPOINT_ADDRESS)
+ ((address & UsbEndpointDescriptor.MASK_ENDPOINT_DIRECTION)
== UsbEndpointDescriptor.DIRECTION_OUTPUT ? " [out]" : " [in]"));
int attributes = getAttributes();
canvas.openListItem();
canvas.write("Attributes: " + ReportCanvas.getHexString(attributes) + " ");
switch (attributes & UsbEndpointDescriptor.MASK_ATTRIBS_TRANSTYPE) {
case UsbEndpointDescriptor.TRANSTYPE_CONTROL:
canvas.write("Control");
break;
case UsbEndpointDescriptor.TRANSTYPE_ISO:
canvas.write("Iso");
break;
case UsbEndpointDescriptor.TRANSTYPE_BULK:
canvas.write("Bulk");
break;
case UsbEndpointDescriptor.TRANSTYPE_INTERRUPT:
canvas.write("Interrupt");
break;
}
canvas.closeListItem();
// These flags are only relevant for ISO transfer type
if ((attributes & UsbEndpointDescriptor.MASK_ATTRIBS_TRANSTYPE)
== UsbEndpointDescriptor.TRANSTYPE_ISO) {
canvas.openListItem();
canvas.write("Aync: ");
switch (attributes & UsbEndpointDescriptor.MASK_ATTRIBS_SYNCTYPE) {
case UsbEndpointDescriptor.SYNCTYPE_NONE:
canvas.write("NONE");
break;
case UsbEndpointDescriptor.SYNCTYPE_ASYNC:
canvas.write("ASYNC");
break;
case UsbEndpointDescriptor.SYNCTYPE_ADAPTSYNC:
canvas.write("ADAPTIVE ASYNC");
break;
}
canvas.closeListItem();
canvas.openListItem();
canvas.write("Useage: ");
switch (attributes & UsbEndpointDescriptor.MASK_ATTRIBS_USEAGE) {
case UsbEndpointDescriptor.USEAGE_DATA:
canvas.write("DATA");
break;
case UsbEndpointDescriptor.USEAGE_FEEDBACK:
canvas.write("FEEDBACK");
break;
case UsbEndpointDescriptor.USEAGE_EXPLICIT:
canvas.write("EXPLICIT FEEDBACK");
break;
case UsbEndpointDescriptor.USEAGE_RESERVED:
canvas.write("RESERVED");
break;
}
canvas.closeListItem();
}
canvas.writeListItem("Package Size: " + getPacketSize());
canvas.writeListItem("Interval: " + getInterval());
canvas.closeList();
}
}