/*
 * Copyright (C) 2007 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 TRACE_TAG USB

#include "sysdeps.h"

#include <winsock2.h>  // winsock.h *must* be included before windows.h.
#include <windows.h>
#include <usb100.h>
#include <winerror.h>

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>

#include <mutex>
#include <thread>

#include <adb_api.h>

#include <android-base/errors.h>

#include "adb.h"
#include "sysdeps/chrono.h"
#include "transport.h"

/** Structure usb_handle describes our connection to the usb device via
  AdbWinApi.dll. This structure is returned from usb_open() routine and
  is expected in each subsequent call that is accessing the device.

  Most members are protected by usb_lock, except for adb_{read,write}_pipe which
  rely on AdbWinApi.dll's handle validation and AdbCloseHandle(endpoint)'s
  ability to break a thread out of pipe IO.
*/
struct usb_handle {
  /// Previous entry in the list of opened usb handles
  usb_handle *prev;

  /// Next entry in the list of opened usb handles
  usb_handle *next;

  /// Handle to USB interface
  ADBAPIHANDLE  adb_interface;

  /// Handle to USB read pipe (endpoint)
  ADBAPIHANDLE  adb_read_pipe;

  /// Handle to USB write pipe (endpoint)
  ADBAPIHANDLE  adb_write_pipe;

  /// Interface name
  wchar_t*      interface_name;

  /// Mask for determining when to use zero length packets
  unsigned zero_mask;
};

/// Class ID assigned to the device by androidusb.sys
static const GUID usb_class_id = ANDROID_USB_CLASS_ID;

/// List of opened usb handles
static usb_handle handle_list = {
  .prev = &handle_list,
  .next = &handle_list,
};

/// Locker for the list of opened usb handles
static std::mutex& usb_lock = *new std::mutex();

/// Checks if there is opened usb handle in handle_list for this device.
int known_device(const wchar_t* dev_name);

/// Checks if there is opened usb handle in handle_list for this device.
/// usb_lock mutex must be held before calling this routine.
int known_device_locked(const wchar_t* dev_name);

/// Registers opened usb handle (adds it to handle_list).
int register_new_device(usb_handle* handle);

/// Checks if interface (device) matches certain criteria
int recognized_device(usb_handle* handle);

/// Enumerates present and available interfaces (devices), opens new ones and
/// registers usb transport for them.
void find_devices();

/// Kicks all USB devices
static void kick_devices();

/// Entry point for thread that polls (every second) for new usb interfaces.
/// This routine calls find_devices in infinite loop.
static void device_poll_thread();

/// Initializes this module
void usb_init();

/// Opens usb interface (device) by interface (device) name.
usb_handle* do_usb_open(const wchar_t* interface_name);

/// Writes data to the opened usb handle
int usb_write(usb_handle* handle, const void* data, int len);

/// Reads data using the opened usb handle
int usb_read(usb_handle *handle, void* data, int len);

/// Cleans up opened usb handle
void usb_cleanup_handle(usb_handle* handle);

/// Cleans up (but don't close) opened usb handle
void usb_kick(usb_handle* handle);

/// Closes opened usb handle
int usb_close(usb_handle* handle);

int known_device_locked(const wchar_t* dev_name) {
  usb_handle* usb;

  if (NULL != dev_name) {
    // Iterate through the list looking for the name match.
    for(usb = handle_list.next; usb != &handle_list; usb = usb->next) {
      // In Windows names are not case sensetive!
      if((NULL != usb->interface_name) &&
         (0 == wcsicmp(usb->interface_name, dev_name))) {
        return 1;
      }
    }
  }

  return 0;
}

int known_device(const wchar_t* dev_name) {
  int ret = 0;

  if (NULL != dev_name) {
    std::lock_guard<std::mutex> lock(usb_lock);
    ret = known_device_locked(dev_name);
  }

  return ret;
}

int register_new_device(usb_handle* handle) {
  if (NULL == handle)
    return 0;

  std::lock_guard<std::mutex> lock(usb_lock);

  // Check if device is already in the list
  if (known_device_locked(handle->interface_name)) {
    return 0;
  }

  // Not in the list. Add this handle to the list.
  handle->next = &handle_list;
  handle->prev = handle_list.prev;
  handle->prev->next = handle;
  handle->next->prev = handle;

  return 1;
}

void device_poll_thread() {
  adb_thread_setname("Device Poll");
  D("Created device thread");

  while (true) {
    find_devices();
    std::this_thread::sleep_for(1s);
  }
}

static LRESULT CALLBACK _power_window_proc(HWND hwnd, UINT uMsg, WPARAM wParam,
                                           LPARAM lParam) {
  switch (uMsg) {
  case WM_POWERBROADCAST:
    switch (wParam) {
    case PBT_APMRESUMEAUTOMATIC:
      // Resuming from sleep or hibernation, so kick all existing USB devices
      // and then allow the device_poll_thread to redetect USB devices from
      // scratch. If we don't do this, existing USB devices will never respond
      // to us because they'll be waiting for the connect/auth handshake.
      D("Received (WM_POWERBROADCAST, PBT_APMRESUMEAUTOMATIC) notification, "
        "so kicking all USB devices\n");
      kick_devices();
      return TRUE;
    }
  }
  return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}

static void _power_notification_thread() {
  // This uses a thread with its own window message pump to get power
  // notifications. If adb runs from a non-interactive service account, this
  // might not work (not sure). If that happens to not work, we could use
  // heavyweight WMI APIs to get power notifications. But for the common case
  // of a developer's interactive session, a window message pump is more
  // appropriate.
  D("Created power notification thread");
  adb_thread_setname("Power Notifier");

  // Window class names are process specific.
  static const WCHAR kPowerNotificationWindowClassName[] =
    L"PowerNotificationWindow";

  // Get the HINSTANCE corresponding to the module that _power_window_proc
  // is in (the main module).
  const HINSTANCE instance = GetModuleHandleW(NULL);
  if (!instance) {
    // This is such a common API call that this should never fail.
    fatal("GetModuleHandleW failed: %s",
          android::base::SystemErrorCodeToString(GetLastError()).c_str());
  }

  WNDCLASSEXW wndclass;
  memset(&wndclass, 0, sizeof(wndclass));
  wndclass.cbSize = sizeof(wndclass);
  wndclass.lpfnWndProc = _power_window_proc;
  wndclass.hInstance = instance;
  wndclass.lpszClassName = kPowerNotificationWindowClassName;
  if (!RegisterClassExW(&wndclass)) {
    fatal("RegisterClassExW failed: %s",
          android::base::SystemErrorCodeToString(GetLastError()).c_str());
  }

  if (!CreateWindowExW(WS_EX_NOACTIVATE, kPowerNotificationWindowClassName,
                       L"ADB Power Notification Window", WS_POPUP, 0, 0, 0, 0,
                       NULL, NULL, instance, NULL)) {
    fatal("CreateWindowExW failed: %s",
          android::base::SystemErrorCodeToString(GetLastError()).c_str());
  }

  MSG msg;
  while (GetMessageW(&msg, NULL, 0, 0)) {
    TranslateMessage(&msg);
    DispatchMessageW(&msg);
  }

  // GetMessageW() will return false if a quit message is posted. We don't
  // do that, but it might be possible for that to occur when logging off or
  // shutting down. Not a big deal since the whole process will be going away
  // soon anyway.
  D("Power notification thread exiting");
}

void usb_init() {
  std::thread(device_poll_thread).detach();
  std::thread(_power_notification_thread).detach();
}

usb_handle* do_usb_open(const wchar_t* interface_name) {
  unsigned long name_len = 0;

  // Allocate our handle
  usb_handle* ret = (usb_handle*)calloc(1, sizeof(usb_handle));
  if (NULL == ret) {
    D("Could not allocate %u bytes for usb_handle: %s", sizeof(usb_handle),
      strerror(errno));
    goto fail;
  }

  // Set linkers back to the handle
  ret->next = ret;
  ret->prev = ret;

  // Create interface.
  ret->adb_interface = AdbCreateInterfaceByName(interface_name);
  if (NULL == ret->adb_interface) {
    D("AdbCreateInterfaceByName failed: %s",
      android::base::SystemErrorCodeToString(GetLastError()).c_str());
    goto fail;
  }

  // Open read pipe (endpoint)
  ret->adb_read_pipe =
    AdbOpenDefaultBulkReadEndpoint(ret->adb_interface,
                                   AdbOpenAccessTypeReadWrite,
                                   AdbOpenSharingModeReadWrite);
  if (NULL == ret->adb_read_pipe) {
    D("AdbOpenDefaultBulkReadEndpoint failed: %s",
      android::base::SystemErrorCodeToString(GetLastError()).c_str());
    goto fail;
  }

  // Open write pipe (endpoint)
  ret->adb_write_pipe =
    AdbOpenDefaultBulkWriteEndpoint(ret->adb_interface,
                                    AdbOpenAccessTypeReadWrite,
                                    AdbOpenSharingModeReadWrite);
  if (NULL == ret->adb_write_pipe) {
    D("AdbOpenDefaultBulkWriteEndpoint failed: %s",
      android::base::SystemErrorCodeToString(GetLastError()).c_str());
    goto fail;
  }

  // Save interface name
  // First get expected name length
  AdbGetInterfaceName(ret->adb_interface,
                      NULL,
                      &name_len,
                      false);
  if (0 == name_len) {
    D("AdbGetInterfaceName returned name length of zero: %s",
      android::base::SystemErrorCodeToString(GetLastError()).c_str());
    goto fail;
  }

  ret->interface_name = (wchar_t*)malloc(name_len * sizeof(ret->interface_name[0]));
  if (NULL == ret->interface_name) {
    D("Could not allocate %lu characters for interface_name: %s", name_len, strerror(errno));
    goto fail;
  }

  // Now save the name
  if (!AdbGetInterfaceName(ret->adb_interface,
                           ret->interface_name,
                           &name_len,
                           false)) {
    D("AdbGetInterfaceName failed: %s",
      android::base::SystemErrorCodeToString(GetLastError()).c_str());
    goto fail;
  }

  // We're done at this point
  return ret;

fail:
  if (NULL != ret) {
    usb_cleanup_handle(ret);
    free(ret);
  }

  return NULL;
}

int usb_write(usb_handle* handle, const void* data, int len) {
  unsigned long time_out = 5000;
  unsigned long written = 0;
  int err = 0;

  D("usb_write %d", len);
  if (NULL == handle) {
    D("usb_write was passed NULL handle");
    err = EINVAL;
    goto fail;
  }

  // Perform write
  if (!AdbWriteEndpointSync(handle->adb_write_pipe,
                            (void*)data,
                            (unsigned long)len,
                            &written,
                            time_out)) {
    D("AdbWriteEndpointSync failed: %s",
      android::base::SystemErrorCodeToString(GetLastError()).c_str());
    err = EIO;
    goto fail;
  }

  // Make sure that we've written what we were asked to write
  D("usb_write got: %ld, expected: %d", written, len);
  if (written != (unsigned long)len) {
    // If this occurs, this code should be changed to repeatedly call
    // AdbWriteEndpointSync() until all bytes are written.
    D("AdbWriteEndpointSync was supposed to write %d, but only wrote %ld",
      len, written);
    err = EIO;
    goto fail;
  }

  if (handle->zero_mask && (len & handle->zero_mask) == 0) {
    // Send a zero length packet
    if (!AdbWriteEndpointSync(handle->adb_write_pipe,
                              (void*)data,
                              0,
                              &written,
                              time_out)) {
      D("AdbWriteEndpointSync of zero length packet failed: %s",
        android::base::SystemErrorCodeToString(GetLastError()).c_str());
      err = EIO;
      goto fail;
    }
  }

  return 0;

fail:
  // Any failure should cause us to kick the device instead of leaving it a
  // zombie state with potential to hang.
  if (NULL != handle) {
    D("Kicking device due to error in usb_write");
    usb_kick(handle);
  }

  D("usb_write failed");
  errno = err;
  return -1;
}

int usb_read(usb_handle *handle, void* data, int len) {
  unsigned long time_out = 0;
  unsigned long read = 0;
  int err = 0;
  int orig_len = len;

  D("usb_read %d", len);
  if (NULL == handle) {
    D("usb_read was passed NULL handle");
    err = EINVAL;
    goto fail;
  }

  while (len == orig_len) {
    if (!AdbReadEndpointSync(handle->adb_read_pipe, data, len, &read, time_out)) {
      D("AdbReadEndpointSync failed: %s",
        android::base::SystemErrorCodeToString(GetLastError()).c_str());
      err = EIO;
      goto fail;
    }
    D("usb_read got: %ld, expected: %d", read, len);

    data = (char*)data + read;
    len -= read;
  }

  return orig_len - len;

fail:
  // Any failure should cause us to kick the device instead of leaving it a
  // zombie state with potential to hang.
  if (NULL != handle) {
    D("Kicking device due to error in usb_read");
    usb_kick(handle);
  }

  D("usb_read failed");
  errno = err;
  return -1;
}

// Wrapper around AdbCloseHandle() that logs diagnostics.
static void _adb_close_handle(ADBAPIHANDLE adb_handle) {
  if (!AdbCloseHandle(adb_handle)) {
    D("AdbCloseHandle(%p) failed: %s", adb_handle,
      android::base::SystemErrorCodeToString(GetLastError()).c_str());
  }
}

void usb_cleanup_handle(usb_handle* handle) {
  D("usb_cleanup_handle");
  if (NULL != handle) {
    if (NULL != handle->interface_name)
      free(handle->interface_name);
    // AdbCloseHandle(pipe) will break any threads out of pending IO calls and
    // wait until the pipe no longer uses the interface. Then we can
    // AdbCloseHandle() the interface.
    if (NULL != handle->adb_write_pipe)
      _adb_close_handle(handle->adb_write_pipe);
    if (NULL != handle->adb_read_pipe)
      _adb_close_handle(handle->adb_read_pipe);
    if (NULL != handle->adb_interface)
      _adb_close_handle(handle->adb_interface);

    handle->interface_name = NULL;
    handle->adb_write_pipe = NULL;
    handle->adb_read_pipe = NULL;
    handle->adb_interface = NULL;
  }
}

static void usb_kick_locked(usb_handle* handle) {
  // The reason the lock must be acquired before calling this function is in
  // case multiple threads are trying to kick the same device at the same time.
  usb_cleanup_handle(handle);
}

void usb_kick(usb_handle* handle) {
  D("usb_kick");
  if (NULL != handle) {
    std::lock_guard<std::mutex> lock(usb_lock);
    usb_kick_locked(handle);
  } else {
    errno = EINVAL;
  }
}

int usb_close(usb_handle* handle) {
  D("usb_close");

  if (NULL != handle) {
    // Remove handle from the list
    {
      std::lock_guard<std::mutex> lock(usb_lock);

      if ((handle->next != handle) && (handle->prev != handle)) {
        handle->next->prev = handle->prev;
        handle->prev->next = handle->next;
        handle->prev = handle;
        handle->next = handle;
      }
    }

    // Cleanup handle
    usb_cleanup_handle(handle);
    free(handle);
  }

  return 0;
}

int recognized_device(usb_handle* handle) {
  if (NULL == handle)
    return 0;

  // Check vendor and product id first
  USB_DEVICE_DESCRIPTOR device_desc;

  if (!AdbGetUsbDeviceDescriptor(handle->adb_interface,
                                 &device_desc)) {
    D("AdbGetUsbDeviceDescriptor failed: %s",
      android::base::SystemErrorCodeToString(GetLastError()).c_str());
    return 0;
  }

  // Then check interface properties
  USB_INTERFACE_DESCRIPTOR interf_desc;

  if (!AdbGetUsbInterfaceDescriptor(handle->adb_interface,
                                    &interf_desc)) {
    D("AdbGetUsbInterfaceDescriptor failed: %s",
      android::base::SystemErrorCodeToString(GetLastError()).c_str());
    return 0;
  }

  // Must have two endpoints
  if (2 != interf_desc.bNumEndpoints) {
    return 0;
  }

  if (is_adb_interface(interf_desc.bInterfaceClass, interf_desc.bInterfaceSubClass,
                       interf_desc.bInterfaceProtocol)) {
    if (interf_desc.bInterfaceProtocol == 0x01) {
      AdbEndpointInformation endpoint_info;
      // assuming zero is a valid bulk endpoint ID
      if (AdbGetEndpointInformation(handle->adb_interface, 0, &endpoint_info)) {
        handle->zero_mask = endpoint_info.max_packet_size - 1;
        D("device zero_mask: 0x%x", handle->zero_mask);
      } else {
        D("AdbGetEndpointInformation failed: %s",
          android::base::SystemErrorCodeToString(GetLastError()).c_str());
      }
    }

    return 1;
  }

  return 0;
}

void find_devices() {
  usb_handle* handle = NULL;
  char entry_buffer[2048];
  AdbInterfaceInfo* next_interface = (AdbInterfaceInfo*)(&entry_buffer[0]);
  unsigned long entry_buffer_size = sizeof(entry_buffer);

  // Enumerate all present and active interfaces.
  ADBAPIHANDLE enum_handle =
    AdbEnumInterfaces(usb_class_id, true, true, true);

  if (NULL == enum_handle) {
    D("AdbEnumInterfaces failed: %s",
      android::base::SystemErrorCodeToString(GetLastError()).c_str());
    return;
  }

  while (AdbNextInterface(enum_handle, next_interface, &entry_buffer_size)) {
    // Lets see if we already have this device in the list
    if (!known_device(next_interface->device_name)) {
      // This seems to be a new device. Open it!
      handle = do_usb_open(next_interface->device_name);
      if (NULL != handle) {
        // Lets see if this interface (device) belongs to us
        if (recognized_device(handle)) {
          D("adding a new device %ls", next_interface->device_name);

          // We don't request a wchar_t string from AdbGetSerialNumber() because of a bug in
          // adb_winusb_interface.cpp:CopyMemory(buffer, ser_num->bString, bytes_written) where the
          // last parameter should be (str_len * sizeof(wchar_t)). The bug reads 2 bytes past the
          // end of a stack buffer in the best case, and in the unlikely case of a long serial
          // number, it will read 2 bytes past the end of a heap allocation. This doesn't affect the
          // resulting string, but we should avoid the bad reads in the first place.
          char serial_number[512];
          unsigned long serial_number_len = sizeof(serial_number);
          if (AdbGetSerialNumber(handle->adb_interface,
                                serial_number,
                                &serial_number_len,
                                true)) {
            // Lets make sure that we don't duplicate this device
            if (register_new_device(handle)) {
              register_usb_transport(handle, serial_number, NULL, 1);
            } else {
              D("register_new_device failed for %ls", next_interface->device_name);
              usb_cleanup_handle(handle);
              free(handle);
            }
          } else {
            D("cannot get serial number: %s",
              android::base::SystemErrorCodeToString(GetLastError()).c_str());
            usb_cleanup_handle(handle);
            free(handle);
          }
        } else {
          usb_cleanup_handle(handle);
          free(handle);
        }
      }
    }

    entry_buffer_size = sizeof(entry_buffer);
  }

  if (GetLastError() != ERROR_NO_MORE_ITEMS) {
    // Only ERROR_NO_MORE_ITEMS is expected at the end of enumeration.
    D("AdbNextInterface failed: %s",
      android::base::SystemErrorCodeToString(GetLastError()).c_str());
  }

  _adb_close_handle(enum_handle);
}

static void kick_devices() {
  // Need to acquire lock to safely walk the list which might be modified
  // by another thread.
  std::lock_guard<std::mutex> lock(usb_lock);
  for (usb_handle* usb = handle_list.next; usb != &handle_list; usb = usb->next) {
    usb_kick_locked(usb);
  }
}
