// 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/udev_linux/udev_watcher.h"

#include <utility>

#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_piece.h"
#include "base/threading/scoped_blocking_call.h"

namespace device {

UdevWatcher::Filter::Filter(base::StringPiece subsystem_in,
                            base::StringPiece devtype_in) {
  if (!subsystem_in.empty())
    subsystem_ = std::string(subsystem_in);
  if (!devtype_in.empty())
    devtype_ = std::string(devtype_in);
}

UdevWatcher::Filter::Filter(const Filter&) = default;
UdevWatcher::Filter::~Filter() = default;

const char* UdevWatcher::Filter::devtype() const {
  return devtype_ ? devtype_.value().c_str() : nullptr;
}

const char* UdevWatcher::Filter::subsystem() const {
  return subsystem_ ? subsystem_.value().c_str() : nullptr;
}

UdevWatcher::Observer::~Observer() = default;

std::unique_ptr<UdevWatcher> UdevWatcher::StartWatching(
    Observer* observer,
    const std::vector<Filter>& filters) {
  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                base::BlockingType::MAY_BLOCK);
  ScopedUdevPtr udev(udev_new());
  if (!udev) {
    LOG(ERROR) << "Failed to initialize udev.";
    return nullptr;
  }

  ScopedUdevMonitorPtr udev_monitor(
      udev_monitor_new_from_netlink(udev.get(), "udev"));
  if (!udev_monitor) {
    LOG(ERROR) << "Failed to initialize a udev monitor.";
    return nullptr;
  }

  for (const Filter& filter : filters) {
    const int ret = udev_monitor_filter_add_match_subsystem_devtype(
        udev_monitor.get(), filter.subsystem(), filter.devtype());
    CHECK_EQ(0, ret);
  }

  if (udev_monitor_enable_receiving(udev_monitor.get()) != 0) {
    LOG(ERROR) << "Failed to enable receiving udev events.";
    return nullptr;
  }

  int monitor_fd = udev_monitor_get_fd(udev_monitor.get());
  if (monitor_fd < 0) {
    LOG(ERROR) << "Udev monitor file descriptor unavailable.";
    return nullptr;
  }

  return base::WrapUnique(new UdevWatcher(
      std::move(udev), std::move(udev_monitor), monitor_fd, observer, filters));
}

UdevWatcher::~UdevWatcher() {
  DCHECK(sequence_checker_.CalledOnValidSequence());
}

void UdevWatcher::EnumerateExistingDevices() {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                base::BlockingType::MAY_BLOCK);
  ScopedUdevEnumeratePtr enumerate(udev_enumerate_new(udev_.get()));
  if (!enumerate) {
    LOG(ERROR) << "Failed to initialize a udev enumerator.";
    return;
  }

  for (const Filter& filter : udev_filters_) {
    const int ret =
        udev_enumerate_add_match_subsystem(enumerate.get(), filter.subsystem());
    CHECK_EQ(0, ret);
  }

  if (udev_enumerate_scan_devices(enumerate.get()) != 0) {
    LOG(ERROR) << "Failed to begin udev enumeration.";
    return;
  }

  udev_list_entry* devices = udev_enumerate_get_list_entry(enumerate.get());
  for (udev_list_entry* i = devices; i != nullptr;
       i = udev_list_entry_get_next(i)) {
    ScopedUdevDevicePtr device(
        udev_device_new_from_syspath(udev_.get(), udev_list_entry_get_name(i)));
    if (device)
      observer_->OnDeviceAdded(std::move(device));
  }
}

UdevWatcher::UdevWatcher(ScopedUdevPtr udev,
                         ScopedUdevMonitorPtr udev_monitor,
                         int monitor_fd,
                         Observer* observer,
                         const std::vector<Filter>& filters)
    : udev_(std::move(udev)),
      udev_monitor_(std::move(udev_monitor)),
      observer_(observer),
      udev_filters_(filters) {
  file_watcher_ = base::FileDescriptorWatcher::WatchReadable(
      monitor_fd, base::BindRepeating(&UdevWatcher::OnMonitorReadable,
                                      base::Unretained(this)));
}

void UdevWatcher::OnMonitorReadable() {
  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                base::BlockingType::MAY_BLOCK);
  ScopedUdevDevicePtr device(udev_monitor_receive_device(udev_monitor_.get()));
  if (!device)
    return;

  std::string action(udev_device_get_action(device.get()));
  if (action == "add")
    observer_->OnDeviceAdded(std::move(device));
  else if (action == "remove")
    observer_->OnDeviceRemoved(std::move(device));
  else if (action == "change")
    observer_->OnDeviceChanged(std::move(device));
  else
    DVLOG(1) << "Unknown udev action: " << action;
}

}  // namespace device
