| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <libudev.h> | 5 #include <libudev.h> |
| 6 #include <stdint.h> | 6 #include <stdint.h> |
| 7 | 7 |
| 8 #include <string> | 8 #include <string> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 #include "base/bind.h" |
| 11 #include "base/logging.h" | 12 #include "base/logging.h" |
| 12 #include "base/platform_file.h" | 13 #include "base/platform_file.h" |
| 13 #include "base/stl_util.h" | 14 #include "base/stl_util.h" |
| 14 #include "base/strings/string_number_conversions.h" | 15 #include "base/strings/string_number_conversions.h" |
| 15 #include "base/strings/string_piece.h" | 16 #include "base/strings/string_piece.h" |
| 16 #include "base/strings/string_split.h" | 17 #include "base/strings/string_split.h" |
| 17 #include "device/hid/hid_connection_linux.h" | 18 #include "device/hid/hid_connection_linux.h" |
| 18 #include "device/hid/hid_device_info.h" | 19 #include "device/hid/hid_device_info.h" |
| 19 #include "device/hid/hid_service_linux.h" | 20 #include "device/hid/hid_service_linux.h" |
| 21 #include "device/hid/udev_common.h" |
| 20 | 22 |
| 21 namespace device { | 23 namespace device { |
| 22 | 24 |
| 23 namespace { | 25 namespace { |
| 24 | 26 |
| 25 const char kUdevName[] = "udev"; | |
| 26 const char kUdevActionAdd[] = "add"; | |
| 27 const char kUdevActionRemove[] = "remove"; | |
| 28 const char kHIDSubSystem[] = "hid"; | 27 const char kHIDSubSystem[] = "hid"; |
| 29 | 28 |
| 30 const char kHIDID[] = "HID_ID"; | 29 const char kHIDID[] = "HID_ID"; |
| 31 const char kHIDName[] = "HID_NAME"; | 30 const char kHIDName[] = "HID_NAME"; |
| 32 const char kHIDUnique[] = "HID_UNIQ"; | 31 const char kHIDUnique[] = "HID_UNIQ"; |
| 33 | 32 |
| 34 } // namespace | 33 } // namespace |
| 35 | 34 |
| 36 HidServiceLinux::HidServiceLinux() { | 35 HidServiceLinux::HidServiceLinux() { |
| 37 udev_.reset(udev_new()); | 36 DeviceMonitorLinux* monitor = DeviceMonitorLinux::GetInstance(); |
| 38 if (!udev_) { | 37 monitor->AddObserver(this); |
| 39 LOG(ERROR) << "Failed to create udev."; | 38 monitor->Enumerate( |
| 40 return; | 39 base::Bind(&HidServiceLinux::OnDeviceAdded, base::Unretained(this))); |
| 41 } | |
| 42 monitor_.reset(udev_monitor_new_from_netlink(udev_.get(), kUdevName)); | |
| 43 if (!monitor_) { | |
| 44 LOG(ERROR) << "Failed to create udev monitor."; | |
| 45 return; | |
| 46 } | |
| 47 int ret = udev_monitor_filter_add_match_subsystem_devtype( | |
| 48 monitor_.get(), | |
| 49 kHIDSubSystem, | |
| 50 NULL); | |
| 51 if (ret != 0) { | |
| 52 LOG(ERROR) << "Failed to add udev monitor filter."; | |
| 53 return; | |
| 54 } | |
| 55 | |
| 56 ret = udev_monitor_enable_receiving(monitor_.get()); | |
| 57 if (ret != 0) { | |
| 58 LOG(ERROR) << "Failed to start udev monitoring."; | |
| 59 return; | |
| 60 } | |
| 61 | |
| 62 monitor_fd_ = udev_monitor_get_fd(monitor_.get()); | |
| 63 if (monitor_fd_ <= 0) { | |
| 64 LOG(ERROR) << "Failed to start udev monitoring."; | |
| 65 return; | |
| 66 } | |
| 67 | |
| 68 if (!base::MessageLoopForIO::current()->WatchFileDescriptor( | |
| 69 monitor_fd_, | |
| 70 true, | |
| 71 base::MessageLoopForIO::WATCH_READ, | |
| 72 &monitor_watcher_, | |
| 73 this)) | |
| 74 return; | |
| 75 | |
| 76 Enumerate(); | |
| 77 } | 40 } |
| 78 | 41 |
| 79 scoped_refptr<HidConnection> HidServiceLinux::Connect( | 42 scoped_refptr<HidConnection> HidServiceLinux::Connect( |
| 80 const HidDeviceId& device_id) { | 43 const HidDeviceId& device_id) { |
| 81 HidDeviceInfo device_info; | 44 HidDeviceInfo device_info; |
| 82 if (!GetDeviceInfo(device_id, &device_info)) | 45 if (!GetDeviceInfo(device_id, &device_info)) |
| 83 return NULL; | 46 return NULL; |
| 84 | 47 |
| 85 ScopedUdevDevicePtr hid_device( | 48 ScopedUdevDevicePtr device = |
| 86 udev_device_new_from_syspath(udev_.get(), device_info.device_id.c_str())); | 49 DeviceMonitorLinux::GetInstance()->GetDeviceFromPath( |
| 87 if (hid_device) { | 50 device_info.device_id); |
| 88 return new HidConnectionLinux(device_info, hid_device.Pass()); | 51 if (device) |
| 89 } | 52 return new HidConnectionLinux(device_info, device.Pass()); |
| 90 return NULL; | 53 return NULL; |
| 91 } | 54 } |
| 92 | 55 |
| 93 void HidServiceLinux::OnFileCanReadWithoutBlocking(int fd) { | 56 HidServiceLinux::~HidServiceLinux() { |
| 94 DCHECK_EQ(monitor_fd_, fd); | 57 if (DeviceMonitorLinux::HasInstance()) |
| 95 | 58 DeviceMonitorLinux::GetInstance()->RemoveObserver(this); |
| 96 ScopedUdevDevicePtr dev(udev_monitor_receive_device(monitor_.get())); | |
| 97 if (!dev) | |
| 98 return; | |
| 99 | |
| 100 std::string action(udev_device_get_action(dev.get())); | |
| 101 if (action == kUdevActionAdd) { | |
| 102 PlatformAddDevice(dev.get()); | |
| 103 } else if (action == kUdevActionRemove) { | |
| 104 PlatformRemoveDevice(dev.get()); | |
| 105 } | |
| 106 } | 59 } |
| 107 | 60 |
| 108 void HidServiceLinux::OnFileCanWriteWithoutBlocking(int fd) {} | 61 void HidServiceLinux::OnDeviceAdded(udev_device* device) { |
| 109 | |
| 110 HidServiceLinux::~HidServiceLinux() { | |
| 111 monitor_watcher_.StopWatchingFileDescriptor(); | |
| 112 close(monitor_fd_); | |
| 113 } | |
| 114 | |
| 115 void HidServiceLinux::Enumerate() { | |
| 116 scoped_ptr<udev_enumerate, UdevEnumerateDeleter> enumerate( | |
| 117 udev_enumerate_new(udev_.get())); | |
| 118 | |
| 119 if (!enumerate) { | |
| 120 LOG(ERROR) << "Failed to enumerate devices."; | |
| 121 return; | |
| 122 } | |
| 123 | |
| 124 if (udev_enumerate_add_match_subsystem(enumerate.get(), kHIDSubSystem)) { | |
| 125 LOG(ERROR) << "Failed to enumerate devices."; | |
| 126 return; | |
| 127 } | |
| 128 | |
| 129 if (udev_enumerate_scan_devices(enumerate.get()) != 0) { | |
| 130 LOG(ERROR) << "Failed to enumerate devices."; | |
| 131 return; | |
| 132 } | |
| 133 | |
| 134 // This list is managed by |enumerate|. | |
| 135 udev_list_entry* devices = udev_enumerate_get_list_entry(enumerate.get()); | |
| 136 for (udev_list_entry* i = devices; i != NULL; | |
| 137 i = udev_list_entry_get_next(i)) { | |
| 138 ScopedUdevDevicePtr hid_dev( | |
| 139 udev_device_new_from_syspath(udev_.get(), udev_list_entry_get_name(i))); | |
| 140 if (hid_dev) { | |
| 141 PlatformAddDevice(hid_dev.get()); | |
| 142 } | |
| 143 } | |
| 144 } | |
| 145 | |
| 146 void HidServiceLinux::PlatformAddDevice(udev_device* device) { | |
| 147 if (!device) | 62 if (!device) |
| 148 return; | 63 return; |
| 149 | 64 |
| 150 const char* device_path = udev_device_get_syspath(device); | 65 const char* device_path = udev_device_get_syspath(device); |
| 151 if (!device_path) | 66 if (!device_path) |
| 152 return; | 67 return; |
| 68 const char* subsystem = udev_device_get_subsystem(device); |
| 69 if (!subsystem || strcmp(subsystem, kHIDSubSystem) != 0) |
| 70 return; |
| 153 | 71 |
| 154 HidDeviceInfo device_info; | 72 HidDeviceInfo device_info; |
| 155 device_info.device_id = device_path; | 73 device_info.device_id = device_path; |
| 156 | 74 |
| 157 uint32_t int_property = 0; | 75 uint32_t int_property = 0; |
| 158 const char* str_property = NULL; | 76 const char* str_property = NULL; |
| 159 | 77 |
| 160 const char* hid_id = udev_device_get_property_value(device, kHIDID); | 78 const char* hid_id = udev_device_get_property_value(device, kHIDID); |
| 161 if (!hid_id) | 79 if (!hid_id) |
| 162 return; | 80 return; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 179 if (str_property != NULL) | 97 if (str_property != NULL) |
| 180 device_info.serial_number = str_property; | 98 device_info.serial_number = str_property; |
| 181 | 99 |
| 182 str_property = udev_device_get_property_value(device, kHIDName); | 100 str_property = udev_device_get_property_value(device, kHIDName); |
| 183 if (str_property != NULL) | 101 if (str_property != NULL) |
| 184 device_info.product_name = str_property; | 102 device_info.product_name = str_property; |
| 185 | 103 |
| 186 AddDevice(device_info); | 104 AddDevice(device_info); |
| 187 } | 105 } |
| 188 | 106 |
| 189 void HidServiceLinux::PlatformRemoveDevice(udev_device* raw_dev) { | 107 void HidServiceLinux::OnDeviceRemoved(udev_device* device) { |
| 190 const char* device_path = NULL; | 108 const char* device_path = udev_device_get_syspath(device);; |
| 191 device_path = udev_device_get_syspath(raw_dev); | 109 if (device_path) |
| 192 if (device_path == NULL) | 110 RemoveDevice(device_path); |
| 193 return; | |
| 194 RemoveDevice(device_path); | |
| 195 } | 111 } |
| 196 | 112 |
| 197 } // namespace dev | 113 } // namespace dev |
| OLD | NEW |