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

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

Issue 317783010: chrome.hid: enrich model with report IDs (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Filter reports + refactor HID connections (ongoing) Created 6 years, 6 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
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 <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 27 matching lines...) Expand all
38 new net::IOBufferWithSize(buffer->size() + 1)); 38 new net::IOBufferWithSize(buffer->size() + 1));
39 new_buffer->data()[0] = report_id; 39 new_buffer->data()[0] = report_id;
40 memcpy(new_buffer->data() + 1, buffer->data(), buffer->size()); 40 memcpy(new_buffer->data() + 1, buffer->data(), buffer->size());
41 return new_buffer; 41 return new_buffer;
42 } 42 }
43 43
44 } // namespace 44 } // namespace
45 45
46 HidConnectionLinux::HidConnectionLinux(HidDeviceInfo device_info, 46 HidConnectionLinux::HidConnectionLinux(HidDeviceInfo device_info,
47 std::string dev_node) 47 std::string dev_node)
48 : HidConnection(device_info) { 48 : HidConnection2(device_info) {
49 DCHECK(thread_checker_.CalledOnValidThread());
50
51 int flags = base::File::FLAG_OPEN | 49 int flags = base::File::FLAG_OPEN |
52 base::File::FLAG_READ | 50 base::File::FLAG_READ |
53 base::File::FLAG_WRITE; 51 base::File::FLAG_WRITE;
54 52
55 base::File device_file(base::FilePath(dev_node), flags); 53 base::File device_file(base::FilePath(dev_node), flags);
56 if (!device_file.IsValid()) { 54 if (!device_file.IsValid()) {
57 base::File::Error file_error = device_file.error_details(); 55 base::File::Error file_error = device_file.error_details();
58 56
59 if (file_error == base::File::FILE_ERROR_ACCESS_DENIED) { 57 if (file_error == base::File::FILE_ERROR_ACCESS_DENIED) {
60 flags = base::File::FLAG_OPEN | base::File::FLAG_READ; 58 flags = base::File::FLAG_OPEN | base::File::FLAG_READ;
(...skipping 19 matching lines...) Expand all
80 device_file_.GetPlatformFile(), 78 device_file_.GetPlatformFile(),
81 true, 79 true,
82 base::MessageLoopForIO::WATCH_READ_WRITE, 80 base::MessageLoopForIO::WATCH_READ_WRITE,
83 &device_file_watcher_, 81 &device_file_watcher_,
84 this)) { 82 this)) {
85 LOG(ERROR) << "Failed to start watching device file."; 83 LOG(ERROR) << "Failed to start watching device file.";
86 } 84 }
87 } 85 }
88 86
89 HidConnectionLinux::~HidConnectionLinux() { 87 HidConnectionLinux::~HidConnectionLinux() {
90 DCHECK(thread_checker_.CalledOnValidThread());
91 Disconnect(); 88 Disconnect();
92 } 89 }
93 90
94 void HidConnectionLinux::OnFileCanReadWithoutBlocking(int fd) { 91 void HidConnectionLinux::PlatformWrite(
95 DCHECK(thread_checker_.CalledOnValidThread()); 92 uint8_t report_id,
96 DCHECK_EQ(fd, device_file_.GetPlatformFile()); 93 scoped_refptr<net::IOBufferWithSize> buffer,
97 94 const IOCallback& callback) {
98 uint8 buffer[1024] = {0};
99 int bytes_read =
100 HANDLE_EINTR(read(device_file_.GetPlatformFile(), buffer, 1024));
101 if (bytes_read < 0) {
102 if (errno == EAGAIN) {
103 return;
104 }
105 Disconnect();
106 return;
107 }
108
109 PendingHidReport report;
110 report.buffer = new net::IOBufferWithSize(bytes_read);
111 memcpy(report.buffer->data(), buffer, bytes_read);
112 pending_reports_.push(report);
113 ProcessReadQueue();
114 }
115
116 void HidConnectionLinux::OnFileCanWriteWithoutBlocking(int fd) {}
117
118 void HidConnectionLinux::Disconnect() {
119 DCHECK(thread_checker_.CalledOnValidThread());
120 device_file_watcher_.StopWatchingFileDescriptor();
121 device_file_.Close();
122 while (!pending_reads_.empty()) {
123 PendingHidRead pending_read = pending_reads_.front();
124 pending_reads_.pop();
125 pending_read.callback.Run(false, 0);
126 }
127 }
128
129 void HidConnectionLinux::Read(scoped_refptr<net::IOBufferWithSize> buffer,
130 const IOCallback& callback) {
131 DCHECK(thread_checker_.CalledOnValidThread());
132 PendingHidRead pending_read;
133 pending_read.buffer = buffer;
134 pending_read.callback = callback;
135 pending_reads_.push(pending_read);
136 ProcessReadQueue();
137 }
138
139 void HidConnectionLinux::Write(uint8_t report_id,
140 scoped_refptr<net::IOBufferWithSize> buffer,
141 const IOCallback& callback) {
142 DCHECK(thread_checker_.CalledOnValidThread());
143 // If report ID is non-zero, insert it into a new copy of the buffer. 95 // If report ID is non-zero, insert it into a new copy of the buffer.
144 if (report_id != 0) 96 if (report_id != 0)
145 buffer = CopyBufferWithReportId(buffer, report_id); 97 buffer = CopyBufferWithReportId(buffer, report_id);
146 int bytes_written = HANDLE_EINTR( 98 int bytes_written = HANDLE_EINTR(
147 write(device_file_.GetPlatformFile(), buffer->data(), buffer->size())); 99 write(device_file_.GetPlatformFile(), buffer->data(), buffer->size()));
148 if (bytes_written < 0) { 100 if (bytes_written < 0) {
149 Disconnect(); 101 Disconnect();
150 callback.Run(false, 0); 102 callback.Run(false, 0);
151 } else { 103 } else {
152 callback.Run(true, bytes_written); 104 callback.Run(true, bytes_written);
153 } 105 }
154 } 106 }
155 107
156 void HidConnectionLinux::GetFeatureReport( 108 void HidConnectionLinux::PlatformGetFeatureReport(
157 uint8_t report_id, 109 uint8_t report_id,
158 scoped_refptr<net::IOBufferWithSize> buffer, 110 scoped_refptr<net::IOBufferWithSize> buffer,
159 const IOCallback& callback) { 111 const IOCallback& callback) {
160 DCHECK(thread_checker_.CalledOnValidThread());
161
162 if (buffer->size() == 0) { 112 if (buffer->size() == 0) {
163 callback.Run(false, 0); 113 callback.Run(false, 0);
164 return; 114 return;
165 } 115 }
166 116
167 // The first byte of the destination buffer is the report ID being requested. 117 // The first byte of the destination buffer is the report ID being requested.
168 buffer->data()[0] = report_id; 118 buffer->data()[0] = report_id;
169 int result = ioctl(device_file_.GetPlatformFile(), 119 int result = ioctl(device_file_.GetPlatformFile(),
170 HIDIOCGFEATURE(buffer->size()), 120 HIDIOCGFEATURE(buffer->size()),
171 buffer->data()); 121 buffer->data());
172 if (result < 0) 122 if (result < 0)
173 callback.Run(false, 0); 123 callback.Run(false, 0);
174 else 124 else
175 callback.Run(true, result); 125 callback.Run(true, result);
176 } 126 }
177 127
178 void HidConnectionLinux::SendFeatureReport( 128 void HidConnectionLinux::PlatformSendFeatureReport(
179 uint8_t report_id, 129 uint8_t report_id,
180 scoped_refptr<net::IOBufferWithSize> buffer, 130 scoped_refptr<net::IOBufferWithSize> buffer,
181 const IOCallback& callback) { 131 const IOCallback& callback) {
182 DCHECK(thread_checker_.CalledOnValidThread());
183 if (report_id != 0) 132 if (report_id != 0)
184 buffer = CopyBufferWithReportId(buffer, report_id); 133 buffer = CopyBufferWithReportId(buffer, report_id);
185 int result = ioctl(device_file_.GetPlatformFile(), 134 int result = ioctl(device_file_.GetPlatformFile(),
186 HIDIOCSFEATURE(buffer->size()), 135 HIDIOCSFEATURE(buffer->size()),
187 buffer->data()); 136 buffer->data());
188 if (result < 0) 137 if (result < 0)
189 callback.Run(false, 0); 138 callback.Run(false, 0);
190 else 139 else
191 callback.Run(true, result); 140 callback.Run(true, result);
192 } 141 }
193 142
194 void HidConnectionLinux::ProcessReadQueue() { 143 void HidConnectionLinux::OnFileCanReadWithoutBlocking(int fd) {
195 while (pending_reads_.size() && pending_reports_.size()) { 144 DCHECK(thread_checker().CalledOnValidThread());
196 PendingHidRead read = pending_reads_.front(); 145 DCHECK_EQ(fd, device_file_.GetPlatformFile());
197 pending_reads_.pop(); 146
198 PendingHidReport report = pending_reports_.front(); 147 uint8 raw_buffer[1024] = {0};
199 if (report.buffer->size() > read.buffer->size()) { 148 int bytes_read =
200 read.callback.Run(false, report.buffer->size()); 149 HANDLE_EINTR(read(device_file_.GetPlatformFile(), raw_buffer, 1024));
201 } else { 150 if (bytes_read < 0) {
202 memcpy(read.buffer->data(), report.buffer->data(), report.buffer->size()); 151 if (errno == EAGAIN) {
203 pending_reports_.pop(); 152 return;
204 read.callback.Run(true, report.buffer->size());
205 } 153 }
154 Disconnect();
155 return;
206 } 156 }
157
158 scoped_refptr<net::IOBufferWithSize> buffer =
159 new net::IOBufferWithSize(bytes_read);
160 memcpy(buffer->data(), raw_buffer, bytes_read);
161
162 ProcessInputReport(buffer);
163 }
164
165 void HidConnectionLinux::OnFileCanWriteWithoutBlocking(int fd) {
166 }
167
168 void HidConnectionLinux::Disconnect() {
169 DCHECK(thread_checker().CalledOnValidThread());
170 device_file_watcher_.StopWatchingFileDescriptor();
171 device_file_.Close();
172
173 Flush();
207 } 174 }
208 175
209 } // namespace device 176 } // namespace device
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698