/*
 * 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.
 */

#define LOG_TAG "UsbRequestJNI"

#include "utils/Log.h"

#include "jni.h"
#include "JNIHelp.h"
#include "core_jni_helpers.h"

#include <usbhost/usbhost.h>

#include <stdio.h>

using namespace android;

static jfieldID field_context;

struct usb_request* get_request_from_object(JNIEnv* env, jobject java_request)
{
    return (struct usb_request*)env->GetLongField(java_request, field_context);
}

// in android_hardware_UsbDeviceConnection.cpp
extern struct usb_device* get_device_from_object(JNIEnv* env, jobject connection);

static jboolean
android_hardware_UsbRequest_init(JNIEnv *env, jobject thiz, jobject java_device,
        jint ep_address, jint ep_attributes, jint ep_max_packet_size, jint ep_interval)
{
    ALOGD("init\n");

    struct usb_device* device = get_device_from_object(env, java_device);
    if (!device) {
        ALOGE("device null in native_init");
        return false;
    }

    // construct an endpoint descriptor from the Java object fields
    struct usb_endpoint_descriptor desc;
    desc.bLength = USB_DT_ENDPOINT_SIZE;
    desc.bDescriptorType = USB_DT_ENDPOINT;
    desc.bEndpointAddress = ep_address;
    desc.bmAttributes = ep_attributes;
    desc.wMaxPacketSize = ep_max_packet_size;
    desc.bInterval = ep_interval;

    struct usb_request* request = usb_request_new(device, &desc);
    if (request)
        env->SetLongField(thiz, field_context, (jlong)request);
    return (request != NULL);
}

static void
android_hardware_UsbRequest_close(JNIEnv *env, jobject thiz)
{
    ALOGD("close\n");
    struct usb_request* request = get_request_from_object(env, thiz);
    if (request) {
        usb_request_free(request);
        env->SetLongField(thiz, field_context, 0);
    }
}

static jboolean
android_hardware_UsbRequest_queue_array(JNIEnv *env, jobject thiz,
        jbyteArray buffer, jint length, jboolean out)
{
    struct usb_request* request = get_request_from_object(env, thiz);
    if (!request) {
        ALOGE("request is closed in native_queue");
        return false;
    }

    if (buffer && length) {
        request->buffer = malloc(length);
        if (!request->buffer)
            return false;
        memset(request->buffer, 0, length);
        if (out) {
            // copy data from Java buffer to native buffer
            env->GetByteArrayRegion(buffer, 0, length, (jbyte *)request->buffer);
        }
    } else {
        request->buffer = NULL;
    }
    request->buffer_length = length;

    // save a reference to ourselves so UsbDeviceConnection.waitRequest() can find us
    request->client_data = (void *)env->NewGlobalRef(thiz);

    if (usb_request_queue(request)) {
        if (request->buffer) {
            // free our buffer if usb_request_queue fails
            free(request->buffer);
            request->buffer = NULL;
        }
        env->DeleteGlobalRef((jobject)request->client_data);
        return false;
    }
    return true;
}

static jint
android_hardware_UsbRequest_dequeue_array(JNIEnv *env, jobject thiz,
        jbyteArray buffer, jint length, jboolean out)
{
    struct usb_request* request = get_request_from_object(env, thiz);
    if (!request) {
        ALOGE("request is closed in native_dequeue");
        return (jint) -1;
    }

    if (buffer && length && request->buffer && !out) {
        // copy data from native buffer to Java buffer
        env->SetByteArrayRegion(buffer, 0, length, (jbyte *)request->buffer);
    }
    free(request->buffer);
    env->DeleteGlobalRef((jobject)request->client_data);
    return (jint) request->actual_length;
}

static jboolean
android_hardware_UsbRequest_queue_direct(JNIEnv *env, jobject thiz,
        jobject buffer, jint length, jboolean out)
{
    struct usb_request* request = get_request_from_object(env, thiz);
    if (!request) {
        ALOGE("request is closed in native_queue");
        return false;
    }

    if (buffer && length) {
        request->buffer = env->GetDirectBufferAddress(buffer);
        if (!request->buffer)
            return false;
    } else {
        request->buffer = NULL;
    }
    request->buffer_length = length;

    // save a reference to ourselves so UsbDeviceConnection.waitRequest() can find us
    // we also need this to make sure our native buffer is not deallocated
    // while IO is active
    request->client_data = (void *)env->NewGlobalRef(thiz);

    if (usb_request_queue(request)) {
        request->buffer = NULL;
        env->DeleteGlobalRef((jobject)request->client_data);
        return false;
    }
    return true;
}

static jint
android_hardware_UsbRequest_dequeue_direct(JNIEnv *env, jobject thiz)
{
    struct usb_request* request = get_request_from_object(env, thiz);
    if (!request) {
        ALOGE("request is closed in native_dequeue");
        return (jint) -1;
    }
    // all we need to do is delete our global ref
    env->DeleteGlobalRef((jobject)request->client_data);
    return (jint) request->actual_length;
}

static jboolean
android_hardware_UsbRequest_cancel(JNIEnv *env, jobject thiz)
{
    struct usb_request* request = get_request_from_object(env, thiz);
    if (!request) {
        ALOGE("request is closed in native_cancel");
        return false;
    }
    return (usb_request_cancel(request) == 0);
}

static JNINativeMethod method_table[] = {
    {"native_init",             "(Landroid/hardware/usb/UsbDeviceConnection;IIII)Z",
                                            (void *)android_hardware_UsbRequest_init},
    {"native_close",            "()V",      (void *)android_hardware_UsbRequest_close},
    {"native_queue_array",      "([BIZ)Z",  (void *)android_hardware_UsbRequest_queue_array},
    {"native_dequeue_array",    "([BIZ)I",  (void *)android_hardware_UsbRequest_dequeue_array},
    {"native_queue_direct",     "(Ljava/nio/ByteBuffer;IZ)Z",
                                            (void *)android_hardware_UsbRequest_queue_direct},
    {"native_dequeue_direct",   "()I",      (void *)android_hardware_UsbRequest_dequeue_direct},
    {"native_cancel",           "()Z",      (void *)android_hardware_UsbRequest_cancel},
};

int register_android_hardware_UsbRequest(JNIEnv *env)
{
    jclass clazz = env->FindClass("android/hardware/usb/UsbRequest");
    if (clazz == NULL) {
        ALOGE("Can't find android/hardware/usb/UsbRequest");
        return -1;
    }
    field_context = env->GetFieldID(clazz, "mNativeContext", "J");
    if (field_context == NULL) {
        ALOGE("Can't find UsbRequest.mNativeContext");
        return -1;
    }

    return RegisterMethodsOrDie(env, "android/hardware/usb/UsbRequest",
            method_table, NELEM(method_table));
}

