• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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