| /* |
| * Copyright (C) 2010 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.util.Log; |
| |
| import java.nio.ByteBuffer; |
| |
| /** |
| * A class representing USB request packet. |
| * This can be used for both reading and writing data to or from a |
| * {@link android.hardware.usb.UsbDeviceConnection}. |
| * UsbRequests can be used to transfer data on bulk and interrupt endpoints. |
| * Requests on bulk endpoints can be sent synchronously via {@link UsbDeviceConnection#bulkTransfer} |
| * or asynchronously via {@link #queue} and {@link UsbDeviceConnection#requestWait}. |
| * Requests on interrupt endpoints are only send and received asynchronously. |
| * |
| * <p>Requests on endpoint zero are not supported by this class; |
| * use {@link UsbDeviceConnection#controlTransfer} for endpoint zero requests instead. |
| */ |
| public class UsbRequest { |
| |
| private static final String TAG = "UsbRequest"; |
| |
| // used by the JNI code |
| private long mNativeContext; |
| |
| private UsbEndpoint mEndpoint; |
| |
| // for temporarily saving current buffer across queue and dequeue |
| private ByteBuffer mBuffer; |
| private int mLength; |
| |
| // for client use |
| private Object mClientData; |
| |
| public UsbRequest() { |
| } |
| |
| /** |
| * Initializes the request so it can read or write data on the given endpoint. |
| * Whether the request allows reading or writing depends on the direction of the endpoint. |
| * |
| * @param endpoint the endpoint to be used for this request. |
| * @return true if the request was successfully opened. |
| */ |
| public boolean initialize(UsbDeviceConnection connection, UsbEndpoint endpoint) { |
| mEndpoint = endpoint; |
| return native_init(connection, endpoint.getAddress(), endpoint.getAttributes(), |
| endpoint.getMaxPacketSize(), endpoint.getInterval()); |
| } |
| |
| /** |
| * Releases all resources related to this request. |
| */ |
| public void close() { |
| mEndpoint = null; |
| native_close(); |
| } |
| |
| @Override |
| protected void finalize() throws Throwable { |
| try { |
| if (mEndpoint != null) { |
| Log.v(TAG, "endpoint still open in finalize(): " + this); |
| close(); |
| } |
| } finally { |
| super.finalize(); |
| } |
| } |
| |
| /** |
| * Returns the endpoint for the request, or null if the request is not opened. |
| * |
| * @return the request's endpoint |
| */ |
| public UsbEndpoint getEndpoint() { |
| return mEndpoint; |
| } |
| |
| /** |
| * Returns the client data for the request. |
| * This can be used in conjunction with {@link #setClientData} |
| * to associate another object with this request, which can be useful for |
| * maintaining state between calls to {@link #queue} and |
| * {@link android.hardware.usb.UsbDeviceConnection#requestWait} |
| * |
| * @return the client data for the request |
| */ |
| public Object getClientData() { |
| return mClientData; |
| } |
| |
| /** |
| * Sets the client data for the request. |
| * This can be used in conjunction with {@link #getClientData} |
| * to associate another object with this request, which can be useful for |
| * maintaining state between calls to {@link #queue} and |
| * {@link android.hardware.usb.UsbDeviceConnection#requestWait} |
| * |
| * @param data the client data for the request |
| */ |
| public void setClientData(Object data) { |
| mClientData = data; |
| } |
| |
| /** |
| * Queues the request to send or receive data on its endpoint. |
| * For OUT endpoints, the given buffer data will be sent on the endpoint. |
| * For IN endpoints, the endpoint will attempt to read the given number of bytes |
| * into the specified buffer. |
| * If the queueing operation is successful, we return true and the result will be |
| * returned via {@link android.hardware.usb.UsbDeviceConnection#requestWait} |
| * |
| * @param buffer the buffer containing the bytes to write, or location to store |
| * the results of a read |
| * @param length number of bytes to read or write |
| * @return true if the queueing operation succeeded |
| */ |
| public boolean queue(ByteBuffer buffer, int length) { |
| boolean out = (mEndpoint.getDirection() == UsbConstants.USB_DIR_OUT); |
| boolean result; |
| if (buffer.isDirect()) { |
| result = native_queue_direct(buffer, length, out); |
| } else if (buffer.hasArray()) { |
| result = native_queue_array(buffer.array(), length, out); |
| } else { |
| throw new IllegalArgumentException("buffer is not direct and has no array"); |
| } |
| if (result) { |
| // save our buffer for when the request has completed |
| mBuffer = buffer; |
| mLength = length; |
| } |
| return result; |
| } |
| |
| /* package */ void dequeue() { |
| boolean out = (mEndpoint.getDirection() == UsbConstants.USB_DIR_OUT); |
| int bytesRead; |
| if (mBuffer.isDirect()) { |
| bytesRead = native_dequeue_direct(); |
| } else { |
| bytesRead = native_dequeue_array(mBuffer.array(), mLength, out); |
| } |
| if (bytesRead >= 0) { |
| mBuffer.position(Math.min(bytesRead, mLength)); |
| } |
| mBuffer = null; |
| mLength = 0; |
| } |
| |
| /** |
| * Cancels a pending queue operation. |
| * |
| * @return true if cancelling succeeded |
| */ |
| public boolean cancel() { |
| return native_cancel(); |
| } |
| |
| private native boolean native_init(UsbDeviceConnection connection, int ep_address, |
| int ep_attributes, int ep_max_packet_size, int ep_interval); |
| private native void native_close(); |
| private native boolean native_queue_array(byte[] buffer, int length, boolean out); |
| private native int native_dequeue_array(byte[] buffer, int length, boolean out); |
| private native boolean native_queue_direct(ByteBuffer buffer, int length, boolean out); |
| private native int native_dequeue_direct(); |
| private native boolean native_cancel(); |
| } |