/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.hardware.usb; import com.android.internal.util.Preconditions; import android.os.Parcel; import android.os.Parcelable; /** * Represents a physical USB port and describes its characteristics. * <p> * This object is immutable. * </p> * * @hide */ public final class UsbPort implements Parcelable { private final String mId; private final int mSupportedModes; /** * Mode bit: This USB port can act as a downstream facing port (host). * <p> * Implies that the port supports the {@link #POWER_ROLE_SOURCE} and {@link #DATA_ROLE_HOST} * combination of roles (and possibly others as well). * </p> */ public static final int MODE_DFP = 1 << 0; /** * Mode bit: This USB port can act as an upstream facing port (device). * <p> * Implies that the port supports the {@link #POWER_ROLE_SINK} and {@link #DATA_ROLE_DEVICE} * combination of roles (and possibly others as well). * </p> */ public static final int MODE_UFP = 1 << 1; /** * Mode bit: This USB port can act either as an downstream facing port (host) or as * an upstream facing port (device). * <p> * Implies that the port supports the {@link #POWER_ROLE_SOURCE} and {@link #DATA_ROLE_HOST} * combination of roles and the {@link #POWER_ROLE_SINK} and {@link #DATA_ROLE_DEVICE} * combination of roles (and possibly others as well). * </p> */ public static final int MODE_DUAL = MODE_DFP | MODE_UFP; /** * Power role: This USB port can act as a source (provide power). */ public static final int POWER_ROLE_SOURCE = 1; /** * Power role: This USB port can act as a sink (receive power). */ public static final int POWER_ROLE_SINK = 2; /** * Data role: This USB port can act as a host (access data services). */ public static final int DATA_ROLE_HOST = 1; /** * Data role: This USB port can act as a device (offer data services). */ public static final int DATA_ROLE_DEVICE = 2; private static final int NUM_DATA_ROLES = 3; /** @hide */ public UsbPort(String id, int supportedModes) { mId = id; mSupportedModes = supportedModes; } /** * Gets the unique id of the port. * * @return The unique id of the port; not intended for display. */ public String getId() { return mId; } /** * Gets the supported modes of the port. * <p> * The actual mode of the port may vary depending on what is plugged into it. * </p> * * @return The supported modes: one of {@link #MODE_DFP}, {@link #MODE_UFP}, or * {@link #MODE_DUAL}. */ public int getSupportedModes() { return mSupportedModes; } /** * Combines one power and one data role together into a unique value with * exactly one bit set. This can be used to efficiently determine whether * a combination of roles is supported by testing whether that bit is present * in a bit-field. * * @param powerRole The desired power role: {@link UsbPort#POWER_ROLE_SOURCE} * or {@link UsbPort#POWER_ROLE_SINK}, or 0 if no power role. * @param dataRole The desired data role: {@link UsbPort#DATA_ROLE_HOST} * or {@link UsbPort#DATA_ROLE_DEVICE}, or 0 if no data role. * @hide */ public static int combineRolesAsBit(int powerRole, int dataRole) { checkRoles(powerRole, dataRole); final int index = powerRole * NUM_DATA_ROLES + dataRole; return 1 << index; } /** @hide */ public static String modeToString(int mode) { switch (mode) { case 0: return "none"; case MODE_DFP: return "dfp"; case MODE_UFP: return "ufp"; case MODE_DUAL: return "dual"; default: return Integer.toString(mode); } } /** @hide */ public static String powerRoleToString(int role) { switch (role) { case 0: return "no-power"; case POWER_ROLE_SOURCE: return "source"; case POWER_ROLE_SINK: return "sink"; default: return Integer.toString(role); } } /** @hide */ public static String dataRoleToString(int role) { switch (role) { case 0: return "no-data"; case DATA_ROLE_HOST: return "host"; case DATA_ROLE_DEVICE: return "device"; default: return Integer.toString(role); } } /** @hide */ public static String roleCombinationsToString(int combo) { StringBuilder result = new StringBuilder(); result.append("["); boolean first = true; while (combo != 0) { final int index = Integer.numberOfTrailingZeros(combo); combo &= ~(1 << index); final int powerRole = index / NUM_DATA_ROLES; final int dataRole = index % NUM_DATA_ROLES; if (first) { first = false; } else { result.append(", "); } result.append(powerRoleToString(powerRole)); result.append(':'); result.append(dataRoleToString(dataRole)); } result.append("]"); return result.toString(); } /** @hide */ public static void checkRoles(int powerRole, int dataRole) { Preconditions.checkArgumentInRange(powerRole, 0, POWER_ROLE_SINK, "powerRole"); Preconditions.checkArgumentInRange(dataRole, 0, DATA_ROLE_DEVICE, "dataRole"); } @Override public String toString() { return "UsbPort{id=" + mId + ", supportedModes=" + modeToString(mSupportedModes) + "}"; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(mId); dest.writeInt(mSupportedModes); } public static final Parcelable.Creator<UsbPort> CREATOR = new Parcelable.Creator<UsbPort>() { @Override public UsbPort createFromParcel(Parcel in) { String id = in.readString(); int supportedModes = in.readInt(); return new UsbPort(id, supportedModes); } @Override public UsbPort[] newArray(int size) { return new UsbPort[size]; } }; }