// Copyright 2014 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/bluetooth/bluetooth_low_energy_win.h"

#include "base/files/file.h"
#include "base/logging.h"
#include "base/strings/sys_string_conversions.h"
#include "base/win/scoped_handle.h"
#include "base/win/windows_version.h"

namespace {

using device::win::DeviceRegistryPropertyValue;
using device::win::DevicePropertyValue;
using device::win::BluetoothLowEnergyDeviceInfo;
using device::win::BluetoothLowEnergyServiceInfo;

const char kPlatformNotSupported[] =
    "Bluetooth Low energy is only supported on Windows 8 and later.";
const char kDeviceEnumError[] = "Error enumerating Bluetooth LE devices.";
const char kDeviceInfoError[] =
    "Error retrieving Bluetooth LE device information.";
const char kDeviceAddressError[] =
    "Device instance ID value does not seem to contain a Bluetooth Adapter "
    "address.";
const char kDeviceFriendlyNameError[] = "Device name is not valid.";
const char kInvalidBluetoothAddress[] = "Bluetooth address format is invalid.";

// Like ScopedHandle but for HDEVINFO.  Only use this on HDEVINFO returned from
// SetupDiGetClassDevs.
class DeviceInfoSetTraits {
 public:
  typedef HDEVINFO Handle;

  static bool CloseHandle(HDEVINFO handle) {
    return ::SetupDiDestroyDeviceInfoList(handle) != FALSE;
  }

  static bool IsHandleValid(HDEVINFO handle) {
    return handle != INVALID_HANDLE_VALUE;
  }

  static HDEVINFO NullHandle() { return INVALID_HANDLE_VALUE; }

 private:
  DISALLOW_IMPLICIT_CONSTRUCTORS(DeviceInfoSetTraits);
};

typedef base::win::GenericScopedHandle<DeviceInfoSetTraits,
                                       base::win::VerifierTraits>
    ScopedDeviceInfoSetHandle;

bool StringToBluetoothAddress(const std::string& value,
                              BLUETOOTH_ADDRESS* btha,
                              std::string* error) {
  if (value.length() != 6 * 2) {
    *error = kInvalidBluetoothAddress;
    return false;
  }

  int buffer[6];
  int result = sscanf_s(value.c_str(),
                        "%02X%02X%02X%02X%02X%02X",
                        &buffer[5],
                        &buffer[4],
                        &buffer[3],
                        &buffer[2],
                        &buffer[1],
                        &buffer[0]);
  if (result != 6) {
    *error = kInvalidBluetoothAddress;
    return false;
  }

  ZeroMemory(btha, sizeof(*btha));
  btha->rgBytes[0] = buffer[0];
  btha->rgBytes[1] = buffer[1];
  btha->rgBytes[2] = buffer[2];
  btha->rgBytes[3] = buffer[3];
  btha->rgBytes[4] = buffer[4];
  btha->rgBytes[5] = buffer[5];
  return true;
}

std::string FormatBluetoothError(const char* message, HRESULT hr) {
  std::ostringstream string_stream;
  string_stream << message;
  if (FAILED(hr))
    string_stream << logging::SystemErrorCodeToString(hr);
  return string_stream.str();
}

bool CheckInsufficientBuffer(bool success,
                             const char* message,
                             std::string* error) {
  if (success) {
    *error = FormatBluetoothError(message, S_OK);
    return false;
  }

  HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
  if (hr != HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) {
    *error = FormatBluetoothError(message, hr);
    return false;
  }

  return true;
}

bool CheckHResult(HRESULT hr, const char* message, std::string* error) {
  if (FAILED(hr)) {
    *error = FormatBluetoothError(message, hr);
    return false;
  }

  return true;
}

bool CheckSuccess(bool success, const char* message, std::string* error) {
  if (!success) {
    CheckHResult(HRESULT_FROM_WIN32(GetLastError()), message, error);
    return false;
  }

  return true;
}

bool CheckNoData(HRESULT hr, size_t length) {
  if (hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND))
    return true;

  if (SUCCEEDED(hr) && length == 0)
    return true;

  return false;
}

bool CheckMoreData(HRESULT hr, const char* message, std::string* error) {
  if (SUCCEEDED(hr)) {
    *error = FormatBluetoothError(message, hr);
    return false;
  }

  if (hr != HRESULT_FROM_WIN32(ERROR_MORE_DATA)) {
    *error = FormatBluetoothError(message, hr);
    return false;
  }

  return true;
}

bool CheckExpectedLength(size_t actual_length,
                         size_t expected_length,
                         const char* message,
                         std::string* error) {
  if (actual_length != expected_length) {
    *error = FormatBluetoothError(message, E_FAIL);
    return false;
  }

  return true;
}

bool CollectBluetoothLowEnergyDeviceProperty(
    const ScopedDeviceInfoSetHandle& device_info_handle,
    PSP_DEVINFO_DATA device_info_data,
    const DEVPROPKEY& key,
    scoped_ptr<DevicePropertyValue>* value,
    std::string* error) {
  DWORD required_length;
  DEVPROPTYPE prop_type;
  BOOL success = SetupDiGetDeviceProperty(device_info_handle.Get(),
                                          device_info_data,
                                          &key,
                                          &prop_type,
                                          NULL,
                                          0,
                                          &required_length,
                                          0);
  if (!CheckInsufficientBuffer(!!success, kDeviceInfoError, error))
    return false;

  scoped_ptr<uint8_t[]> prop_value(new uint8_t[required_length]);
  DWORD actual_length = required_length;
  success = SetupDiGetDeviceProperty(device_info_handle.Get(),
                                     device_info_data,
                                     &key,
                                     &prop_type,
                                     prop_value.get(),
                                     actual_length,
                                     &required_length,
                                     0);
  if (!CheckSuccess(!!success, kDeviceInfoError, error))
    return false;
  if (!CheckExpectedLength(
          actual_length, required_length, kDeviceInfoError, error)) {
    return false;
  }

  (*value) = scoped_ptr<DevicePropertyValue>(
      new DevicePropertyValue(prop_type, prop_value.Pass(), actual_length));
  return true;
}

bool CollectBluetoothLowEnergyDeviceRegistryProperty(
    const ScopedDeviceInfoSetHandle& device_info_handle,
    PSP_DEVINFO_DATA device_info_data,
    DWORD property_id,
    scoped_ptr<DeviceRegistryPropertyValue>* value,
    std::string* error) {
  ULONG required_length = 0;
  BOOL success = SetupDiGetDeviceRegistryProperty(device_info_handle.Get(),
                                                  device_info_data,
                                                  property_id,
                                                  NULL,
                                                  NULL,
                                                  0,
                                                  &required_length);
  if (!CheckInsufficientBuffer(!!success, kDeviceInfoError, error))
    return false;

  scoped_ptr<uint8_t[]> property_value(new uint8_t[required_length]);
  ULONG actual_length = required_length;
  DWORD property_type;
  success = SetupDiGetDeviceRegistryProperty(device_info_handle.Get(),
                                             device_info_data,
                                             property_id,
                                             &property_type,
                                             property_value.get(),
                                             actual_length,
                                             &required_length);
  if (!CheckSuccess(!!success, kDeviceInfoError, error))
    return false;
  if (!CheckExpectedLength(
          actual_length, required_length, kDeviceInfoError, error)) {
    return false;
  }

  (*value) = DeviceRegistryPropertyValue::Create(
                 property_type, property_value.Pass(), actual_length).Pass();
  return true;
}

bool CollectBluetoothLowEnergyDeviceInstanceId(
    const ScopedDeviceInfoSetHandle& device_info_handle,
    PSP_DEVINFO_DATA device_info_data,
    scoped_ptr<device::win::BluetoothLowEnergyDeviceInfo>& device_info,
    std::string* error) {
  ULONG required_length = 0;
  BOOL success = SetupDiGetDeviceInstanceId(
      device_info_handle.Get(), device_info_data, NULL, 0, &required_length);
  if (!CheckInsufficientBuffer(!!success, kDeviceInfoError, error))
    return false;

  scoped_ptr<WCHAR[]> instance_id(new WCHAR[required_length]);
  ULONG actual_length = required_length;
  success = SetupDiGetDeviceInstanceId(device_info_handle.Get(),
                                       device_info_data,
                                       instance_id.get(),
                                       actual_length,
                                       &required_length);
  if (!CheckSuccess(!!success, kDeviceInfoError, error))
    return false;
  if (!CheckExpectedLength(
          actual_length, required_length, kDeviceInfoError, error)) {
    return false;
  }

  if (actual_length >= 1) {
    // Ensure string is zero terminated.
    instance_id.get()[actual_length - 1] = 0;
    device_info->id = base::SysWideToUTF8(instance_id.get());
  }
  return true;
}

bool CollectBluetoothLowEnergyDeviceFriendlyName(
    const ScopedDeviceInfoSetHandle& device_info_handle,
    PSP_DEVINFO_DATA device_info_data,
    scoped_ptr<device::win::BluetoothLowEnergyDeviceInfo>& device_info,
    std::string* error) {
  scoped_ptr<DeviceRegistryPropertyValue> property_value;
  if (!CollectBluetoothLowEnergyDeviceRegistryProperty(device_info_handle,
                                                       device_info_data,
                                                       SPDRP_FRIENDLYNAME,
                                                       &property_value,
                                                       error)) {
    return false;
  }

  if (property_value->property_type() != REG_SZ) {
    *error = kDeviceFriendlyNameError;
    return false;
  }

  device_info->friendly_name = property_value->AsString();
  return true;
}

bool ExtractBluetoothAddressFromDeviceInstanceId(const std::string& instance_id,
                                                 BLUETOOTH_ADDRESS* btha,
                                                 std::string* error) {
  size_t start = instance_id.find("_");
  if (start == std::string::npos) {
    *error = kDeviceAddressError;
    return false;
  }
  size_t end = instance_id.find("\\", start);
  if (end == std::string::npos) {
    *error = kDeviceAddressError;
    return false;
  }

  start++;
  std::string address = instance_id.substr(start, end - start);
  if (!StringToBluetoothAddress(address, btha, error))
    return false;

  return true;
}

bool CollectBluetoothLowEnergyDeviceAddress(
    const ScopedDeviceInfoSetHandle& device_info_handle,
    PSP_DEVINFO_DATA device_info_data,
    scoped_ptr<device::win::BluetoothLowEnergyDeviceInfo>& device_info,
    std::string* error) {
  // TODO(rpaquay): We exctract the bluetooth device address from the device
  // instance ID string, as we did not find a more formal API for retrieving the
  // bluetooth address of a Bluetooth Low Energy device.
  // An Bluetooth device instance ID has the following format (under Win8+):
  // BTHLE\DEV_BC6A29AB5FB0\8&31038925&0&BC6A29AB5FB0
  return ExtractBluetoothAddressFromDeviceInstanceId(
      device_info->id, &device_info->address, error);
}

bool CollectBluetoothLowEnergyDeviceStatus(
    const ScopedDeviceInfoSetHandle& device_info_handle,
    PSP_DEVINFO_DATA device_info_data,
    scoped_ptr<device::win::BluetoothLowEnergyDeviceInfo>& device_info,
    std::string* error) {
  scoped_ptr<DevicePropertyValue> value;
  if (!CollectBluetoothLowEnergyDeviceProperty(device_info_handle,
                                               device_info_data,
                                               DEVPKEY_Device_DevNodeStatus,
                                               &value,
                                               error)) {
    return false;
  }

  if (value->property_type() != DEVPROP_TYPE_UINT32) {
    *error = kDeviceInfoError;
    return false;
  }

  device_info->connected = !(value->AsUint32() & DN_DEVICE_DISCONNECTED);
  // Windows 8 exposes BLE devices only if they are visible and paired. This
  // might change in the future if Windows offers a public API for discovering
  // and pairing BLE devices.
  device_info->visible = true;
  device_info->authenticated = true;
  return true;
}

bool CollectBluetoothLowEnergyDeviceServices(
    const base::FilePath& device_path,
    ScopedVector<BluetoothLowEnergyServiceInfo>* services,
    std::string* error) {
  base::File file(device_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
  if (!file.IsValid()) {
    *error = file.ErrorToString(file.error_details());
    return false;
  }

  USHORT required_length;
  HRESULT hr = BluetoothGATTGetServices(file.GetPlatformFile(),
                                        0,
                                        NULL,
                                        &required_length,
                                        BLUETOOTH_GATT_FLAG_NONE);
  if (CheckNoData(hr, required_length))
    return true;
  if (!CheckMoreData(hr, kDeviceInfoError, error))
    return false;

  scoped_ptr<BTH_LE_GATT_SERVICE[]> gatt_services(
      new BTH_LE_GATT_SERVICE[required_length]);
  USHORT actual_length = required_length;
  hr = BluetoothGATTGetServices(file.GetPlatformFile(),
                                actual_length,
                                gatt_services.get(),
                                &required_length,
                                BLUETOOTH_GATT_FLAG_NONE);
  if (!CheckHResult(hr, kDeviceInfoError, error))
    return false;
  if (!CheckExpectedLength(
          actual_length, required_length, kDeviceInfoError, error)) {
    return false;
  }

  for (USHORT i = 0; i < actual_length; ++i) {
    BTH_LE_GATT_SERVICE& gatt_service(gatt_services.get()[i]);
    BluetoothLowEnergyServiceInfo* service_info =
        new BluetoothLowEnergyServiceInfo();
    service_info->uuid = gatt_service.ServiceUuid;
    services->push_back(service_info);
  }

  return true;
}

bool CollectBluetoothLowEnergyDeviceInfo(
    const ScopedDeviceInfoSetHandle& device_info_handle,
    PSP_DEVICE_INTERFACE_DATA device_interface_data,
    scoped_ptr<device::win::BluetoothLowEnergyDeviceInfo>* device_info,
    std::string* error) {
  // Retrieve required # of bytes for interface details
  ULONG required_length = 0;
  BOOL success = SetupDiGetDeviceInterfaceDetail(device_info_handle.Get(),
                                                 device_interface_data,
                                                 NULL,
                                                 0,
                                                 &required_length,
                                                 NULL);
  if (!CheckInsufficientBuffer(!!success, kDeviceInfoError, error))
    return false;

  scoped_ptr<uint8_t[]> interface_data(new uint8_t[required_length]);
  ZeroMemory(interface_data.get(), required_length);

  PSP_DEVICE_INTERFACE_DETAIL_DATA device_interface_detail_data =
      reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA>(interface_data.get());
  device_interface_detail_data->cbSize =
      sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

  SP_DEVINFO_DATA device_info_data = {0};
  device_info_data.cbSize = sizeof(SP_DEVINFO_DATA);

  ULONG actual_length = required_length;
  success = SetupDiGetDeviceInterfaceDetail(device_info_handle.Get(),
                                            device_interface_data,
                                            device_interface_detail_data,
                                            actual_length,
                                            &required_length,
                                            &device_info_data);
  if (!CheckSuccess(!!success, kDeviceInfoError, error))
    return false;
  if (!CheckExpectedLength(
          actual_length, required_length, kDeviceInfoError, error)) {
    return false;
  }

  scoped_ptr<device::win::BluetoothLowEnergyDeviceInfo> result(
      new device::win::BluetoothLowEnergyDeviceInfo());
  result->path =
      base::FilePath(std::wstring(device_interface_detail_data->DevicePath));
  if (!CollectBluetoothLowEnergyDeviceInstanceId(
          device_info_handle, &device_info_data, result, error)) {
    return false;
  }
  if (!CollectBluetoothLowEnergyDeviceFriendlyName(
          device_info_handle, &device_info_data, result, error)) {
    return false;
  }
  if (!CollectBluetoothLowEnergyDeviceAddress(
          device_info_handle, &device_info_data, result, error)) {
    return false;
  }
  if (!CollectBluetoothLowEnergyDeviceStatus(
          device_info_handle, &device_info_data, result, error)) {
    return false;
  }
  (*device_info) = result.Pass();
  return true;
}

enum DeviceInfoResult { kOk, kError, kNoMoreDevices };

DeviceInfoResult EnumerateSingleBluetoothLowEnergyDevice(
    const ScopedDeviceInfoSetHandle& device_info_handle,
    DWORD device_index,
    scoped_ptr<device::win::BluetoothLowEnergyDeviceInfo>* device_info,
    std::string* error) {
  // Enumerate device of BLUETOOTHLE_DEVICE interface class
  GUID BluetoothInterfaceGUID = GUID_BLUETOOTHLE_DEVICE_INTERFACE;
  SP_DEVICE_INTERFACE_DATA device_interface_data = {0};
  device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  BOOL success = ::SetupDiEnumDeviceInterfaces(device_info_handle.Get(),
                                               NULL,
                                               &BluetoothInterfaceGUID,
                                               device_index,
                                               &device_interface_data);
  if (!success) {
    HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
    if (hr == HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS)) {
      return kNoMoreDevices;
    }
    *error = FormatBluetoothError(kDeviceInfoError, hr);
    return kError;
  }

  if (!CollectBluetoothLowEnergyDeviceInfo(
          device_info_handle, &device_interface_data, device_info, error)) {
    return kError;
  }

  return kOk;
}

// Opens a Device Info Set that can be used to enumerate Bluetooth LE devices
// present on the machine.
HRESULT OpenBluetoothLowEnergyDevices(ScopedDeviceInfoSetHandle* handle) {
  GUID BluetoothClassGUID = GUID_BLUETOOTHLE_DEVICE_INTERFACE;
  ScopedDeviceInfoSetHandle result(SetupDiGetClassDevs(
      &BluetoothClassGUID, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
  if (!result.IsValid()) {
    return HRESULT_FROM_WIN32(::GetLastError());
  }

  (*handle) = result.Pass();
  return S_OK;
}

// Opens a Device Info Set that can be used to enumerate Bluetooth LE devices
// exposing a service GUID.
HRESULT OpenBluetoothLowEnergyService(const GUID& service_guid,
                                      ScopedDeviceInfoSetHandle* handle) {
  ScopedDeviceInfoSetHandle result(SetupDiGetClassDevs(
      &service_guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
  if (!result.IsValid()) {
    return HRESULT_FROM_WIN32(::GetLastError());
  }

  (*handle) = result.Pass();
  return S_OK;
}

}  // namespace

namespace device {
namespace win {

// static
scoped_ptr<DeviceRegistryPropertyValue> DeviceRegistryPropertyValue::Create(
    DWORD property_type,
    scoped_ptr<uint8_t[]> value,
    size_t value_size) {
  switch (property_type) {
    case REG_SZ: {
      // Ensure string is zero terminated.
      size_t character_size = value_size / sizeof(WCHAR);
      CHECK_EQ(character_size * sizeof(WCHAR), value_size);
      CHECK_GE(character_size, 1u);
      WCHAR* value_string = reinterpret_cast<WCHAR*>(value.get());
      value_string[character_size - 1] = 0;
      break;
    }
    case REG_DWORD: {
      CHECK_EQ(value_size, sizeof(DWORD));
      break;
    }
  }
  return scoped_ptr<DeviceRegistryPropertyValue>(
      new DeviceRegistryPropertyValue(property_type, value.Pass(), value_size));
}

DeviceRegistryPropertyValue::DeviceRegistryPropertyValue(
    DWORD property_type,
    scoped_ptr<uint8_t[]> value,
    size_t value_size)
    : property_type_(property_type),
      value_(value.Pass()),
      value_size_(value_size) {
}

DeviceRegistryPropertyValue::~DeviceRegistryPropertyValue() {
}

std::string DeviceRegistryPropertyValue::AsString() const {
  CHECK_EQ(property_type_, static_cast<DWORD>(REG_SZ));
  WCHAR* value_string = reinterpret_cast<WCHAR*>(value_.get());
  return base::SysWideToUTF8(value_string);
}

DWORD DeviceRegistryPropertyValue::AsDWORD() const {
  CHECK_EQ(property_type_, static_cast<DWORD>(REG_DWORD));
  DWORD* value = reinterpret_cast<DWORD*>(value_.get());
  return *value;
}

DevicePropertyValue::DevicePropertyValue(DEVPROPTYPE property_type,
                                         scoped_ptr<uint8_t[]> value,
                                         size_t value_size)
    : property_type_(property_type),
      value_(value.Pass()),
      value_size_(value_size) {
}

uint32_t DevicePropertyValue::AsUint32() const {
  CHECK_EQ(property_type_, static_cast<DEVPROPTYPE>(DEVPROP_TYPE_UINT32));
  CHECK_EQ(value_size_, sizeof(uint32_t));
  return *reinterpret_cast<uint32_t*>(value_.get());
}

BluetoothLowEnergyServiceInfo::BluetoothLowEnergyServiceInfo() {
}

BluetoothLowEnergyServiceInfo::~BluetoothLowEnergyServiceInfo() {
}

BluetoothLowEnergyDeviceInfo::BluetoothLowEnergyDeviceInfo()
    : visible(false), authenticated(false), connected(false) {
  address.ullLong = BLUETOOTH_NULL_ADDRESS;
}

BluetoothLowEnergyDeviceInfo::~BluetoothLowEnergyDeviceInfo() {
}

bool IsBluetoothLowEnergySupported() {
  return base::win::GetVersion() >= base::win::VERSION_WIN8;
}

bool EnumerateKnownBluetoothLowEnergyDevices(
    ScopedVector<BluetoothLowEnergyDeviceInfo>* devices,
    std::string* error) {
  if (!IsBluetoothLowEnergySupported()) {
    *error = kPlatformNotSupported;
    return false;
  }

  ScopedDeviceInfoSetHandle info_set_handle;
  HRESULT hr = OpenBluetoothLowEnergyDevices(&info_set_handle);
  if (FAILED(hr)) {
    *error = FormatBluetoothError(kDeviceEnumError, hr);
    return false;
  }

  for (DWORD i = 0;; ++i) {
    scoped_ptr<BluetoothLowEnergyDeviceInfo> device_info;
    DeviceInfoResult result = EnumerateSingleBluetoothLowEnergyDevice(
        info_set_handle, i, &device_info, error);
    switch (result) {
      case kNoMoreDevices:
        return true;
      case kError:
        return false;
      case kOk:
        devices->push_back(device_info.release());
    }
  }
}

bool EnumerateKnownBluetoothLowEnergyServices(
    const base::FilePath& device_path,
    ScopedVector<BluetoothLowEnergyServiceInfo>* services,
    std::string* error) {
  if (!IsBluetoothLowEnergySupported()) {
    *error = kPlatformNotSupported;
    return false;
  }

  return CollectBluetoothLowEnergyDeviceServices(device_path, services, error);
}

bool ExtractBluetoothAddressFromDeviceInstanceIdForTesting(
    const std::string& instance_id,
    BLUETOOTH_ADDRESS* btha,
    std::string* error) {
  return ExtractBluetoothAddressFromDeviceInstanceId(instance_id, btha, error);
}

}  // namespace win
}  // namespace device
