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 "device/hid/hid_service_linux.h" | 5 #include "device/hid/hid_service_linux.h" |
6 | 6 |
7 #include <fcntl.h> | 7 #include <fcntl.h> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 25 matching lines...) Expand all Loading... |
36 | 36 |
37 const char kHidrawSubsystem[] = "hidraw"; | 37 const char kHidrawSubsystem[] = "hidraw"; |
38 const char kHIDID[] = "HID_ID"; | 38 const char kHIDID[] = "HID_ID"; |
39 const char kHIDName[] = "HID_NAME"; | 39 const char kHIDName[] = "HID_NAME"; |
40 const char kHIDUnique[] = "HID_UNIQ"; | 40 const char kHIDUnique[] = "HID_UNIQ"; |
41 const char kSysfsReportDescriptorKey[] = "report_descriptor"; | 41 const char kSysfsReportDescriptorKey[] = "report_descriptor"; |
42 | 42 |
43 } // namespace | 43 } // namespace |
44 | 44 |
45 struct HidServiceLinux::ConnectParams { | 45 struct HidServiceLinux::ConnectParams { |
46 ConnectParams(const HidDeviceInfo& device_info, | 46 ConnectParams(scoped_refptr<HidDeviceInfo> device_info, |
47 const ConnectCallback& callback, | 47 const ConnectCallback& callback, |
48 scoped_refptr<base::SingleThreadTaskRunner> task_runner, | 48 scoped_refptr<base::SingleThreadTaskRunner> task_runner, |
49 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) | 49 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) |
50 : device_info(device_info), | 50 : device_info(device_info), |
51 callback(callback), | 51 callback(callback), |
52 task_runner(task_runner), | 52 task_runner(task_runner), |
53 file_task_runner(file_task_runner) {} | 53 file_task_runner(file_task_runner) {} |
54 ~ConnectParams() {} | 54 ~ConnectParams() {} |
55 | 55 |
56 HidDeviceInfo device_info; | 56 scoped_refptr<HidDeviceInfo> device_info; |
57 ConnectCallback callback; | 57 ConnectCallback callback; |
58 scoped_refptr<base::SingleThreadTaskRunner> task_runner; | 58 scoped_refptr<base::SingleThreadTaskRunner> task_runner; |
59 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner; | 59 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner; |
60 base::File device_file; | 60 base::File device_file; |
61 }; | 61 }; |
62 | 62 |
63 class HidServiceLinux::Helper : public DeviceMonitorLinux::Observer, | 63 class HidServiceLinux::Helper : public DeviceMonitorLinux::Observer, |
64 public base::MessageLoop::DestructionObserver { | 64 public base::MessageLoop::DestructionObserver { |
65 public: | 65 public: |
66 Helper(base::WeakPtr<HidServiceLinux> service, | 66 Helper(base::WeakPtr<HidServiceLinux> service, |
(...skipping 16 matching lines...) Expand all Loading... |
83 DCHECK(thread_checker_.CalledOnValidThread()); | 83 DCHECK(thread_checker_.CalledOnValidThread()); |
84 const char* device_path = udev_device_get_syspath(device); | 84 const char* device_path = udev_device_get_syspath(device); |
85 if (!device_path) { | 85 if (!device_path) { |
86 return; | 86 return; |
87 } | 87 } |
88 const char* subsystem = udev_device_get_subsystem(device); | 88 const char* subsystem = udev_device_get_subsystem(device); |
89 if (!subsystem || strcmp(subsystem, kHidrawSubsystem) != 0) { | 89 if (!subsystem || strcmp(subsystem, kHidrawSubsystem) != 0) { |
90 return; | 90 return; |
91 } | 91 } |
92 | 92 |
93 HidDeviceInfo device_info; | 93 scoped_refptr<HidDeviceInfo> device_info(new HidDeviceInfo()); |
94 device_info.device_id = device_path; | 94 device_info->device_id_ = device_path; |
95 | 95 |
96 const char* str_property = udev_device_get_devnode(device); | 96 const char* str_property = udev_device_get_devnode(device); |
97 if (!str_property) { | 97 if (!str_property) { |
98 return; | 98 return; |
99 } | 99 } |
100 device_info.device_node = str_property; | 100 device_info->device_node_ = str_property; |
101 | 101 |
102 udev_device* parent = udev_device_get_parent(device); | 102 udev_device* parent = udev_device_get_parent(device); |
103 if (!parent) { | 103 if (!parent) { |
104 return; | 104 return; |
105 } | 105 } |
106 | 106 |
107 const char* hid_id = udev_device_get_property_value(parent, kHIDID); | 107 const char* hid_id = udev_device_get_property_value(parent, kHIDID); |
108 if (!hid_id) { | 108 if (!hid_id) { |
109 return; | 109 return; |
110 } | 110 } |
111 | 111 |
112 std::vector<std::string> parts; | 112 std::vector<std::string> parts; |
113 base::SplitString(hid_id, ':', &parts); | 113 base::SplitString(hid_id, ':', &parts); |
114 if (parts.size() != 3) { | 114 if (parts.size() != 3) { |
115 return; | 115 return; |
116 } | 116 } |
117 | 117 |
118 uint32_t int_property = 0; | 118 uint32_t int_property = 0; |
119 if (HexStringToUInt(base::StringPiece(parts[1]), &int_property)) { | 119 if (HexStringToUInt(base::StringPiece(parts[1]), &int_property)) { |
120 device_info.vendor_id = int_property; | 120 device_info->vendor_id_ = int_property; |
121 } | 121 } |
122 | 122 |
123 if (HexStringToUInt(base::StringPiece(parts[2]), &int_property)) { | 123 if (HexStringToUInt(base::StringPiece(parts[2]), &int_property)) { |
124 device_info.product_id = int_property; | 124 device_info->product_id_ = int_property; |
125 } | 125 } |
126 | 126 |
127 str_property = udev_device_get_property_value(parent, kHIDUnique); | 127 str_property = udev_device_get_property_value(parent, kHIDUnique); |
128 if (str_property != NULL) { | 128 if (str_property != NULL) { |
129 device_info.serial_number = str_property; | 129 device_info->serial_number_ = str_property; |
130 } | 130 } |
131 | 131 |
132 str_property = udev_device_get_property_value(parent, kHIDName); | 132 str_property = udev_device_get_property_value(parent, kHIDName); |
133 if (str_property != NULL) { | 133 if (str_property != NULL) { |
134 device_info.product_name = str_property; | 134 device_info->product_name_ = str_property; |
135 } | 135 } |
136 | 136 |
137 const char* parent_sysfs_path = udev_device_get_syspath(parent); | 137 const char* parent_sysfs_path = udev_device_get_syspath(parent); |
138 if (!parent_sysfs_path) { | 138 if (!parent_sysfs_path) { |
139 return; | 139 return; |
140 } | 140 } |
141 base::FilePath report_descriptor_path = | 141 base::FilePath report_descriptor_path = |
142 base::FilePath(parent_sysfs_path).Append(kSysfsReportDescriptorKey); | 142 base::FilePath(parent_sysfs_path).Append(kSysfsReportDescriptorKey); |
143 std::string report_descriptor_str; | 143 std::string report_descriptor_str; |
144 if (!base::ReadFileToString(report_descriptor_path, | 144 if (!base::ReadFileToString(report_descriptor_path, |
145 &report_descriptor_str)) { | 145 &report_descriptor_str)) { |
146 return; | 146 return; |
147 } | 147 } |
148 | 148 |
149 HidReportDescriptor report_descriptor( | 149 HidReportDescriptor report_descriptor( |
150 reinterpret_cast<uint8_t*>(&report_descriptor_str[0]), | 150 reinterpret_cast<uint8_t*>(&report_descriptor_str[0]), |
151 report_descriptor_str.length()); | 151 report_descriptor_str.length()); |
152 report_descriptor.GetDetails( | 152 report_descriptor.GetDetails(&device_info->collections_, |
153 &device_info.collections, &device_info.has_report_id, | 153 &device_info->has_report_id_, |
154 &device_info.max_input_report_size, &device_info.max_output_report_size, | 154 &device_info->max_input_report_size_, |
155 &device_info.max_feature_report_size); | 155 &device_info->max_output_report_size_, |
| 156 &device_info->max_feature_report_size_); |
156 | 157 |
157 task_runner_->PostTask(FROM_HERE, base::Bind(&HidServiceLinux::AddDevice, | 158 task_runner_->PostTask(FROM_HERE, base::Bind(&HidServiceLinux::AddDevice, |
158 service_, device_info)); | 159 service_, device_info)); |
159 } | 160 } |
160 | 161 |
161 void OnDeviceRemoved(udev_device* device) override { | 162 void OnDeviceRemoved(udev_device* device) override { |
162 DCHECK(thread_checker_.CalledOnValidThread()); | 163 DCHECK(thread_checker_.CalledOnValidThread()); |
163 const char* device_path = udev_device_get_syspath(device); | 164 const char* device_path = udev_device_get_syspath(device); |
164 if (device_path) { | 165 if (device_path) { |
165 task_runner_->PostTask( | 166 task_runner_->PostTask( |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 | 207 |
207 void HidServiceLinux::Connect(const HidDeviceId& device_id, | 208 void HidServiceLinux::Connect(const HidDeviceId& device_id, |
208 const ConnectCallback& callback) { | 209 const ConnectCallback& callback) { |
209 DCHECK(thread_checker_.CalledOnValidThread()); | 210 DCHECK(thread_checker_.CalledOnValidThread()); |
210 | 211 |
211 const auto& map_entry = devices().find(device_id); | 212 const auto& map_entry = devices().find(device_id); |
212 if (map_entry == devices().end()) { | 213 if (map_entry == devices().end()) { |
213 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); | 214 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); |
214 return; | 215 return; |
215 } | 216 } |
216 const HidDeviceInfo& device_info = map_entry->second; | 217 scoped_refptr<HidDeviceInfo> device_info = map_entry->second; |
217 | 218 |
218 scoped_ptr<ConnectParams> params(new ConnectParams( | 219 scoped_ptr<ConnectParams> params(new ConnectParams( |
219 device_info, callback, task_runner_, file_task_runner_)); | 220 device_info, callback, task_runner_, file_task_runner_)); |
220 | 221 |
221 #if defined(OS_CHROMEOS) | 222 #if defined(OS_CHROMEOS) |
222 if (base::SysInfo::IsRunningOnChromeOS()) { | 223 if (base::SysInfo::IsRunningOnChromeOS()) { |
223 chromeos::PermissionBrokerClient* client = | 224 chromeos::PermissionBrokerClient* client = |
224 chromeos::DBusThreadManager::Get()->GetPermissionBrokerClient(); | 225 chromeos::DBusThreadManager::Get()->GetPermissionBrokerClient(); |
225 DCHECK(client) << "Could not get permission broker client."; | 226 DCHECK(client) << "Could not get permission broker client."; |
226 if (client) { | 227 if (client) { |
227 client->RequestPathAccess( | 228 client->RequestPathAccess( |
228 device_info.device_node, -1, | 229 device_info->device_node(), -1, |
229 base::Bind(&HidServiceLinux::OnRequestPathAccessComplete, | 230 base::Bind(&HidServiceLinux::OnRequestPathAccessComplete, |
230 base::Passed(¶ms))); | 231 base::Passed(¶ms))); |
231 } else { | 232 } else { |
232 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); | 233 task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr)); |
233 } | 234 } |
234 return; | 235 return; |
235 } | 236 } |
236 #endif // defined(OS_CHROMEOS) | 237 #endif // defined(OS_CHROMEOS) |
237 | 238 |
238 file_task_runner_->PostTask( | 239 file_task_runner_->PostTask( |
(...skipping 19 matching lines...) Expand all Loading... |
258 } else { | 259 } else { |
259 params->callback.Run(nullptr); | 260 params->callback.Run(nullptr); |
260 } | 261 } |
261 } | 262 } |
262 #endif // defined(OS_CHROMEOS) | 263 #endif // defined(OS_CHROMEOS) |
263 | 264 |
264 // static | 265 // static |
265 void HidServiceLinux::OpenDevice(scoped_ptr<ConnectParams> params) { | 266 void HidServiceLinux::OpenDevice(scoped_ptr<ConnectParams> params) { |
266 base::ThreadRestrictions::AssertIOAllowed(); | 267 base::ThreadRestrictions::AssertIOAllowed(); |
267 scoped_refptr<base::SingleThreadTaskRunner> task_runner = params->task_runner; | 268 scoped_refptr<base::SingleThreadTaskRunner> task_runner = params->task_runner; |
268 base::FilePath device_path(params->device_info.device_node); | 269 base::FilePath device_path(params->device_info->device_node()); |
269 base::File& device_file = params->device_file; | 270 base::File& device_file = params->device_file; |
270 int flags = | 271 int flags = |
271 base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE; | 272 base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE; |
272 device_file.Initialize(device_path, flags); | 273 device_file.Initialize(device_path, flags); |
273 if (!device_file.IsValid()) { | 274 if (!device_file.IsValid()) { |
274 base::File::Error file_error = device_file.error_details(); | 275 base::File::Error file_error = device_file.error_details(); |
275 | 276 |
276 if (file_error == base::File::FILE_ERROR_ACCESS_DENIED) { | 277 if (file_error == base::File::FILE_ERROR_ACCESS_DENIED) { |
277 VLOG(1) << "Access denied opening device read-write, trying read-only."; | 278 VLOG(1) << "Access denied opening device read-write, trying read-only."; |
278 flags = base::File::FLAG_OPEN | base::File::FLAG_READ; | 279 flags = base::File::FLAG_OPEN | base::File::FLAG_READ; |
279 device_file.Initialize(device_path, flags); | 280 device_file.Initialize(device_path, flags); |
280 } | 281 } |
281 } | 282 } |
282 if (!device_file.IsValid()) { | 283 if (!device_file.IsValid()) { |
283 LOG(ERROR) << "Failed to open '" << params->device_info.device_node << "': " | 284 LOG(ERROR) << "Failed to open '" << params->device_info->device_node() |
| 285 << "': " |
284 << base::File::ErrorToString(device_file.error_details()); | 286 << base::File::ErrorToString(device_file.error_details()); |
285 task_runner->PostTask(FROM_HERE, base::Bind(params->callback, nullptr)); | 287 task_runner->PostTask(FROM_HERE, base::Bind(params->callback, nullptr)); |
286 return; | 288 return; |
287 } | 289 } |
288 | 290 |
289 int result = fcntl(device_file.GetPlatformFile(), F_GETFL); | 291 int result = fcntl(device_file.GetPlatformFile(), F_GETFL); |
290 if (result == -1) { | 292 if (result == -1) { |
291 PLOG(ERROR) << "Failed to get flags from the device file descriptor"; | 293 PLOG(ERROR) << "Failed to get flags from the device file descriptor"; |
292 task_runner->PostTask(FROM_HERE, base::Bind(params->callback, nullptr)); | 294 task_runner->PostTask(FROM_HERE, base::Bind(params->callback, nullptr)); |
293 return; | 295 return; |
(...skipping 12 matching lines...) Expand all Loading... |
306 | 308 |
307 // static | 309 // static |
308 void HidServiceLinux::ConnectImpl(scoped_ptr<ConnectParams> params) { | 310 void HidServiceLinux::ConnectImpl(scoped_ptr<ConnectParams> params) { |
309 DCHECK(params->device_file.IsValid()); | 311 DCHECK(params->device_file.IsValid()); |
310 params->callback.Run(make_scoped_refptr( | 312 params->callback.Run(make_scoped_refptr( |
311 new HidConnectionLinux(params->device_info, params->device_file.Pass(), | 313 new HidConnectionLinux(params->device_info, params->device_file.Pass(), |
312 params->file_task_runner))); | 314 params->file_task_runner))); |
313 } | 315 } |
314 | 316 |
315 } // namespace device | 317 } // namespace device |
OLD | NEW |