1e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood/* 2e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * Copyright (C) 2010 The Android Open Source Project 3e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * 4e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * Licensed under the Apache License, Version 2.0 (the "License"); 5e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * you may not use this file except in compliance with the License. 6e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * You may obtain a copy of the License at 7e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * 8e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * http://www.apache.org/licenses/LICENSE-2.0 9e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * 10e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * Unless required by applicable law or agreed to in writing, software 11e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * distributed under the License is distributed on an "AS IS" BASIS, 12e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * See the License for the specific language governing permissions and 14e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * limitations under the License. 15e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood */ 16e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood 17c4308f01c965571dc2354107c3574df113e397eeMike Lockwoodpackage android.hardware.usb; 18e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood 19e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodimport android.util.Log; 20e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood 21e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodimport java.nio.ByteBuffer; 22e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood 23e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood/** 24e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * A class representing USB request packet. 25e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * This can be used for both reading and writing data to or from a 26acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood * {@link android.hardware.usb.UsbDeviceConnection}. 2711dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood * UsbRequests can be used to transfer data on bulk and interrupt endpoints. 2811dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood * Requests on bulk endpoints can be sent synchronously via {@link UsbDeviceConnection#bulkTransfer} 2911dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood * or asynchronously via {@link #queue} and {@link UsbDeviceConnection#requestWait}. 3011dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood * Requests on interrupt endpoints are only send and received asynchronously. 3111dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood * 3211dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood * <p>Requests on endpoint zero are not supported by this class; 3311dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood * use {@link UsbDeviceConnection#controlTransfer} for endpoint zero requests instead. 34e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood */ 35e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodpublic class UsbRequest { 36e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood 37e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood private static final String TAG = "UsbRequest"; 38e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood 39e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood // used by the JNI code 40e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood private int mNativeContext; 41e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood 42e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood private UsbEndpoint mEndpoint; 43e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood 44e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood // for temporarily saving current buffer across queue and dequeue 45e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood private ByteBuffer mBuffer; 46e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood private int mLength; 47e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood 48e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood // for client use 49e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood private Object mClientData; 50e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood 51e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood public UsbRequest() { 52e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood } 53e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood 54e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood /** 55e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * Initializes the request so it can read or write data on the given endpoint. 56e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * Whether the request allows reading or writing depends on the direction of the endpoint. 57e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * 58e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * @param endpoint the endpoint to be used for this request. 59e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * @return true if the request was successfully opened. 60e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood */ 61acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood public boolean initialize(UsbDeviceConnection connection, UsbEndpoint endpoint) { 62e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood mEndpoint = endpoint; 63acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood return native_init(connection, endpoint.getAddress(), endpoint.getAttributes(), 64e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood endpoint.getMaxPacketSize(), endpoint.getInterval()); 65e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood } 66e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood 67e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood /** 68e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * Releases all resources related to this request. 69e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood */ 70e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood public void close() { 71e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood mEndpoint = null; 72e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood native_close(); 73e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood } 74e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood 75e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood @Override 76e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood protected void finalize() throws Throwable { 77e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood try { 78e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood if (mEndpoint != null) { 79e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood Log.v(TAG, "endpoint still open in finalize(): " + this); 80e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood close(); 81e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood } 82e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood } finally { 83e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood super.finalize(); 84e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood } 85e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood } 86e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood 87e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood /** 88e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * Returns the endpoint for the request, or null if the request is not opened. 89e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * 90e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * @return the request's endpoint 91e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood */ 92e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood public UsbEndpoint getEndpoint() { 93e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood return mEndpoint; 94e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood } 95e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood 96e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood /** 97e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * Returns the client data for the request. 98e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * This can be used in conjunction with {@link #setClientData} 99e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * to associate another object with this request, which can be useful for 100e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * maintaining state between calls to {@link #queue} and 101acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood * {@link android.hardware.usb.UsbDeviceConnection#requestWait} 102e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * 103e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * @return the client data for the request 104e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood */ 105e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood public Object getClientData() { 106e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood return mClientData; 107e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood } 108e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood 109e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood /** 110e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * Sets the client data for the request. 111e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * This can be used in conjunction with {@link #getClientData} 112e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * to associate another object with this request, which can be useful for 113e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * maintaining state between calls to {@link #queue} and 114acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood * {@link android.hardware.usb.UsbDeviceConnection#requestWait} 115e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * 116e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * @param data the client data for the request 117e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood */ 118e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood public void setClientData(Object data) { 119e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood mClientData = data; 120e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood } 121e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood 122e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood /** 123e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * Queues the request to send or receive data on its endpoint. 124e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * For OUT endpoints, the given buffer data will be sent on the endpoint. 125e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * For IN endpoints, the endpoint will attempt to read the given number of bytes 126e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * into the specified buffer. 127e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * If the queueing operation is successful, we return true and the result will be 128acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood * returned via {@link android.hardware.usb.UsbDeviceConnection#requestWait} 129e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * 130e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * @param buffer the buffer containing the bytes to write, or location to store 131e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * the results of a read 132e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * @param length number of bytes to read or write 133e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * @return true if the queueing operation succeeded 134e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood */ 135e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood public boolean queue(ByteBuffer buffer, int length) { 136e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood boolean out = (mEndpoint.getDirection() == UsbConstants.USB_DIR_OUT); 137e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood boolean result; 138e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood if (buffer.isDirect()) { 139e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood result = native_queue_direct(buffer, length, out); 140e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood } else if (buffer.hasArray()) { 141e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood result = native_queue_array(buffer.array(), length, out); 142e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood } else { 143e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood throw new IllegalArgumentException("buffer is not direct and has no array"); 144e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood } 145e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood if (result) { 146e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood // save our buffer for when the request has completed 147e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood mBuffer = buffer; 148e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood mLength = length; 149e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood } 150e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood return result; 151e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood } 152e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood 153e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood /* package */ void dequeue() { 154e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood boolean out = (mEndpoint.getDirection() == UsbConstants.USB_DIR_OUT); 155a3665ba95d806fcb6780d29d49bd0f1032e8bc86mike wakerly int bytesRead; 156e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood if (mBuffer.isDirect()) { 157a3665ba95d806fcb6780d29d49bd0f1032e8bc86mike wakerly bytesRead = native_dequeue_direct(); 158e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood } else { 159a3665ba95d806fcb6780d29d49bd0f1032e8bc86mike wakerly bytesRead = native_dequeue_array(mBuffer.array(), mLength, out); 160a3665ba95d806fcb6780d29d49bd0f1032e8bc86mike wakerly } 161a3665ba95d806fcb6780d29d49bd0f1032e8bc86mike wakerly if (bytesRead >= 0) { 162a3665ba95d806fcb6780d29d49bd0f1032e8bc86mike wakerly mBuffer.position(Math.min(bytesRead, mLength)); 163e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood } 164e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood mBuffer = null; 165e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood mLength = 0; 166e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood } 167e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood 168e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood /** 169e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * Cancels a pending queue operation. 170e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * 171e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * @return true if cancelling succeeded 172e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood */ 173e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood public boolean cancel() { 174e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood return native_cancel(); 175e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood } 176e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood 177acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood private native boolean native_init(UsbDeviceConnection connection, int ep_address, 178acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood int ep_attributes, int ep_max_packet_size, int ep_interval); 179e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood private native void native_close(); 180e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood private native boolean native_queue_array(byte[] buffer, int length, boolean out); 181a3665ba95d806fcb6780d29d49bd0f1032e8bc86mike wakerly private native int native_dequeue_array(byte[] buffer, int length, boolean out); 182e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood private native boolean native_queue_direct(ByteBuffer buffer, int length, boolean out); 183a3665ba95d806fcb6780d29d49bd0f1032e8bc86mike wakerly private native int native_dequeue_direct(); 184e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood private native boolean native_cancel(); 185e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood} 186