UsbEndpointDescriptor.java revision f25c4eb7fdf89e8a012c92c585c988fe1b410b2c
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 android.hardware.usb.UsbEndpoint;
19import android.util.Log;
20
21import 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 */
28public 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