1 /*
2  * Copyright (C) 2015 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 
17 package android.hardware.usb;
18 
19 import android.hardware.usb.V1_0.Constants;
20 import android.os.Parcel;
21 import android.os.Parcelable;
22 
23 import com.android.internal.util.Preconditions;
24 
25 /**
26  * Represents a physical USB port and describes its characteristics.
27  * <p>
28  * This object is immutable.
29  * </p>
30  *
31  * @hide
32  */
33 public final class UsbPort implements Parcelable {
34     private final String mId;
35     private final int mSupportedModes;
36 
37     public static final int MODE_NONE = Constants.PortMode.NONE;
38     /**
39      * Mode bit: This USB port can act as a downstream facing port (host).
40      * <p>
41      * Implies that the port supports the {@link #POWER_ROLE_SOURCE} and {@link #DATA_ROLE_HOST}
42      * combination of roles (and possibly others as well).
43      * </p>
44      */
45     public static final int MODE_DFP = Constants.PortMode.DFP;
46 
47     /**
48      * Mode bit: This USB port can act as an upstream facing port (device).
49      * <p>
50      * Implies that the port supports the {@link #POWER_ROLE_SINK} and {@link #DATA_ROLE_DEVICE}
51      * combination of roles (and possibly others as well).
52      * </p>
53      */
54     public static final int MODE_UFP = Constants.PortMode.UFP;
55 
56     /**
57      * Mode bit: This USB port can act either as an downstream facing port (host) or as
58      * an upstream facing port (device).
59      * <p>
60      * Implies that the port supports the {@link #POWER_ROLE_SOURCE} and {@link #DATA_ROLE_HOST}
61      * combination of roles and the {@link #POWER_ROLE_SINK} and {@link #DATA_ROLE_DEVICE}
62      * combination of roles (and possibly others as well).
63      * </p>
64      */
65     public static final int MODE_DUAL = Constants.PortMode.DRP;
66 
67     /**
68      * Power role: This USB port does not have a power role.
69      */
70     public static final int POWER_ROLE_NONE = Constants.PortPowerRole.NONE;
71 
72     /**
73      * Power role: This USB port can act as a source (provide power).
74      */
75     public static final int POWER_ROLE_SOURCE = Constants.PortPowerRole.SOURCE;
76 
77     /**
78      * Power role: This USB port can act as a sink (receive power).
79      */
80     public static final int POWER_ROLE_SINK = Constants.PortPowerRole.SINK;
81 
82     /**
83      * Power role: This USB port does not have a data role.
84      */
85     public static final int DATA_ROLE_NONE = Constants.PortDataRole.NONE;
86 
87     /**
88      * Data role: This USB port can act as a host (access data services).
89      */
90     public static final int DATA_ROLE_HOST = Constants.PortDataRole.HOST;
91 
92     /**
93      * Data role: This USB port can act as a device (offer data services).
94      */
95     public static final int DATA_ROLE_DEVICE = Constants.PortDataRole.DEVICE;
96 
97     private static final int NUM_DATA_ROLES = Constants.PortDataRole.NUM_DATA_ROLES;
98     /**
99      * Points to the first power role in the IUsb HAL.
100      */
101     private static final int POWER_ROLE_OFFSET = Constants.PortPowerRole.NONE;
102 
103     /** @hide */
UsbPort(String id, int supportedModes)104     public UsbPort(String id, int supportedModes) {
105         mId = id;
106         mSupportedModes = supportedModes;
107     }
108 
109     /**
110      * Gets the unique id of the port.
111      *
112      * @return The unique id of the port; not intended for display.
113      */
getId()114     public String getId() {
115         return mId;
116     }
117 
118     /**
119      * Gets the supported modes of the port.
120      * <p>
121      * The actual mode of the port may vary depending on what is plugged into it.
122      * </p>
123      *
124      * @return The supported modes: one of {@link #MODE_DFP}, {@link #MODE_UFP}, or
125      * {@link #MODE_DUAL}.
126      */
getSupportedModes()127     public int getSupportedModes() {
128         return mSupportedModes;
129     }
130 
131     /**
132      * Combines one power and one data role together into a unique value with
133      * exactly one bit set.  This can be used to efficiently determine whether
134      * a combination of roles is supported by testing whether that bit is present
135      * in a bit-field.
136      *
137      * @param powerRole The desired power role: {@link UsbPort#POWER_ROLE_SOURCE}
138      * or {@link UsbPort#POWER_ROLE_SINK}, or 0 if no power role.
139      * @param dataRole The desired data role: {@link UsbPort#DATA_ROLE_HOST}
140      * or {@link UsbPort#DATA_ROLE_DEVICE}, or 0 if no data role.
141      * @hide
142      */
combineRolesAsBit(int powerRole, int dataRole)143     public static int combineRolesAsBit(int powerRole, int dataRole) {
144         checkRoles(powerRole, dataRole);
145         final int index = ((powerRole - POWER_ROLE_OFFSET) * NUM_DATA_ROLES) + dataRole;
146         return 1 << index;
147     }
148 
149     /** @hide */
modeToString(int mode)150     public static String modeToString(int mode) {
151         switch (mode) {
152             case MODE_NONE:
153                 return "none";
154             case MODE_DFP:
155                 return "dfp";
156             case MODE_UFP:
157                 return "ufp";
158             case MODE_DUAL:
159                 return "dual";
160             default:
161                 return Integer.toString(mode);
162         }
163     }
164 
165     /** @hide */
powerRoleToString(int role)166     public static String powerRoleToString(int role) {
167         switch (role) {
168             case POWER_ROLE_NONE:
169                 return "no-power";
170             case POWER_ROLE_SOURCE:
171                 return "source";
172             case POWER_ROLE_SINK:
173                 return "sink";
174             default:
175                 return Integer.toString(role);
176         }
177     }
178 
179     /** @hide */
dataRoleToString(int role)180     public static String dataRoleToString(int role) {
181         switch (role) {
182             case DATA_ROLE_NONE:
183                 return "no-data";
184             case DATA_ROLE_HOST:
185                 return "host";
186             case DATA_ROLE_DEVICE:
187                 return "device";
188             default:
189                 return Integer.toString(role);
190         }
191     }
192 
193     /** @hide */
roleCombinationsToString(int combo)194     public static String roleCombinationsToString(int combo) {
195         StringBuilder result = new StringBuilder();
196         result.append("[");
197 
198         boolean first = true;
199         while (combo != 0) {
200             final int index = Integer.numberOfTrailingZeros(combo);
201             combo &= ~(1 << index);
202             final int powerRole = (index / NUM_DATA_ROLES + POWER_ROLE_OFFSET);
203             final int dataRole = index % NUM_DATA_ROLES;
204             if (first) {
205                 first = false;
206             } else {
207                 result.append(", ");
208             }
209             result.append(powerRoleToString(powerRole));
210             result.append(':');
211             result.append(dataRoleToString(dataRole));
212         }
213 
214         result.append("]");
215         return result.toString();
216     }
217 
218     /** @hide */
checkMode(int powerRole)219     public static void checkMode(int powerRole) {
220         Preconditions.checkArgumentInRange(powerRole, Constants.PortMode.NONE,
221                 Constants.PortMode.NUM_MODES - 1, "portMode");
222     }
223 
224     /** @hide */
checkPowerRole(int dataRole)225     public static void checkPowerRole(int dataRole) {
226         Preconditions.checkArgumentInRange(dataRole, Constants.PortPowerRole.NONE,
227                 Constants.PortPowerRole.NUM_POWER_ROLES - 1, "powerRole");
228     }
229 
230     /** @hide */
checkDataRole(int mode)231     public static void checkDataRole(int mode) {
232         Preconditions.checkArgumentInRange(mode, Constants.PortDataRole.NONE,
233                 Constants.PortDataRole.NUM_DATA_ROLES - 1, "powerRole");
234     }
235 
236     /** @hide */
checkRoles(int powerRole, int dataRole)237     public static void checkRoles(int powerRole, int dataRole) {
238         Preconditions.checkArgumentInRange(powerRole, POWER_ROLE_NONE, POWER_ROLE_SINK,
239                 "powerRole");
240         Preconditions.checkArgumentInRange(dataRole, DATA_ROLE_NONE, DATA_ROLE_DEVICE, "dataRole");
241     }
242 
243     @Override
toString()244     public String toString() {
245         return "UsbPort{id=" + mId + ", supportedModes=" + modeToString(mSupportedModes) + "}";
246     }
247 
248     @Override
describeContents()249     public int describeContents() {
250         return 0;
251     }
252 
253     @Override
writeToParcel(Parcel dest, int flags)254     public void writeToParcel(Parcel dest, int flags) {
255         dest.writeString(mId);
256         dest.writeInt(mSupportedModes);
257     }
258 
259     public static final Parcelable.Creator<UsbPort> CREATOR =
260             new Parcelable.Creator<UsbPort>() {
261         @Override
262         public UsbPort createFromParcel(Parcel in) {
263             String id = in.readString();
264             int supportedModes = in.readInt();
265             return new UsbPort(id, supportedModes);
266         }
267 
268         @Override
269         public UsbPort[] newArray(int size) {
270             return new UsbPort[size];
271         }
272     };
273 }
274