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
17e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood#define LOG_TAG "UsbRequestJNI"
18e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
19e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood#include "utils/Log.h"
20e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
21e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood#include "jni.h"
22e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood#include "JNIHelp.h"
23e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood#include "android_runtime/AndroidRuntime.h"
24e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
25e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood#include <usbhost/usbhost.h>
26e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
27e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood#include <stdio.h>
28e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
29e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodusing namespace android;
30e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
31e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodstatic jfieldID field_context;
32e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
33e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodstruct usb_request* get_request_from_object(JNIEnv* env, jobject java_request)
34e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood{
35e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    return (struct usb_request*)env->GetIntField(java_request, field_context);
36e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood}
37e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
38acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood// in android_hardware_UsbDeviceConnection.cpp
39acc29cc91be634070c92a807df412ced97b9b375Mike Lockwoodextern struct usb_device* get_device_from_object(JNIEnv* env, jobject connection);
40e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
41e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodstatic jboolean
42e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodandroid_hardware_UsbRequest_init(JNIEnv *env, jobject thiz, jobject java_device,
43e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        jint ep_address, jint ep_attributes, jint ep_max_packet_size, jint ep_interval)
44e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood{
455baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    ALOGD("init\n");
46e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
47e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    struct usb_device* device = get_device_from_object(env, java_device);
48e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    if (!device) {
493762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("device null in native_init");
50e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        return false;
51e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
52e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
53e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    // construct an endpoint descriptor from the Java object fields
54e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    struct usb_endpoint_descriptor desc;
55e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    desc.bLength = USB_DT_ENDPOINT_SIZE;
56e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    desc.bDescriptorType = USB_DT_ENDPOINT;
57e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    desc.bEndpointAddress = ep_address;
58e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    desc.bmAttributes = ep_attributes;
59e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    desc.wMaxPacketSize = ep_max_packet_size;
60e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    desc.bInterval = ep_interval;
61e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
62e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    struct usb_request* request = usb_request_new(device, &desc);
63e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    if (request)
64e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        env->SetIntField(thiz, field_context, (int)request);
65e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    return (request != NULL);
66e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood}
67e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
68e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodstatic void
69e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodandroid_hardware_UsbRequest_close(JNIEnv *env, jobject thiz)
70e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood{
715baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    ALOGD("close\n");
72e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    struct usb_request* request = get_request_from_object(env, thiz);
73e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    if (request) {
74e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        usb_request_free(request);
75e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        env->SetIntField(thiz, field_context, 0);
76e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
77e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood}
78e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
79e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodstatic jboolean
80e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodandroid_hardware_UsbRequest_queue_array(JNIEnv *env, jobject thiz,
81e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        jbyteArray buffer, jint length, jboolean out)
82e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood{
83e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    struct usb_request* request = get_request_from_object(env, thiz);
84e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    if (!request) {
853762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("request is closed in native_queue");
86e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        return false;
87e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
88e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
89e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    if (buffer && length) {
90e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        request->buffer = malloc(length);
91e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        if (!request->buffer)
92e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood            return false;
93a3665ba95d806fcb6780d29d49bd0f1032e8bc86mike wakerly        memset(request->buffer, 0, length);
94e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        if (out) {
95e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood            // copy data from Java buffer to native buffer
96e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood            env->GetByteArrayRegion(buffer, 0, length, (jbyte *)request->buffer);
97e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        }
98e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    } else {
99e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        request->buffer = NULL;
100e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
101e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    request->buffer_length = length;
102e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
103e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    if (usb_request_queue(request)) {
104e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        if (request->buffer) {
105e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood            // free our buffer if usb_request_queue fails
106e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood            free(request->buffer);
107e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood            request->buffer = NULL;
108e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        }
109e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        return false;
110e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    } else {
111acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood        // save a reference to ourselves so UsbDeviceConnection.waitRequest() can find us
112e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        request->client_data = (void *)env->NewGlobalRef(thiz);
113e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        return true;
114e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
115e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood}
116e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
117a3665ba95d806fcb6780d29d49bd0f1032e8bc86mike wakerlystatic int
118e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodandroid_hardware_UsbRequest_dequeue_array(JNIEnv *env, jobject thiz,
119e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        jbyteArray buffer, jint length, jboolean out)
120e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood{
121e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    struct usb_request* request = get_request_from_object(env, thiz);
122e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    if (!request) {
1233762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("request is closed in native_dequeue");
124a3665ba95d806fcb6780d29d49bd0f1032e8bc86mike wakerly        return -1;
125e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
126e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
127e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    if (buffer && length && request->buffer && !out) {
128e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        // copy data from native buffer to Java buffer
129e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        env->SetByteArrayRegion(buffer, 0, length, (jbyte *)request->buffer);
130e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
131e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    free(request->buffer);
132e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    env->DeleteGlobalRef((jobject)request->client_data);
133a3665ba95d806fcb6780d29d49bd0f1032e8bc86mike wakerly    return request->actual_length;
134e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood}
135e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
136e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodstatic jboolean
137e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodandroid_hardware_UsbRequest_queue_direct(JNIEnv *env, jobject thiz,
138e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        jobject buffer, jint length, jboolean out)
139e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood{
140e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    struct usb_request* request = get_request_from_object(env, thiz);
141e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    if (!request) {
1423762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("request is closed in native_queue");
143e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        return false;
144e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
145e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
146e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    if (buffer && length) {
147e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        request->buffer = env->GetDirectBufferAddress(buffer);
148e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        if (!request->buffer)
149e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood            return false;
150e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    } else {
151e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        request->buffer = NULL;
152e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
153e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    request->buffer_length = length;
154e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
155e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    if (usb_request_queue(request)) {
156e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        request->buffer = NULL;
157e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        return false;
158e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    } else {
159acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood        // save a reference to ourselves so UsbDeviceConnection.waitRequest() can find us
160e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        // we also need this to make sure our native buffer is not deallocated
161e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        // while IO is active
162e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        request->client_data = (void *)env->NewGlobalRef(thiz);
163e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        return true;
164e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
165e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood}
166e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
167a3665ba95d806fcb6780d29d49bd0f1032e8bc86mike wakerlystatic int
168e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodandroid_hardware_UsbRequest_dequeue_direct(JNIEnv *env, jobject thiz)
169e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood{
170e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    struct usb_request* request = get_request_from_object(env, thiz);
171e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    if (!request) {
1723762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("request is closed in native_dequeue");
173a3665ba95d806fcb6780d29d49bd0f1032e8bc86mike wakerly        return -1;
174e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
175e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    // all we need to do is delete our global ref
176e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    env->DeleteGlobalRef((jobject)request->client_data);
177a3665ba95d806fcb6780d29d49bd0f1032e8bc86mike wakerly    return request->actual_length;
178e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood}
179e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
180e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodstatic jboolean
181e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodandroid_hardware_UsbRequest_cancel(JNIEnv *env, jobject thiz)
182e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood{
183e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    struct usb_request* request = get_request_from_object(env, thiz);
184e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    if (!request) {
1853762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("request is closed in native_cancel");
186e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        return false;
187e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
188e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    return (usb_request_cancel(request) == 0);
189e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood}
190e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
191e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodstatic JNINativeMethod method_table[] = {
192acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood    {"native_init",             "(Landroid/hardware/usb/UsbDeviceConnection;IIII)Z",
193e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood                                            (void *)android_hardware_UsbRequest_init},
194e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    {"native_close",            "()V",      (void *)android_hardware_UsbRequest_close},
195e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    {"native_queue_array",      "([BIZ)Z",  (void *)android_hardware_UsbRequest_queue_array},
196a3665ba95d806fcb6780d29d49bd0f1032e8bc86mike wakerly    {"native_dequeue_array",    "([BIZ)I",  (void *)android_hardware_UsbRequest_dequeue_array},
197e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    {"native_queue_direct",     "(Ljava/nio/ByteBuffer;IZ)Z",
198e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood                                            (void *)android_hardware_UsbRequest_queue_direct},
199a3665ba95d806fcb6780d29d49bd0f1032e8bc86mike wakerly    {"native_dequeue_direct",   "()I",      (void *)android_hardware_UsbRequest_dequeue_direct},
200e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    {"native_cancel",           "()Z",      (void *)android_hardware_UsbRequest_cancel},
201e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood};
202e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
203e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodint register_android_hardware_UsbRequest(JNIEnv *env)
204e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood{
205c4308f01c965571dc2354107c3574df113e397eeMike Lockwood    jclass clazz = env->FindClass("android/hardware/usb/UsbRequest");
206e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    if (clazz == NULL) {
2073762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find android/hardware/usb/UsbRequest");
208e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        return -1;
209e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
210e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    field_context = env->GetFieldID(clazz, "mNativeContext", "I");
211e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    if (field_context == NULL) {
2123762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find UsbRequest.mNativeContext");
213e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        return -1;
214e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
215e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
216c4308f01c965571dc2354107c3574df113e397eeMike Lockwood    return AndroidRuntime::registerNativeMethods(env, "android/hardware/usb/UsbRequest",
217e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood            method_table, NELEM(method_table));
218e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood}
219e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
220