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 base::File::Error file_error = device_file.error_details(); | 58 base::File::Error file_error = device_file.error_details(); |
68 | 59 |
69 if (file_error == base::File::FILE_ERROR_ACCESS_DENIED) { | 60 if (file_error == base::File::FILE_ERROR_ACCESS_DENIED) { |
70 flags = base::File::FLAG_OPEN | base::File::FLAG_READ; | 61 flags = base::File::FLAG_OPEN | base::File::FLAG_READ; |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 if (report.buffer->size() > read.buffer->size()) { | 200 if (report.buffer->size() > read.buffer->size()) { |
210 read.callback.Run(false, report.buffer->size()); | 201 read.callback.Run(false, report.buffer->size()); |
211 } else { | 202 } else { |
212 memcpy(read.buffer->data(), report.buffer->data(), report.buffer->size()); | 203 memcpy(read.buffer->data(), report.buffer->data(), report.buffer->size()); |
213 pending_reports_.pop(); | 204 pending_reports_.pop(); |
214 read.callback.Run(true, report.buffer->size()); | 205 read.callback.Run(true, report.buffer->size()); |
215 } | 206 } |
216 } | 207 } |
217 } | 208 } |
218 | 209 |
219 bool HidConnectionLinux::FindHidrawDevNode(udev_device* parent, | |
220 std::string* result) { | |
221 udev* udev = udev_device_get_udev(parent); | |
222 if (!udev) { | |
223 return false; | |
224 } | |
225 ScopedUdevEnumeratePtr enumerate(udev_enumerate_new(udev)); | |
226 if (!enumerate) { | |
227 return false; | |
228 } | |
229 if (udev_enumerate_add_match_subsystem(enumerate.get(), kHidrawSubsystem)) { | |
230 return false; | |
231 } | |
232 if (udev_enumerate_scan_devices(enumerate.get())) { | |
233 return false; | |
234 } | |
235 std::string parent_path(udev_device_get_devpath(parent)); | |
236 if (parent_path.length() == 0 || *parent_path.rbegin() != '/') | |
237 parent_path += '/'; | |
238 udev_list_entry* devices = udev_enumerate_get_list_entry(enumerate.get()); | |
239 for (udev_list_entry* i = devices; i != NULL; | |
240 i = udev_list_entry_get_next(i)) { | |
241 ScopedUdevDevicePtr hid_dev( | |
242 udev_device_new_from_syspath(udev, udev_list_entry_get_name(i))); | |
243 const char* raw_path = udev_device_get_devnode(hid_dev.get()); | |
244 std::string device_path = udev_device_get_devpath(hid_dev.get()); | |
245 if (raw_path && | |
246 !device_path.compare(0, parent_path.length(), parent_path)) { | |
247 std::string sub_path = device_path.substr(parent_path.length()); | |
248 if (sub_path.substr(0, sizeof(kHidrawSubsystem)-1) == kHidrawSubsystem) { | |
249 *result = raw_path; | |
250 return true; | |
251 } | |
252 } | |
253 } | |
254 | |
255 return false; | |
256 } | |
257 | |
258 } // namespace device | 210 } // namespace device |
259 | |
OLD | NEW |