1 /* 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 17 package android.hardware.usb; 18 19 import android.os.ParcelFileDescriptor; 20 21 import java.io.FileDescriptor; 22 23 24 /** 25 * This class is used for sending and receiving data and control messages to a USB device. 26 * Instances of this class are created by {@link UsbManager#openDevice}. 27 */ 28 public class UsbDeviceConnection { 29 30 private static final String TAG = "UsbDeviceConnection"; 31 32 private final UsbDevice mDevice; 33 34 // used by the JNI code 35 private long mNativeContext; 36 37 /** 38 * UsbDevice should only be instantiated by UsbService implementation 39 * @hide 40 */ 41 public UsbDeviceConnection(UsbDevice device) { 42 mDevice = device; 43 } 44 45 /* package */ boolean open(String name, ParcelFileDescriptor pfd) { 46 return native_open(name, pfd.getFileDescriptor()); 47 } 48 49 /** 50 * Releases all system resources related to the device. 51 * Once the object is closed it cannot be used again. 52 * The client must call {@link UsbManager#openDevice} again 53 * to retrieve a new instance to reestablish communication with the device. 54 */ 55 public void close() { 56 native_close(); 57 } 58 59 /** 60 * Returns the native file descriptor for the device, or 61 * -1 if the device is not opened. 62 * This is intended for passing to native code to access the device. 63 * 64 * @return the native file descriptor 65 */ 66 public int getFileDescriptor() { 67 return native_get_fd(); 68 } 69 70 /** 71 * Returns the raw USB descriptors for the device. 72 * This can be used to access descriptors not supported directly 73 * via the higher level APIs. 74 * 75 * @return raw USB descriptors 76 */ 77 public byte[] getRawDescriptors() { 78 return native_get_desc(); 79 } 80 81 /** 82 * Claims exclusive access to a {@link android.hardware.usb.UsbInterface}. 83 * This must be done before sending or receiving data on any 84 * {@link android.hardware.usb.UsbEndpoint}s belonging to the interface. 85 * 86 * @param intf the interface to claim 87 * @param force true to disconnect kernel driver if necessary 88 * @return true if the interface was successfully claimed 89 */ 90 public boolean claimInterface(UsbInterface intf, boolean force) { 91 return native_claim_interface(intf.getId(), force); 92 } 93 94 /** 95 * Releases exclusive access to a {@link android.hardware.usb.UsbInterface}. 96 * 97 * @return true if the interface was successfully released 98 */ 99 public boolean releaseInterface(UsbInterface intf) { 100 return native_release_interface(intf.getId()); 101 } 102 103 /** 104 * Sets the current {@link android.hardware.usb.UsbInterface}. 105 * Used to select between two interfaces with the same ID but different alternate setting. 106 * 107 * @return true if the interface was successfully selected 108 */ 109 public boolean setInterface(UsbInterface intf) { 110 return native_set_interface(intf.getId(), intf.getAlternateSetting()); 111 } 112 113 /** 114 * Sets the device's current {@link android.hardware.usb.UsbConfiguration}. 115 * 116 * @return true if the configuration was successfully set 117 */ 118 public boolean setConfiguration(UsbConfiguration configuration) { 119 return native_set_configuration(configuration.getId()); 120 } 121 122 /** 123 * Performs a control transaction on endpoint zero for this device. 124 * The direction of the transfer is determined by the request type. 125 * If requestType & {@link UsbConstants#USB_ENDPOINT_DIR_MASK} is 126 * {@link UsbConstants#USB_DIR_OUT}, then the transfer is a write, 127 * and if it is {@link UsbConstants#USB_DIR_IN}, then the transfer 128 * is a read. 129 * <p> 130 * This method transfers data starting from index 0 in the buffer. 131 * To specify a different offset, use 132 * {@link #controlTransfer(int, int, int, int, byte[], int, int, int)}. 133 * </p> 134 * 135 * @param requestType request type for this transaction 136 * @param request request ID for this transaction 137 * @param value value field for this transaction 138 * @param index index field for this transaction 139 * @param buffer buffer for data portion of transaction, 140 * or null if no data needs to be sent or received 141 * @param length the length of the data to send or receive 142 * @param timeout in milliseconds 143 * @return length of data transferred (or zero) for success, 144 * or negative value for failure 145 */ 146 public int controlTransfer(int requestType, int request, int value, 147 int index, byte[] buffer, int length, int timeout) { 148 return controlTransfer(requestType, request, value, index, buffer, 0, length, timeout); 149 } 150 151 /** 152 * Performs a control transaction on endpoint zero for this device. 153 * The direction of the transfer is determined by the request type. 154 * If requestType & {@link UsbConstants#USB_ENDPOINT_DIR_MASK} is 155 * {@link UsbConstants#USB_DIR_OUT}, then the transfer is a write, 156 * and if it is {@link UsbConstants#USB_DIR_IN}, then the transfer 157 * is a read. 158 * 159 * @param requestType request type for this transaction 160 * @param request request ID for this transaction 161 * @param value value field for this transaction 162 * @param index index field for this transaction 163 * @param buffer buffer for data portion of transaction, 164 * or null if no data needs to be sent or received 165 * @param offset the index of the first byte in the buffer to send or receive 166 * @param length the length of the data to send or receive 167 * @param timeout in milliseconds 168 * @return length of data transferred (or zero) for success, 169 * or negative value for failure 170 */ 171 public int controlTransfer(int requestType, int request, int value, int index, 172 byte[] buffer, int offset, int length, int timeout) { 173 checkBounds(buffer, offset, length); 174 return native_control_request(requestType, request, value, index, 175 buffer, offset, length, timeout); 176 } 177 178 /** 179 * Performs a bulk transaction on the given endpoint. 180 * The direction of the transfer is determined by the direction of the endpoint. 181 * <p> 182 * This method transfers data starting from index 0 in the buffer. 183 * To specify a different offset, use 184 * {@link #bulkTransfer(UsbEndpoint, byte[], int, int, int)}. 185 * </p> 186 * 187 * @param endpoint the endpoint for this transaction 188 * @param buffer buffer for data to send or receive 189 * @param length the length of the data to send or receive 190 * @param timeout in milliseconds 191 * @return length of data transferred (or zero) for success, 192 * or negative value for failure 193 */ 194 public int bulkTransfer(UsbEndpoint endpoint, 195 byte[] buffer, int length, int timeout) { 196 return bulkTransfer(endpoint, buffer, 0, length, timeout); 197 } 198 199 /** 200 * Performs a bulk transaction on the given endpoint. 201 * The direction of the transfer is determined by the direction of the endpoint. 202 * 203 * @param endpoint the endpoint for this transaction 204 * @param buffer buffer for data to send or receive 205 * @param offset the index of the first byte in the buffer to send or receive 206 * @param length the length of the data to send or receive 207 * @param timeout in milliseconds 208 * @return length of data transferred (or zero) for success, 209 * or negative value for failure 210 */ 211 public int bulkTransfer(UsbEndpoint endpoint, 212 byte[] buffer, int offset, int length, int timeout) { 213 checkBounds(buffer, offset, length); 214 return native_bulk_request(endpoint.getAddress(), buffer, offset, length, timeout); 215 } 216 217 /** 218 * Waits for the result of a {@link android.hardware.usb.UsbRequest#queue} operation 219 * Note that this may return requests queued on multiple 220 * {@link android.hardware.usb.UsbEndpoint}s. 221 * When multiple endpoints are in use, {@link android.hardware.usb.UsbRequest#getEndpoint} and 222 * {@link android.hardware.usb.UsbRequest#getClientData} can be useful in determining 223 * how to process the result of this function. 224 * 225 * @return a completed USB request, or null if an error occurred 226 */ 227 public UsbRequest requestWait() { 228 UsbRequest request = native_request_wait(); 229 if (request != null) { 230 request.dequeue(); 231 } 232 return request; 233 } 234 235 /** 236 * Returns the serial number for the device. 237 * This will return null if the device has not been opened. 238 * 239 * @return the device serial number 240 */ 241 public String getSerial() { 242 return native_get_serial(); 243 } 244 245 private static void checkBounds(byte[] buffer, int start, int length) { 246 final int bufferLength = (buffer != null ? buffer.length : 0); 247 if (start < 0 || start + length > bufferLength) { 248 throw new IllegalArgumentException("Buffer start or length out of bounds."); 249 } 250 } 251 252 private native boolean native_open(String deviceName, FileDescriptor pfd); 253 private native void native_close(); 254 private native int native_get_fd(); 255 private native byte[] native_get_desc(); 256 private native boolean native_claim_interface(int interfaceID, boolean force); 257 private native boolean native_release_interface(int interfaceID); 258 private native boolean native_set_interface(int interfaceID, int alternateSetting); 259 private native boolean native_set_configuration(int configurationID); 260 private native int native_control_request(int requestType, int request, int value, 261 int index, byte[] buffer, int offset, int length, int timeout); 262 private native int native_bulk_request(int endpoint, byte[] buffer, 263 int offset, int length, int timeout); 264 private native UsbRequest native_request_wait(); 265 private native String native_get_serial(); 266 } 267