| 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 |