/*
 * Copyright (C) 2016 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.
 */

#include "usb.h"

#include "sysdeps.h"

#include <stdint.h>

#include <atomic>
#include <chrono>
#include <memory>
#include <mutex>
#include <string>
#include <thread>
#include <unordered_map>

#include <libusb/libusb.h>

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/quick_exit.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>

#include "adb.h"
#include "transport.h"
#include "usb.h"

using namespace std::literals;

using android::base::StringPrintf;

// RAII wrappers for libusb.
struct ConfigDescriptorDeleter {
    void operator()(libusb_config_descriptor* desc) {
        libusb_free_config_descriptor(desc);
    }
};

using unique_config_descriptor = std::unique_ptr<libusb_config_descriptor, ConfigDescriptorDeleter>;

struct DeviceHandleDeleter {
    void operator()(libusb_device_handle* h) {
        libusb_close(h);
    }
};

using unique_device_handle = std::unique_ptr<libusb_device_handle, DeviceHandleDeleter>;

struct transfer_info {
    transfer_info(const char* name, uint16_t zero_mask, bool is_bulk_out)
        : name(name),
          transfer(libusb_alloc_transfer(0)),
          is_bulk_out(is_bulk_out),
          zero_mask(zero_mask) {}

    ~transfer_info() {
        libusb_free_transfer(transfer);
    }

    const char* name;
    libusb_transfer* transfer;
    bool is_bulk_out;
    bool transfer_complete;
    std::condition_variable cv;
    std::mutex mutex;
    uint16_t zero_mask;

    void Notify() {
        LOG(DEBUG) << "notifying " << name << " transfer complete";
        transfer_complete = true;
        cv.notify_one();
    }
};

namespace libusb {
struct usb_handle : public ::usb_handle {
    usb_handle(const std::string& device_address, const std::string& serial,
               unique_device_handle&& device_handle, uint8_t interface, uint8_t bulk_in,
               uint8_t bulk_out, size_t zero_mask, size_t max_packet_size)
        : device_address(device_address),
          serial(serial),
          closing(false),
          device_handle(device_handle.release()),
          read("read", zero_mask, false),
          write("write", zero_mask, true),
          interface(interface),
          bulk_in(bulk_in),
          bulk_out(bulk_out),
          max_packet_size(max_packet_size) {}

    ~usb_handle() {
        Close();
    }

    void Close() {
        std::unique_lock<std::mutex> lock(device_handle_mutex);
        // Cancelling transfers will trigger more Closes, so make sure this only happens once.
        if (closing) {
            return;
        }
        closing = true;

        // Make sure that no new transfers come in.
        libusb_device_handle* handle = device_handle;
        if (!handle) {
            return;
        }

        device_handle = nullptr;

        // Cancel already dispatched transfers.
        libusb_cancel_transfer(read.transfer);
        libusb_cancel_transfer(write.transfer);

        libusb_release_interface(handle, interface);
        libusb_close(handle);
    }

    std::string device_address;
    std::string serial;

    std::atomic<bool> closing;
    std::mutex device_handle_mutex;
    libusb_device_handle* device_handle;

    transfer_info read;
    transfer_info write;

    uint8_t interface;
    uint8_t bulk_in;
    uint8_t bulk_out;

    size_t max_packet_size;
};

static auto& usb_handles = *new std::unordered_map<std::string, std::unique_ptr<usb_handle>>();
static auto& usb_handles_mutex = *new std::mutex();

static std::thread* device_poll_thread = nullptr;
static std::atomic<bool> terminate_device_poll_thread(false);

static std::string get_device_address(libusb_device* device) {
    return StringPrintf("usb:%d:%d", libusb_get_bus_number(device),
                        libusb_get_device_address(device));
}

static bool endpoint_is_output(uint8_t endpoint) {
    return (endpoint & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT;
}

static bool should_perform_zero_transfer(uint8_t endpoint, size_t write_length, uint16_t zero_mask) {
    return endpoint_is_output(endpoint) && write_length != 0 && zero_mask != 0 &&
           (write_length & zero_mask) == 0;
}

static void poll_for_devices() {
    libusb_device** list;
    adb_thread_setname("device poll");
    while (!terminate_device_poll_thread) {
        const ssize_t device_count = libusb_get_device_list(nullptr, &list);

        LOG(VERBOSE) << "found " << device_count << " attached devices";

        for (ssize_t i = 0; i < device_count; ++i) {
            libusb_device* device = list[i];
            std::string device_address = get_device_address(device);
            std::string device_serial;

            // Figure out if we want to open the device.
            libusb_device_descriptor device_desc;
            int rc = libusb_get_device_descriptor(device, &device_desc);
            if (rc != 0) {
                LOG(WARNING) << "failed to get device descriptor for device at " << device_address
                             << ": " << libusb_error_name(rc);
            }

            if (device_desc.bDeviceClass != LIBUSB_CLASS_PER_INTERFACE) {
                // Assume that all Android devices have the device class set to per interface.
                // TODO: Is this assumption valid?
                LOG(VERBOSE) << "skipping device with incorrect class at " << device_address;
                continue;
            }

            libusb_config_descriptor* config_raw;
            rc = libusb_get_active_config_descriptor(device, &config_raw);
            if (rc != 0) {
                LOG(WARNING) << "failed to get active config descriptor for device at "
                             << device_address << ": " << libusb_error_name(rc);
                continue;
            }
            const unique_config_descriptor config(config_raw);

            // Use size_t for interface_num so <iostream>s don't mangle it.
            size_t interface_num;
            uint16_t zero_mask;
            uint8_t bulk_in = 0, bulk_out = 0;
            size_t packet_size = 0;
            bool found_adb = false;

            for (interface_num = 0; interface_num < config->bNumInterfaces; ++interface_num) {
                const libusb_interface& interface = config->interface[interface_num];
                if (interface.num_altsetting != 1) {
                    // Assume that interfaces with alternate settings aren't adb interfaces.
                    // TODO: Is this assumption valid?
                    LOG(VERBOSE) << "skipping interface with incorrect num_altsetting at "
                                 << device_address << " (interface " << interface_num << ")";
                    continue;
                }

                const libusb_interface_descriptor& interface_desc = interface.altsetting[0];
                if (!is_adb_interface(interface_desc.bInterfaceClass,
                                      interface_desc.bInterfaceSubClass,
                                      interface_desc.bInterfaceProtocol)) {
                    LOG(VERBOSE) << "skipping non-adb interface at " << device_address
                                 << " (interface " << interface_num << ")";
                    continue;
                }

                LOG(VERBOSE) << "found potential adb interface at " << device_address
                             << " (interface " << interface_num << ")";

                bool found_in = false;
                bool found_out = false;
                for (size_t endpoint_num = 0; endpoint_num < interface_desc.bNumEndpoints;
                     ++endpoint_num) {
                    const auto& endpoint_desc = interface_desc.endpoint[endpoint_num];
                    const uint8_t endpoint_addr = endpoint_desc.bEndpointAddress;
                    const uint8_t endpoint_attr = endpoint_desc.bmAttributes;

                    const uint8_t transfer_type = endpoint_attr & LIBUSB_TRANSFER_TYPE_MASK;

                    if (transfer_type != LIBUSB_TRANSFER_TYPE_BULK) {
                        continue;
                    }

                    if (endpoint_is_output(endpoint_addr) && !found_out) {
                        found_out = true;
                        bulk_out = endpoint_addr;
                        zero_mask = endpoint_desc.wMaxPacketSize - 1;
                    } else if (!endpoint_is_output(endpoint_addr) && !found_in) {
                        found_in = true;
                        bulk_in = endpoint_addr;
                    }

                    size_t endpoint_packet_size = endpoint_desc.wMaxPacketSize;
                    CHECK(endpoint_packet_size != 0);
                    if (packet_size == 0) {
                        packet_size = endpoint_packet_size;
                    } else {
                        CHECK(packet_size == endpoint_packet_size);
                    }
                }

                if (found_in && found_out) {
                    found_adb = true;
                    break;
                } else {
                    LOG(VERBOSE) << "rejecting potential adb interface at " << device_address
                                 << "(interface " << interface_num << "): missing bulk endpoints "
                                 << "(found_in = " << found_in << ", found_out = " << found_out
                                 << ")";
                }
            }

            if (!found_adb) {
                LOG(VERBOSE) << "skipping device with no adb interfaces at " << device_address;
                continue;
            }

            {
                std::unique_lock<std::mutex> lock(usb_handles_mutex);
                if (usb_handles.find(device_address) != usb_handles.end()) {
                    LOG(VERBOSE) << "device at " << device_address
                                 << " has already been registered, skipping";
                    continue;
                }
            }

            libusb_device_handle* handle_raw;
            rc = libusb_open(device, &handle_raw);
            if (rc != 0) {
                LOG(WARNING) << "failed to open usb device at " << device_address << ": "
                             << libusb_error_name(rc);
                continue;
            }

            unique_device_handle handle(handle_raw);
            LOG(DEBUG) << "successfully opened adb device at " << device_address << ", "
                       << StringPrintf("bulk_in = %#x, bulk_out = %#x", bulk_in, bulk_out);

            device_serial.resize(255);
            rc = libusb_get_string_descriptor_ascii(
                handle_raw, device_desc.iSerialNumber,
                reinterpret_cast<unsigned char*>(&device_serial[0]), device_serial.length());
            if (rc == 0) {
                LOG(WARNING) << "received empty serial from device at " << device_address;
                continue;
            } else if (rc < 0) {
                LOG(WARNING) << "failed to get serial from device at " << device_address
                             << libusb_error_name(rc);
                continue;
            }
            device_serial.resize(rc);

            // WARNING: this isn't released via RAII.
            rc = libusb_claim_interface(handle.get(), interface_num);
            if (rc != 0) {
                LOG(WARNING) << "failed to claim adb interface for device '" << device_serial << "'"
                             << libusb_error_name(rc);
                continue;
            }

            for (uint8_t endpoint : {bulk_in, bulk_out}) {
                rc = libusb_clear_halt(handle.get(), endpoint);
                if (rc != 0) {
                    LOG(WARNING) << "failed to clear halt on device '" << device_serial
                                 << "' endpoint 0x" << std::hex << endpoint << ": "
                                 << libusb_error_name(rc);
                    libusb_release_interface(handle.get(), interface_num);
                    continue;
                }
            }

            auto result = std::make_unique<usb_handle>(device_address, device_serial,
                                                       std::move(handle), interface_num, bulk_in,
                                                       bulk_out, zero_mask, packet_size);
            usb_handle* usb_handle_raw = result.get();

            {
                std::unique_lock<std::mutex> lock(usb_handles_mutex);
                usb_handles[device_address] = std::move(result);
            }

            register_usb_transport(usb_handle_raw, device_serial.c_str(), device_address.c_str(), 1);

            LOG(INFO) << "registered new usb device '" << device_serial << "'";
        }
        libusb_free_device_list(list, 1);

        std::this_thread::sleep_for(500ms);
    }
}

void usb_init() {
    LOG(DEBUG) << "initializing libusb...";
    int rc = libusb_init(nullptr);
    if (rc != 0) {
        LOG(FATAL) << "failed to initialize libusb: " << libusb_error_name(rc);
    }

    // Spawn a thread for libusb_handle_events.
    std::thread([]() {
        adb_thread_setname("libusb");
        while (true) {
            libusb_handle_events(nullptr);
        }
    }).detach();

    // Spawn a thread to do device enumeration.
    // TODO: Use libusb_hotplug_* instead?
    device_poll_thread = new std::thread(poll_for_devices);
    android::base::at_quick_exit([]() {
        terminate_device_poll_thread = true;
        device_poll_thread->join();
    });
}

// Dispatch a libusb transfer, unlock |device_lock|, and then wait for the result.
static int perform_usb_transfer(usb_handle* h, transfer_info* info,
                                std::unique_lock<std::mutex> device_lock) {
    libusb_transfer* transfer = info->transfer;

    transfer->user_data = info;
    transfer->callback = [](libusb_transfer* transfer) {
        transfer_info* info = static_cast<transfer_info*>(transfer->user_data);

        LOG(DEBUG) << info->name << " transfer callback entered";

        // Make sure that the original submitter has made it to the condition_variable wait.
        std::unique_lock<std::mutex> lock(info->mutex);

        LOG(DEBUG) << info->name << " callback successfully acquired lock";

        if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
            LOG(WARNING) << info->name
                         << " transfer failed: " << libusb_error_name(transfer->status);
            info->Notify();
            return;
        }

        // usb_read() can return when receiving some data.
        if (info->is_bulk_out && transfer->actual_length != transfer->length) {
            LOG(DEBUG) << info->name << " transfer incomplete, resubmitting";
            transfer->length -= transfer->actual_length;
            transfer->buffer += transfer->actual_length;
            int rc = libusb_submit_transfer(transfer);
            if (rc != 0) {
                LOG(WARNING) << "failed to submit " << info->name
                             << " transfer: " << libusb_error_name(rc);
                transfer->status = LIBUSB_TRANSFER_ERROR;
                info->Notify();
            }
            return;
        }

        if (should_perform_zero_transfer(transfer->endpoint, transfer->length, info->zero_mask)) {
            LOG(DEBUG) << "submitting zero-length write";
            transfer->length = 0;
            int rc = libusb_submit_transfer(transfer);
            if (rc != 0) {
                LOG(WARNING) << "failed to submit zero-length write: " << libusb_error_name(rc);
                transfer->status = LIBUSB_TRANSFER_ERROR;
                info->Notify();
            }
            return;
        }

        LOG(VERBOSE) << info->name << "transfer fully complete";
        info->Notify();
    };

    LOG(DEBUG) << "locking " << info->name << " transfer_info mutex";
    std::unique_lock<std::mutex> lock(info->mutex);
    info->transfer_complete = false;
    LOG(DEBUG) << "submitting " << info->name << " transfer";
    int rc = libusb_submit_transfer(transfer);
    if (rc != 0) {
        LOG(WARNING) << "failed to submit " << info->name << " transfer: " << libusb_error_name(rc);
        errno = EIO;
        return -1;
    }

    LOG(DEBUG) << info->name << " transfer successfully submitted";
    device_lock.unlock();
    info->cv.wait(lock, [info]() { return info->transfer_complete; });
    if (transfer->status != 0) {
        errno = EIO;
        return -1;
    }

    return 0;
}

int usb_write(usb_handle* h, const void* d, int len) {
    LOG(DEBUG) << "usb_write of length " << len;

    std::unique_lock<std::mutex> lock(h->device_handle_mutex);
    if (!h->device_handle) {
        errno = EIO;
        return -1;
    }

    transfer_info* info = &h->write;
    info->transfer->dev_handle = h->device_handle;
    info->transfer->flags = 0;
    info->transfer->endpoint = h->bulk_out;
    info->transfer->type = LIBUSB_TRANSFER_TYPE_BULK;
    info->transfer->length = len;
    info->transfer->buffer = reinterpret_cast<unsigned char*>(const_cast<void*>(d));
    info->transfer->num_iso_packets = 0;

    int rc = perform_usb_transfer(h, info, std::move(lock));
    LOG(DEBUG) << "usb_write(" << len << ") = " << rc;
    return rc;
}

int usb_read(usb_handle* h, void* d, int len) {
    LOG(DEBUG) << "usb_read of length " << len;

    std::unique_lock<std::mutex> lock(h->device_handle_mutex);
    if (!h->device_handle) {
        errno = EIO;
        return -1;
    }

    transfer_info* info = &h->read;
    info->transfer->dev_handle = h->device_handle;
    info->transfer->flags = 0;
    info->transfer->endpoint = h->bulk_in;
    info->transfer->type = LIBUSB_TRANSFER_TYPE_BULK;
    info->transfer->length = len;
    info->transfer->buffer = reinterpret_cast<unsigned char*>(d);
    info->transfer->num_iso_packets = 0;

    int rc = perform_usb_transfer(h, info, std::move(lock));
    LOG(DEBUG) << "usb_read(" << len << ") = " << rc << ", actual_length "
               << info->transfer->actual_length;
    if (rc < 0) {
        return rc;
    }
    return info->transfer->actual_length;
}

int usb_close(usb_handle* h) {
    std::unique_lock<std::mutex> lock(usb_handles_mutex);
    auto it = usb_handles.find(h->device_address);
    if (it == usb_handles.end()) {
        LOG(FATAL) << "attempted to close unregistered usb_handle for '" << h->serial << "'";
    }
    usb_handles.erase(h->device_address);
    return 0;
}

void usb_kick(usb_handle* h) {
    h->Close();
}

size_t usb_get_max_packet_size(usb_handle* h) {
    CHECK(h->max_packet_size != 0);
    return h->max_packet_size;
}

} // namespace libusb
