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 * Mode bit: This USB port can support USB Type-C Audio accessory. 69 */ 70 public static final int MODE_AUDIO_ACCESSORY = 71 android.hardware.usb.V1_1.Constants.PortMode_1_1.AUDIO_ACCESSORY; 72 73 /** 74 * Mode bit: This USB port can support USB Type-C debug accessory. 75 */ 76 public static final int MODE_DEBUG_ACCESSORY = 77 android.hardware.usb.V1_1.Constants.PortMode_1_1.DEBUG_ACCESSORY; 78 79 /** 80 * Power role: This USB port does not have a power role. 81 */ 82 public static final int POWER_ROLE_NONE = Constants.PortPowerRole.NONE; 83 84 /** 85 * Power role: This USB port can act as a source (provide power). 86 */ 87 public static final int POWER_ROLE_SOURCE = Constants.PortPowerRole.SOURCE; 88 89 /** 90 * Power role: This USB port can act as a sink (receive power). 91 */ 92 public static final int POWER_ROLE_SINK = Constants.PortPowerRole.SINK; 93 94 /** 95 * Power role: This USB port does not have a data role. 96 */ 97 public static final int DATA_ROLE_NONE = Constants.PortDataRole.NONE; 98 99 /** 100 * Data role: This USB port can act as a host (access data services). 101 */ 102 public static final int DATA_ROLE_HOST = Constants.PortDataRole.HOST; 103 104 /** 105 * Data role: This USB port can act as a device (offer data services). 106 */ 107 public static final int DATA_ROLE_DEVICE = Constants.PortDataRole.DEVICE; 108 109 private static final int NUM_DATA_ROLES = Constants.PortDataRole.NUM_DATA_ROLES; 110 /** 111 * Points to the first power role in the IUsb HAL. 112 */ 113 private static final int POWER_ROLE_OFFSET = Constants.PortPowerRole.NONE; 114 115 /** @hide */ UsbPort(String id, int supportedModes)116 public UsbPort(String id, int supportedModes) { 117 mId = id; 118 mSupportedModes = supportedModes; 119 } 120 121 /** 122 * Gets the unique id of the port. 123 * 124 * @return The unique id of the port; not intended for display. 125 */ getId()126 public String getId() { 127 return mId; 128 } 129 130 /** 131 * Gets the supported modes of the port. 132 * <p> 133 * The actual mode of the port may vary depending on what is plugged into it. 134 * </p> 135 * 136 * @return The supported modes: one of {@link #MODE_DFP}, {@link #MODE_UFP}, or 137 * {@link #MODE_DUAL}. 138 */ getSupportedModes()139 public int getSupportedModes() { 140 return mSupportedModes; 141 } 142 143 /** 144 * Combines one power and one data role together into a unique value with 145 * exactly one bit set. This can be used to efficiently determine whether 146 * a combination of roles is supported by testing whether that bit is present 147 * in a bit-field. 148 * 149 * @param powerRole The desired power role: {@link UsbPort#POWER_ROLE_SOURCE} 150 * or {@link UsbPort#POWER_ROLE_SINK}, or 0 if no power role. 151 * @param dataRole The desired data role: {@link UsbPort#DATA_ROLE_HOST} 152 * or {@link UsbPort#DATA_ROLE_DEVICE}, or 0 if no data role. 153 * @hide 154 */ combineRolesAsBit(int powerRole, int dataRole)155 public static int combineRolesAsBit(int powerRole, int dataRole) { 156 checkRoles(powerRole, dataRole); 157 final int index = ((powerRole - POWER_ROLE_OFFSET) * NUM_DATA_ROLES) + dataRole; 158 return 1 << index; 159 } 160 161 /** @hide */ modeToString(int mode)162 public static String modeToString(int mode) { 163 StringBuilder modeString = new StringBuilder(); 164 if (mode == MODE_NONE) { 165 return "none"; 166 } 167 168 if ((mode & MODE_DUAL) == MODE_DUAL) { 169 modeString.append("dual, "); 170 } else { 171 if ((mode & MODE_DFP) == MODE_DFP) { 172 modeString.append("dfp, "); 173 } else if ((mode & MODE_UFP) == MODE_UFP) { 174 modeString.append("ufp, "); 175 } 176 } 177 if ((mode & MODE_AUDIO_ACCESSORY) == MODE_AUDIO_ACCESSORY) { 178 modeString.append("audio_acc, "); 179 } 180 if ((mode & MODE_DEBUG_ACCESSORY) == MODE_DEBUG_ACCESSORY) { 181 modeString.append("debug_acc, "); 182 } 183 184 if (modeString.length() == 0) { 185 return Integer.toString(mode); 186 } 187 return modeString.substring(0, modeString.length() - 2); 188 } 189 190 /** @hide */ powerRoleToString(int role)191 public static String powerRoleToString(int role) { 192 switch (role) { 193 case POWER_ROLE_NONE: 194 return "no-power"; 195 case POWER_ROLE_SOURCE: 196 return "source"; 197 case POWER_ROLE_SINK: 198 return "sink"; 199 default: 200 return Integer.toString(role); 201 } 202 } 203 204 /** @hide */ dataRoleToString(int role)205 public static String dataRoleToString(int role) { 206 switch (role) { 207 case DATA_ROLE_NONE: 208 return "no-data"; 209 case DATA_ROLE_HOST: 210 return "host"; 211 case DATA_ROLE_DEVICE: 212 return "device"; 213 default: 214 return Integer.toString(role); 215 } 216 } 217 218 /** @hide */ roleCombinationsToString(int combo)219 public static String roleCombinationsToString(int combo) { 220 StringBuilder result = new StringBuilder(); 221 result.append("["); 222 223 boolean first = true; 224 while (combo != 0) { 225 final int index = Integer.numberOfTrailingZeros(combo); 226 combo &= ~(1 << index); 227 final int powerRole = (index / NUM_DATA_ROLES + POWER_ROLE_OFFSET); 228 final int dataRole = index % NUM_DATA_ROLES; 229 if (first) { 230 first = false; 231 } else { 232 result.append(", "); 233 } 234 result.append(powerRoleToString(powerRole)); 235 result.append(':'); 236 result.append(dataRoleToString(dataRole)); 237 } 238 239 result.append("]"); 240 return result.toString(); 241 } 242 243 /** @hide */ checkMode(int powerRole)244 public static void checkMode(int powerRole) { 245 Preconditions.checkArgumentInRange(powerRole, Constants.PortMode.NONE, 246 Constants.PortMode.NUM_MODES - 1, "portMode"); 247 } 248 249 /** @hide */ checkPowerRole(int dataRole)250 public static void checkPowerRole(int dataRole) { 251 Preconditions.checkArgumentInRange(dataRole, Constants.PortPowerRole.NONE, 252 Constants.PortPowerRole.NUM_POWER_ROLES - 1, "powerRole"); 253 } 254 255 /** @hide */ checkDataRole(int mode)256 public static void checkDataRole(int mode) { 257 Preconditions.checkArgumentInRange(mode, Constants.PortDataRole.NONE, 258 Constants.PortDataRole.NUM_DATA_ROLES - 1, "powerRole"); 259 } 260 261 /** @hide */ checkRoles(int powerRole, int dataRole)262 public static void checkRoles(int powerRole, int dataRole) { 263 Preconditions.checkArgumentInRange(powerRole, POWER_ROLE_NONE, POWER_ROLE_SINK, 264 "powerRole"); 265 Preconditions.checkArgumentInRange(dataRole, DATA_ROLE_NONE, DATA_ROLE_DEVICE, "dataRole"); 266 } 267 268 /** @hide */ isModeSupported(int mode)269 public boolean isModeSupported(int mode) { 270 if ((mSupportedModes & mode) == mode) return true; 271 return false; 272 } 273 274 275 @Override toString()276 public String toString() { 277 return "UsbPort{id=" + mId + ", supportedModes=" + modeToString(mSupportedModes) + "}"; 278 } 279 280 @Override describeContents()281 public int describeContents() { 282 return 0; 283 } 284 285 @Override writeToParcel(Parcel dest, int flags)286 public void writeToParcel(Parcel dest, int flags) { 287 dest.writeString(mId); 288 dest.writeInt(mSupportedModes); 289 } 290 291 public static final Parcelable.Creator<UsbPort> CREATOR = 292 new Parcelable.Creator<UsbPort>() { 293 @Override 294 public UsbPort createFromParcel(Parcel in) { 295 String id = in.readString(); 296 int supportedModes = in.readInt(); 297 return new UsbPort(id, supportedModes); 298 } 299 300 @Override 301 public UsbPort[] newArray(int size) { 302 return new UsbPort[size]; 303 } 304 }; 305 } 306