blob: 1a5cdd9ec2a509202a100d8b5f8db1937f7007c1 [file] [log] [blame]
Mike Lockwoodacc29cc2011-03-11 08:18:08 -05001/*
2 * Copyright (C) 2011 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
17package android.hardware.usb;
18
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -070019import android.annotation.NonNull;
20import android.annotation.Nullable;
Jeff Sharkey6f95ab22017-07-17 13:15:16 -060021import android.annotation.SuppressLint;
Keun-young Parkbadbbae2016-01-05 13:27:29 -080022import android.annotation.SystemApi;
Mathew Inwoodbcbe4402018-08-08 15:42:59 +010023import android.annotation.UnsupportedAppUsage;
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -070024import android.content.Context;
Philip P. Moltmann9b6dd2b2017-04-06 15:34:04 -070025import android.os.Build;
Mike Lockwoodacc29cc2011-03-11 08:18:08 -050026import android.os.ParcelFileDescriptor;
Philip P. Moltmann927fefe2016-10-18 12:57:34 -070027
28import com.android.internal.util.Preconditions;
29
Philip P. Moltmann674e8c32016-08-29 12:28:31 -070030import dalvik.system.CloseGuard;
Mike Lockwoodacc29cc2011-03-11 08:18:08 -050031
32import java.io.FileDescriptor;
Philip P. Moltmann9b6dd2b2017-04-06 15:34:04 -070033import java.nio.BufferOverflowException;
Philip P. Moltmann5dd4e6c2016-09-23 15:31:23 -070034import java.nio.ByteBuffer;
Philip P. Moltmann9b6dd2b2017-04-06 15:34:04 -070035import java.util.concurrent.TimeoutException;
Mike Lockwoodacc29cc2011-03-11 08:18:08 -050036
37/**
Mike Lockwood11dd5ae2011-04-01 14:00:08 -040038 * This class is used for sending and receiving data and control messages to a USB device.
39 * Instances of this class are created by {@link UsbManager#openDevice}.
Mike Lockwoodacc29cc2011-03-11 08:18:08 -050040 */
41public class UsbDeviceConnection {
42
43 private static final String TAG = "UsbDeviceConnection";
44
45 private final UsbDevice mDevice;
46
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -070047 private Context mContext;
48
Mike Lockwoodacc29cc2011-03-11 08:18:08 -050049 // used by the JNI code
Mathew Inwoodbcbe4402018-08-08 15:42:59 +010050 @UnsupportedAppUsage
Ashok Bhat4838e332014-01-03 14:37:19 +000051 private long mNativeContext;
Mike Lockwoodacc29cc2011-03-11 08:18:08 -050052
Philip P. Moltmann674e8c32016-08-29 12:28:31 -070053 private final CloseGuard mCloseGuard = CloseGuard.get();
54
Al Suttonca53d072019-05-16 12:53:42 +010055 private final Object mLock = new Object();
56
Mike Lockwoodacc29cc2011-03-11 08:18:08 -050057 /**
58 * UsbDevice should only be instantiated by UsbService implementation
59 * @hide
60 */
61 public UsbDeviceConnection(UsbDevice device) {
62 mDevice = device;
63 }
64
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -070065 /* package */ boolean open(String name, ParcelFileDescriptor pfd, @NonNull Context context) {
66 mContext = context.getApplicationContext();
Philip P. Moltmann674e8c32016-08-29 12:28:31 -070067
Al Suttonca53d072019-05-16 12:53:42 +010068 synchronized (mLock) {
69 boolean wasOpened = native_open(name, pfd.getFileDescriptor());
70
71 if (wasOpened) {
72 mCloseGuard.open("close");
73 }
74
75 return wasOpened;
Philip P. Moltmann674e8c32016-08-29 12:28:31 -070076 }
Al Suttonca53d072019-05-16 12:53:42 +010077 }
Philip P. Moltmann674e8c32016-08-29 12:28:31 -070078
Al Suttonca53d072019-05-16 12:53:42 +010079 /***
80 * @return If this connection is currently open and usable.
81 */
82 boolean isOpen() {
83 return mNativeContext != 0;
Mike Lockwoodacc29cc2011-03-11 08:18:08 -050084 }
85
86 /**
Philip P. Moltmannec3cbb22016-09-14 13:24:52 -070087 * @return The application context the connection was created for.
88 *
89 * @hide
90 */
91 public @Nullable Context getContext() {
92 return mContext;
93 }
94
95 /**
Al Suttonca53d072019-05-16 12:53:42 +010096 * Cancel a request which relates to this connection.
97 *
98 * @return true if the request was successfully cancelled.
99 */
100 /* package */ boolean cancelRequest(UsbRequest request) {
101 synchronized (mLock) {
102 if (!isOpen()) {
103 return false;
104 }
105
106 return request.cancelIfOpen();
107 }
108 }
109
110 /**
Mike Lockwoodacc29cc2011-03-11 08:18:08 -0500111 * Releases all system resources related to the device.
Mike Lockwood11dd5ae2011-04-01 14:00:08 -0400112 * Once the object is closed it cannot be used again.
113 * The client must call {@link UsbManager#openDevice} again
114 * to retrieve a new instance to reestablish communication with the device.
Mike Lockwoodacc29cc2011-03-11 08:18:08 -0500115 */
116 public void close() {
Al Suttonca53d072019-05-16 12:53:42 +0100117 synchronized (mLock) {
118 if (isOpen()) {
119 native_close();
120 mCloseGuard.close();
121 }
Philip P. Moltmann674e8c32016-08-29 12:28:31 -0700122 }
Mike Lockwoodacc29cc2011-03-11 08:18:08 -0500123 }
124
125 /**
Mike Lockwood11dd5ae2011-04-01 14:00:08 -0400126 * Returns the native file descriptor for the device, or
Mike Lockwoodacc29cc2011-03-11 08:18:08 -0500127 * -1 if the device is not opened.
Mike Lockwood11dd5ae2011-04-01 14:00:08 -0400128 * This is intended for passing to native code to access the device.
129 *
130 * @return the native file descriptor
Mike Lockwoodacc29cc2011-03-11 08:18:08 -0500131 */
132 public int getFileDescriptor() {
133 return native_get_fd();
134 }
135
136 /**
Mike Lockwooda88b42d2011-05-19 11:52:40 -0400137 * Returns the raw USB descriptors for the device.
138 * This can be used to access descriptors not supported directly
139 * via the higher level APIs.
140 *
141 * @return raw USB descriptors
142 */
143 public byte[] getRawDescriptors() {
144 return native_get_desc();
145 }
146
147 /**
Mike Lockwoodacc29cc2011-03-11 08:18:08 -0500148 * Claims exclusive access to a {@link android.hardware.usb.UsbInterface}.
149 * This must be done before sending or receiving data on any
Mike Lockwood11dd5ae2011-04-01 14:00:08 -0400150 * {@link android.hardware.usb.UsbEndpoint}s belonging to the interface.
151 *
Mike Lockwoodacc29cc2011-03-11 08:18:08 -0500152 * @param intf the interface to claim
153 * @param force true to disconnect kernel driver if necessary
154 * @return true if the interface was successfully claimed
155 */
156 public boolean claimInterface(UsbInterface intf, boolean force) {
157 return native_claim_interface(intf.getId(), force);
158 }
159
160 /**
161 * Releases exclusive access to a {@link android.hardware.usb.UsbInterface}.
162 *
163 * @return true if the interface was successfully released
164 */
165 public boolean releaseInterface(UsbInterface intf) {
166 return native_release_interface(intf.getId());
167 }
168
169 /**
Mike Lockwood7531aa22014-01-13 10:31:01 -0800170 * Sets the current {@link android.hardware.usb.UsbInterface}.
171 * Used to select between two interfaces with the same ID but different alternate setting.
172 *
Mike Lockwoodfa2b3fc2014-05-20 08:08:37 -0700173 * @return true if the interface was successfully selected
Mike Lockwood7531aa22014-01-13 10:31:01 -0800174 */
175 public boolean setInterface(UsbInterface intf) {
176 return native_set_interface(intf.getId(), intf.getAlternateSetting());
177 }
178
179 /**
180 * Sets the device's current {@link android.hardware.usb.UsbConfiguration}.
181 *
182 * @return true if the configuration was successfully set
183 */
184 public boolean setConfiguration(UsbConfiguration configuration) {
185 return native_set_configuration(configuration.getId());
186 }
187
188 /**
Mike Lockwoodacc29cc2011-03-11 08:18:08 -0500189 * Performs a control transaction on endpoint zero for this device.
190 * The direction of the transfer is determined by the request type.
191 * If requestType & {@link UsbConstants#USB_ENDPOINT_DIR_MASK} is
192 * {@link UsbConstants#USB_DIR_OUT}, then the transfer is a write,
193 * and if it is {@link UsbConstants#USB_DIR_IN}, then the transfer
194 * is a read.
Jeff Browne783d992013-04-18 19:15:17 -0700195 * <p>
196 * This method transfers data starting from index 0 in the buffer.
197 * To specify a different offset, use
198 * {@link #controlTransfer(int, int, int, int, byte[], int, int, int)}.
199 * </p>
Mike Lockwoodacc29cc2011-03-11 08:18:08 -0500200 *
201 * @param requestType request type for this transaction
202 * @param request request ID for this transaction
203 * @param value value field for this transaction
204 * @param index index field for this transaction
205 * @param buffer buffer for data portion of transaction,
206 * or null if no data needs to be sent or received
207 * @param length the length of the data to send or receive
208 * @param timeout in milliseconds
209 * @return length of data transferred (or zero) for success,
210 * or negative value for failure
211 */
212 public int controlTransfer(int requestType, int request, int value,
213 int index, byte[] buffer, int length, int timeout) {
Jeff Brown6c81a932013-03-28 03:13:09 -0700214 return controlTransfer(requestType, request, value, index, buffer, 0, length, timeout);
215 }
216
217 /**
218 * Performs a control transaction on endpoint zero for this device.
219 * The direction of the transfer is determined by the request type.
220 * If requestType & {@link UsbConstants#USB_ENDPOINT_DIR_MASK} is
221 * {@link UsbConstants#USB_DIR_OUT}, then the transfer is a write,
222 * and if it is {@link UsbConstants#USB_DIR_IN}, then the transfer
223 * is a read.
224 *
225 * @param requestType request type for this transaction
226 * @param request request ID for this transaction
227 * @param value value field for this transaction
228 * @param index index field for this transaction
229 * @param buffer buffer for data portion of transaction,
230 * or null if no data needs to be sent or received
Jeff Browne783d992013-04-18 19:15:17 -0700231 * @param offset the index of the first byte in the buffer to send or receive
Jeff Brown6c81a932013-03-28 03:13:09 -0700232 * @param length the length of the data to send or receive
233 * @param timeout in milliseconds
234 * @return length of data transferred (or zero) for success,
235 * or negative value for failure
236 */
237 public int controlTransfer(int requestType, int request, int value, int index,
Jeff Browne783d992013-04-18 19:15:17 -0700238 byte[] buffer, int offset, int length, int timeout) {
239 checkBounds(buffer, offset, length);
Jeff Brown6c81a932013-03-28 03:13:09 -0700240 return native_control_request(requestType, request, value, index,
Jeff Browne783d992013-04-18 19:15:17 -0700241 buffer, offset, length, timeout);
Mike Lockwoodacc29cc2011-03-11 08:18:08 -0500242 }
243
244 /**
245 * Performs a bulk transaction on the given endpoint.
Jeff Browne783d992013-04-18 19:15:17 -0700246 * The direction of the transfer is determined by the direction of the endpoint.
247 * <p>
248 * This method transfers data starting from index 0 in the buffer.
249 * To specify a different offset, use
250 * {@link #bulkTransfer(UsbEndpoint, byte[], int, int, int)}.
251 * </p>
Mike Lockwoodacc29cc2011-03-11 08:18:08 -0500252 *
253 * @param endpoint the endpoint for this transaction
Philip P. Moltmann5e040ae2016-09-20 14:09:20 -0700254 * @param buffer buffer for data to send or receive; can be {@code null} to wait for next
255 * transaction without reading data
Jerry Zhang910e9b02018-02-07 16:14:25 -0800256 * @param length the length of the data to send or receive. Before
257 * {@value Build.VERSION_CODES#P}, a value larger than 16384 bytes
258 * would be truncated down to 16384. In API {@value Build.VERSION_CODES#P}
259 * and after, any value of length is valid.
Philip P. Moltmann5e040ae2016-09-20 14:09:20 -0700260 * @param timeout in milliseconds, 0 is infinite
Jeff Brown6c81a932013-03-28 03:13:09 -0700261 * @return length of data transferred (or zero) for success,
262 * or negative value for failure
Jeff Brown6c81a932013-03-28 03:13:09 -0700263 */
Jeff Brown6c81a932013-03-28 03:13:09 -0700264 public int bulkTransfer(UsbEndpoint endpoint,
265 byte[] buffer, int length, int timeout) {
266 return bulkTransfer(endpoint, buffer, 0, length, timeout);
267 }
268
269 /**
270 * Performs a bulk transaction on the given endpoint.
Jeff Browne783d992013-04-18 19:15:17 -0700271 * The direction of the transfer is determined by the direction of the endpoint.
Jeff Brown6c81a932013-03-28 03:13:09 -0700272 *
273 * @param endpoint the endpoint for this transaction
274 * @param buffer buffer for data to send or receive
Jeff Browne783d992013-04-18 19:15:17 -0700275 * @param offset the index of the first byte in the buffer to send or receive
Jerry Zhang910e9b02018-02-07 16:14:25 -0800276 * @param length the length of the data to send or receive. Before
277 * {@value Build.VERSION_CODES#P}, a value larger than 16384 bytes
278 * would be truncated down to 16384. In API {@value Build.VERSION_CODES#P}
279 * and after, any value of length is valid.
Philip P. Moltmann5e040ae2016-09-20 14:09:20 -0700280 * @param timeout in milliseconds, 0 is infinite
Mike Lockwoodacc29cc2011-03-11 08:18:08 -0500281 * @return length of data transferred (or zero) for success,
282 * or negative value for failure
283 */
Jeff Brown6c81a932013-03-28 03:13:09 -0700284 public int bulkTransfer(UsbEndpoint endpoint,
Jeff Browne783d992013-04-18 19:15:17 -0700285 byte[] buffer, int offset, int length, int timeout) {
286 checkBounds(buffer, offset, length);
Jerry Zhang910e9b02018-02-07 16:14:25 -0800287 if (mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.P
288 && length > UsbRequest.MAX_USBFS_BUFFER_SIZE) {
289 length = UsbRequest.MAX_USBFS_BUFFER_SIZE;
290 }
Jeff Browne783d992013-04-18 19:15:17 -0700291 return native_bulk_request(endpoint.getAddress(), buffer, offset, length, timeout);
Mike Lockwoodacc29cc2011-03-11 08:18:08 -0500292 }
293
294 /**
Keun-young Parkbadbbae2016-01-05 13:27:29 -0800295 * Reset USB port for the connected device.
296 *
297 * @return true if reset succeeds.
298 *
299 * @hide
300 */
301 @SystemApi
Jeff Sharkey6f95ab22017-07-17 13:15:16 -0600302 @SuppressLint("Doclava125")
Keun-young Parkbadbbae2016-01-05 13:27:29 -0800303 public boolean resetDevice() {
304 return native_reset_device();
305 }
306
307 /**
Mike Lockwoodacc29cc2011-03-11 08:18:08 -0500308 * Waits for the result of a {@link android.hardware.usb.UsbRequest#queue} operation
Philip P. Moltmann5dd4e6c2016-09-23 15:31:23 -0700309 * <p>Note that this may return requests queued on multiple
310 * {@link android.hardware.usb.UsbEndpoint}s. When multiple endpoints are in use,
311 * {@link android.hardware.usb.UsbRequest#getEndpoint} and {@link
312 * android.hardware.usb.UsbRequest#getClientData} can be useful in determining how to process
313 * the result of this function.</p>
Mike Lockwoodacc29cc2011-03-11 08:18:08 -0500314 *
315 * @return a completed USB request, or null if an error occurred
Philip P. Moltmann5dd4e6c2016-09-23 15:31:23 -0700316 *
Philip P. Moltmann9b6dd2b2017-04-06 15:34:04 -0700317 * @throws IllegalArgumentException Before API {@value Build.VERSION_CODES#O}: if the number of
318 * bytes read or written is more than the limit of the
319 * request's buffer. The number of bytes is determined by the
320 * {@code length} parameter of
Philip P. Moltmann5dd4e6c2016-09-23 15:31:23 -0700321 * {@link UsbRequest#queue(ByteBuffer, int)}
Philip P. Moltmann9b6dd2b2017-04-06 15:34:04 -0700322 * @throws BufferOverflowException In API {@value Build.VERSION_CODES#O} and after: if the
323 * number of bytes read or written is more than the limit of the
324 * request's buffer. The number of bytes is determined by the
325 * {@code length} parameter of
326 * {@link UsbRequest#queue(ByteBuffer, int)}
Mike Lockwoodacc29cc2011-03-11 08:18:08 -0500327 */
328 public UsbRequest requestWait() {
Philip P. Moltmann9b6dd2b2017-04-06 15:34:04 -0700329 UsbRequest request = null;
330 try {
331 // -1 is special value indicating infinite wait
332 request = native_request_wait(-1);
333 } catch (TimeoutException e) {
334 // Does not happen, infinite timeout
335 }
336
Philip P. Moltmann927fefe2016-10-18 12:57:34 -0700337 if (request != null) {
Philip P. Moltmann9b6dd2b2017-04-06 15:34:04 -0700338 request.dequeue(
339 mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.O);
Philip P. Moltmann927fefe2016-10-18 12:57:34 -0700340 }
341 return request;
342 }
343
344 /**
345 * Waits for the result of a {@link android.hardware.usb.UsbRequest#queue} operation
346 * <p>Note that this may return requests queued on multiple
347 * {@link android.hardware.usb.UsbEndpoint}s. When multiple endpoints are in use,
348 * {@link android.hardware.usb.UsbRequest#getEndpoint} and {@link
349 * android.hardware.usb.UsbRequest#getClientData} can be useful in determining how to process
350 * the result of this function.</p>
Philip P. Moltmann927fefe2016-10-18 12:57:34 -0700351 * <p>Android processes {@link UsbRequest UsbRequests} asynchronously. Hence it is not
Philip P. Moltmann9b6dd2b2017-04-06 15:34:04 -0700352 * guaranteed that {@link #requestWait(long) requestWait(0)} returns a request that has been
Philip P. Moltmann927fefe2016-10-18 12:57:34 -0700353 * queued right before even if the request could have been processed immediately.</p>
354 *
355 * @param timeout timeout in milliseconds. If 0 this method does not wait.
356 *
Philip P. Moltmann9b6dd2b2017-04-06 15:34:04 -0700357 * @return a completed USB request, or {@code null} if an error occurred
Philip P. Moltmann927fefe2016-10-18 12:57:34 -0700358 *
Philip P. Moltmann9b6dd2b2017-04-06 15:34:04 -0700359 * @throws BufferOverflowException if the number of bytes read or written is more than the
360 * limit of the request's buffer. The number of bytes is
361 * determined by the {@code length} parameter of
362 * {@link UsbRequest#queue(ByteBuffer, int)}
363 * @throws TimeoutException if no request was received in {@code timeout} milliseconds.
Philip P. Moltmann927fefe2016-10-18 12:57:34 -0700364 */
Philip P. Moltmann9b6dd2b2017-04-06 15:34:04 -0700365 public UsbRequest requestWait(long timeout) throws TimeoutException {
Philip P. Moltmann08b678c2016-10-18 17:43:37 -0700366 timeout = Preconditions.checkArgumentNonnegative(timeout, "timeout");
Philip P. Moltmann927fefe2016-10-18 12:57:34 -0700367
368 UsbRequest request = native_request_wait(timeout);
Mike Lockwoodacc29cc2011-03-11 08:18:08 -0500369 if (request != null) {
Philip P. Moltmann9b6dd2b2017-04-06 15:34:04 -0700370 request.dequeue(true);
Mike Lockwoodacc29cc2011-03-11 08:18:08 -0500371 }
372 return request;
373 }
374
375 /**
376 * Returns the serial number for the device.
377 * This will return null if the device has not been opened.
378 *
379 * @return the device serial number
380 */
381 public String getSerial() {
382 return native_get_serial();
383 }
384
Jeff Brown6c81a932013-03-28 03:13:09 -0700385 private static void checkBounds(byte[] buffer, int start, int length) {
386 final int bufferLength = (buffer != null ? buffer.length : 0);
Philip P. Moltmann5e040ae2016-09-20 14:09:20 -0700387 if (length < 0 || start < 0 || start + length > bufferLength) {
Jeff Brown6c81a932013-03-28 03:13:09 -0700388 throw new IllegalArgumentException("Buffer start or length out of bounds.");
389 }
390 }
391
Philip P. Moltmann674e8c32016-08-29 12:28:31 -0700392 @Override
393 protected void finalize() throws Throwable {
394 try {
Narayan Kamath492e9e82017-03-22 14:28:08 +0000395 if (mCloseGuard != null) {
396 mCloseGuard.warnIfOpen();
397 }
Philip P. Moltmann674e8c32016-08-29 12:28:31 -0700398 } finally {
399 super.finalize();
400 }
401 }
402
Mike Lockwoodacc29cc2011-03-11 08:18:08 -0500403 private native boolean native_open(String deviceName, FileDescriptor pfd);
404 private native void native_close();
405 private native int native_get_fd();
Mike Lockwooda88b42d2011-05-19 11:52:40 -0400406 private native byte[] native_get_desc();
Mike Lockwoodacc29cc2011-03-11 08:18:08 -0500407 private native boolean native_claim_interface(int interfaceID, boolean force);
408 private native boolean native_release_interface(int interfaceID);
Mike Lockwood7531aa22014-01-13 10:31:01 -0800409 private native boolean native_set_interface(int interfaceID, int alternateSetting);
410 private native boolean native_set_configuration(int configurationID);
Mike Lockwoodacc29cc2011-03-11 08:18:08 -0500411 private native int native_control_request(int requestType, int request, int value,
Jeff Browne783d992013-04-18 19:15:17 -0700412 int index, byte[] buffer, int offset, int length, int timeout);
Jeff Brown6c81a932013-03-28 03:13:09 -0700413 private native int native_bulk_request(int endpoint, byte[] buffer,
Jeff Browne783d992013-04-18 19:15:17 -0700414 int offset, int length, int timeout);
Philip P. Moltmann9b6dd2b2017-04-06 15:34:04 -0700415 private native UsbRequest native_request_wait(long timeout) throws TimeoutException;
Mike Lockwoodacc29cc2011-03-11 08:18:08 -0500416 private native String native_get_serial();
Keun-young Parkbadbbae2016-01-05 13:27:29 -0800417 private native boolean native_reset_device();
Mike Lockwoodacc29cc2011-03-11 08:18:08 -0500418}