Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(219)

Side by Side Diff: device/hid/hid_connection_linux.cc

Issue 2394343003: Use FileDescriptorWatcher in HidConnectionLinux::FileThreadHelper. (Closed)
Patch Set: fix build error Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 <linux/hidraw.h> 8 #include <linux/hidraw.h>
9 #include <sys/ioctl.h> 9 #include <sys/ioctl.h>
10 10
11 #include <memory> 11 #include <memory>
12 #include <string> 12 #include <string>
13 #include <utility> 13 #include <utility>
14 14
15 #include "base/bind.h" 15 #include "base/bind.h"
16 #include "base/files/file_descriptor_watcher_posix.h"
16 #include "base/files/file_path.h" 17 #include "base/files/file_path.h"
17 #include "base/macros.h" 18 #include "base/macros.h"
18 #include "base/message_loop/message_loop.h" 19 #include "base/message_loop/message_loop.h"
19 #include "base/message_loop/message_pump_libevent.h"
20 #include "base/posix/eintr_wrapper.h" 20 #include "base/posix/eintr_wrapper.h"
21 #include "base/threading/thread_restrictions.h" 21 #include "base/threading/thread_restrictions.h"
22 #include "base/threading/thread_task_runner_handle.h" 22 #include "base/threading/thread_task_runner_handle.h"
23 #include "components/device_event_log/device_event_log.h" 23 #include "components/device_event_log/device_event_log.h"
24 #include "device/hid/hid_service.h" 24 #include "device/hid/hid_service.h"
25 25
26 // These are already defined in newer versions of linux/hidraw.h. 26 // These are already defined in newer versions of linux/hidraw.h.
27 #ifndef HIDIOCSFEATURE 27 #ifndef HIDIOCSFEATURE
28 #define HIDIOCSFEATURE(len) _IOC(_IOC_WRITE | _IOC_READ, 'H', 0x06, len) 28 #define HIDIOCSFEATURE(len) _IOC(_IOC_WRITE | _IOC_READ, 'H', 0x06, len)
29 #endif 29 #endif
30 #ifndef HIDIOCGFEATURE 30 #ifndef HIDIOCGFEATURE
31 #define HIDIOCGFEATURE(len) _IOC(_IOC_WRITE | _IOC_READ, 'H', 0x07, len) 31 #define HIDIOCGFEATURE(len) _IOC(_IOC_WRITE | _IOC_READ, 'H', 0x07, len)
32 #endif 32 #endif
33 33
34 namespace device { 34 namespace device {
35 35
36 class HidConnectionLinux::FileThreadHelper 36 class HidConnectionLinux::FileThreadHelper
37 : public base::MessagePumpLibevent::Watcher, 37 : public base::MessageLoop::DestructionObserver {
38 public base::MessageLoop::DestructionObserver {
39 public: 38 public:
40 FileThreadHelper(base::PlatformFile platform_file, 39 FileThreadHelper(base::PlatformFile platform_file,
41 scoped_refptr<HidDeviceInfo> device_info, 40 scoped_refptr<HidDeviceInfo> device_info,
42 base::WeakPtr<HidConnectionLinux> connection, 41 base::WeakPtr<HidConnectionLinux> connection,
43 scoped_refptr<base::SingleThreadTaskRunner> task_runner) 42 scoped_refptr<base::SingleThreadTaskRunner> task_runner)
44 : platform_file_(platform_file), 43 : platform_file_(platform_file),
45 connection_(connection), 44 connection_(connection),
46 task_runner_(task_runner) { 45 task_runner_(task_runner) {
47 // Report buffers must always have room for the report ID. 46 // Report buffers must always have room for the report ID.
48 report_buffer_size_ = device_info->max_input_report_size() + 1; 47 report_buffer_size_ = device_info->max_input_report_size() + 1;
49 has_report_id_ = device_info->has_report_id(); 48 has_report_id_ = device_info->has_report_id();
50 } 49 }
51 50
52 ~FileThreadHelper() override { 51 ~FileThreadHelper() override {
53 DCHECK(thread_checker_.CalledOnValidThread()); 52 DCHECK(thread_checker_.CalledOnValidThread());
54 base::MessageLoop::current()->RemoveDestructionObserver(this); 53 base::MessageLoop::current()->RemoveDestructionObserver(this);
55 } 54 }
56 55
57 // Starts the FileDescriptorWatcher that reads input events from the device. 56 // Starts the FileDescriptorWatcher that reads input events from the device.
58 // Must be called on a thread that has a base::MessageLoopForIO. 57 // Must be called on a thread that has a base::MessageLoopForIO.
59 static void Start(std::unique_ptr<FileThreadHelper> self) { 58 static void Start(std::unique_ptr<FileThreadHelper> self) {
60 base::ThreadRestrictions::AssertIOAllowed(); 59 base::ThreadRestrictions::AssertIOAllowed();
61 self->thread_checker_.DetachFromThread(); 60 self->thread_checker_.DetachFromThread();
62 61
63 if (!base::MessageLoopForIO::current()->WatchFileDescriptor( 62 self->file_watcher_ = base::FileDescriptorWatcher::WatchReadable(
64 self->platform_file_, true, base::MessageLoopForIO::WATCH_READ, 63 self->platform_file_,
65 &self->file_watcher_, self.get())) { 64 base::Bind(&FileThreadHelper::OnFileCanReadWithoutBlocking,
66 HID_LOG(ERROR) << "Failed to start watching device file."; 65 base::Unretained(self.get())));
67 }
68 66
69 // |self| is now owned by the current message loop. 67 // |self| is now owned by the current message loop.
70 base::MessageLoop::current()->AddDestructionObserver(self.release()); 68 base::MessageLoop::current()->AddDestructionObserver(self.release());
71 } 69 }
72 70
73 private: 71 private:
74 // base::MessagePumpLibevent::Watcher implementation. 72 void OnFileCanReadWithoutBlocking() {
75 void OnFileCanReadWithoutBlocking(int fd) override {
76 DCHECK(thread_checker_.CalledOnValidThread()); 73 DCHECK(thread_checker_.CalledOnValidThread());
77 DCHECK_EQ(fd, platform_file_);
78 74
79 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(report_buffer_size_)); 75 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(report_buffer_size_));
80 char* data = buffer->data(); 76 char* data = buffer->data();
81 size_t length = report_buffer_size_; 77 size_t length = report_buffer_size_;
82 if (!has_report_id_) { 78 if (!has_report_id_) {
83 // Linux will not prefix the buffer with a report ID if report IDs are not 79 // Linux will not prefix the buffer with a report ID if report IDs are not
84 // used by the device. Prefix the buffer with 0. 80 // used by the device. Prefix the buffer with 0.
85 *data++ = 0; 81 *data++ = 0;
86 length--; 82 length--;
87 } 83 }
88 84
89 ssize_t bytes_read = HANDLE_EINTR(read(platform_file_, data, length)); 85 ssize_t bytes_read = HANDLE_EINTR(read(platform_file_, data, length));
90 if (bytes_read < 0) { 86 if (bytes_read < 0) {
91 if (errno != EAGAIN) { 87 if (errno != EAGAIN) {
92 HID_PLOG(EVENT) << "Read failed"; 88 HID_PLOG(EVENT) << "Read failed";
93 // This assumes that the error is unrecoverable and disables reading 89 // This assumes that the error is unrecoverable and disables reading
94 // from the device until it has been re-opened. 90 // from the device until it has been re-opened.
95 // TODO(reillyg): Investigate starting and stopping the file descriptor 91 // TODO(reillyg): Investigate starting and stopping the file descriptor
96 // watcher in response to pending read requests so that per-request 92 // watcher in response to pending read requests so that per-request
97 // errors can be returned to the client. 93 // errors can be returned to the client.
98 file_watcher_.StopWatchingFileDescriptor(); 94 file_watcher_.reset();
99 } 95 }
100 return; 96 return;
101 } 97 }
102 if (!has_report_id_) { 98 if (!has_report_id_) {
103 // Behave as if the byte prefixed above as the the report ID was read. 99 // Behave as if the byte prefixed above as the the report ID was read.
104 bytes_read++; 100 bytes_read++;
105 } 101 }
106 102
107 task_runner_->PostTask(FROM_HERE, 103 task_runner_->PostTask(FROM_HERE,
108 base::Bind(&HidConnectionLinux::ProcessInputReport, 104 base::Bind(&HidConnectionLinux::ProcessInputReport,
109 connection_, buffer, bytes_read)); 105 connection_, buffer, bytes_read));
110 } 106 }
111 107
112 void OnFileCanWriteWithoutBlocking(int fd) override {
113 NOTREACHED(); // Only listening for reads.
114 }
115
116 // base::MessageLoop::DestructionObserver: 108 // base::MessageLoop::DestructionObserver:
117 void WillDestroyCurrentMessageLoop() override { 109 void WillDestroyCurrentMessageLoop() override {
118 DCHECK(thread_checker_.CalledOnValidThread()); 110 DCHECK(thread_checker_.CalledOnValidThread());
119 delete this; 111 delete this;
120 } 112 }
121 113
122 base::ThreadChecker thread_checker_; 114 base::ThreadChecker thread_checker_;
123 base::PlatformFile platform_file_; 115 base::PlatformFile platform_file_;
124 size_t report_buffer_size_; 116 size_t report_buffer_size_;
125 bool has_report_id_; 117 bool has_report_id_;
126 base::WeakPtr<HidConnectionLinux> connection_; 118 base::WeakPtr<HidConnectionLinux> connection_;
127 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 119 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
128 base::MessagePumpLibevent::FileDescriptorWatcher file_watcher_; 120 std::unique_ptr<base::FileDescriptorWatcher::Controller> file_watcher_;
129 121
130 DISALLOW_COPY_AND_ASSIGN(FileThreadHelper); 122 DISALLOW_COPY_AND_ASSIGN(FileThreadHelper);
131 }; 123 };
132 124
133 HidConnectionLinux::HidConnectionLinux( 125 HidConnectionLinux::HidConnectionLinux(
134 scoped_refptr<HidDeviceInfo> device_info, 126 scoped_refptr<HidDeviceInfo> device_info,
135 base::File device_file, 127 base::File device_file,
136 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) 128 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner)
137 : HidConnection(device_info), 129 : HidConnection(device_info),
138 file_task_runner_(file_task_runner), 130 file_task_runner_(file_task_runner),
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 PendingHidReport report = pending_reports_.front(); 311 PendingHidReport report = pending_reports_.front();
320 312
321 pending_reports_.pop(); 313 pending_reports_.pop();
322 if (CompleteRead(report.buffer, report.size, read.callback)) { 314 if (CompleteRead(report.buffer, report.size, read.callback)) {
323 pending_reads_.pop(); 315 pending_reads_.pop();
324 } 316 }
325 } 317 }
326 } 318 }
327 319
328 } // namespace device 320 } // namespace device
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698