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

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

Issue 2797433005: Remove MessageLoop destruction observer from //device/usb (Closed)
Patch Set: Add back in the correct closed device checks 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())));
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 }
scheib 2017/04/04 20:42:04 Could release reference to blocking_task_runner_ h
Reilly Grant (use Gerrit) 2017/04/04 23:52:19 It turns out that that doesn't work with the Andro
355 429
356 void UsbDeviceHandleUsbfs::SetConfiguration(int configuration_value, 430 void UsbDeviceHandleUsbfs::SetConfiguration(int configuration_value,
357 const ResultCallback& callback) { 431 const ResultCallback& callback) {
432 if (!device_) {
433 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
434 return;
435 }
436
358 // USBDEVFS_SETCONFIGURATION synchronously issues a SET_CONFIGURATION request 437 // 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 438 // to the device so it must be performed on a thread where it is okay to
360 // block. 439 // block.
361 blocking_task_runner_->PostTask( 440 blocking_task_runner_->PostTask(
362 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::SetConfigurationBlocking, 441 FROM_HERE,
363 this, configuration_value, callback)); 442 base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::SetConfiguration,
443 base::Unretained(helper_.get()), configuration_value,
444 callback));
364 } 445 }
365 446
366 void UsbDeviceHandleUsbfs::ClaimInterface(int interface_number, 447 void UsbDeviceHandleUsbfs::ClaimInterface(int interface_number,
367 const ResultCallback& callback) { 448 const ResultCallback& callback) {
368 if (!device_) { 449 if (!device_) {
369 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 450 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
370 return; 451 return;
371 } 452 }
372 453
373 if (base::ContainsKey(interfaces_, interface_number)) { 454 if (base::ContainsKey(interfaces_, interface_number)) {
374 USB_LOG(DEBUG) << "Interface " << interface_number << " already claimed."; 455 USB_LOG(DEBUG) << "Interface " << interface_number << " already claimed.";
375 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 456 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
376 return; 457 return;
377 } 458 }
378 459
379 // It appears safe to assume that this ioctl will not block. 460 // It appears safe to assume that this ioctl will not block.
380 int rc = HANDLE_EINTR( 461 int rc = HANDLE_EINTR(
381 ioctl(fd_.get(), USBDEVFS_CLAIMINTERFACE, &interface_number)); 462 ioctl(fd_.get(), USBDEVFS_CLAIMINTERFACE, &interface_number));
382 if (rc) { 463 if (rc) {
383 USB_PLOG(DEBUG) << "Failed to claim interface " << interface_number; 464 USB_PLOG(DEBUG) << "Failed to claim interface " << interface_number;
384 } else { 465 } else {
385 interfaces_[interface_number].alternate_setting = 0; 466 interfaces_[interface_number].alternate_setting = 0;
386 RefreshEndpointInfo(); 467 RefreshEndpointInfo();
387 } 468 }
388 task_runner_->PostTask(FROM_HERE, base::Bind(callback, rc == 0)); 469 task_runner_->PostTask(FROM_HERE, base::Bind(callback, rc == 0));
389 } 470 }
390 471
391 void UsbDeviceHandleUsbfs::ReleaseInterface(int interface_number, 472 void UsbDeviceHandleUsbfs::ReleaseInterface(int interface_number,
392 const ResultCallback& callback) { 473 const ResultCallback& callback) {
474 if (!device_) {
475 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
476 return;
477 }
478
393 // USBDEVFS_RELEASEINTERFACE may issue a SET_INTERFACE request to the 479 // 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 480 // device to restore alternate setting 0 so it must be performed on a thread
395 // where it is okay to block. 481 // where it is okay to block.
396 blocking_task_runner_->PostTask( 482 blocking_task_runner_->PostTask(
397 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::ReleaseInterfaceBlocking, 483 FROM_HERE,
398 this, interface_number, callback)); 484 base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::ReleaseInterface,
485 base::Unretained(helper_.get()), interface_number, callback));
399 } 486 }
400 487
401 void UsbDeviceHandleUsbfs::SetInterfaceAlternateSetting( 488 void UsbDeviceHandleUsbfs::SetInterfaceAlternateSetting(
402 int interface_number, 489 int interface_number,
403 int alternate_setting, 490 int alternate_setting,
404 const ResultCallback& callback) { 491 const ResultCallback& callback) {
492 if (!device_) {
493 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
494 return;
495 }
496
405 // USBDEVFS_SETINTERFACE is synchronous because it issues a SET_INTERFACE 497 // 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 498 // request to the device so it must be performed on a thread where it is okay
407 // to block. 499 // to block.
408 blocking_task_runner_->PostTask( 500 blocking_task_runner_->PostTask(
409 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::SetInterfaceBlocking, this, 501 FROM_HERE,
410 interface_number, alternate_setting, callback)); 502 base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::SetInterface,
503 base::Unretained(helper_.get()), interface_number,
504 alternate_setting, callback));
411 } 505 }
412 506
413 void UsbDeviceHandleUsbfs::ResetDevice(const ResultCallback& callback) { 507 void UsbDeviceHandleUsbfs::ResetDevice(const ResultCallback& callback) {
508 if (!device_) {
509 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
510 return;
511 }
512
414 // USBDEVFS_RESET is synchronous because it waits for the port to be reset 513 // 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 514 // and the device re-enumerated so it must be performed on a thread where it
416 // is okay to block. 515 // is okay to block.
417 blocking_task_runner_->PostTask( 516 blocking_task_runner_->PostTask(
418 FROM_HERE, 517 FROM_HERE,
419 base::Bind(&UsbDeviceHandleUsbfs::ResetDeviceBlocking, this, callback)); 518 base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::ResetDevice,
519 base::Unretained(helper_.get()), callback));
420 } 520 }
421 521
422 void UsbDeviceHandleUsbfs::ClearHalt(uint8_t endpoint_address, 522 void UsbDeviceHandleUsbfs::ClearHalt(uint8_t endpoint_address,
423 const ResultCallback& callback) { 523 const ResultCallback& callback) {
524 if (!device_) {
525 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
526 return;
527 }
528
424 // USBDEVFS_CLEAR_HALT is synchronous because it issues a CLEAR_FEATURE 529 // 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 530 // request to the device so it must be performed on a thread where it is okay
426 // to block. 531 // to block.
427 blocking_task_runner_->PostTask( 532 blocking_task_runner_->PostTask(
428 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::ClearHaltBlocking, this, 533 FROM_HERE,
429 endpoint_address, callback)); 534 base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::ClearHalt,
535 base::Unretained(helper_.get()), endpoint_address, callback));
430 } 536 }
431 537
432 void UsbDeviceHandleUsbfs::ControlTransfer(UsbEndpointDirection direction, 538 void UsbDeviceHandleUsbfs::ControlTransfer(UsbEndpointDirection direction,
433 TransferRequestType request_type, 539 TransferRequestType request_type,
434 TransferRecipient recipient, 540 TransferRecipient recipient,
435 uint8_t request, 541 uint8_t request,
436 uint16_t value, 542 uint16_t value,
437 uint16_t index, 543 uint16_t index,
438 scoped_refptr<net::IOBuffer> buffer, 544 scoped_refptr<net::IOBuffer> buffer,
439 size_t length, 545 size_t length,
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 return it->second.interface; 626 return it->second.interface;
521 return nullptr; 627 return nullptr;
522 } 628 }
523 629
524 UsbDeviceHandleUsbfs::~UsbDeviceHandleUsbfs() { 630 UsbDeviceHandleUsbfs::~UsbDeviceHandleUsbfs() {
525 DCHECK(!device_) << "Handle must be closed before it is destroyed."; 631 DCHECK(!device_) << "Handle must be closed before it is destroyed.";
526 } 632 }
527 633
528 void UsbDeviceHandleUsbfs::ReleaseFileDescriptor() { 634 void UsbDeviceHandleUsbfs::ReleaseFileDescriptor() {
529 ignore_result(fd_.release()); 635 ignore_result(fd_.release());
530 delete helper_; 636 helper_.reset();
531 } 637 }
532 638
533 void UsbDeviceHandleUsbfs::CloseBlocking() { 639 void UsbDeviceHandleUsbfs::CloseBlocking() {
534 fd_.reset(-1); 640 fd_.reset(-1);
535 delete helper_; 641 helper_.reset();
536 }
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 } 642 }
554 643
555 void UsbDeviceHandleUsbfs::SetConfigurationComplete( 644 void UsbDeviceHandleUsbfs::SetConfigurationComplete(
556 int configuration_value, 645 int configuration_value,
557 bool success, 646 bool success,
558 const ResultCallback& callback) { 647 const ResultCallback& callback) {
559 if (success && device_) { 648 if (success && device_) {
560 device_->ActiveConfigurationChanged(configuration_value); 649 device_->ActiveConfigurationChanged(configuration_value);
561 // TODO(reillyg): If all interfaces are unclaimed before a new configuration 650 // TODO(reillyg): If all interfaces are unclaimed before a new configuration
562 // is set then this will do nothing. Investigate. 651 // is set then this will do nothing. Investigate.
563 RefreshEndpointInfo(); 652 RefreshEndpointInfo();
564 } 653 }
565 callback.Run(success); 654 callback.Run(success);
566 } 655 }
567 656
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( 657 void UsbDeviceHandleUsbfs::ReleaseInterfaceComplete(
589 int interface_number, 658 int interface_number,
590 const ResultCallback& callback) { 659 const ResultCallback& callback) {
591 auto it = interfaces_.find(interface_number); 660 auto it = interfaces_.find(interface_number);
592 DCHECK(it != interfaces_.end()); 661 DCHECK(it != interfaces_.end());
593 interfaces_.erase(it); 662 interfaces_.erase(it);
594 RefreshEndpointInfo(); 663 RefreshEndpointInfo();
595 callback.Run(true); 664 callback.Run(true);
596 } 665 }
597 666
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( 667 void UsbDeviceHandleUsbfs::IsochronousTransferInternal(
650 uint8_t endpoint_address, 668 uint8_t endpoint_address,
651 scoped_refptr<net::IOBuffer> buffer, 669 scoped_refptr<net::IOBuffer> buffer,
652 size_t total_length, 670 size_t total_length,
653 const std::vector<uint32_t>& packet_lengths, 671 const std::vector<uint32_t>& packet_lengths,
654 unsigned int timeout, 672 unsigned int timeout,
655 const IsochronousTransferCallback& callback) { 673 const IsochronousTransferCallback& callback) {
656 if (!device_) { 674 if (!device_) {
657 ReportIsochronousError(packet_lengths, callback, USB_TRANSFER_DISCONNECT); 675 ReportIsochronousError(packet_lengths, callback, USB_TRANSFER_DISCONNECT);
658 return; 676 return;
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
868 packets[i].length = transfer->urb.iso_frame_desc[i].length; 886 packets[i].length = transfer->urb.iso_frame_desc[i].length;
869 packets[i].transferred_length = 0; 887 packets[i].transferred_length = 0;
870 packets[i].status = status; 888 packets[i].status = status;
871 } 889 }
872 transfer->RunIsochronousCallback(packets); 890 transfer->RunIsochronousCallback(packets);
873 } else { 891 } else {
874 transfer->RunCallback(status, 0); 892 transfer->RunCallback(status, 0);
875 } 893 }
876 894
877 blocking_task_runner_->PostTask( 895 blocking_task_runner_->PostTask(
878 FROM_HERE, 896 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::DiscardUrb,
879 base::Bind(&UsbDeviceHandleUsbfs::DiscardUrbBlocking, this, transfer)); 897 base::Unretained(helper_.get()), transfer));
880 } 898 }
881 899
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 900
891 void UsbDeviceHandleUsbfs::UrbDiscarded(Transfer* transfer) { 901 void UsbDeviceHandleUsbfs::UrbDiscarded(Transfer* transfer) {
892 transfer->discarded = true; 902 transfer->discarded = true;
893 if (transfer->reaped) 903 if (transfer->reaped)
894 RemoveFromTransferList(transfer); 904 RemoveFromTransferList(transfer);
895 } 905 }
896 906
897 } // namespace device 907 } // 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