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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 209 public String toString() { 210 return "UsbPort{id=" + mId + ", supportedModes=" + modeToString(mSupportedModes) + "}"; 211 } 212 213 @Override 214 public int describeContents() { 215 return 0; 216 } 217 218 @Override 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