| Index: device/hid/device_monitor_linux.cc
|
| diff --git a/device/hid/device_monitor_linux.cc b/device/hid/device_monitor_linux.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..37c4588fcecc3017285b143c90d4b664c2784a0f
|
| --- /dev/null
|
| +++ b/device/hid/device_monitor_linux.cc
|
| @@ -0,0 +1,135 @@
|
| +// 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/hid/device_monitor_linux.h"
|
| +
|
| +#include <libudev.h>
|
| +
|
| +#include "base/lazy_instance.h"
|
| +#include "base/logging.h"
|
| +#include "base/message_loop/message_loop.h"
|
| +
|
| +namespace device {
|
| +
|
| +namespace {
|
| +
|
| +const char kUdevName[] = "udev";
|
| +const char kUdevActionAdd[] = "add";
|
| +const char kUdevActionRemove[] = "remove";
|
| +
|
| +// The instance will be reset when message loop destroys.
|
| +base::LazyInstance<scoped_ptr<DeviceMonitorLinux> >::Leaky
|
| + g_device_monitor_linux_ptr = LAZY_INSTANCE_INITIALIZER;
|
| +
|
| +} // namespace
|
| +
|
| +DeviceMonitorLinux::DeviceMonitorLinux() : monitor_fd_(-1) {
|
| + udev_.reset(udev_new());
|
| + if (!udev_) {
|
| + LOG(ERROR) << "Failed to create udev.";
|
| + return;
|
| + }
|
| + monitor_.reset(udev_monitor_new_from_netlink(udev_.get(), kUdevName));
|
| + if (!monitor_) {
|
| + LOG(ERROR) << "Failed to create udev monitor.";
|
| + return;
|
| + }
|
| +
|
| + int ret = udev_monitor_enable_receiving(monitor_.get());
|
| + if (ret != 0) {
|
| + LOG(ERROR) << "Failed to start udev monitoring.";
|
| + return;
|
| + }
|
| +
|
| + monitor_fd_ = udev_monitor_get_fd(monitor_.get());
|
| + if (monitor_fd_ <= 0) {
|
| + LOG(ERROR) << "Failed to start udev monitoring.";
|
| + return;
|
| + }
|
| +
|
| + if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
|
| + monitor_fd_,
|
| + true,
|
| + base::MessageLoopForIO::WATCH_READ,
|
| + &monitor_watcher_,
|
| + this)) {
|
| + return;
|
| + }
|
| +}
|
| +
|
| +DeviceMonitorLinux::~DeviceMonitorLinux() {
|
| + monitor_watcher_.StopWatchingFileDescriptor();
|
| + close(monitor_fd_);
|
| +}
|
| +
|
| +// static
|
| +DeviceMonitorLinux* DeviceMonitorLinux::GetInstance() {
|
| + if (!HasInstance())
|
| + g_device_monitor_linux_ptr.Get().reset(new DeviceMonitorLinux());
|
| + return g_device_monitor_linux_ptr.Get().get();
|
| +}
|
| +
|
| +// static
|
| +bool DeviceMonitorLinux::HasInstance() {
|
| + return g_device_monitor_linux_ptr.Get().get();
|
| +}
|
| +
|
| +void DeviceMonitorLinux::AddObserver(Observer* observer) {
|
| + if (observer)
|
| + observers_.AddObserver(observer);
|
| +}
|
| +
|
| +void DeviceMonitorLinux::RemoveObserver(Observer* observer) {
|
| + if (observer)
|
| + observers_.RemoveObserver(observer);
|
| +}
|
| +
|
| +ScopedUdevDevicePtr DeviceMonitorLinux::GetDeviceFromPath(
|
| + const std::string& path) {
|
| + ScopedUdevDevicePtr device(
|
| + udev_device_new_from_syspath(udev_.get(), path.c_str()));
|
| + return device.Pass();
|
| +}
|
| +
|
| +void DeviceMonitorLinux::Enumerate(const EnumerateCallback& callback) {
|
| + ScopedUdevEnumeratePtr enumerate(udev_enumerate_new(udev_.get()));
|
| +
|
| + if (!enumerate) {
|
| + LOG(ERROR) << "Failed to enumerate devices.";
|
| + return;
|
| + }
|
| +
|
| + if (udev_enumerate_scan_devices(enumerate.get()) != 0) {
|
| + LOG(ERROR) << "Failed to enumerate devices.";
|
| + return;
|
| + }
|
| +
|
| + // This list is managed by |enumerate|.
|
| + udev_list_entry* devices = udev_enumerate_get_list_entry(enumerate.get());
|
| + for (udev_list_entry* i = devices; i != NULL;
|
| + i = udev_list_entry_get_next(i)) {
|
| + ScopedUdevDevicePtr device(
|
| + udev_device_new_from_syspath(udev_.get(), udev_list_entry_get_name(i)));
|
| + if (device)
|
| + callback.Run(device.get());
|
| + }
|
| +}
|
| +
|
| +void DeviceMonitorLinux::OnFileCanReadWithoutBlocking(int fd) {
|
| + DCHECK_EQ(monitor_fd_, fd);
|
| +
|
| + ScopedUdevDevicePtr device(udev_monitor_receive_device(monitor_.get()));
|
| + if (!device)
|
| + return;
|
| +
|
| + std::string action(udev_device_get_action(device.get()));
|
| + if (action == kUdevActionAdd)
|
| + FOR_EACH_OBSERVER(Observer, observers_, OnDeviceAdded(device.get()));
|
| + else if (action == kUdevActionRemove)
|
| + FOR_EACH_OBSERVER(Observer, observers_, OnDeviceRemoved(device.get()));
|
| +}
|
| +
|
| +void DeviceMonitorLinux::OnFileCanWriteWithoutBlocking(int fd) {}
|
| +
|
| +} // namespace device
|
|
|