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