Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 17c402d6 authored by Mike Lockwood's avatar Mike Lockwood Committed by Android (Google) Code Review
Browse files

Merge "Add support for USB devices with multiple configurations and alternate interfaces"

parents 29f75e70 7531aa22
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -11826,6 +11826,20 @@ package android.hardware.usb {
    field public static final android.os.Parcelable.Creator CREATOR;
  }
  public class UsbConfiguration implements android.os.Parcelable {
    method public int describeContents();
    method public int getAttributes();
    method public int getId();
    method public android.hardware.usb.UsbInterface getInterface(int);
    method public int getInterfaceCount();
    method public int getMaxPower();
    method public java.lang.String getName();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final int ATTR_REMOTE_WAKEUP_MASK = 32; // 0x20
    field public static final int ATTR_SELF_POWERED_MASK = 64; // 0x40
    field public static final android.os.Parcelable.Creator CREATOR;
  }
  public final class UsbConstants {
    ctor public UsbConstants();
    field public static final int USB_CLASS_APP_SPEC = 254; // 0xfe
@@ -11865,6 +11879,8 @@ package android.hardware.usb {
  public class UsbDevice implements android.os.Parcelable {
    method public int describeContents();
    method public android.hardware.usb.UsbConfiguration getConfiguration(int);
    method public int getConfigurationCount();
    method public int getDeviceClass();
    method public int getDeviceId();
    method public static int getDeviceId(java.lang.String);
@@ -11895,6 +11911,8 @@ package android.hardware.usb {
    method public java.lang.String getSerial();
    method public boolean releaseInterface(android.hardware.usb.UsbInterface);
    method public android.hardware.usb.UsbRequest requestWait();
    method public boolean setConfiguration(android.hardware.usb.UsbConfiguration);
    method public boolean setInterface(android.hardware.usb.UsbInterface);
  }
  public class UsbEndpoint implements android.os.Parcelable {
@@ -11912,12 +11930,14 @@ package android.hardware.usb {
  public class UsbInterface implements android.os.Parcelable {
    method public int describeContents();
    method public int getAlternateSetting();
    method public android.hardware.usb.UsbEndpoint getEndpoint(int);
    method public int getEndpointCount();
    method public int getId();
    method public int getInterfaceClass();
    method public int getInterfaceProtocol();
    method public int getInterfaceSubclass();
    method public java.lang.String getName();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final android.os.Parcelable.Creator CREATOR;
  }
+178 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 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 android.os.Parcel;
import android.os.Parcelable;

/**
 * A class representing a configuration on a {@link UsbDevice}.
 * A USB configuration can have one or more interfaces, each one providing a different
 * piece of functionality, separate from the other interfaces.
 * An interface will have one or more {@link UsbEndpoint}s, which are the
 * channels by which the host transfers data with the device.
 *
 * <div class="special reference">
 * <h3>Developer Guides</h3>
 * <p>For more information about communicating with USB hardware, read the
 * <a href="{@docRoot}guide/topics/usb/index.html">USB</a> developer guide.</p>
 * </div>
 */
public class UsbConfiguration implements Parcelable {

    private final int mId;
    private final String mName;
    private final int mAttributes;
    private final int mMaxPower;
    private Parcelable[] mInterfaces;

    /**
     * Mask for "self-powered" bit in the configuration's attributes.
     * @see #getAttributes
     */
    public static final int ATTR_SELF_POWERED_MASK = 1 << 6;

    /**
     * Mask for "remote wakeup" bit in the configuration's attributes.
     * @see #getAttributes
     */
    public static final int ATTR_REMOTE_WAKEUP_MASK = 1 << 5;

    /**
     * UsbConfiguration should only be instantiated by UsbService implementation
     * @hide
     */
    public UsbConfiguration(int id, String name, int attributes, int maxPower) {
        mId = id;
        mName = name;
        mAttributes = attributes;
        mMaxPower = maxPower;
    }

    /**
     * Returns the configuration's ID field.
     * This is an integer that uniquely identifies the configuration on the device.
     *
     * @return the configuration's ID
     */
    public int getId() {
        return mId;
    }

    /**
     * Returns the configuration's name.
     *
     * @return the configuration's name
     */
    public String getName() {
        return mName;
    }

    /**
     * Returns the configuration's attributes field.
     * This field contains a bit field with the following flags:
     *
     * Bit 7: always set to 1
     * Bit 6: self-powered
     * Bit 5: remote wakeup enabled
     * Bit 0-4: reserved
     * @see #ATTR_SELF_POWERED_MASK
     * @see #ATTR_REMOTE_WAKEUP_MASK
     * @return the configuration's attributes
     */
    public int getAttributes() {
        return mAttributes;
    }

    /**
     * Returns the configuration's max power consumption, in milliamps.
     *
     * @return the configuration's max power
     */
    public int getMaxPower() {
        return mMaxPower * 2;
    }

    /**
     * Returns the number of {@link UsbInterface}s this configuration contains.
     *
     * @return the number of endpoints
     */
    public int getInterfaceCount() {
        return mInterfaces.length;
    }

    /**
     * Returns the {@link UsbInterface} at the given index.
     *
     * @return the interface
     */
    public UsbInterface getInterface(int index) {
        return (UsbInterface)mInterfaces[index];
    }

    /**
     * Only used by UsbService implementation
     * @hide
     */
    public void setInterfaces(Parcelable[] interfaces) {
        mInterfaces = interfaces;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder("UsbConfiguration[mId=" + mId +
                ",mName=" + mName + ",mAttributes=" + mAttributes +
                ",mMaxPower=" + mMaxPower + ",mInterfaces=[");
        for (int i = 0; i < mInterfaces.length; i++) {
            builder.append("\n");
            builder.append(mInterfaces[i].toString());
        }
        builder.append("]");
        return builder.toString();
    }

    public static final Parcelable.Creator<UsbConfiguration> CREATOR =
        new Parcelable.Creator<UsbConfiguration>() {
        public UsbConfiguration createFromParcel(Parcel in) {
            int id = in.readInt();
            String name = in.readString();
            int attributes = in.readInt();
            int maxPower = in.readInt();
            Parcelable[] interfaces = in.readParcelableArray(UsbInterface.class.getClassLoader());
            UsbConfiguration configuration = new UsbConfiguration(id, name, attributes, maxPower);
            configuration.setInterfaces(interfaces);
            return configuration;
        }

        public UsbConfiguration[] newArray(int size) {
            return new UsbConfiguration[size];
        }
    };

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeInt(mId);
        parcel.writeString(mName);
        parcel.writeInt(mAttributes);
        parcel.writeInt(mMaxPower);
        parcel.writeParcelableArray(mInterfaces, 0);
   }
}
+76 −14
Original line number Diff line number Diff line
@@ -50,7 +50,10 @@ public class UsbDevice implements Parcelable {
    private final int mClass;
    private final int mSubclass;
    private final int mProtocol;
    private final Parcelable[] mInterfaces;
    private Parcelable[] mConfigurations;

    // list of all interfaces on the device
    private UsbInterface[] mInterfaces;

    /**
     * UsbDevice should only be instantiated by UsbService implementation
@@ -58,8 +61,7 @@ public class UsbDevice implements Parcelable {
     */
    public UsbDevice(String name, int vendorId, int productId,
            int Class, int subClass, int protocol,
            String manufacturerName, String productName, String serialNumber,
            Parcelable[] interfaces) {
            String manufacturerName, String productName, String serialNumber) {
        mName = name;
        mVendorId = vendorId;
        mProductId = productId;
@@ -69,7 +71,6 @@ public class UsbDevice implements Parcelable {
        mManufacturerName = manufacturerName;
        mProductName = productName;
        mSerialNumber = serialNumber;
        mInterfaces = interfaces;
    }

    /**
@@ -168,22 +169,75 @@ public class UsbDevice implements Parcelable {
        return mProtocol;
    }

    /**
     * Returns the number of {@link UsbConfiguration}s this device contains.
     *
     * @return the number of configurations
     */
    public int getConfigurationCount() {
        return mConfigurations.length;
    }

    /**
     * Returns the {@link UsbConfiguration} at the given index.
     *
     * @return the configuration
     */
    public UsbConfiguration getConfiguration(int index) {
        return (UsbConfiguration)mConfigurations[index];
    }

    private UsbInterface[] getInterfaceList() {
        if (mInterfaces == null) {
            int configurationCount = mConfigurations.length;
            int interfaceCount = 0;
            for (int i = 0; i < configurationCount; i++) {
                UsbConfiguration configuration = (UsbConfiguration)mConfigurations[i];
                interfaceCount += configuration.getInterfaceCount();
            }

            mInterfaces = new UsbInterface[interfaceCount];
            int offset = 0;
            for (int i = 0; i < configurationCount; i++) {
                UsbConfiguration configuration = (UsbConfiguration)mConfigurations[i];
                interfaceCount = configuration.getInterfaceCount();
                for (int j = 0; j < interfaceCount; j++) {
                    mInterfaces[offset++] = configuration.getInterface(j);
                }
            }
        }

        return mInterfaces;
    }

    /**
     * Returns the number of {@link UsbInterface}s this device contains.
     * For devices with multiple configurations, you will probably want to use
     * {@link UsbConfiguration#getInterfaceCount} instead.
     *
     * @return the number of interfaces
     */
    public int getInterfaceCount() {
        return mInterfaces.length;
        return getInterfaceList().length;
    }

    /**
     * Returns the {@link UsbInterface} at the given index.
     * For devices with multiple configurations, you will probably want to use
     * {@link UsbConfiguration#getInterface} instead.
     *
     * @return the interface
     */
    public UsbInterface getInterface(int index) {
        return (UsbInterface)mInterfaces[index];
        return getInterfaceList()[index];
    }

    /**
     * Only used by UsbService implementation
     * @hide
     */
    public void setConfigurations(Parcelable[] configuration) {
        mConfigurations = configuration;
    }

    @Override
@@ -204,11 +258,17 @@ public class UsbDevice implements Parcelable {

    @Override
    public String toString() {
        return "UsbDevice[mName=" + mName + ",mVendorId=" + mVendorId +
                ",mProductId=" + mProductId + ",mClass=" + mClass +
                ",mSubclass=" + mSubclass + ",mProtocol=" + mProtocol +
        StringBuilder builder = new StringBuilder("UsbDevice[mName=" + mName +
                ",mVendorId=" + mVendorId + ",mProductId=" + mProductId +
                ",mClass=" + mClass + ",mSubclass=" + mSubclass + ",mProtocol=" + mProtocol +
                ",mManufacturerName=" + mManufacturerName + ",mProductName=" + mProductName +
                ",mSerialNumber=" + mSerialNumber + ",mInterfaces=" + mInterfaces + "]";
                ",mSerialNumber=" + mSerialNumber + ",mConfigurations=[");
        for (int i = 0; i < mConfigurations.length; i++) {
            builder.append("\n");
            builder.append(mConfigurations[i].toString());
        }
        builder.append("]");
        return builder.toString();
    }

    public static final Parcelable.Creator<UsbDevice> CREATOR =
@@ -223,9 +283,11 @@ public class UsbDevice implements Parcelable {
            String manufacturerName = in.readString();
            String productName = in.readString();
            String serialNumber = in.readString();
            Parcelable[] interfaces = in.readParcelableArray(UsbInterface.class.getClassLoader());
            return new UsbDevice(name, vendorId, productId, clasz, subClass, protocol,
                                 manufacturerName, productName, serialNumber, interfaces);
            Parcelable[] configurations = in.readParcelableArray(UsbInterface.class.getClassLoader());
            UsbDevice device = new UsbDevice(name, vendorId, productId, clasz, subClass, protocol,
                                 manufacturerName, productName, serialNumber);
            device.setConfigurations(configurations);
            return device;
        }

        public UsbDevice[] newArray(int size) {
@@ -247,7 +309,7 @@ public class UsbDevice implements Parcelable {
        parcel.writeString(mManufacturerName);
        parcel.writeString(mProductName);
        parcel.writeString(mSerialNumber);
        parcel.writeParcelableArray(mInterfaces, 0);
        parcel.writeParcelableArray(mConfigurations, 0);
   }

    public static int getDeviceId(String name) {
+21 −0
Original line number Diff line number Diff line
@@ -100,6 +100,25 @@ public class UsbDeviceConnection {
        return native_release_interface(intf.getId());
    }

    /**
     * Sets the current {@link android.hardware.usb.UsbInterface}.
     * Used to select between two interfaces with the same ID but different alternate setting.
     *
     * @return true if the interface was successfully released
     */
    public boolean setInterface(UsbInterface intf) {
        return native_set_interface(intf.getId(), intf.getAlternateSetting());
    }

    /**
     * Sets the device's current {@link android.hardware.usb.UsbConfiguration}.
     *
     * @return true if the configuration was successfully set
     */
    public boolean setConfiguration(UsbConfiguration configuration) {
        return native_set_configuration(configuration.getId());
    }

    /**
     * Performs a control transaction on endpoint zero for this device.
     * The direction of the transfer is determined by the request type.
@@ -236,6 +255,8 @@ public class UsbDeviceConnection {
    private native byte[] native_get_desc();
    private native boolean native_claim_interface(int interfaceID, boolean force);
    private native boolean native_release_interface(int interfaceID);
    private native boolean native_set_interface(int interfaceID, int alternateSetting);
    private native boolean native_set_configuration(int configurationID);
    private native int native_control_request(int requestType, int request, int value,
            int index, byte[] buffer, int offset, int length, int timeout);
    private native int native_bulk_request(int endpoint, byte[] buffer,
+57 −9
Original line number Diff line number Diff line
@@ -35,27 +35,31 @@ import android.os.Parcelable;
public class UsbInterface implements Parcelable {

    private final int mId;
    private final int mAlternateSetting;
    private final String mName;
    private final int mClass;
    private final int mSubclass;
    private final int mProtocol;
    private final Parcelable[] mEndpoints;
    private Parcelable[] mEndpoints;

    /**
     * UsbInterface should only be instantiated by UsbService implementation
     * @hide
     */
    public UsbInterface(int id, int Class, int subClass, int protocol,
            Parcelable[] endpoints) {
    public UsbInterface(int id, int alternateSetting, String name,
            int Class, int subClass, int protocol) {
        mId = id;
        mAlternateSetting = alternateSetting;
        mName = name;
        mClass = Class;
        mSubclass = subClass;
        mProtocol = protocol;
        mEndpoints = endpoints;
    }

    /**
     * Returns the interface's ID field.
     * This is an integer that uniquely identifies the interface on the device.
     * Returns the interface's bInterfaceNumber field.
     * This is an integer that along with the alternate setting uniquely identifies
     * the interface on the device.
     *
     * @return the interface's ID
     */
@@ -63,6 +67,28 @@ public class UsbInterface implements Parcelable {
        return mId;
    }

    /**
     * Returns the interface's bAlternateSetting field.
     * This is an integer that along with the ID uniquely identifies
     * the interface on the device.
     * {@link UsbDeviceConnection#setInterface} can be used to switch between
     * two interfaces with the same ID but different alternate setting.
     *
     * @return the interface's alternate setting
     */
    public int getAlternateSetting() {
        return mAlternateSetting;
    }

    /**
     * Returns the interface's name.
     *
     * @return the interface's name
     */
    public String getName() {
        return mName;
    }

    /**
     * Returns the interface's class field.
     * Some useful constants for USB classes can be found in {@link UsbConstants}
@@ -109,22 +135,42 @@ public class UsbInterface implements Parcelable {
        return (UsbEndpoint)mEndpoints[index];
    }

    /**
     * Only used by UsbService implementation
     * @hide
     */
    public void setEndpoints(Parcelable[] endpoints) {
        mEndpoints = endpoints;
    }

    @Override
    public String toString() {
        return "UsbInterface[mId=" + mId + ",mClass=" + mClass +
        StringBuilder builder = new StringBuilder("UsbInterface[mId=" + mId +
                ",mAlternateSetting=" + mAlternateSetting +
                ",mName=" + mName + ",mClass=" + mClass +
                ",mSubclass=" + mSubclass + ",mProtocol=" + mProtocol +
                ",mEndpoints=" + mEndpoints + "]";
                ",mEndpoints=[");
        for (int i = 0; i < mEndpoints.length; i++) {
            builder.append("\n");
            builder.append(mEndpoints[i].toString());
        }
        builder.append("]");
        return builder.toString();
    }

    public static final Parcelable.Creator<UsbInterface> CREATOR =
        new Parcelable.Creator<UsbInterface>() {
        public UsbInterface createFromParcel(Parcel in) {
            int id = in.readInt();
            int alternateSetting = in.readInt();
            String name = in.readString();
            int Class = in.readInt();
            int subClass = in.readInt();
            int protocol = in.readInt();
            Parcelable[] endpoints = in.readParcelableArray(UsbEndpoint.class.getClassLoader());
            return new UsbInterface(id, Class, subClass, protocol, endpoints);
            UsbInterface intf = new UsbInterface(id, alternateSetting, name, Class, subClass, protocol);
            intf.setEndpoints(endpoints);
            return intf;
        }

        public UsbInterface[] newArray(int size) {
@@ -138,6 +184,8 @@ public class UsbInterface implements Parcelable {

    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeInt(mId);
        parcel.writeInt(mAlternateSetting);
        parcel.writeString(mName);
        parcel.writeInt(mClass);
        parcel.writeInt(mSubclass);
        parcel.writeInt(mProtocol);
Loading