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.UsbConfiguration;
19 import android.hardware.usb.UsbInterface;
20 import android.util.Log;
21 
22 import com.android.server.usb.descriptors.report.ReportCanvas;
23 
24 import java.util.ArrayList;
25 
26 /**
27  * @hide
28  * An USB Config Descriptor.
29  * see usb11.pdf section 9.6.2
30  */
31 public final class UsbConfigDescriptor extends UsbDescriptor {
32     private static final String TAG = "UsbConfigDescriptor";
33 
34     private int mTotalLength;    // 2:2 Total length in bytes of data returned
35     private byte mNumInterfaces; // 4:1 Number of Interfaces
36     private int mConfigValue;    // 5:1 Value to use as an argument to select this configuration
37     private byte mConfigIndex;   // 6:1 Index of String Descriptor describing this configuration
38     private int mAttribs;        // 7:1 D7 Reserved, set to 1. (USB 1.0 Bus Powered)
39                                  //     D6 Self Powered
40                                  //     D5 Remote Wakeup
41                                  //     D4..0 Reserved, set to 0.
42     private int mMaxPower;       // 8:1 Maximum Power Consumption in 2mA units
43 
44     private boolean mBlockAudio; // leave it off for now. We be replace with a "Developer Option"
45 
46     private ArrayList<UsbInterfaceDescriptor> mInterfaceDescriptors =
47             new ArrayList<UsbInterfaceDescriptor>();
48 
UsbConfigDescriptor(int length, byte type)49     UsbConfigDescriptor(int length, byte type) {
50         super(length, type);
51         mHierarchyLevel = 2;
52     }
53 
getTotalLength()54     public int getTotalLength() {
55         return mTotalLength;
56     }
57 
getNumInterfaces()58     public byte getNumInterfaces() {
59         return mNumInterfaces;
60     }
61 
getConfigValue()62     public int getConfigValue() {
63         return mConfigValue;
64     }
65 
getConfigIndex()66     public byte getConfigIndex() {
67         return mConfigIndex;
68     }
69 
getAttribs()70     public int getAttribs() {
71         return mAttribs;
72     }
73 
getMaxPower()74     public int getMaxPower() {
75         return mMaxPower;
76     }
77 
addInterfaceDescriptor(UsbInterfaceDescriptor interfaceDesc)78     void addInterfaceDescriptor(UsbInterfaceDescriptor interfaceDesc) {
79         mInterfaceDescriptors.add(interfaceDesc);
80     }
81 
getInterfaceDescriptors()82     ArrayList<UsbInterfaceDescriptor> getInterfaceDescriptors() {
83         return mInterfaceDescriptors;
84     }
85 
isAudioInterface(UsbInterfaceDescriptor descriptor)86     private boolean isAudioInterface(UsbInterfaceDescriptor descriptor) {
87         return descriptor.getUsbClass() == UsbDescriptor.CLASSID_AUDIO
88                 && descriptor.getUsbSubclass() == UsbDescriptor.AUDIO_AUDIOSTREAMING;
89     }
90 
toAndroid(UsbDescriptorParser parser)91     UsbConfiguration toAndroid(UsbDescriptorParser parser) {
92         if (UsbDescriptorParser.DEBUG) {
93             Log.d(TAG, "  toAndroid()");
94         }
95 
96         // NOTE - This code running in the server process.
97         //TODO (pmclean@) - remove this
98 //        int pid = android.os.Process.myPid();
99 //        int uid = android.os.Process.myUid();
100 //        Log.d(TAG, "  ---- pid:" + pid + " uid:" + uid);
101 
102         String name = parser.getDescriptorString(mConfigIndex);
103         UsbConfiguration config = new
104                 UsbConfiguration(mConfigValue, name, mAttribs, mMaxPower);
105 
106         ArrayList<UsbInterface> filteredInterfaces = new ArrayList<UsbInterface>();
107         for (UsbInterfaceDescriptor descriptor : mInterfaceDescriptors) {
108             if (!mBlockAudio || !isAudioInterface(descriptor)) {
109                 filteredInterfaces.add(descriptor.toAndroid(parser));
110             }
111         }
112         UsbInterface[] interfaceArray = new UsbInterface[0];
113         interfaceArray = filteredInterfaces.toArray(interfaceArray);
114         config.setInterfaces(interfaceArray);
115         return config;
116     }
117 
118     @Override
parseRawDescriptors(ByteStream stream)119     public int parseRawDescriptors(ByteStream stream) {
120         mTotalLength = stream.unpackUsbShort();
121         mNumInterfaces = stream.getByte();
122         mConfigValue = stream.getUnsignedByte();
123         mConfigIndex = stream.getByte();
124         mAttribs = stream.getUnsignedByte();
125         mMaxPower = stream.getUnsignedByte();
126 
127         return mLength;
128     }
129 
130     @Override
report(ReportCanvas canvas)131     public void report(ReportCanvas canvas) {
132         super.report(canvas);
133 
134         canvas.openList();
135         canvas.writeListItem("Config # " + getConfigValue());
136         canvas.writeListItem(getNumInterfaces() + " Interfaces.");
137         canvas.writeListItem("Attributes: " + ReportCanvas.getHexString(getAttribs()));
138         canvas.closeList();
139     }
140 }
141