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