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

Side by Side Diff: device/usb/usb_device_handle_usbfs.cc

Issue 2797433005: Remove MessageLoop destruction observer from //device/usb (Closed)
Patch Set: Add test for shutdown Created 3 years, 8 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 | « device/usb/usb_device_handle_usbfs.h ('k') | device/usb/usb_service.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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/usb/usb_device_handle_usbfs.h" 5 #include "device/usb/usb_device_handle_usbfs.h"
6 6
7 #if defined(OS_ANDROID) && __ANDROID_API__ < 21 7 #if defined(OS_ANDROID) && __ANDROID_API__ < 21
8 #include <linux/usb_ch9.h> 8 #include <linux/usb_ch9.h>
9 #else 9 #else
10 #include <linux/usb/ch9.h> 10 #include <linux/usb/ch9.h>
11 #endif 11 #endif
12 12
13 #include <linux/usbdevice_fs.h> 13 #include <linux/usbdevice_fs.h>
14 #include <sys/ioctl.h> 14 #include <sys/ioctl.h>
15 15
16 #include <numeric> 16 #include <numeric>
17 17
18 #include "base/bind.h" 18 #include "base/bind.h"
19 #include "base/cancelable_callback.h" 19 #include "base/cancelable_callback.h"
20 #include "base/files/file_descriptor_watcher_posix.h" 20 #include "base/files/file_descriptor_watcher_posix.h"
21 #include "base/logging.h" 21 #include "base/logging.h"
22 #include "base/message_loop/message_loop.h"
23 #include "base/posix/eintr_wrapper.h" 22 #include "base/posix/eintr_wrapper.h"
24 #include "base/stl_util.h" 23 #include "base/stl_util.h"
25 #include "base/threading/thread_restrictions.h" 24 #include "base/threading/thread_restrictions.h"
26 #include "base/threading/thread_task_runner_handle.h" 25 #include "base/threading/thread_task_runner_handle.h"
27 #include "components/device_event_log/device_event_log.h" 26 #include "components/device_event_log/device_event_log.h"
28 #include "device/usb/usb_device_linux.h" 27 #include "device/usb/usb_device_linux.h"
29 #include "net/base/io_buffer.h" 28 #include "net/base/io_buffer.h"
30 29
31 namespace device { 30 namespace device {
32 31
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 // TODO(reillyg): Add a specific error message whenever one of the cases 126 // TODO(reillyg): Add a specific error message whenever one of the cases
128 // above fails to match. 127 // above fails to match.
129 USB_LOG(ERROR) << "Unknown system error: " 128 USB_LOG(ERROR) << "Unknown system error: "
130 << logging::SystemErrorCodeToString(rc); 129 << logging::SystemErrorCodeToString(rc);
131 return USB_TRANSFER_ERROR; 130 return USB_TRANSFER_ERROR;
132 } 131 }
133 } 132 }
134 133
135 } // namespace 134 } // namespace
136 135
137 class UsbDeviceHandleUsbfs::FileThreadHelper 136 class UsbDeviceHandleUsbfs::FileThreadHelper {
138 : public base::MessageLoop::DestructionObserver {
139 public: 137 public:
140 FileThreadHelper(int fd, 138 FileThreadHelper(int fd,
141 scoped_refptr<UsbDeviceHandleUsbfs> device_handle, 139 scoped_refptr<UsbDeviceHandleUsbfs> device_handle,
142 scoped_refptr<base::SequencedTaskRunner> task_runner); 140 scoped_refptr<base::SequencedTaskRunner> task_runner);
143 ~FileThreadHelper() override; 141 ~FileThreadHelper();
144 142
145 static void Start(std::unique_ptr<FileThreadHelper> self); 143 void Start();
146 144
147 // base::MessageLoop::DestructionObserver overrides. 145 void SetConfiguration(int configuration_value,
148 void WillDestroyCurrentMessageLoop() override; 146 const ResultCallback& callback);
147 void ReleaseInterface(int interface_number, const ResultCallback& callback);
148 void SetInterface(int interface_number,
149 int alternate_setting,
150 const ResultCallback& callback);
151 void ResetDevice(const ResultCallback& callback);
152 void ClearHalt(uint8_t endpoint_address, const ResultCallback& callback);
153 void DiscardUrb(Transfer* transfer);
149 154
150 private: 155 private:
151 // Called when |fd_| is writable without blocking. 156 // Called when |fd_| is writable without blocking.
152 void OnFileCanWriteWithoutBlocking(); 157 void OnFileCanWriteWithoutBlocking();
153 158
154 int fd_; 159 int fd_;
155 scoped_refptr<UsbDeviceHandleUsbfs> device_handle_; 160 scoped_refptr<UsbDeviceHandleUsbfs> device_handle_;
156 scoped_refptr<base::SequencedTaskRunner> task_runner_; 161 scoped_refptr<base::SequencedTaskRunner> task_runner_;
157 std::unique_ptr<base::FileDescriptorWatcher::Controller> watch_controller_; 162 std::unique_ptr<base::FileDescriptorWatcher::Controller> watch_controller_;
158 base::ThreadChecker thread_checker_; 163 base::ThreadChecker thread_checker_;
159 164
160 DISALLOW_COPY_AND_ASSIGN(FileThreadHelper); 165 DISALLOW_COPY_AND_ASSIGN(FileThreadHelper);
161 }; 166 };
162 167
168 struct UsbDeviceHandleUsbfs::Transfer {
169 Transfer() = delete;
170 Transfer(scoped_refptr<net::IOBuffer> buffer,
171 const TransferCallback& callback,
172 scoped_refptr<base::SingleThreadTaskRunner> callback_runner);
173 Transfer(scoped_refptr<net::IOBuffer> buffer,
174 const IsochronousTransferCallback& callback);
175 ~Transfer();
176
177 void* operator new(std::size_t size, size_t number_of_iso_packets);
178 void RunCallback(UsbTransferStatus status, size_t bytes_transferred);
179 void RunIsochronousCallback(const std::vector<IsochronousPacket>& packets);
180
181 scoped_refptr<net::IOBuffer> control_transfer_buffer;
182 scoped_refptr<net::IOBuffer> buffer;
183 base::CancelableClosure timeout_closure;
184 bool cancelled = false;
185
186 // When the URB is |cancelled| these two flags track whether the URB has both
187 // been |discarded| and |reaped| since the possiblity of last-minute
188 // completion makes these two conditions race.
189 bool discarded = false;
190 bool reaped = false;
191
192 private:
193 TransferCallback callback;
194 IsochronousTransferCallback isoc_callback;
195 scoped_refptr<base::SingleThreadTaskRunner> callback_runner;
196
197 DISALLOW_COPY_AND_ASSIGN(Transfer);
198
199 public:
200 // The |urb| field must be the last in the struct so that the extra space
201 // allocated by the overridden new function above extends the length of its
202 // |iso_frame_desc| field.
203 usbdevfs_urb urb;
204 };
205
163 UsbDeviceHandleUsbfs::FileThreadHelper::FileThreadHelper( 206 UsbDeviceHandleUsbfs::FileThreadHelper::FileThreadHelper(
164 int fd, 207 int fd,
165 scoped_refptr<UsbDeviceHandleUsbfs> device_handle, 208 scoped_refptr<UsbDeviceHandleUsbfs> device_handle,
166 scoped_refptr<base::SequencedTaskRunner> task_runner) 209 scoped_refptr<base::SequencedTaskRunner> task_runner)
167 : fd_(fd), device_handle_(device_handle), task_runner_(task_runner) {} 210 : fd_(fd), device_handle_(device_handle), task_runner_(task_runner) {}
168 211
169 UsbDeviceHandleUsbfs::FileThreadHelper::~FileThreadHelper() { 212 UsbDeviceHandleUsbfs::FileThreadHelper::~FileThreadHelper() {
170 DCHECK(thread_checker_.CalledOnValidThread()); 213 DCHECK(thread_checker_.CalledOnValidThread());
171 base::MessageLoop::current()->RemoveDestructionObserver(this);
172 } 214 }
173 215
174 // static 216 void UsbDeviceHandleUsbfs::FileThreadHelper::Start() {
175 void UsbDeviceHandleUsbfs::FileThreadHelper::Start(
176 std::unique_ptr<FileThreadHelper> self) {
177 base::ThreadRestrictions::AssertIOAllowed(); 217 base::ThreadRestrictions::AssertIOAllowed();
178 self->thread_checker_.DetachFromThread(); 218 thread_checker_.DetachFromThread();
219 DCHECK(thread_checker_.CalledOnValidThread());
179 220
180 // Linux indicates that URBs are available to reap by marking the file 221 // Linux indicates that URBs are available to reap by marking the file
181 // descriptor writable. 222 // descriptor writable.
182 self->watch_controller_ = base::FileDescriptorWatcher::WatchWritable( 223 watch_controller_ = base::FileDescriptorWatcher::WatchWritable(
183 self->fd_, base::Bind(&FileThreadHelper::OnFileCanWriteWithoutBlocking, 224 fd_, base::Bind(&FileThreadHelper::OnFileCanWriteWithoutBlocking,
184 base::Unretained(self.get()))); 225 base::Unretained(this)));
185
186 // |self| is now owned by the current message loop.
187 base::MessageLoop::current()->AddDestructionObserver(self.release());
188 } 226 }
189 227
190 void UsbDeviceHandleUsbfs::FileThreadHelper::WillDestroyCurrentMessageLoop() { 228 void UsbDeviceHandleUsbfs::FileThreadHelper::SetConfiguration(
229 int configuration_value,
230 const ResultCallback& callback) {
191 DCHECK(thread_checker_.CalledOnValidThread()); 231 DCHECK(thread_checker_.CalledOnValidThread());
192 delete this; 232 int rc =
233 HANDLE_EINTR(ioctl(fd_, USBDEVFS_SETCONFIGURATION, &configuration_value));
234 if (rc)
235 USB_PLOG(DEBUG) << "Failed to set configuration " << configuration_value;
236 task_runner_->PostTask(
237 FROM_HERE,
238 base::Bind(&UsbDeviceHandleUsbfs::SetConfigurationComplete,
239 device_handle_, configuration_value, rc == 0, callback));
240 }
241
242 void UsbDeviceHandleUsbfs::FileThreadHelper::ReleaseInterface(
243 int interface_number,
244 const ResultCallback& callback) {
245 DCHECK(thread_checker_.CalledOnValidThread());
246 int rc =
247 HANDLE_EINTR(ioctl(fd_, USBDEVFS_RELEASEINTERFACE, &interface_number));
248 if (rc) {
249 USB_PLOG(DEBUG) << "Failed to release interface " << interface_number;
250 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
251 } else {
252 task_runner_->PostTask(
253 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::ReleaseInterfaceComplete,
254 device_handle_, interface_number, callback));
255 }
256 }
257
258 void UsbDeviceHandleUsbfs::FileThreadHelper::SetInterface(
259 int interface_number,
260 int alternate_setting,
261 const ResultCallback& callback) {
262 DCHECK(thread_checker_.CalledOnValidThread());
263 usbdevfs_setinterface cmd = {0};
264 cmd.interface = interface_number;
265 cmd.altsetting = alternate_setting;
266 int rc = HANDLE_EINTR(ioctl(fd_, USBDEVFS_SETINTERFACE, &cmd));
267 if (rc) {
268 USB_PLOG(DEBUG) << "Failed to set interface " << interface_number
269 << " to alternate setting " << alternate_setting;
270 }
271 task_runner_->PostTask(FROM_HERE, base::Bind(callback, rc == 0));
272 }
273
274 void UsbDeviceHandleUsbfs::FileThreadHelper::ResetDevice(
275 const ResultCallback& callback) {
276 DCHECK(thread_checker_.CalledOnValidThread());
277 // TODO(reillyg): libusb releases interfaces before and then reclaims
278 // interfaces after a reset. We should probably do this too or document that
279 // callers have to call ClaimInterface as well.
280 int rc = HANDLE_EINTR(ioctl(fd_, USBDEVFS_RESET, nullptr));
281 if (rc)
282 USB_PLOG(DEBUG) << "Failed to reset the device";
283 task_runner_->PostTask(FROM_HERE, base::Bind(callback, rc == 0));
284 }
285
286 void UsbDeviceHandleUsbfs::FileThreadHelper::ClearHalt(
287 uint8_t endpoint_address,
288 const ResultCallback& callback) {
289 DCHECK(thread_checker_.CalledOnValidThread());
290 int tmp_endpoint = endpoint_address;
291 int rc = HANDLE_EINTR(ioctl(fd_, USBDEVFS_CLEAR_HALT, &tmp_endpoint));
292 if (rc) {
293 USB_PLOG(DEBUG) << "Failed to clear the stall condition on endpoint "
294 << static_cast<int>(endpoint_address);
295 }
296 task_runner_->PostTask(FROM_HERE, base::Bind(callback, rc == 0));
297 }
298
299 void UsbDeviceHandleUsbfs::FileThreadHelper::DiscardUrb(Transfer* transfer) {
300 DCHECK(thread_checker_.CalledOnValidThread());
301 HANDLE_EINTR(ioctl(fd_, USBDEVFS_DISCARDURB, &transfer->urb));
302
303 task_runner_->PostTask(
304 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::UrbDiscarded, device_handle_,
305 transfer));
193 } 306 }
194 307
195 void UsbDeviceHandleUsbfs::FileThreadHelper::OnFileCanWriteWithoutBlocking() { 308 void UsbDeviceHandleUsbfs::FileThreadHelper::OnFileCanWriteWithoutBlocking() {
196 DCHECK(thread_checker_.CalledOnValidThread()); 309 DCHECK(thread_checker_.CalledOnValidThread());
197 310
198 const size_t MAX_URBS_PER_EVENT = 10; 311 const size_t MAX_URBS_PER_EVENT = 10;
199 std::vector<usbdevfs_urb*> urbs; 312 std::vector<usbdevfs_urb*> urbs;
200 urbs.reserve(MAX_URBS_PER_EVENT); 313 urbs.reserve(MAX_URBS_PER_EVENT);
201 for (size_t i = 0; i < MAX_URBS_PER_EVENT; ++i) { 314 for (size_t i = 0; i < MAX_URBS_PER_EVENT; ++i) {
202 usbdevfs_urb* urb; 315 usbdevfs_urb* urb;
(...skipping 11 matching lines...) Expand all
214 } else { 327 } else {
215 urbs.push_back(urb); 328 urbs.push_back(urb);
216 } 329 }
217 } 330 }
218 331
219 task_runner_->PostTask( 332 task_runner_->PostTask(
220 FROM_HERE, 333 FROM_HERE,
221 base::Bind(&UsbDeviceHandleUsbfs::ReapedUrbs, device_handle_, urbs)); 334 base::Bind(&UsbDeviceHandleUsbfs::ReapedUrbs, device_handle_, urbs));
222 } 335 }
223 336
224 struct UsbDeviceHandleUsbfs::Transfer {
225 Transfer() = delete;
226 Transfer(scoped_refptr<net::IOBuffer> buffer,
227 const TransferCallback& callback,
228 scoped_refptr<base::SingleThreadTaskRunner> callback_runner);
229 Transfer(scoped_refptr<net::IOBuffer> buffer,
230 const IsochronousTransferCallback& callback);
231 ~Transfer();
232
233 void* operator new(std::size_t size, size_t number_of_iso_packets);
234 void RunCallback(UsbTransferStatus status, size_t bytes_transferred);
235 void RunIsochronousCallback(const std::vector<IsochronousPacket>& packets);
236
237 scoped_refptr<net::IOBuffer> control_transfer_buffer;
238 scoped_refptr<net::IOBuffer> buffer;
239 base::CancelableClosure timeout_closure;
240 bool cancelled = false;
241
242 // When the URB is |cancelled| these two flags track whether the URB has both
243 // been |discarded| and |reaped| since the possiblity of last-minute
244 // completion makes these two conditions race.
245 bool discarded = false;
246 bool reaped = false;
247
248 private:
249 TransferCallback callback;
250 IsochronousTransferCallback isoc_callback;
251 scoped_refptr<base::SingleThreadTaskRunner> callback_runner;
252
253 DISALLOW_COPY_AND_ASSIGN(Transfer);
254
255 public:
256 // The |urb| field must be the last in the struct so that the extra space
257 // allocated by the overridden new function above extends the length of its
258 // |iso_frame_desc| field.
259 usbdevfs_urb urb;
260 };
261
262 UsbDeviceHandleUsbfs::Transfer::Transfer( 337 UsbDeviceHandleUsbfs::Transfer::Transfer(
263 scoped_refptr<net::IOBuffer> buffer, 338 scoped_refptr<net::IOBuffer> buffer,
264 const TransferCallback& callback, 339 const TransferCallback& callback,
265 scoped_refptr<base::SingleThreadTaskRunner> callback_runner) 340 scoped_refptr<base::SingleThreadTaskRunner> callback_runner)
266 : buffer(buffer), callback(callback), callback_runner(callback_runner) { 341 : buffer(buffer), callback(callback), callback_runner(callback_runner) {
267 memset(&urb, 0, sizeof(urb)); 342 memset(&urb, 0, sizeof(urb));
268 urb.usercontext = this; 343 urb.usercontext = this;
269 urb.buffer = buffer->data(); 344 urb.buffer = buffer->data();
270 } 345 }
271 346
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) 393 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner)
319 : device_(device), 394 : device_(device),
320 fd_(std::move(fd)), 395 fd_(std::move(fd)),
321 blocking_task_runner_(blocking_task_runner) { 396 blocking_task_runner_(blocking_task_runner) {
322 DCHECK(device_); 397 DCHECK(device_);
323 DCHECK(fd_.is_valid()); 398 DCHECK(fd_.is_valid());
324 DCHECK(blocking_task_runner_); 399 DCHECK(blocking_task_runner_);
325 400
326 task_runner_ = base::ThreadTaskRunnerHandle::Get(); 401 task_runner_ = base::ThreadTaskRunnerHandle::Get();
327 402
328 std::unique_ptr<FileThreadHelper> helper( 403 helper_.reset(new FileThreadHelper(fd_.get(), this, task_runner_));
329 new FileThreadHelper(fd_.get(), this, task_runner_));
330 helper_ = helper.get();
331 blocking_task_runner_->PostTask( 404 blocking_task_runner_->PostTask(
332 FROM_HERE, base::Bind(&FileThreadHelper::Start, base::Passed(&helper))); 405 FROM_HERE,
406 base::Bind(&FileThreadHelper::Start, base::Unretained(helper_.get())));
scheib 2017/04/04 20:17:15 blocking_task_runner is ref counted. And helper_ i
Reilly Grant (use Gerrit) 2017/04/04 20:31:40 helper_ can only be destroyed on the FILE thread a
333 } 407 }
334 408
335 scoped_refptr<UsbDevice> UsbDeviceHandleUsbfs::GetDevice() const { 409 scoped_refptr<UsbDevice> UsbDeviceHandleUsbfs::GetDevice() const {
336 return device_; 410 return device_;
337 } 411 }
338 412
339 void UsbDeviceHandleUsbfs::Close() { 413 void UsbDeviceHandleUsbfs::Close() {
340 if (!device_) 414 if (!device_)
341 return; // Already closed. 415 return; // Already closed.
342 416
343 // On the |task_runner_| thread check |device_| to see if the handle is 417 // On the |task_runner_| thread check |device_| to see if the handle is
344 // closed. On the |blocking_task_runner_| thread check |fd_.is_valid()| to 418 // closed. On the |blocking_task_runner_| thread check |fd_.is_valid()| to
345 // see if the handle is closed. 419 // see if the handle is closed.
346 device_->HandleClosed(this); 420 device_->HandleClosed(this);
347 device_ = nullptr; 421 device_ = nullptr;
348 422
349 for (const auto& transfer : transfers_) 423 for (const auto& transfer : transfers_)
350 CancelTransfer(transfer.get(), USB_TRANSFER_CANCELLED); 424 CancelTransfer(transfer.get(), USB_TRANSFER_CANCELLED);
351 425
352 blocking_task_runner_->PostTask( 426 blocking_task_runner_->PostTask(
353 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::CloseBlocking, this)); 427 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::CloseBlocking, this));
354 } 428 }
355 429
356 void UsbDeviceHandleUsbfs::SetConfiguration(int configuration_value, 430 void UsbDeviceHandleUsbfs::SetConfiguration(int configuration_value,
357 const ResultCallback& callback) { 431 const ResultCallback& callback) {
358 // USBDEVFS_SETCONFIGURATION synchronously issues a SET_CONFIGURATION request 432 // USBDEVFS_SETCONFIGURATION synchronously issues a SET_CONFIGURATION request
359 // to the device so it must be performed on a thread where it is okay to 433 // to the device so it must be performed on a thread where it is okay to
360 // block. 434 // block.
361 blocking_task_runner_->PostTask( 435 blocking_task_runner_->PostTask(
362 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::SetConfigurationBlocking, 436 FROM_HERE,
363 this, configuration_value, callback)); 437 base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::SetConfiguration,
438 base::Unretained(helper_.get()), configuration_value,
439 callback));
364 } 440 }
365 441
366 void UsbDeviceHandleUsbfs::ClaimInterface(int interface_number, 442 void UsbDeviceHandleUsbfs::ClaimInterface(int interface_number,
367 const ResultCallback& callback) { 443 const ResultCallback& callback) {
368 if (!device_) { 444 if (!device_) {
369 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 445 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
370 return; 446 return;
371 } 447 }
372 448
373 if (base::ContainsKey(interfaces_, interface_number)) { 449 if (base::ContainsKey(interfaces_, interface_number)) {
(...skipping 13 matching lines...) Expand all
387 } 463 }
388 task_runner_->PostTask(FROM_HERE, base::Bind(callback, rc == 0)); 464 task_runner_->PostTask(FROM_HERE, base::Bind(callback, rc == 0));
389 } 465 }
390 466
391 void UsbDeviceHandleUsbfs::ReleaseInterface(int interface_number, 467 void UsbDeviceHandleUsbfs::ReleaseInterface(int interface_number,
392 const ResultCallback& callback) { 468 const ResultCallback& callback) {
393 // USBDEVFS_RELEASEINTERFACE may issue a SET_INTERFACE request to the 469 // USBDEVFS_RELEASEINTERFACE may issue a SET_INTERFACE request to the
394 // device to restore alternate setting 0 so it must be performed on a thread 470 // device to restore alternate setting 0 so it must be performed on a thread
395 // where it is okay to block. 471 // where it is okay to block.
396 blocking_task_runner_->PostTask( 472 blocking_task_runner_->PostTask(
397 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::ReleaseInterfaceBlocking, 473 FROM_HERE,
398 this, interface_number, callback)); 474 base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::ReleaseInterface,
475 base::Unretained(helper_.get()), interface_number, callback));
399 } 476 }
400 477
401 void UsbDeviceHandleUsbfs::SetInterfaceAlternateSetting( 478 void UsbDeviceHandleUsbfs::SetInterfaceAlternateSetting(
402 int interface_number, 479 int interface_number,
403 int alternate_setting, 480 int alternate_setting,
404 const ResultCallback& callback) { 481 const ResultCallback& callback) {
405 // USBDEVFS_SETINTERFACE is synchronous because it issues a SET_INTERFACE 482 // USBDEVFS_SETINTERFACE is synchronous because it issues a SET_INTERFACE
406 // request to the device so it must be performed on a thread where it is okay 483 // request to the device so it must be performed on a thread where it is okay
407 // to block. 484 // to block.
408 blocking_task_runner_->PostTask( 485 blocking_task_runner_->PostTask(
409 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::SetInterfaceBlocking, this, 486 FROM_HERE,
410 interface_number, alternate_setting, callback)); 487 base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::SetInterface,
488 base::Unretained(helper_.get()), interface_number,
489 alternate_setting, callback));
411 } 490 }
412 491
413 void UsbDeviceHandleUsbfs::ResetDevice(const ResultCallback& callback) { 492 void UsbDeviceHandleUsbfs::ResetDevice(const ResultCallback& callback) {
414 // USBDEVFS_RESET is synchronous because it waits for the port to be reset 493 // USBDEVFS_RESET is synchronous because it waits for the port to be reset
415 // and the device re-enumerated so it must be performed on a thread where it 494 // and the device re-enumerated so it must be performed on a thread where it
416 // is okay to block. 495 // is okay to block.
417 blocking_task_runner_->PostTask( 496 blocking_task_runner_->PostTask(
418 FROM_HERE, 497 FROM_HERE,
419 base::Bind(&UsbDeviceHandleUsbfs::ResetDeviceBlocking, this, callback)); 498 base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::ResetDevice,
499 base::Unretained(helper_.get()), callback));
420 } 500 }
421 501
422 void UsbDeviceHandleUsbfs::ClearHalt(uint8_t endpoint_address, 502 void UsbDeviceHandleUsbfs::ClearHalt(uint8_t endpoint_address,
423 const ResultCallback& callback) { 503 const ResultCallback& callback) {
424 // USBDEVFS_CLEAR_HALT is synchronous because it issues a CLEAR_FEATURE 504 // USBDEVFS_CLEAR_HALT is synchronous because it issues a CLEAR_FEATURE
425 // request to the device so it must be performed on a thread where it is okay 505 // request to the device so it must be performed on a thread where it is okay
426 // to block. 506 // to block.
427 blocking_task_runner_->PostTask( 507 blocking_task_runner_->PostTask(
428 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::ClearHaltBlocking, this, 508 FROM_HERE,
429 endpoint_address, callback)); 509 base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::ClearHalt,
510 base::Unretained(helper_.get()), endpoint_address, callback));
430 } 511 }
431 512
432 void UsbDeviceHandleUsbfs::ControlTransfer(UsbEndpointDirection direction, 513 void UsbDeviceHandleUsbfs::ControlTransfer(UsbEndpointDirection direction,
433 TransferRequestType request_type, 514 TransferRequestType request_type,
434 TransferRecipient recipient, 515 TransferRecipient recipient,
435 uint8_t request, 516 uint8_t request,
436 uint16_t value, 517 uint16_t value,
437 uint16_t index, 518 uint16_t index,
438 scoped_refptr<net::IOBuffer> buffer, 519 scoped_refptr<net::IOBuffer> buffer,
439 size_t length, 520 size_t length,
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 return it->second.interface; 601 return it->second.interface;
521 return nullptr; 602 return nullptr;
522 } 603 }
523 604
524 UsbDeviceHandleUsbfs::~UsbDeviceHandleUsbfs() { 605 UsbDeviceHandleUsbfs::~UsbDeviceHandleUsbfs() {
525 DCHECK(!device_) << "Handle must be closed before it is destroyed."; 606 DCHECK(!device_) << "Handle must be closed before it is destroyed.";
526 } 607 }
527 608
528 void UsbDeviceHandleUsbfs::ReleaseFileDescriptor() { 609 void UsbDeviceHandleUsbfs::ReleaseFileDescriptor() {
529 ignore_result(fd_.release()); 610 ignore_result(fd_.release());
530 delete helper_; 611 helper_.reset();
531 } 612 }
532 613
533 void UsbDeviceHandleUsbfs::CloseBlocking() { 614 void UsbDeviceHandleUsbfs::CloseBlocking() {
534 fd_.reset(-1); 615 fd_.reset(-1);
535 delete helper_; 616 helper_.reset();
536 } 617 ;
scheib 2017/04/04 20:17:15 ;
Reilly Grant (use Gerrit) 2017/04/04 20:31:40 Done.
537
538 void UsbDeviceHandleUsbfs::SetConfigurationBlocking(
539 int configuration_value,
540 const ResultCallback& callback) {
541 if (!fd_.is_valid()) {
542 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
543 return;
544 }
545
546 int rc = HANDLE_EINTR(
547 ioctl(fd_.get(), USBDEVFS_SETCONFIGURATION, &configuration_value));
548 if (rc)
549 USB_PLOG(DEBUG) << "Failed to set configuration " << configuration_value;
550 task_runner_->PostTask(
551 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::SetConfigurationComplete,
552 this, configuration_value, rc == 0, callback));
553 } 618 }
554 619
555 void UsbDeviceHandleUsbfs::SetConfigurationComplete( 620 void UsbDeviceHandleUsbfs::SetConfigurationComplete(
556 int configuration_value, 621 int configuration_value,
557 bool success, 622 bool success,
558 const ResultCallback& callback) { 623 const ResultCallback& callback) {
559 if (success && device_) { 624 if (success && device_) {
560 device_->ActiveConfigurationChanged(configuration_value); 625 device_->ActiveConfigurationChanged(configuration_value);
561 // TODO(reillyg): If all interfaces are unclaimed before a new configuration 626 // TODO(reillyg): If all interfaces are unclaimed before a new configuration
562 // is set then this will do nothing. Investigate. 627 // is set then this will do nothing. Investigate.
563 RefreshEndpointInfo(); 628 RefreshEndpointInfo();
564 } 629 }
565 callback.Run(success); 630 callback.Run(success);
566 } 631 }
567 632
568 void UsbDeviceHandleUsbfs::ReleaseInterfaceBlocking(
569 int interface_number,
570 const ResultCallback& callback) {
571 if (!fd_.is_valid()) {
572 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
573 return;
574 }
575
576 int rc = HANDLE_EINTR(
577 ioctl(fd_.get(), USBDEVFS_RELEASEINTERFACE, &interface_number));
578 if (rc) {
579 USB_PLOG(DEBUG) << "Failed to release interface " << interface_number;
580 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
581 } else {
582 task_runner_->PostTask(
583 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::ReleaseInterfaceComplete,
584 this, interface_number, callback));
585 }
586 }
587
588 void UsbDeviceHandleUsbfs::ReleaseInterfaceComplete( 633 void UsbDeviceHandleUsbfs::ReleaseInterfaceComplete(
589 int interface_number, 634 int interface_number,
590 const ResultCallback& callback) { 635 const ResultCallback& callback) {
591 auto it = interfaces_.find(interface_number); 636 auto it = interfaces_.find(interface_number);
592 DCHECK(it != interfaces_.end()); 637 DCHECK(it != interfaces_.end());
593 interfaces_.erase(it); 638 interfaces_.erase(it);
594 RefreshEndpointInfo(); 639 RefreshEndpointInfo();
595 callback.Run(true); 640 callback.Run(true);
596 } 641 }
597 642
598 void UsbDeviceHandleUsbfs::SetInterfaceBlocking(
599 int interface_number,
600 int alternate_setting,
601 const ResultCallback& callback) {
602 if (!fd_.is_valid()) {
603 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
604 return;
605 }
606
607 usbdevfs_setinterface cmd = {0};
608 cmd.interface = interface_number;
609 cmd.altsetting = alternate_setting;
610 int rc = HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_SETINTERFACE, &cmd));
611 if (rc) {
612 USB_PLOG(DEBUG) << "Failed to set interface " << interface_number
613 << " to alternate setting " << alternate_setting;
614 }
615 task_runner_->PostTask(FROM_HERE, base::Bind(callback, rc == 0));
616 }
617
618 void UsbDeviceHandleUsbfs::ResetDeviceBlocking(const ResultCallback& callback) {
619 if (!fd_.is_valid()) {
620 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
621 return;
622 }
623
624 // TODO(reillyg): libusb releases interfaces before and then reclaims
625 // interfaces after a reset. We should probably do this too or document that
626 // callers have to call ClaimInterface as well.
627 int rc = HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_RESET, nullptr));
628 if (rc)
629 USB_PLOG(DEBUG) << "Failed to reset the device";
630 task_runner_->PostTask(FROM_HERE, base::Bind(callback, rc == 0));
631 }
632
633 void UsbDeviceHandleUsbfs::ClearHaltBlocking(uint8_t endpoint_address,
634 const ResultCallback& callback) {
635 if (!fd_.is_valid()) {
636 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
637 return;
638 }
639
640 int tmp_endpoint = endpoint_address;
641 int rc = HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_CLEAR_HALT, &tmp_endpoint));
642 if (rc) {
643 USB_PLOG(DEBUG) << "Failed to clear the stall condition on endpoint "
644 << static_cast<int>(endpoint_address);
645 }
646 task_runner_->PostTask(FROM_HERE, base::Bind(callback, rc == 0));
647 }
648
649 void UsbDeviceHandleUsbfs::IsochronousTransferInternal( 643 void UsbDeviceHandleUsbfs::IsochronousTransferInternal(
650 uint8_t endpoint_address, 644 uint8_t endpoint_address,
651 scoped_refptr<net::IOBuffer> buffer, 645 scoped_refptr<net::IOBuffer> buffer,
652 size_t total_length, 646 size_t total_length,
653 const std::vector<uint32_t>& packet_lengths, 647 const std::vector<uint32_t>& packet_lengths,
654 unsigned int timeout, 648 unsigned int timeout,
655 const IsochronousTransferCallback& callback) { 649 const IsochronousTransferCallback& callback) {
656 if (!device_) { 650 if (!device_) {
657 ReportIsochronousError(packet_lengths, callback, USB_TRANSFER_DISCONNECT); 651 ReportIsochronousError(packet_lengths, callback, USB_TRANSFER_DISCONNECT);
658 return; 652 return;
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
868 packets[i].length = transfer->urb.iso_frame_desc[i].length; 862 packets[i].length = transfer->urb.iso_frame_desc[i].length;
869 packets[i].transferred_length = 0; 863 packets[i].transferred_length = 0;
870 packets[i].status = status; 864 packets[i].status = status;
871 } 865 }
872 transfer->RunIsochronousCallback(packets); 866 transfer->RunIsochronousCallback(packets);
873 } else { 867 } else {
874 transfer->RunCallback(status, 0); 868 transfer->RunCallback(status, 0);
875 } 869 }
876 870
877 blocking_task_runner_->PostTask( 871 blocking_task_runner_->PostTask(
878 FROM_HERE, 872 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::DiscardUrb,
879 base::Bind(&UsbDeviceHandleUsbfs::DiscardUrbBlocking, this, transfer)); 873 base::Unretained(helper_.get()), transfer));
880 } 874 }
881 875
882 void UsbDeviceHandleUsbfs::DiscardUrbBlocking(Transfer* transfer) {
883 if (fd_.is_valid())
884 HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_DISCARDURB, &transfer->urb));
885
886 task_runner_->PostTask(
887 FROM_HERE,
888 base::Bind(&UsbDeviceHandleUsbfs::UrbDiscarded, this, transfer));
889 }
890 876
891 void UsbDeviceHandleUsbfs::UrbDiscarded(Transfer* transfer) { 877 void UsbDeviceHandleUsbfs::UrbDiscarded(Transfer* transfer) {
892 transfer->discarded = true; 878 transfer->discarded = true;
893 if (transfer->reaped) 879 if (transfer->reaped)
894 RemoveFromTransferList(transfer); 880 RemoveFromTransferList(transfer);
895 } 881 }
896 882
897 } // namespace device 883 } // namespace device
OLDNEW
« no previous file with comments | « device/usb/usb_device_handle_usbfs.h ('k') | device/usb/usb_service.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698