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 |