Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |