Index: device/udev_linux/udev_watcher.cc |
diff --git a/device/udev_linux/udev_watcher.cc b/device/udev_linux/udev_watcher.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d9e490de63a0f6bd2f4d501726bd549b615bda6c |
--- /dev/null |
+++ b/device/udev_linux/udev_watcher.cc |
@@ -0,0 +1,98 @@ |
+// 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 "base/bind.h" |
+#include "base/memory/ptr_util.h" |
+ |
+namespace device { |
+ |
+UdevWatcher::Observer::~Observer() = default; |
+ |
+void UdevWatcher::Observer::OnDeviceAdded(ScopedUdevDevicePtr device) {} |
+ |
+void UdevWatcher::Observer::OnDeviceRemoved(ScopedUdevDevicePtr device) {} |
+ |
+std::unique_ptr<UdevWatcher> UdevWatcher::StartWatching(Observer* observer) { |
+ 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; |
+ } |
+ |
+ 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)); |
+} |
+ |
+UdevWatcher::~UdevWatcher() { |
+ DCHECK(sequence_checker_.CalledOnValidSequence()); |
+}; |
+ |
+void UdevWatcher::EnumerateExistingDevices() { |
+ DCHECK(sequence_checker_.CalledOnValidSequence()); |
+ ScopedUdevEnumeratePtr enumerate(udev_enumerate_new(udev_.get())); |
+ if (!enumerate) { |
+ LOG(ERROR) << "Failed to initialize a udev enumerator."; |
+ return; |
+ } |
+ |
+ 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) |
+ : udev_(std::move(udev)), |
+ udev_monitor_(std::move(udev_monitor)), |
+ observer_(observer) { |
+ file_watcher_ = base::FileDescriptorWatcher::WatchReadable( |
+ monitor_fd, |
+ base::Bind(&UdevWatcher::OnMonitorReadable, base::Unretained(this))); |
+} |
+ |
+void UdevWatcher::OnMonitorReadable() { |
+ 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)); |
+} |
+ |
+} // namespace device |