OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "device/hid/device_monitor_linux.h" |
| 6 |
| 7 #include <libudev.h> |
| 8 |
| 9 #include "base/lazy_instance.h" |
| 10 #include "base/logging.h" |
| 11 #include "base/message_loop/message_loop.h" |
| 12 |
| 13 namespace device { |
| 14 |
| 15 namespace { |
| 16 |
| 17 const char kUdevName[] = "udev"; |
| 18 const char kUdevActionAdd[] = "add"; |
| 19 const char kUdevActionRemove[] = "remove"; |
| 20 |
| 21 // The instance will be reset when message loop destroys. |
| 22 base::LazyInstance<scoped_ptr<DeviceMonitorLinux> >::Leaky |
| 23 g_device_monitor_linux_ptr = LAZY_INSTANCE_INITIALIZER; |
| 24 |
| 25 } // namespace |
| 26 |
| 27 DeviceMonitorLinux::DeviceMonitorLinux() : monitor_fd_(-1) { |
| 28 udev_.reset(udev_new()); |
| 29 if (!udev_) { |
| 30 LOG(ERROR) << "Failed to create udev."; |
| 31 return; |
| 32 } |
| 33 monitor_.reset(udev_monitor_new_from_netlink(udev_.get(), kUdevName)); |
| 34 if (!monitor_) { |
| 35 LOG(ERROR) << "Failed to create udev monitor."; |
| 36 return; |
| 37 } |
| 38 |
| 39 int ret = udev_monitor_enable_receiving(monitor_.get()); |
| 40 if (ret != 0) { |
| 41 LOG(ERROR) << "Failed to start udev monitoring."; |
| 42 return; |
| 43 } |
| 44 |
| 45 monitor_fd_ = udev_monitor_get_fd(monitor_.get()); |
| 46 if (monitor_fd_ <= 0) { |
| 47 LOG(ERROR) << "Failed to start udev monitoring."; |
| 48 return; |
| 49 } |
| 50 |
| 51 if (!base::MessageLoopForIO::current()->WatchFileDescriptor( |
| 52 monitor_fd_, |
| 53 true, |
| 54 base::MessageLoopForIO::WATCH_READ, |
| 55 &monitor_watcher_, |
| 56 this)) { |
| 57 return; |
| 58 } |
| 59 } |
| 60 |
| 61 DeviceMonitorLinux::~DeviceMonitorLinux() { |
| 62 monitor_watcher_.StopWatchingFileDescriptor(); |
| 63 close(monitor_fd_); |
| 64 } |
| 65 |
| 66 // static |
| 67 DeviceMonitorLinux* DeviceMonitorLinux::GetInstance() { |
| 68 if (!HasInstance()) |
| 69 g_device_monitor_linux_ptr.Get().reset(new DeviceMonitorLinux()); |
| 70 return g_device_monitor_linux_ptr.Get().get(); |
| 71 } |
| 72 |
| 73 // static |
| 74 bool DeviceMonitorLinux::HasInstance() { |
| 75 return g_device_monitor_linux_ptr.Get().get(); |
| 76 } |
| 77 |
| 78 void DeviceMonitorLinux::AddObserver(Observer* observer) { |
| 79 if (observer) |
| 80 observers_.AddObserver(observer); |
| 81 } |
| 82 |
| 83 void DeviceMonitorLinux::RemoveObserver(Observer* observer) { |
| 84 if (observer) |
| 85 observers_.RemoveObserver(observer); |
| 86 } |
| 87 |
| 88 ScopedUdevDevicePtr DeviceMonitorLinux::GetDeviceFromPath( |
| 89 const std::string& path) { |
| 90 ScopedUdevDevicePtr device( |
| 91 udev_device_new_from_syspath(udev_.get(), path.c_str())); |
| 92 return device.Pass(); |
| 93 } |
| 94 |
| 95 void DeviceMonitorLinux::Enumerate(const EnumerateCallback& callback) { |
| 96 ScopedUdevEnumeratePtr enumerate(udev_enumerate_new(udev_.get())); |
| 97 |
| 98 if (!enumerate) { |
| 99 LOG(ERROR) << "Failed to enumerate devices."; |
| 100 return; |
| 101 } |
| 102 |
| 103 if (udev_enumerate_scan_devices(enumerate.get()) != 0) { |
| 104 LOG(ERROR) << "Failed to enumerate devices."; |
| 105 return; |
| 106 } |
| 107 |
| 108 // This list is managed by |enumerate|. |
| 109 udev_list_entry* devices = udev_enumerate_get_list_entry(enumerate.get()); |
| 110 for (udev_list_entry* i = devices; i != NULL; |
| 111 i = udev_list_entry_get_next(i)) { |
| 112 ScopedUdevDevicePtr device( |
| 113 udev_device_new_from_syspath(udev_.get(), udev_list_entry_get_name(i))); |
| 114 if (device) |
| 115 callback.Run(device.get()); |
| 116 } |
| 117 } |
| 118 |
| 119 void DeviceMonitorLinux::OnFileCanReadWithoutBlocking(int fd) { |
| 120 DCHECK_EQ(monitor_fd_, fd); |
| 121 |
| 122 ScopedUdevDevicePtr device(udev_monitor_receive_device(monitor_.get())); |
| 123 if (!device) |
| 124 return; |
| 125 |
| 126 std::string action(udev_device_get_action(device.get())); |
| 127 if (action == kUdevActionAdd) |
| 128 FOR_EACH_OBSERVER(Observer, observers_, OnDeviceAdded(device.get())); |
| 129 else if (action == kUdevActionRemove) |
| 130 FOR_EACH_OBSERVER(Observer, observers_, OnDeviceRemoved(device.get())); |
| 131 } |
| 132 |
| 133 void DeviceMonitorLinux::OnFileCanWriteWithoutBlocking(int fd) {} |
| 134 |
| 135 } // namespace device |
OLD | NEW |