Use multiline attribute to check for IA2_STATE_MULTILINE.
[chromium-blink-merge.git] / device / hid / device_monitor_linux.cc
blob5dffc85e061051d24322bc6b823c120e035f257a
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.
5 #include "device/hid/device_monitor_linux.h"
7 #include "base/lazy_instance.h"
8 #include "base/logging.h"
9 #include "base/threading/thread_restrictions.h"
10 #include "device/udev_linux/udev.h"
12 namespace device {
14 namespace {
16 const char kUdevName[] = "udev";
17 const char kUdevActionAdd[] = "add";
18 const char kUdevActionRemove[] = "remove";
20 // The instance will be reset when message loop destroys.
21 base::LazyInstance<scoped_ptr<DeviceMonitorLinux> >::Leaky
22 g_device_monitor_linux_ptr = LAZY_INSTANCE_INITIALIZER;
24 } // namespace
26 DeviceMonitorLinux::DeviceMonitorLinux() : monitor_fd_(-1) {
27 base::ThreadRestrictions::AssertIOAllowed();
28 base::MessageLoop::current()->AddDestructionObserver(this);
30 udev_.reset(udev_new());
31 if (!udev_) {
32 LOG(ERROR) << "Failed to create udev.";
33 return;
35 monitor_.reset(udev_monitor_new_from_netlink(udev_.get(), kUdevName));
36 if (!monitor_) {
37 LOG(ERROR) << "Failed to create udev monitor.";
38 return;
41 int ret = udev_monitor_enable_receiving(monitor_.get());
42 if (ret != 0) {
43 LOG(ERROR) << "Failed to start udev monitoring.";
44 return;
47 monitor_fd_ = udev_monitor_get_fd(monitor_.get());
48 if (monitor_fd_ <= 0) {
49 LOG(ERROR) << "Failed to start udev monitoring.";
50 return;
53 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
54 monitor_fd_,
55 true,
56 base::MessageLoopForIO::WATCH_READ,
57 &monitor_watcher_,
58 this)) {
59 return;
63 // static
64 DeviceMonitorLinux* DeviceMonitorLinux::GetInstance() {
65 if (!HasInstance())
66 g_device_monitor_linux_ptr.Get().reset(new DeviceMonitorLinux());
67 return g_device_monitor_linux_ptr.Get().get();
70 // static
71 bool DeviceMonitorLinux::HasInstance() {
72 return g_device_monitor_linux_ptr.Get().get();
75 void DeviceMonitorLinux::AddObserver(Observer* observer) {
76 DCHECK(thread_checker_.CalledOnValidThread());
77 if (observer)
78 observers_.AddObserver(observer);
81 void DeviceMonitorLinux::RemoveObserver(Observer* observer) {
82 DCHECK(thread_checker_.CalledOnValidThread());
83 if (observer)
84 observers_.RemoveObserver(observer);
87 ScopedUdevDevicePtr DeviceMonitorLinux::GetDeviceFromPath(
88 const std::string& path) {
89 DCHECK(thread_checker_.CalledOnValidThread());
90 ScopedUdevDevicePtr device(
91 udev_device_new_from_syspath(udev_.get(), path.c_str()));
92 return device.Pass();
95 void DeviceMonitorLinux::Enumerate(const EnumerateCallback& callback) {
96 DCHECK(thread_checker_.CalledOnValidThread());
97 ScopedUdevEnumeratePtr enumerate(udev_enumerate_new(udev_.get()));
99 if (!enumerate) {
100 LOG(ERROR) << "Failed to enumerate devices.";
101 return;
104 if (udev_enumerate_scan_devices(enumerate.get()) != 0) {
105 LOG(ERROR) << "Failed to enumerate devices.";
106 return;
109 // This list is managed by |enumerate|.
110 udev_list_entry* devices = udev_enumerate_get_list_entry(enumerate.get());
111 for (udev_list_entry* i = devices; i != NULL;
112 i = udev_list_entry_get_next(i)) {
113 ScopedUdevDevicePtr device(
114 udev_device_new_from_syspath(udev_.get(), udev_list_entry_get_name(i)));
115 if (device)
116 callback.Run(device.get());
120 void DeviceMonitorLinux::WillDestroyCurrentMessageLoop() {
121 DCHECK(thread_checker_.CalledOnValidThread());
122 g_device_monitor_linux_ptr.Get().reset(NULL);
125 void DeviceMonitorLinux::OnFileCanReadWithoutBlocking(int fd) {
126 DCHECK(thread_checker_.CalledOnValidThread());
127 DCHECK_EQ(monitor_fd_, fd);
129 ScopedUdevDevicePtr device(udev_monitor_receive_device(monitor_.get()));
130 if (!device)
131 return;
133 std::string action(udev_device_get_action(device.get()));
134 if (action == kUdevActionAdd)
135 FOR_EACH_OBSERVER(Observer, observers_, OnDeviceAdded(device.get()));
136 else if (action == kUdevActionRemove)
137 FOR_EACH_OBSERVER(Observer, observers_, OnDeviceRemoved(device.get()));
140 void DeviceMonitorLinux::OnFileCanWriteWithoutBlocking(int fd) {}
142 DeviceMonitorLinux::~DeviceMonitorLinux() {
143 DCHECK(thread_checker_.CalledOnValidThread());
144 base::MessageLoop::current()->RemoveDestructionObserver(this);
145 monitor_watcher_.StopWatchingFileDescriptor();
146 close(monitor_fd_);
149 } // namespace device