| OLD | NEW |
| 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 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_connection_linux.h" | 5 #include "device/hid/hid_connection_linux.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <libudev.h> | 9 #include <libudev.h> |
| 10 #include <linux/hidraw.h> | 10 #include <linux/hidraw.h> |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 scoped_refptr<net::IOBufferWithSize> CopyBufferWithReportId( | 35 scoped_refptr<net::IOBufferWithSize> CopyBufferWithReportId( |
| 36 scoped_refptr<net::IOBufferWithSize> buffer, | 36 scoped_refptr<net::IOBufferWithSize> buffer, |
| 37 uint8_t report_id) { | 37 uint8_t report_id) { |
| 38 scoped_refptr<net::IOBufferWithSize> new_buffer( | 38 scoped_refptr<net::IOBufferWithSize> new_buffer( |
| 39 new net::IOBufferWithSize(buffer->size() + 1)); | 39 new net::IOBufferWithSize(buffer->size() + 1)); |
| 40 new_buffer->data()[0] = report_id; | 40 new_buffer->data()[0] = report_id; |
| 41 memcpy(new_buffer->data() + 1, buffer->data(), buffer->size()); | 41 memcpy(new_buffer->data() + 1, buffer->data(), buffer->size()); |
| 42 return new_buffer; | 42 return new_buffer; |
| 43 } | 43 } |
| 44 | 44 |
| 45 const char kHidrawSubsystem[] = "hidraw"; | |
| 46 | |
| 47 } // namespace | 45 } // namespace |
| 48 | 46 |
| 49 HidConnectionLinux::HidConnectionLinux(HidDeviceInfo device_info, | 47 HidConnectionLinux::HidConnectionLinux(HidDeviceInfo device_info, |
| 50 ScopedUdevDevicePtr udev_raw_device) | 48 std::string dev_node) |
| 51 : HidConnection(device_info) { | 49 : HidConnection(device_info) { |
| 52 DCHECK(thread_checker_.CalledOnValidThread()); | 50 DCHECK(thread_checker_.CalledOnValidThread()); |
| 53 | 51 |
| 54 udev_device* dev = udev_raw_device.get(); | |
| 55 std::string dev_node; | |
| 56 if (!FindHidrawDevNode(dev, &dev_node)) { | |
| 57 LOG(ERROR) << "Cannot open HID device as hidraw device."; | |
| 58 return; | |
| 59 } | |
| 60 | |
| 61 int flags = base::File::FLAG_OPEN | | 52 int flags = base::File::FLAG_OPEN | |
| 62 base::File::FLAG_READ | | 53 base::File::FLAG_READ | |
| 63 base::File::FLAG_WRITE; | 54 base::File::FLAG_WRITE; |
| 64 | 55 |
| 65 base::File device_file(base::FilePath(dev_node), flags); | 56 base::File device_file(base::FilePath(dev_node), flags); |
| 66 if (!device_file.IsValid()) { | 57 if (!device_file.IsValid()) { |
| 67 LOG(ERROR) << device_file.error_details(); | 58 LOG(ERROR) << device_file.error_details(); |
| 68 return; | 59 return; |
| 69 } | 60 } |
| 70 if (fcntl(device_file.GetPlatformFile(), F_SETFL, | 61 if (fcntl(device_file.GetPlatformFile(), F_SETFL, |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 if (report.buffer->size() > read.buffer->size()) { | 188 if (report.buffer->size() > read.buffer->size()) { |
| 198 read.callback.Run(false, report.buffer->size()); | 189 read.callback.Run(false, report.buffer->size()); |
| 199 } else { | 190 } else { |
| 200 memcpy(read.buffer->data(), report.buffer->data(), report.buffer->size()); | 191 memcpy(read.buffer->data(), report.buffer->data(), report.buffer->size()); |
| 201 pending_reports_.pop(); | 192 pending_reports_.pop(); |
| 202 read.callback.Run(true, report.buffer->size()); | 193 read.callback.Run(true, report.buffer->size()); |
| 203 } | 194 } |
| 204 } | 195 } |
| 205 } | 196 } |
| 206 | 197 |
| 207 bool HidConnectionLinux::FindHidrawDevNode(udev_device* parent, | |
| 208 std::string* result) { | |
| 209 udev* udev = udev_device_get_udev(parent); | |
| 210 if (!udev) { | |
| 211 return false; | |
| 212 } | |
| 213 ScopedUdevEnumeratePtr enumerate(udev_enumerate_new(udev)); | |
| 214 if (!enumerate) { | |
| 215 return false; | |
| 216 } | |
| 217 if (udev_enumerate_add_match_subsystem(enumerate.get(), kHidrawSubsystem)) { | |
| 218 return false; | |
| 219 } | |
| 220 if (udev_enumerate_scan_devices(enumerate.get())) { | |
| 221 return false; | |
| 222 } | |
| 223 std::string parent_path(udev_device_get_devpath(parent)); | |
| 224 if (parent_path.length() == 0 || *parent_path.rbegin() != '/') | |
| 225 parent_path += '/'; | |
| 226 udev_list_entry* devices = udev_enumerate_get_list_entry(enumerate.get()); | |
| 227 for (udev_list_entry* i = devices; i != NULL; | |
| 228 i = udev_list_entry_get_next(i)) { | |
| 229 ScopedUdevDevicePtr hid_dev( | |
| 230 udev_device_new_from_syspath(udev, udev_list_entry_get_name(i))); | |
| 231 const char* raw_path = udev_device_get_devnode(hid_dev.get()); | |
| 232 std::string device_path = udev_device_get_devpath(hid_dev.get()); | |
| 233 if (raw_path && | |
| 234 !device_path.compare(0, parent_path.length(), parent_path)) { | |
| 235 std::string sub_path = device_path.substr(parent_path.length()); | |
| 236 if (sub_path.substr(0, sizeof(kHidrawSubsystem)-1) == kHidrawSubsystem) { | |
| 237 *result = raw_path; | |
| 238 return true; | |
| 239 } | |
| 240 } | |
| 241 } | |
| 242 | |
| 243 return false; | |
| 244 } | |
| 245 | |
| 246 } // namespace device | 198 } // namespace device |
| 247 | |
| OLD | NEW |