// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "device/usb/usb_service_win.h"

#include <setupapi.h>
#include <stdint.h>
#include <usbiodef.h>

#define INITGUID
#include <devpkey.h>

#include "base/bind.h"
#include "base/location.h"
#include "base/memory/free_deleter.h"
#include "base/memory/ptr_util.h"
#include "base/scoped_generic.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/win/scoped_handle.h"
#include "components/device_event_log/device_event_log.h"
#include "device/usb/usb_descriptors.h"
#include "device/usb/usb_device_handle.h"
#include "device/usb/webusb_descriptors.h"

namespace device {

namespace {

struct DevInfoScopedTraits {
  static HDEVINFO InvalidValue() { return INVALID_HANDLE_VALUE; }
  static void Free(HDEVINFO h) { SetupDiDestroyDeviceInfoList(h); }
};

using ScopedDevInfo = base::ScopedGeneric<HDEVINFO, DevInfoScopedTraits>;

bool GetDeviceUint32Property(HDEVINFO dev_info,
                             SP_DEVINFO_DATA* dev_info_data,
                             const DEVPROPKEY& property,
                             uint32_t* property_buffer) {
  DEVPROPTYPE property_type;
  if (!SetupDiGetDeviceProperty(dev_info, dev_info_data, &property,
                                &property_type,
                                reinterpret_cast<PBYTE>(property_buffer),
                                sizeof(*property_buffer), nullptr, 0) ||
      property_type != DEVPROP_TYPE_UINT32) {
    return false;
  }

  return true;
}

bool GetDeviceStringProperty(HDEVINFO dev_info,
                             SP_DEVINFO_DATA* dev_info_data,
                             const DEVPROPKEY& property,
                             std::string* property_buffer) {
  DEVPROPTYPE property_type;
  DWORD required_size;
  if (SetupDiGetDeviceProperty(dev_info, dev_info_data, &property,
                               &property_type, nullptr, 0, &required_size, 0) ||
      GetLastError() != ERROR_INSUFFICIENT_BUFFER ||
      property_type != DEVPROP_TYPE_STRING) {
    return false;
  }

  std::wstring wide_buffer;
  if (!SetupDiGetDeviceProperty(
          dev_info, dev_info_data, &property, &property_type,
          reinterpret_cast<PBYTE>(base::WriteInto(&wide_buffer, required_size)),
          required_size, nullptr, 0)) {
    return false;
  }

  *property_buffer = base::SysWideToUTF8(wide_buffer);
  return true;
}

bool GetDeviceInterfaceDetails(HDEVINFO dev_info,
                               SP_DEVICE_INTERFACE_DATA* device_interface_data,
                               std::string* device_path,
                               uint32_t* bus_number, uint32_t* port_number,
                               std::string* parent_instance_id,
                               std::string* service_name) {
  DWORD required_size = 0;
  if (SetupDiGetDeviceInterfaceDetail(dev_info, device_interface_data, nullptr,
                                      0, &required_size, nullptr) ||
      GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
    return false;
  }

  std::unique_ptr<SP_DEVICE_INTERFACE_DETAIL_DATA, base::FreeDeleter>
  device_interface_detail_data(
      static_cast<SP_DEVICE_INTERFACE_DETAIL_DATA*>(malloc(required_size)));
  device_interface_detail_data->cbSize = sizeof(*device_interface_detail_data);

  SP_DEVINFO_DATA dev_info_data;
  dev_info_data.cbSize = sizeof(dev_info_data);

  if (!SetupDiGetDeviceInterfaceDetail(
          dev_info, device_interface_data, device_interface_detail_data.get(),
          required_size, nullptr, &dev_info_data)) {
    USB_PLOG(ERROR) << "SetupDiGetDeviceInterfaceDetail";
    return false;
  }

  if (device_path) {
    *device_path =
        base::SysWideToUTF8(device_interface_detail_data->DevicePath);
  }

  if (bus_number) {
    if (!GetDeviceUint32Property(dev_info, &dev_info_data,
                                 DEVPKEY_Device_BusNumber, bus_number)) {
      USB_PLOG(ERROR) << "Failed to get device bus number";
      return false;
    }
  }

  if (port_number) {
    if (!GetDeviceUint32Property(dev_info, &dev_info_data,
                                 DEVPKEY_Device_Address, port_number)) {
      USB_PLOG(ERROR) << "Failed to get device address";
      return false;
    }
  }

  if (parent_instance_id) {
    if (!GetDeviceStringProperty(dev_info, &dev_info_data,
                                 DEVPKEY_Device_Parent, parent_instance_id)) {
      USB_PLOG(ERROR) << "Failed to get the device parent";
      return false;
    }
  }

  if (service_name) {
    if (!GetDeviceStringProperty(dev_info, &dev_info_data,
                                 DEVPKEY_Device_Service, service_name)) {
      USB_PLOG(ERROR) << "Failed to get device driver name";
      return false;
    }

    // Windows pads this string with a variable number of NUL bytes for no
    // discernible reason.
    size_t end = service_name->find_last_not_of('\0');
    if (end != std::string::npos)
      service_name->erase(end + 1);
  }

  return true;
}

bool GetHubDevicePath(const std::string& instance_id,
                      std::string* device_path) {
  ScopedDevInfo dev_info(
      SetupDiGetClassDevsA(&GUID_DEVINTERFACE_USB_HUB, instance_id.c_str(), 0,
                           DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
  if (!dev_info.is_valid()) {
    USB_PLOG(ERROR) << "SetupDiGetClassDevs";
    return false;
  }

  SP_DEVICE_INTERFACE_DATA device_interface_data;
  device_interface_data.cbSize = sizeof(device_interface_data);
  if (!SetupDiEnumDeviceInterfaces(dev_info.get(), nullptr,
                                   &GUID_DEVINTERFACE_USB_HUB, 0,
                                   &device_interface_data)) {
    USB_PLOG(ERROR) << "SetupDiEnumDeviceInterfaces";
    return false;
  }

  return GetDeviceInterfaceDetails(dev_info.get(), &device_interface_data,
                                   device_path, nullptr, nullptr, nullptr,
                                   nullptr);
}

}  // namespace

class UsbServiceWin::BlockingTaskHelper {
 public:
  explicit BlockingTaskHelper(base::WeakPtr<UsbServiceWin> service)
      : service_task_runner_(base::ThreadTaskRunnerHandle::Get()),
        service_(service) {}
  ~BlockingTaskHelper() {}

  void EnumerateDevices() {
    ScopedDevInfo dev_info(
        SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_DEVICE, nullptr, 0,
                            DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
    if (!dev_info.is_valid()) {
      USB_PLOG(ERROR) << "Failed to set up device enumeration";
      service_task_runner_->PostTask(
          FROM_HERE, base::Bind(&UsbServiceWin::HelperStarted, service_));
      return;
    }

    SP_DEVICE_INTERFACE_DATA device_interface_data;
    device_interface_data.cbSize = sizeof(device_interface_data);
    for (DWORD i = 0; SetupDiEnumDeviceInterfaces(dev_info.get(), nullptr,
                                                  &GUID_DEVINTERFACE_USB_DEVICE,
                                                  i, &device_interface_data);
         ++i) {
      std::string device_path;
      uint32_t bus_number;
      uint32_t port_number;
      std::string parent_instance_id;
      std::string service_name;
      if (!GetDeviceInterfaceDetails(dev_info.get(), &device_interface_data,
                                     &device_path, &bus_number, &port_number,
                                     &parent_instance_id, &service_name)) {
        continue;
      }

      std::string& hub_path = hub_paths_[parent_instance_id];
      if (hub_path.empty()) {
        std::string parent_path;
        if (!GetHubDevicePath(parent_instance_id, &parent_path))
          continue;

        hub_path = parent_path;
      }

      service_task_runner_->PostTask(
          FROM_HERE,
          base::Bind(&UsbServiceWin::CreateDeviceObject, service_, device_path,
                     hub_path, bus_number, port_number, service_name));
    }

    if (GetLastError() != ERROR_NO_MORE_ITEMS)
      USB_PLOG(ERROR) << "Failed to enumerate devices";

    service_task_runner_->PostTask(
        FROM_HERE, base::Bind(&UsbServiceWin::HelperStarted, service_));
  }

  void EnumerateDevicePath(const std::string& device_path) {
    ScopedDevInfo dev_info(
        SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_DEVICE, nullptr, 0,
                            DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
    if (!dev_info.is_valid()) {
      USB_PLOG(ERROR) << "Failed to set up device enumeration";
      return;
    }

    SP_DEVICE_INTERFACE_DATA device_interface_data;
    device_interface_data.cbSize = sizeof(device_interface_data);
    if (!SetupDiOpenDeviceInterfaceA(dev_info.get(), device_path.c_str(), 0,
                                     &device_interface_data)) {
      USB_PLOG(ERROR) << "Failed to add device interface: " << device_path;
      return;
    }

    uint32_t bus_number;
    uint32_t port_number;
    std::string parent_instance_id;
    std::string service_name;
    if (!GetDeviceInterfaceDetails(dev_info.get(), &device_interface_data,
                                   nullptr, &bus_number, &port_number,
                                   &parent_instance_id, &service_name)) {
      return;
    }

    std::string& hub_path = hub_paths_[parent_instance_id];
    if (hub_path.empty()) {
      std::string parent_path;
      if (!GetHubDevicePath(parent_instance_id, &parent_path))
        return;

      hub_path = parent_path;
    }

    service_task_runner_->PostTask(
        FROM_HERE,
        base::Bind(&UsbServiceWin::CreateDeviceObject, service_, device_path,
                   hub_path, bus_number, port_number, service_name));
  }

 private:
  std::unordered_map<std::string, std::string> hub_paths_;

  // Calls back to |service_| must be posted to |service_task_runner_|, which
  // runs tasks on the thread where that object lives.
  scoped_refptr<base::SingleThreadTaskRunner> service_task_runner_;
  base::WeakPtr<UsbServiceWin> service_;
};

UsbServiceWin::UsbServiceWin()
    : UsbService(CreateBlockingTaskRunner()),
      device_observer_(this),
      weak_factory_(this) {
  DeviceMonitorWin* device_monitor =
      DeviceMonitorWin::GetForDeviceInterface(GUID_DEVINTERFACE_USB_DEVICE);
  if (device_monitor)
    device_observer_.Add(device_monitor);

  helper_ = std::make_unique<BlockingTaskHelper>(weak_factory_.GetWeakPtr());
  blocking_task_runner()->PostTask(
      FROM_HERE, base::Bind(&BlockingTaskHelper::EnumerateDevices,
                            base::Unretained(helper_.get())));
}

UsbServiceWin::~UsbServiceWin() {
  blocking_task_runner()->DeleteSoon(FROM_HERE, helper_.release());
}

void UsbServiceWin::GetDevices(const GetDevicesCallback& callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (enumeration_ready())
    UsbService::GetDevices(callback);
  else
    enumeration_callbacks_.push_back(callback);
}

void UsbServiceWin::OnDeviceAdded(const GUID& class_guid,
                                  const std::string& device_path) {
  blocking_task_runner()->PostTask(
      FROM_HERE, base::Bind(&BlockingTaskHelper::EnumerateDevicePath,
                            base::Unretained(helper_.get()), device_path));
}

void UsbServiceWin::OnDeviceRemoved(const GUID& class_guid,
                                    const std::string& device_path) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  auto by_path_it = devices_by_path_.find(device_path);
  if (by_path_it == devices_by_path_.end())
    return;

  scoped_refptr<UsbDeviceWin> device = by_path_it->second;
  devices_by_path_.erase(by_path_it);
  device->OnDisconnect();

  auto by_guid_it = devices().find(device->guid());
  if (by_guid_it != devices().end() && enumeration_ready()) {
    USB_LOG(USER) << "USB device removed: path=" << device->device_path()
                  << " guid=" << device->guid();

    devices().erase(by_guid_it);
    NotifyDeviceRemoved(device);
  }
}

void UsbServiceWin::HelperStarted() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  helper_started_ = true;
  if (enumeration_ready()) {
    std::vector<scoped_refptr<UsbDevice>> result;
    result.reserve(devices().size());
    for (const auto& map_entry : devices())
      result.push_back(map_entry.second);
    for (const auto& callback : enumeration_callbacks_)
      callback.Run(result);
    enumeration_callbacks_.clear();
  }
}

void UsbServiceWin::CreateDeviceObject(const std::string& device_path,
                                       const std::string& hub_path,
                                       uint32_t bus_number,
                                       uint32_t port_number,
                                       const std::string& driver_name) {
  // Devices that appear during initial enumeration are gathered into the first
  // result returned by GetDevices() and prevent device add/remove notifications
  // from being sent.
  if (!enumeration_ready())
    ++first_enumeration_countdown_;

  scoped_refptr<UsbDeviceWin> device(
      new UsbDeviceWin(device_path, hub_path, bus_number, port_number,
                       driver_name, blocking_task_runner()));
  devices_by_path_[device->device_path()] = device;
  device->ReadDescriptors(base::Bind(&UsbServiceWin::DeviceReady,
                                     weak_factory_.GetWeakPtr(), device));
}

void UsbServiceWin::DeviceReady(scoped_refptr<UsbDeviceWin> device,
                                bool success) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  bool enumeration_became_ready = false;
  if (!enumeration_ready()) {
    DCHECK_GT(first_enumeration_countdown_, 0u);
    first_enumeration_countdown_--;
    if (enumeration_ready())
      enumeration_became_ready = true;
  }

  // If |device| was disconnected while descriptors were being read then it
  // will have been removed from |devices_by_path_|.
  auto it = devices_by_path_.find(device->device_path());
  if (it == devices_by_path_.end()) {
    success = false;
  } else if (success) {
    DCHECK(!base::ContainsKey(devices(), device->guid()));
    devices()[device->guid()] = device;

    USB_LOG(USER) << "USB device added: path=" << device->device_path()
                  << " vendor=" << device->vendor_id() << " \""
                  << device->manufacturer_string()
                  << "\", product=" << device->product_id() << " \""
                  << device->product_string() << "\", serial=\""
                  << device->serial_number() << "\", driver=\""
                  << device->driver_name() << "\", guid=" << device->guid();
  } else {
    devices_by_path_.erase(it);
  }

  if (enumeration_became_ready) {
    std::vector<scoped_refptr<UsbDevice>> result;
    result.reserve(devices().size());
    for (const auto& map_entry : devices())
      result.push_back(map_entry.second);
    for (const auto& callback : enumeration_callbacks_)
      callback.Run(result);
    enumeration_callbacks_.clear();
  } else if (success && enumeration_ready()) {
    NotifyDeviceAdded(device);
  }
}

}  // namespace device
