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