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.util.Log; 20 21 import java.nio.ByteBuffer; 22 23 /** 24 * A class representing USB request packet. 25 * This can be used for both reading and writing data to or from a 26 * {@link android.hardware.usb.UsbDeviceConnection}. 27 * UsbRequests can be used to transfer data on bulk and interrupt endpoints. 28 * Requests on bulk endpoints can be sent synchronously via {@link UsbDeviceConnection#bulkTransfer} 29 * or asynchronously via {@link #queue} and {@link UsbDeviceConnection#requestWait}. 30 * Requests on interrupt endpoints are only send and received asynchronously. 31 * 32 * <p>Requests on endpoint zero are not supported by this class; 33 * use {@link UsbDeviceConnection#controlTransfer} for endpoint zero requests instead. 34 */ 35 public class UsbRequest { 36 37 private static final String TAG = "UsbRequest"; 38 39 // used by the JNI code 40 private long mNativeContext; 41 42 private UsbEndpoint mEndpoint; 43 44 // for temporarily saving current buffer across queue and dequeue 45 private ByteBuffer mBuffer; 46 private int mLength; 47 48 // for client use 49 private Object mClientData; 50 UsbRequest()51 public UsbRequest() { 52 } 53 54 /** 55 * Initializes the request so it can read or write data on the given endpoint. 56 * Whether the request allows reading or writing depends on the direction of the endpoint. 57 * 58 * @param endpoint the endpoint to be used for this request. 59 * @return true if the request was successfully opened. 60 */ initialize(UsbDeviceConnection connection, UsbEndpoint endpoint)61 public boolean initialize(UsbDeviceConnection connection, UsbEndpoint endpoint) { 62 mEndpoint = endpoint; 63 return native_init(connection, endpoint.getAddress(), endpoint.getAttributes(), 64 endpoint.getMaxPacketSize(), endpoint.getInterval()); 65 } 66 67 /** 68 * Releases all resources related to this request. 69 */ close()70 public void close() { 71 mEndpoint = null; 72 native_close(); 73 } 74 75 @Override finalize()76 protected void finalize() throws Throwable { 77 try { 78 if (mEndpoint != null) { 79 Log.v(TAG, "endpoint still open in finalize(): " + this); 80 close(); 81 } 82 } finally { 83 super.finalize(); 84 } 85 } 86 87 /** 88 * Returns the endpoint for the request, or null if the request is not opened. 89 * 90 * @return the request's endpoint 91 */ getEndpoint()92 public UsbEndpoint getEndpoint() { 93 return mEndpoint; 94 } 95 96 /** 97 * Returns the client data for the request. 98 * This can be used in conjunction with {@link #setClientData} 99 * to associate another object with this request, which can be useful for 100 * maintaining state between calls to {@link #queue} and 101 * {@link android.hardware.usb.UsbDeviceConnection#requestWait} 102 * 103 * @return the client data for the request 104 */ getClientData()105 public Object getClientData() { 106 return mClientData; 107 } 108 109 /** 110 * Sets the client data for the request. 111 * This can be used in conjunction with {@link #getClientData} 112 * to associate another object with this request, which can be useful for 113 * maintaining state between calls to {@link #queue} and 114 * {@link android.hardware.usb.UsbDeviceConnection#requestWait} 115 * 116 * @param data the client data for the request 117 */ setClientData(Object data)118 public void setClientData(Object data) { 119 mClientData = data; 120 } 121 122 /** 123 * Queues the request to send or receive data on its endpoint. 124 * For OUT endpoints, the given buffer data will be sent on the endpoint. 125 * For IN endpoints, the endpoint will attempt to read the given number of bytes 126 * into the specified buffer. 127 * If the queueing operation is successful, we return true and the result will be 128 * returned via {@link android.hardware.usb.UsbDeviceConnection#requestWait} 129 * 130 * @param buffer the buffer containing the bytes to write, or location to store 131 * the results of a read 132 * @param length number of bytes to read or write 133 * @return true if the queueing operation succeeded 134 */ queue(ByteBuffer buffer, int length)135 public boolean queue(ByteBuffer buffer, int length) { 136 boolean out = (mEndpoint.getDirection() == UsbConstants.USB_DIR_OUT); 137 boolean result; 138 if (buffer.isDirect()) { 139 result = native_queue_direct(buffer, length, out); 140 } else if (buffer.hasArray()) { 141 result = native_queue_array(buffer.array(), length, out); 142 } else { 143 throw new IllegalArgumentException("buffer is not direct and has no array"); 144 } 145 if (result) { 146 // save our buffer for when the request has completed 147 mBuffer = buffer; 148 mLength = length; 149 } 150 return result; 151 } 152 dequeue()153 /* package */ void dequeue() { 154 boolean out = (mEndpoint.getDirection() == UsbConstants.USB_DIR_OUT); 155 int bytesRead; 156 if (mBuffer.isDirect()) { 157 bytesRead = native_dequeue_direct(); 158 } else { 159 bytesRead = native_dequeue_array(mBuffer.array(), mLength, out); 160 } 161 if (bytesRead >= 0) { 162 mBuffer.position(Math.min(bytesRead, mLength)); 163 } 164 mBuffer = null; 165 mLength = 0; 166 } 167 168 /** 169 * Cancels a pending queue operation. 170 * 171 * @return true if cancelling succeeded 172 */ cancel()173 public boolean cancel() { 174 return native_cancel(); 175 } 176 native_init(UsbDeviceConnection connection, int ep_address, int ep_attributes, int ep_max_packet_size, int ep_interval)177 private native boolean native_init(UsbDeviceConnection connection, int ep_address, 178 int ep_attributes, int ep_max_packet_size, int ep_interval); native_close()179 private native void native_close(); native_queue_array(byte[] buffer, int length, boolean out)180 private native boolean native_queue_array(byte[] buffer, int length, boolean out); native_dequeue_array(byte[] buffer, int length, boolean out)181 private native int native_dequeue_array(byte[] buffer, int length, boolean out); native_queue_direct(ByteBuffer buffer, int length, boolean out)182 private native boolean native_queue_direct(ByteBuffer buffer, int length, boolean out); native_dequeue_direct()183 private native int native_dequeue_direct(); native_cancel()184 private native boolean native_cancel(); 185 } 186