1 /*
2  * Copyright (C) 2010 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.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 import com.android.internal.util.Preconditions;
24 
25 /**
26  * This class represents a USB device attached to the android device with the android device
27  * acting as the USB host.
28  * Each device contains one or more {@link UsbInterface}s, each of which contains a number of
29  * {@link UsbEndpoint}s (the channels via which data is transmitted over USB).
30  *
31  * <p> This class contains information (along with {@link UsbInterface} and {@link UsbEndpoint})
32  * that describes the capabilities of the USB device.
33  * To communicate with the device, you open a {@link UsbDeviceConnection} for the device
34  * and use {@link UsbRequest} to send and receive data on an endpoint.
35  * {@link UsbDeviceConnection#controlTransfer} is used for control requests on endpoint zero.
36  *
37  * <div class="special reference">
38  * <h3>Developer Guides</h3>
39  * <p>For more information about communicating with USB hardware, read the
40  * <a href="{@docRoot}guide/topics/connectivity/usb/index.html">USB</a> developer guide.</p>
41  * </div>
42  */
43 public class UsbDevice implements Parcelable {
44 
45     private static final String TAG = "UsbDevice";
46     private static final boolean DEBUG = false;
47 
48     private final @NonNull String mName;
49     private final @Nullable String mManufacturerName;
50     private final @Nullable String mProductName;
51     private final @NonNull String mVersion;
52     private final @Nullable String mSerialNumber;
53     private final int mVendorId;
54     private final int mProductId;
55     private final int mClass;
56     private final int mSubclass;
57     private final int mProtocol;
58 
59     /** All configurations for this device, only null during creation */
60     private @Nullable Parcelable[] mConfigurations;
61 
62     /** All interfaces on the device. Initialized on first call to getInterfaceList */
63     private @Nullable UsbInterface[] mInterfaces;
64 
65     /**
66      * UsbDevice should only be instantiated by UsbService implementation
67      * @hide
68      */
UsbDevice(@onNull String name, int vendorId, int productId, int Class, int subClass, int protocol, @Nullable String manufacturerName, @Nullable String productName, @NonNull String version, @Nullable String serialNumber)69     public UsbDevice(@NonNull String name, int vendorId, int productId, int Class, int subClass,
70             int protocol, @Nullable String manufacturerName, @Nullable String productName,
71             @NonNull String version, @Nullable String serialNumber) {
72         mName = Preconditions.checkNotNull(name);
73         mVendorId = vendorId;
74         mProductId = productId;
75         mClass = Class;
76         mSubclass = subClass;
77         mProtocol = protocol;
78         mManufacturerName = manufacturerName;
79         mProductName = productName;
80         mVersion = Preconditions.checkStringNotEmpty(version);
81         mSerialNumber = serialNumber;
82     }
83 
84     /**
85      * Returns the name of the device.
86      * In the standard implementation, this is the path of the device file
87      * for the device in the usbfs file system.
88      *
89      * @return the device name
90      */
getDeviceName()91     public @NonNull String getDeviceName() {
92         return mName;
93     }
94 
95     /**
96      * Returns the manufacturer name of the device.
97      *
98      * @return the manufacturer name, or {@code null} if the property could not be read
99      */
getManufacturerName()100     public @Nullable String getManufacturerName() {
101         return mManufacturerName;
102     }
103 
104     /**
105      * Returns the product name of the device.
106      *
107      * @return the product name, or {@code null} if the property could not be read
108      */
getProductName()109     public @Nullable String getProductName() {
110         return mProductName;
111     }
112 
113     /**
114      * Returns the version number of the device.
115      *
116      * @return the device version
117      */
getVersion()118     public @NonNull String getVersion() {
119         return mVersion;
120     }
121 
122     /**
123      * Returns the serial number of the device.
124      *
125      * @return the serial number name, or {@code null} if the property could not be read
126      */
getSerialNumber()127     public @Nullable String getSerialNumber() {
128         return mSerialNumber;
129     }
130 
131     /**
132      * Returns a unique integer ID for the device.
133      * This is a convenience for clients that want to use an integer to represent
134      * the device, rather than the device name.
135      * IDs are not persistent across USB disconnects.
136      *
137      * @return the device ID
138      */
getDeviceId()139     public int getDeviceId() {
140         return getDeviceId(mName);
141     }
142 
143     /**
144      * Returns a vendor ID for the device.
145      *
146      * @return the device vendor ID
147      */
getVendorId()148     public int getVendorId() {
149         return mVendorId;
150     }
151 
152     /**
153      * Returns a product ID for the device.
154      *
155      * @return the device product ID
156      */
getProductId()157     public int getProductId() {
158         return mProductId;
159     }
160 
161     /**
162      * Returns the devices's class field.
163      * Some useful constants for USB device classes can be found in {@link UsbConstants}.
164      *
165      * @return the devices's class
166      */
getDeviceClass()167     public int getDeviceClass() {
168         return mClass;
169     }
170 
171     /**
172      * Returns the device's subclass field.
173      *
174      * @return the device's subclass
175      */
getDeviceSubclass()176     public int getDeviceSubclass() {
177         return mSubclass;
178     }
179 
180     /**
181      * Returns the device's protocol field.
182      *
183      * @return the device's protocol
184      */
getDeviceProtocol()185     public int getDeviceProtocol() {
186         return mProtocol;
187     }
188 
189     /**
190      * Returns the number of {@link UsbConfiguration}s this device contains.
191      *
192      * @return the number of configurations
193      */
getConfigurationCount()194     public int getConfigurationCount() {
195         return mConfigurations.length;
196     }
197 
198     /**
199      * Returns the {@link UsbConfiguration} at the given index.
200      *
201      * @return the configuration
202      */
getConfiguration(int index)203     public @NonNull UsbConfiguration getConfiguration(int index) {
204         return (UsbConfiguration)mConfigurations[index];
205     }
206 
getInterfaceList()207     private @Nullable UsbInterface[] getInterfaceList() {
208         if (mInterfaces == null) {
209             int configurationCount = mConfigurations.length;
210             int interfaceCount = 0;
211             for (int i = 0; i < configurationCount; i++) {
212                 UsbConfiguration configuration = (UsbConfiguration)mConfigurations[i];
213                 interfaceCount += configuration.getInterfaceCount();
214             }
215 
216             mInterfaces = new UsbInterface[interfaceCount];
217             int offset = 0;
218             for (int i = 0; i < configurationCount; i++) {
219                 UsbConfiguration configuration = (UsbConfiguration)mConfigurations[i];
220                 interfaceCount = configuration.getInterfaceCount();
221                 for (int j = 0; j < interfaceCount; j++) {
222                     mInterfaces[offset++] = configuration.getInterface(j);
223                 }
224             }
225         }
226 
227         return mInterfaces;
228     }
229 
230     /**
231      * Returns the number of {@link UsbInterface}s this device contains.
232      * For devices with multiple configurations, you will probably want to use
233      * {@link UsbConfiguration#getInterfaceCount} instead.
234      *
235      * @return the number of interfaces
236      */
getInterfaceCount()237     public int getInterfaceCount() {
238         return getInterfaceList().length;
239     }
240 
241     /**
242      * Returns the {@link UsbInterface} at the given index.
243      * For devices with multiple configurations, you will probably want to use
244      * {@link UsbConfiguration#getInterface} instead.
245      *
246      * @return the interface
247      */
getInterface(int index)248     public @NonNull UsbInterface getInterface(int index) {
249         return getInterfaceList()[index];
250     }
251 
252     /**
253      * Only used by UsbService implementation
254      * @hide
255      */
setConfigurations(@onNull Parcelable[] configuration)256     public void setConfigurations(@NonNull Parcelable[] configuration) {
257         mConfigurations = Preconditions.checkArrayElementsNotNull(configuration, "configuration");
258     }
259 
260     @Override
equals(Object o)261     public boolean equals(Object o) {
262         if (o instanceof UsbDevice) {
263             return ((UsbDevice)o).mName.equals(mName);
264         } else if (o instanceof String) {
265             return ((String)o).equals(mName);
266         } else {
267             return false;
268         }
269     }
270 
271     @Override
hashCode()272     public int hashCode() {
273         return mName.hashCode();
274     }
275 
276     @Override
toString()277     public String toString() {
278         StringBuilder builder = new StringBuilder("UsbDevice[mName=" + mName +
279                 ",mVendorId=" + mVendorId + ",mProductId=" + mProductId +
280                 ",mClass=" + mClass + ",mSubclass=" + mSubclass + ",mProtocol=" + mProtocol +
281                 ",mManufacturerName=" + mManufacturerName + ",mProductName=" + mProductName +
282                 ",mVersion=" + mVersion + ",mSerialNumber=" + mSerialNumber + ",mConfigurations=[");
283         for (int i = 0; i < mConfigurations.length; i++) {
284             builder.append("\n");
285             builder.append(mConfigurations[i].toString());
286         }
287         builder.append("]");
288         return builder.toString();
289     }
290 
291     public static final Parcelable.Creator<UsbDevice> CREATOR =
292         new Parcelable.Creator<UsbDevice>() {
293         public UsbDevice createFromParcel(Parcel in) {
294             String name = in.readString();
295             int vendorId = in.readInt();
296             int productId = in.readInt();
297             int clasz = in.readInt();
298             int subClass = in.readInt();
299             int protocol = in.readInt();
300             String manufacturerName = in.readString();
301             String productName = in.readString();
302             String version = in.readString();
303             String serialNumber = in.readString();
304             Parcelable[] configurations = in.readParcelableArray(UsbInterface.class.getClassLoader());
305             UsbDevice device = new UsbDevice(name, vendorId, productId, clasz, subClass, protocol,
306                                  manufacturerName, productName, version, serialNumber);
307             device.setConfigurations(configurations);
308             return device;
309         }
310 
311         public UsbDevice[] newArray(int size) {
312             return new UsbDevice[size];
313         }
314     };
315 
describeContents()316     public int describeContents() {
317         return 0;
318     }
319 
writeToParcel(Parcel parcel, int flags)320     public void writeToParcel(Parcel parcel, int flags) {
321         parcel.writeString(mName);
322         parcel.writeInt(mVendorId);
323         parcel.writeInt(mProductId);
324         parcel.writeInt(mClass);
325         parcel.writeInt(mSubclass);
326         parcel.writeInt(mProtocol);
327         parcel.writeString(mManufacturerName);
328         parcel.writeString(mProductName);
329         parcel.writeString(mVersion);
330         parcel.writeString(mSerialNumber);
331         parcel.writeParcelableArray(mConfigurations, 0);
332    }
333 
getDeviceId(String name)334     public static int getDeviceId(String name) {
335         return native_get_device_id(name);
336     }
337 
getDeviceName(int id)338     public static String getDeviceName(int id) {
339         return native_get_device_name(id);
340     }
341 
native_get_device_id(String name)342     private static native int native_get_device_id(String name);
native_get_device_name(int id)343     private static native String native_get_device_name(int id);
344 }
345