| 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" |
| 23 #include "base/sequence_checker.h" |
| 24 #include "base/stl_util.h" | 24 #include "base/stl_util.h" |
| 25 #include "base/threading/thread_restrictions.h" | 25 #include "base/threading/thread_restrictions.h" |
| 26 #include "base/threading/thread_task_runner_handle.h" | 26 #include "base/threading/thread_task_runner_handle.h" |
| 27 #include "components/device_event_log/device_event_log.h" | 27 #include "components/device_event_log/device_event_log.h" |
| 28 #include "device/usb/usb_device_linux.h" | 28 #include "device/usb/usb_device_linux.h" |
| 29 #include "net/base/io_buffer.h" | 29 #include "net/base/io_buffer.h" |
| 30 | 30 |
| 31 namespace device { | 31 namespace device { |
| 32 | 32 |
| 33 namespace { | 33 namespace { |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 127 // TODO(reillyg): Add a specific error message whenever one of the cases | 127 // TODO(reillyg): Add a specific error message whenever one of the cases |
| 128 // above fails to match. | 128 // above fails to match. |
| 129 USB_LOG(ERROR) << "Unknown system error: " | 129 USB_LOG(ERROR) << "Unknown system error: " |
| 130 << logging::SystemErrorCodeToString(rc); | 130 << logging::SystemErrorCodeToString(rc); |
| 131 return USB_TRANSFER_ERROR; | 131 return USB_TRANSFER_ERROR; |
| 132 } | 132 } |
| 133 } | 133 } |
| 134 | 134 |
| 135 } // namespace | 135 } // namespace |
| 136 | 136 |
| 137 class UsbDeviceHandleUsbfs::FileThreadHelper | 137 class UsbDeviceHandleUsbfs::FileThreadHelper { |
| 138 : public base::MessageLoop::DestructionObserver { | |
| 139 public: | 138 public: |
| 140 FileThreadHelper(int fd, | 139 FileThreadHelper(base::ScopedFD fd, |
| 141 scoped_refptr<UsbDeviceHandleUsbfs> device_handle, | 140 scoped_refptr<UsbDeviceHandleUsbfs> device_handle, |
| 142 scoped_refptr<base::SequencedTaskRunner> task_runner); | 141 scoped_refptr<base::SequencedTaskRunner> task_runner); |
| 143 ~FileThreadHelper() override; | 142 ~FileThreadHelper(); |
| 144 | 143 |
| 145 static void Start(std::unique_ptr<FileThreadHelper> self); | 144 void Start(); |
| 146 | 145 void ReleaseFileDescriptor(); |
| 147 // base::MessageLoop::DestructionObserver overrides. | 146 |
| 148 void WillDestroyCurrentMessageLoop() override; | 147 void SetConfiguration(int configuration_value, |
| 148 const ResultCallback& callback); |
| 149 void ReleaseInterface(int interface_number, const ResultCallback& callback); |
| 150 void SetInterface(int interface_number, |
| 151 int alternate_setting, |
| 152 const ResultCallback& callback); |
| 153 void ResetDevice(const ResultCallback& callback); |
| 154 void ClearHalt(uint8_t endpoint_address, const ResultCallback& callback); |
| 155 void DiscardUrb(Transfer* transfer); |
| 149 | 156 |
| 150 private: | 157 private: |
| 151 // Called when |fd_| is writable without blocking. | 158 // Called when |fd_| is writable without blocking. |
| 152 void OnFileCanWriteWithoutBlocking(); | 159 void OnFileCanWriteWithoutBlocking(); |
| 153 | 160 |
| 154 int fd_; | 161 base::ScopedFD fd_; |
| 155 scoped_refptr<UsbDeviceHandleUsbfs> device_handle_; | 162 scoped_refptr<UsbDeviceHandleUsbfs> device_handle_; |
| 156 scoped_refptr<base::SequencedTaskRunner> task_runner_; | 163 scoped_refptr<base::SequencedTaskRunner> task_runner_; |
| 157 std::unique_ptr<base::FileDescriptorWatcher::Controller> watch_controller_; | 164 std::unique_ptr<base::FileDescriptorWatcher::Controller> watch_controller_; |
| 158 base::ThreadChecker thread_checker_; | 165 base::SequenceChecker sequence_checker_; |
| 159 | 166 |
| 160 DISALLOW_COPY_AND_ASSIGN(FileThreadHelper); | 167 DISALLOW_COPY_AND_ASSIGN(FileThreadHelper); |
| 161 }; | 168 }; |
| 162 | 169 |
| 170 struct UsbDeviceHandleUsbfs::Transfer { |
| 171 Transfer() = delete; |
| 172 Transfer(scoped_refptr<net::IOBuffer> buffer, |
| 173 const TransferCallback& callback, |
| 174 scoped_refptr<base::SingleThreadTaskRunner> callback_runner); |
| 175 Transfer(scoped_refptr<net::IOBuffer> buffer, |
| 176 const IsochronousTransferCallback& callback); |
| 177 ~Transfer(); |
| 178 |
| 179 void* operator new(std::size_t size, size_t number_of_iso_packets); |
| 180 void RunCallback(UsbTransferStatus status, size_t bytes_transferred); |
| 181 void RunIsochronousCallback(const std::vector<IsochronousPacket>& packets); |
| 182 |
| 183 scoped_refptr<net::IOBuffer> control_transfer_buffer; |
| 184 scoped_refptr<net::IOBuffer> buffer; |
| 185 base::CancelableClosure timeout_closure; |
| 186 bool cancelled = false; |
| 187 |
| 188 // When the URB is |cancelled| these two flags track whether the URB has both |
| 189 // been |discarded| and |reaped| since the possiblity of last-minute |
| 190 // completion makes these two conditions race. |
| 191 bool discarded = false; |
| 192 bool reaped = false; |
| 193 |
| 194 private: |
| 195 TransferCallback callback; |
| 196 IsochronousTransferCallback isoc_callback; |
| 197 scoped_refptr<base::SingleThreadTaskRunner> callback_runner; |
| 198 |
| 199 DISALLOW_COPY_AND_ASSIGN(Transfer); |
| 200 |
| 201 public: |
| 202 // The |urb| field must be the last in the struct so that the extra space |
| 203 // allocated by the overridden new function above extends the length of its |
| 204 // |iso_frame_desc| field. |
| 205 usbdevfs_urb urb; |
| 206 }; |
| 207 |
| 163 UsbDeviceHandleUsbfs::FileThreadHelper::FileThreadHelper( | 208 UsbDeviceHandleUsbfs::FileThreadHelper::FileThreadHelper( |
| 164 int fd, | 209 base::ScopedFD fd, |
| 165 scoped_refptr<UsbDeviceHandleUsbfs> device_handle, | 210 scoped_refptr<UsbDeviceHandleUsbfs> device_handle, |
| 166 scoped_refptr<base::SequencedTaskRunner> task_runner) | 211 scoped_refptr<base::SequencedTaskRunner> task_runner) |
| 167 : fd_(fd), device_handle_(device_handle), task_runner_(task_runner) {} | 212 : fd_(std::move(fd)), |
| 213 device_handle_(std::move(device_handle)), |
| 214 task_runner_(std::move(task_runner)) {} |
| 168 | 215 |
| 169 UsbDeviceHandleUsbfs::FileThreadHelper::~FileThreadHelper() { | 216 UsbDeviceHandleUsbfs::FileThreadHelper::~FileThreadHelper() { |
| 170 DCHECK(thread_checker_.CalledOnValidThread()); | 217 DCHECK(sequence_checker_.CalledOnValidSequence()); |
| 171 base::MessageLoop::current()->RemoveDestructionObserver(this); | 218 } |
| 172 } | 219 |
| 173 | 220 void UsbDeviceHandleUsbfs::FileThreadHelper::Start() { |
| 174 // static | |
| 175 void UsbDeviceHandleUsbfs::FileThreadHelper::Start( | |
| 176 std::unique_ptr<FileThreadHelper> self) { | |
| 177 base::ThreadRestrictions::AssertIOAllowed(); | 221 base::ThreadRestrictions::AssertIOAllowed(); |
| 178 self->thread_checker_.DetachFromThread(); | 222 sequence_checker_.DetachFromSequence(); |
| 223 DCHECK(sequence_checker_.CalledOnValidSequence()); |
| 179 | 224 |
| 180 // Linux indicates that URBs are available to reap by marking the file | 225 // Linux indicates that URBs are available to reap by marking the file |
| 181 // descriptor writable. | 226 // descriptor writable. |
| 182 self->watch_controller_ = base::FileDescriptorWatcher::WatchWritable( | 227 watch_controller_ = base::FileDescriptorWatcher::WatchWritable( |
| 183 self->fd_, base::Bind(&FileThreadHelper::OnFileCanWriteWithoutBlocking, | 228 fd_.get(), base::Bind(&FileThreadHelper::OnFileCanWriteWithoutBlocking, |
| 184 base::Unretained(self.get()))); | 229 base::Unretained(this))); |
| 185 | 230 } |
| 186 // |self| is now owned by the current message loop. | 231 |
| 187 base::MessageLoop::current()->AddDestructionObserver(self.release()); | 232 void UsbDeviceHandleUsbfs::FileThreadHelper::ReleaseFileDescriptor() { |
| 188 } | 233 // This method intentionally leaks the file descriptor. |
| 189 | 234 DCHECK(sequence_checker_.CalledOnValidSequence()); |
| 190 void UsbDeviceHandleUsbfs::FileThreadHelper::WillDestroyCurrentMessageLoop() { | 235 watch_controller_.reset(); |
| 191 DCHECK(thread_checker_.CalledOnValidThread()); | 236 ignore_result(fd_.release()); |
| 192 delete this; | 237 } |
| 238 |
| 239 void UsbDeviceHandleUsbfs::FileThreadHelper::SetConfiguration( |
| 240 int configuration_value, |
| 241 const ResultCallback& callback) { |
| 242 DCHECK(sequence_checker_.CalledOnValidSequence()); |
| 243 |
| 244 int rc = HANDLE_EINTR( |
| 245 ioctl(fd_.get(), USBDEVFS_SETCONFIGURATION, &configuration_value)); |
| 246 if (rc) |
| 247 USB_PLOG(DEBUG) << "Failed to set configuration " << configuration_value; |
| 248 task_runner_->PostTask( |
| 249 FROM_HERE, |
| 250 base::Bind(&UsbDeviceHandleUsbfs::SetConfigurationComplete, |
| 251 device_handle_, configuration_value, rc == 0, callback)); |
| 252 } |
| 253 |
| 254 void UsbDeviceHandleUsbfs::FileThreadHelper::ReleaseInterface( |
| 255 int interface_number, |
| 256 const ResultCallback& callback) { |
| 257 DCHECK(sequence_checker_.CalledOnValidSequence()); |
| 258 |
| 259 int rc = HANDLE_EINTR( |
| 260 ioctl(fd_.get(), USBDEVFS_RELEASEINTERFACE, &interface_number)); |
| 261 if (rc) { |
| 262 USB_PLOG(DEBUG) << "Failed to release interface " << interface_number; |
| 263 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
| 264 } else { |
| 265 task_runner_->PostTask( |
| 266 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::ReleaseInterfaceComplete, |
| 267 device_handle_, interface_number, callback)); |
| 268 } |
| 269 } |
| 270 |
| 271 void UsbDeviceHandleUsbfs::FileThreadHelper::SetInterface( |
| 272 int interface_number, |
| 273 int alternate_setting, |
| 274 const ResultCallback& callback) { |
| 275 DCHECK(sequence_checker_.CalledOnValidSequence()); |
| 276 |
| 277 usbdevfs_setinterface cmd = {0}; |
| 278 cmd.interface = interface_number; |
| 279 cmd.altsetting = alternate_setting; |
| 280 int rc = HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_SETINTERFACE, &cmd)); |
| 281 if (rc) { |
| 282 USB_PLOG(DEBUG) << "Failed to set interface " << interface_number |
| 283 << " to alternate setting " << alternate_setting; |
| 284 } |
| 285 task_runner_->PostTask(FROM_HERE, base::Bind(callback, rc == 0)); |
| 286 } |
| 287 |
| 288 void UsbDeviceHandleUsbfs::FileThreadHelper::ResetDevice( |
| 289 const ResultCallback& callback) { |
| 290 DCHECK(sequence_checker_.CalledOnValidSequence()); |
| 291 |
| 292 // TODO(reillyg): libusb releases interfaces before and then reclaims |
| 293 // interfaces after a reset. We should probably do this too or document that |
| 294 // callers have to call ClaimInterface as well. |
| 295 int rc = HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_RESET, nullptr)); |
| 296 if (rc) |
| 297 USB_PLOG(DEBUG) << "Failed to reset the device"; |
| 298 task_runner_->PostTask(FROM_HERE, base::Bind(callback, rc == 0)); |
| 299 } |
| 300 |
| 301 void UsbDeviceHandleUsbfs::FileThreadHelper::ClearHalt( |
| 302 uint8_t endpoint_address, |
| 303 const ResultCallback& callback) { |
| 304 DCHECK(sequence_checker_.CalledOnValidSequence()); |
| 305 |
| 306 int tmp_endpoint = endpoint_address; |
| 307 int rc = HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_CLEAR_HALT, &tmp_endpoint)); |
| 308 if (rc) { |
| 309 USB_PLOG(DEBUG) << "Failed to clear the stall condition on endpoint " |
| 310 << static_cast<int>(endpoint_address); |
| 311 } |
| 312 task_runner_->PostTask(FROM_HERE, base::Bind(callback, rc == 0)); |
| 313 } |
| 314 |
| 315 void UsbDeviceHandleUsbfs::FileThreadHelper::DiscardUrb(Transfer* transfer) { |
| 316 DCHECK(sequence_checker_.CalledOnValidSequence()); |
| 317 |
| 318 HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_DISCARDURB, &transfer->urb)); |
| 319 |
| 320 task_runner_->PostTask( |
| 321 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::UrbDiscarded, device_handle_, |
| 322 transfer)); |
| 193 } | 323 } |
| 194 | 324 |
| 195 void UsbDeviceHandleUsbfs::FileThreadHelper::OnFileCanWriteWithoutBlocking() { | 325 void UsbDeviceHandleUsbfs::FileThreadHelper::OnFileCanWriteWithoutBlocking() { |
| 196 DCHECK(thread_checker_.CalledOnValidThread()); | 326 DCHECK(sequence_checker_.CalledOnValidSequence()); |
| 197 | 327 |
| 198 const size_t MAX_URBS_PER_EVENT = 10; | 328 const size_t MAX_URBS_PER_EVENT = 10; |
| 199 std::vector<usbdevfs_urb*> urbs; | 329 std::vector<usbdevfs_urb*> urbs; |
| 200 urbs.reserve(MAX_URBS_PER_EVENT); | 330 urbs.reserve(MAX_URBS_PER_EVENT); |
| 201 for (size_t i = 0; i < MAX_URBS_PER_EVENT; ++i) { | 331 for (size_t i = 0; i < MAX_URBS_PER_EVENT; ++i) { |
| 202 usbdevfs_urb* urb; | 332 usbdevfs_urb* urb; |
| 203 int rc = HANDLE_EINTR(ioctl(fd_, USBDEVFS_REAPURBNDELAY, &urb)); | 333 int rc = HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_REAPURBNDELAY, &urb)); |
| 204 if (rc) { | 334 if (rc) { |
| 205 if (errno == EAGAIN) | 335 if (errno == EAGAIN) |
| 206 break; | 336 break; |
| 207 USB_PLOG(DEBUG) << "Failed to reap urbs"; | 337 USB_PLOG(DEBUG) << "Failed to reap urbs"; |
| 208 if (errno == ENODEV) { | 338 if (errno == ENODEV) { |
| 209 // Device has disconnected. Stop watching the file descriptor to avoid | 339 // Device has disconnected. Stop watching the file descriptor to avoid |
| 210 // looping until |device_handle_| is closed. | 340 // looping until |device_handle_| is closed. |
| 211 watch_controller_.reset(); | 341 watch_controller_.reset(); |
| 212 break; | 342 break; |
| 213 } | 343 } |
| 214 } else { | 344 } else { |
| 215 urbs.push_back(urb); | 345 urbs.push_back(urb); |
| 216 } | 346 } |
| 217 } | 347 } |
| 218 | 348 |
| 219 task_runner_->PostTask( | 349 task_runner_->PostTask( |
| 220 FROM_HERE, | 350 FROM_HERE, |
| 221 base::Bind(&UsbDeviceHandleUsbfs::ReapedUrbs, device_handle_, urbs)); | 351 base::Bind(&UsbDeviceHandleUsbfs::ReapedUrbs, device_handle_, urbs)); |
| 222 } | 352 } |
| 223 | 353 |
| 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( | 354 UsbDeviceHandleUsbfs::Transfer::Transfer( |
| 263 scoped_refptr<net::IOBuffer> buffer, | 355 scoped_refptr<net::IOBuffer> buffer, |
| 264 const TransferCallback& callback, | 356 const TransferCallback& callback, |
| 265 scoped_refptr<base::SingleThreadTaskRunner> callback_runner) | 357 scoped_refptr<base::SingleThreadTaskRunner> callback_runner) |
| 266 : buffer(buffer), callback(callback), callback_runner(callback_runner) { | 358 : buffer(buffer), callback(callback), callback_runner(callback_runner) { |
| 267 memset(&urb, 0, sizeof(urb)); | 359 memset(&urb, 0, sizeof(urb)); |
| 268 urb.usercontext = this; | 360 urb.usercontext = this; |
| 269 urb.buffer = buffer->data(); | 361 urb.buffer = buffer->data(); |
| 270 } | 362 } |
| 271 | 363 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 DCHECK(isoc_callback); | 402 DCHECK(isoc_callback); |
| 311 isoc_callback.Run(buffer, packets); | 403 isoc_callback.Run(buffer, packets); |
| 312 isoc_callback.Reset(); | 404 isoc_callback.Reset(); |
| 313 } | 405 } |
| 314 | 406 |
| 315 UsbDeviceHandleUsbfs::UsbDeviceHandleUsbfs( | 407 UsbDeviceHandleUsbfs::UsbDeviceHandleUsbfs( |
| 316 scoped_refptr<UsbDevice> device, | 408 scoped_refptr<UsbDevice> device, |
| 317 base::ScopedFD fd, | 409 base::ScopedFD fd, |
| 318 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) | 410 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) |
| 319 : device_(device), | 411 : device_(device), |
| 320 fd_(std::move(fd)), | 412 fd_(fd.get()), |
| 413 task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 321 blocking_task_runner_(blocking_task_runner) { | 414 blocking_task_runner_(blocking_task_runner) { |
| 322 DCHECK(device_); | 415 DCHECK(device_); |
| 323 DCHECK(fd_.is_valid()); | 416 DCHECK(fd.is_valid()); |
| 324 DCHECK(blocking_task_runner_); | 417 DCHECK(blocking_task_runner_); |
| 325 | 418 |
| 326 task_runner_ = base::ThreadTaskRunnerHandle::Get(); | 419 helper_.reset(new FileThreadHelper(std::move(fd), this, task_runner_)); |
| 327 | |
| 328 std::unique_ptr<FileThreadHelper> helper( | |
| 329 new FileThreadHelper(fd_.get(), this, task_runner_)); | |
| 330 helper_ = helper.get(); | |
| 331 blocking_task_runner_->PostTask( | 420 blocking_task_runner_->PostTask( |
| 332 FROM_HERE, base::Bind(&FileThreadHelper::Start, base::Passed(&helper))); | 421 FROM_HERE, |
| 422 base::Bind(&FileThreadHelper::Start, base::Unretained(helper_.get()))); |
| 333 } | 423 } |
| 334 | 424 |
| 335 scoped_refptr<UsbDevice> UsbDeviceHandleUsbfs::GetDevice() const { | 425 scoped_refptr<UsbDevice> UsbDeviceHandleUsbfs::GetDevice() const { |
| 336 return device_; | 426 return device_; |
| 337 } | 427 } |
| 338 | 428 |
| 339 void UsbDeviceHandleUsbfs::Close() { | 429 void UsbDeviceHandleUsbfs::Close() { |
| 340 if (!device_) | 430 if (!device_) |
| 341 return; // Already closed. | 431 return; // Already closed. |
| 342 | 432 |
| 343 // On the |task_runner_| thread check |device_| to see if the handle is | 433 // 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 | 434 // closed. On the |blocking_task_runner_| thread check |fd_.is_valid()| to |
| 345 // see if the handle is closed. | 435 // see if the handle is closed. |
| 346 device_->HandleClosed(this); | 436 device_->HandleClosed(this); |
| 347 device_ = nullptr; | 437 device_ = nullptr; |
| 348 | 438 |
| 349 for (const auto& transfer : transfers_) | 439 for (const auto& transfer : transfers_) |
| 350 CancelTransfer(transfer.get(), USB_TRANSFER_CANCELLED); | 440 CancelTransfer(transfer.get(), USB_TRANSFER_CANCELLED); |
| 351 | 441 |
| 442 // Releases |helper_|. |
| 352 blocking_task_runner_->PostTask( | 443 blocking_task_runner_->PostTask( |
| 353 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::CloseBlocking, this)); | 444 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::CloseBlocking, this)); |
| 354 } | 445 } |
| 355 | 446 |
| 356 void UsbDeviceHandleUsbfs::SetConfiguration(int configuration_value, | 447 void UsbDeviceHandleUsbfs::SetConfiguration(int configuration_value, |
| 357 const ResultCallback& callback) { | 448 const ResultCallback& callback) { |
| 449 if (!device_) { |
| 450 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
| 451 return; |
| 452 } |
| 453 |
| 358 // USBDEVFS_SETCONFIGURATION synchronously issues a SET_CONFIGURATION request | 454 // 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 | 455 // to the device so it must be performed on a thread where it is okay to |
| 360 // block. | 456 // block. |
| 361 blocking_task_runner_->PostTask( | 457 blocking_task_runner_->PostTask( |
| 362 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::SetConfigurationBlocking, | 458 FROM_HERE, |
| 363 this, configuration_value, callback)); | 459 base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::SetConfiguration, |
| 460 base::Unretained(helper_.get()), configuration_value, |
| 461 callback)); |
| 364 } | 462 } |
| 365 | 463 |
| 366 void UsbDeviceHandleUsbfs::ClaimInterface(int interface_number, | 464 void UsbDeviceHandleUsbfs::ClaimInterface(int interface_number, |
| 367 const ResultCallback& callback) { | 465 const ResultCallback& callback) { |
| 368 if (!device_) { | 466 if (!device_) { |
| 369 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); | 467 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
| 370 return; | 468 return; |
| 371 } | 469 } |
| 372 | 470 |
| 373 if (base::ContainsKey(interfaces_, interface_number)) { | 471 if (base::ContainsKey(interfaces_, interface_number)) { |
| 374 USB_LOG(DEBUG) << "Interface " << interface_number << " already claimed."; | 472 USB_LOG(DEBUG) << "Interface " << interface_number << " already claimed."; |
| 375 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); | 473 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
| 376 return; | 474 return; |
| 377 } | 475 } |
| 378 | 476 |
| 379 // It appears safe to assume that this ioctl will not block. | 477 // It appears safe to assume that this ioctl will not block. |
| 380 int rc = HANDLE_EINTR( | 478 int rc = HANDLE_EINTR(ioctl(fd_, USBDEVFS_CLAIMINTERFACE, &interface_number)); |
| 381 ioctl(fd_.get(), USBDEVFS_CLAIMINTERFACE, &interface_number)); | |
| 382 if (rc) { | 479 if (rc) { |
| 383 USB_PLOG(DEBUG) << "Failed to claim interface " << interface_number; | 480 USB_PLOG(DEBUG) << "Failed to claim interface " << interface_number; |
| 384 } else { | 481 } else { |
| 385 interfaces_[interface_number].alternate_setting = 0; | 482 interfaces_[interface_number].alternate_setting = 0; |
| 386 RefreshEndpointInfo(); | 483 RefreshEndpointInfo(); |
| 387 } | 484 } |
| 388 task_runner_->PostTask(FROM_HERE, base::Bind(callback, rc == 0)); | 485 task_runner_->PostTask(FROM_HERE, base::Bind(callback, rc == 0)); |
| 389 } | 486 } |
| 390 | 487 |
| 391 void UsbDeviceHandleUsbfs::ReleaseInterface(int interface_number, | 488 void UsbDeviceHandleUsbfs::ReleaseInterface(int interface_number, |
| 392 const ResultCallback& callback) { | 489 const ResultCallback& callback) { |
| 490 if (!device_) { |
| 491 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
| 492 return; |
| 493 } |
| 494 |
| 393 // USBDEVFS_RELEASEINTERFACE may issue a SET_INTERFACE request to the | 495 // 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 | 496 // device to restore alternate setting 0 so it must be performed on a thread |
| 395 // where it is okay to block. | 497 // where it is okay to block. |
| 396 blocking_task_runner_->PostTask( | 498 blocking_task_runner_->PostTask( |
| 397 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::ReleaseInterfaceBlocking, | 499 FROM_HERE, |
| 398 this, interface_number, callback)); | 500 base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::ReleaseInterface, |
| 501 base::Unretained(helper_.get()), interface_number, callback)); |
| 399 } | 502 } |
| 400 | 503 |
| 401 void UsbDeviceHandleUsbfs::SetInterfaceAlternateSetting( | 504 void UsbDeviceHandleUsbfs::SetInterfaceAlternateSetting( |
| 402 int interface_number, | 505 int interface_number, |
| 403 int alternate_setting, | 506 int alternate_setting, |
| 404 const ResultCallback& callback) { | 507 const ResultCallback& callback) { |
| 508 if (!device_) { |
| 509 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
| 510 return; |
| 511 } |
| 512 |
| 405 // USBDEVFS_SETINTERFACE is synchronous because it issues a SET_INTERFACE | 513 // 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 | 514 // request to the device so it must be performed on a thread where it is okay |
| 407 // to block. | 515 // to block. |
| 408 blocking_task_runner_->PostTask( | 516 blocking_task_runner_->PostTask( |
| 409 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::SetInterfaceBlocking, this, | 517 FROM_HERE, |
| 410 interface_number, alternate_setting, callback)); | 518 base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::SetInterface, |
| 519 base::Unretained(helper_.get()), interface_number, |
| 520 alternate_setting, callback)); |
| 411 } | 521 } |
| 412 | 522 |
| 413 void UsbDeviceHandleUsbfs::ResetDevice(const ResultCallback& callback) { | 523 void UsbDeviceHandleUsbfs::ResetDevice(const ResultCallback& callback) { |
| 524 if (!device_) { |
| 525 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
| 526 return; |
| 527 } |
| 528 |
| 414 // USBDEVFS_RESET is synchronous because it waits for the port to be reset | 529 // 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 | 530 // and the device re-enumerated so it must be performed on a thread where it |
| 416 // is okay to block. | 531 // is okay to block. |
| 417 blocking_task_runner_->PostTask( | 532 blocking_task_runner_->PostTask( |
| 418 FROM_HERE, | 533 FROM_HERE, |
| 419 base::Bind(&UsbDeviceHandleUsbfs::ResetDeviceBlocking, this, callback)); | 534 base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::ResetDevice, |
| 535 base::Unretained(helper_.get()), callback)); |
| 420 } | 536 } |
| 421 | 537 |
| 422 void UsbDeviceHandleUsbfs::ClearHalt(uint8_t endpoint_address, | 538 void UsbDeviceHandleUsbfs::ClearHalt(uint8_t endpoint_address, |
| 423 const ResultCallback& callback) { | 539 const ResultCallback& callback) { |
| 540 if (!device_) { |
| 541 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
| 542 return; |
| 543 } |
| 544 |
| 424 // USBDEVFS_CLEAR_HALT is synchronous because it issues a CLEAR_FEATURE | 545 // 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 | 546 // request to the device so it must be performed on a thread where it is okay |
| 426 // to block. | 547 // to block. |
| 427 blocking_task_runner_->PostTask( | 548 blocking_task_runner_->PostTask( |
| 428 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::ClearHaltBlocking, this, | 549 FROM_HERE, |
| 429 endpoint_address, callback)); | 550 base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::ClearHalt, |
| 551 base::Unretained(helper_.get()), endpoint_address, callback)); |
| 430 } | 552 } |
| 431 | 553 |
| 432 void UsbDeviceHandleUsbfs::ControlTransfer(UsbEndpointDirection direction, | 554 void UsbDeviceHandleUsbfs::ControlTransfer(UsbEndpointDirection direction, |
| 433 TransferRequestType request_type, | 555 TransferRequestType request_type, |
| 434 TransferRecipient recipient, | 556 TransferRecipient recipient, |
| 435 uint8_t request, | 557 uint8_t request, |
| 436 uint16_t value, | 558 uint16_t value, |
| 437 uint16_t index, | 559 uint16_t index, |
| 438 scoped_refptr<net::IOBuffer> buffer, | 560 scoped_refptr<net::IOBuffer> buffer, |
| 439 size_t length, | 561 size_t length, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 450 transfer->control_transfer_buffer = | 572 transfer->control_transfer_buffer = |
| 451 BuildControlTransferBuffer(direction, request_type, recipient, request, | 573 BuildControlTransferBuffer(direction, request_type, recipient, request, |
| 452 value, index, buffer, length); | 574 value, index, buffer, length); |
| 453 transfer->urb.type = USBDEVFS_URB_TYPE_CONTROL; | 575 transfer->urb.type = USBDEVFS_URB_TYPE_CONTROL; |
| 454 transfer->urb.endpoint = 0; | 576 transfer->urb.endpoint = 0; |
| 455 transfer->urb.buffer = transfer->control_transfer_buffer->data(); | 577 transfer->urb.buffer = transfer->control_transfer_buffer->data(); |
| 456 transfer->urb.buffer_length = 8 + length; | 578 transfer->urb.buffer_length = 8 + length; |
| 457 | 579 |
| 458 // USBDEVFS_SUBMITURB appears to be non-blocking as completion is reported | 580 // USBDEVFS_SUBMITURB appears to be non-blocking as completion is reported |
| 459 // by USBDEVFS_REAPURBNDELAY. | 581 // by USBDEVFS_REAPURBNDELAY. |
| 460 int rc = HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_SUBMITURB, &transfer->urb)); | 582 int rc = HANDLE_EINTR(ioctl(fd_, USBDEVFS_SUBMITURB, &transfer->urb)); |
| 461 if (rc) { | 583 if (rc) { |
| 462 rc = logging::GetLastSystemErrorCode(); | 584 rc = logging::GetLastSystemErrorCode(); |
| 463 USB_PLOG(DEBUG) << "Failed to submit control transfer"; | 585 USB_PLOG(DEBUG) << "Failed to submit control transfer"; |
| 464 task_runner_->PostTask( | 586 task_runner_->PostTask( |
| 465 FROM_HERE, base::Bind(callback, ConvertTransferResult(rc), nullptr, 0)); | 587 FROM_HERE, base::Bind(callback, ConvertTransferResult(rc), nullptr, 0)); |
| 466 } else { | 588 } else { |
| 467 SetUpTimeoutCallback(transfer.get(), timeout); | 589 SetUpTimeoutCallback(transfer.get(), timeout); |
| 468 transfers_.push_back(std::move(transfer)); | 590 transfers_.push_back(std::move(transfer)); |
| 469 } | 591 } |
| 470 } | 592 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 519 if (it != endpoints_.end()) | 641 if (it != endpoints_.end()) |
| 520 return it->second.interface; | 642 return it->second.interface; |
| 521 return nullptr; | 643 return nullptr; |
| 522 } | 644 } |
| 523 | 645 |
| 524 UsbDeviceHandleUsbfs::~UsbDeviceHandleUsbfs() { | 646 UsbDeviceHandleUsbfs::~UsbDeviceHandleUsbfs() { |
| 525 DCHECK(!device_) << "Handle must be closed before it is destroyed."; | 647 DCHECK(!device_) << "Handle must be closed before it is destroyed."; |
| 526 } | 648 } |
| 527 | 649 |
| 528 void UsbDeviceHandleUsbfs::ReleaseFileDescriptor() { | 650 void UsbDeviceHandleUsbfs::ReleaseFileDescriptor() { |
| 529 ignore_result(fd_.release()); | 651 // Calls to this method must be posted to |blocking_task_runner_|. |
| 530 delete helper_; | 652 helper_->ReleaseFileDescriptor(); |
| 653 helper_.reset(); |
| 531 } | 654 } |
| 532 | 655 |
| 533 void UsbDeviceHandleUsbfs::CloseBlocking() { | 656 void UsbDeviceHandleUsbfs::CloseBlocking() { |
| 534 fd_.reset(-1); | 657 // Calls to this method must be posted to |blocking_task_runner_|. |
| 535 delete helper_; | 658 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 } | 659 } |
| 554 | 660 |
| 555 void UsbDeviceHandleUsbfs::SetConfigurationComplete( | 661 void UsbDeviceHandleUsbfs::SetConfigurationComplete( |
| 556 int configuration_value, | 662 int configuration_value, |
| 557 bool success, | 663 bool success, |
| 558 const ResultCallback& callback) { | 664 const ResultCallback& callback) { |
| 559 if (success && device_) { | 665 if (success && device_) { |
| 560 device_->ActiveConfigurationChanged(configuration_value); | 666 device_->ActiveConfigurationChanged(configuration_value); |
| 561 // TODO(reillyg): If all interfaces are unclaimed before a new configuration | 667 // TODO(reillyg): If all interfaces are unclaimed before a new configuration |
| 562 // is set then this will do nothing. Investigate. | 668 // is set then this will do nothing. Investigate. |
| 563 RefreshEndpointInfo(); | 669 RefreshEndpointInfo(); |
| 564 } | 670 } |
| 565 callback.Run(success); | 671 callback.Run(success); |
| 566 } | 672 } |
| 567 | 673 |
| 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( | 674 void UsbDeviceHandleUsbfs::ReleaseInterfaceComplete( |
| 589 int interface_number, | 675 int interface_number, |
| 590 const ResultCallback& callback) { | 676 const ResultCallback& callback) { |
| 591 auto it = interfaces_.find(interface_number); | 677 auto it = interfaces_.find(interface_number); |
| 592 DCHECK(it != interfaces_.end()); | 678 DCHECK(it != interfaces_.end()); |
| 593 interfaces_.erase(it); | 679 interfaces_.erase(it); |
| 594 RefreshEndpointInfo(); | 680 RefreshEndpointInfo(); |
| 595 callback.Run(true); | 681 callback.Run(true); |
| 596 } | 682 } |
| 597 | 683 |
| 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( | 684 void UsbDeviceHandleUsbfs::IsochronousTransferInternal( |
| 650 uint8_t endpoint_address, | 685 uint8_t endpoint_address, |
| 651 scoped_refptr<net::IOBuffer> buffer, | 686 scoped_refptr<net::IOBuffer> buffer, |
| 652 size_t total_length, | 687 size_t total_length, |
| 653 const std::vector<uint32_t>& packet_lengths, | 688 const std::vector<uint32_t>& packet_lengths, |
| 654 unsigned int timeout, | 689 unsigned int timeout, |
| 655 const IsochronousTransferCallback& callback) { | 690 const IsochronousTransferCallback& callback) { |
| 656 if (!device_) { | 691 if (!device_) { |
| 657 ReportIsochronousError(packet_lengths, callback, USB_TRANSFER_DISCONNECT); | 692 ReportIsochronousError(packet_lengths, callback, USB_TRANSFER_DISCONNECT); |
| 658 return; | 693 return; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 672 transfer->urb.endpoint = endpoint_address; | 707 transfer->urb.endpoint = endpoint_address; |
| 673 transfer->urb.buffer_length = total_length; | 708 transfer->urb.buffer_length = total_length; |
| 674 | 709 |
| 675 for (size_t i = 0; i < packet_lengths.size(); ++i) | 710 for (size_t i = 0; i < packet_lengths.size(); ++i) |
| 676 transfer->urb.iso_frame_desc[i].length = packet_lengths[i]; | 711 transfer->urb.iso_frame_desc[i].length = packet_lengths[i]; |
| 677 | 712 |
| 678 // USBDEVFS_SUBMITURB appears to be non-blocking as completion is reported | 713 // USBDEVFS_SUBMITURB appears to be non-blocking as completion is reported |
| 679 // by USBDEVFS_REAPURBNDELAY. This code assumes a recent kernel that can | 714 // by USBDEVFS_REAPURBNDELAY. This code assumes a recent kernel that can |
| 680 // accept arbitrarily large transfer requests, hopefully also using a scatter- | 715 // accept arbitrarily large transfer requests, hopefully also using a scatter- |
| 681 // gather list. | 716 // gather list. |
| 682 int rc = HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_SUBMITURB, &transfer->urb)); | 717 int rc = HANDLE_EINTR(ioctl(fd_, USBDEVFS_SUBMITURB, &transfer->urb)); |
| 683 if (rc) { | 718 if (rc) { |
| 684 rc = logging::GetLastSystemErrorCode(); | 719 rc = logging::GetLastSystemErrorCode(); |
| 685 USB_PLOG(DEBUG) << "Failed to submit transfer"; | 720 USB_PLOG(DEBUG) << "Failed to submit transfer"; |
| 686 ReportIsochronousError(packet_lengths, callback, ConvertTransferResult(rc)); | 721 ReportIsochronousError(packet_lengths, callback, ConvertTransferResult(rc)); |
| 687 } else { | 722 } else { |
| 688 SetUpTimeoutCallback(transfer.get(), timeout); | 723 SetUpTimeoutCallback(transfer.get(), timeout); |
| 689 transfers_.push_back(std::move(transfer)); | 724 transfers_.push_back(std::move(transfer)); |
| 690 } | 725 } |
| 691 } | 726 } |
| 692 | 727 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 718 std::unique_ptr<Transfer> transfer( | 753 std::unique_ptr<Transfer> transfer( |
| 719 new (0) Transfer(buffer, callback, callback_runner)); | 754 new (0) Transfer(buffer, callback, callback_runner)); |
| 720 transfer->urb.endpoint = endpoint_address; | 755 transfer->urb.endpoint = endpoint_address; |
| 721 transfer->urb.buffer_length = length; | 756 transfer->urb.buffer_length = length; |
| 722 transfer->urb.type = ConvertTransferType(it->second.type); | 757 transfer->urb.type = ConvertTransferType(it->second.type); |
| 723 | 758 |
| 724 // USBDEVFS_SUBMITURB appears to be non-blocking as completion is reported | 759 // USBDEVFS_SUBMITURB appears to be non-blocking as completion is reported |
| 725 // by USBDEVFS_REAPURBNDELAY. This code assumes a recent kernel that can | 760 // by USBDEVFS_REAPURBNDELAY. This code assumes a recent kernel that can |
| 726 // accept arbitrarily large transfer requests, hopefully also using a scatter- | 761 // accept arbitrarily large transfer requests, hopefully also using a scatter- |
| 727 // gather list. | 762 // gather list. |
| 728 int rc = HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_SUBMITURB, &transfer->urb)); | 763 int rc = HANDLE_EINTR(ioctl(fd_, USBDEVFS_SUBMITURB, &transfer->urb)); |
| 729 if (rc) { | 764 if (rc) { |
| 730 rc = logging::GetLastSystemErrorCode(); | 765 rc = logging::GetLastSystemErrorCode(); |
| 731 USB_PLOG(DEBUG) << "Failed to submit transfer"; | 766 USB_PLOG(DEBUG) << "Failed to submit transfer"; |
| 732 callback_runner->PostTask( | 767 callback_runner->PostTask( |
| 733 FROM_HERE, base::Bind(callback, ConvertTransferResult(rc), nullptr, 0)); | 768 FROM_HERE, base::Bind(callback, ConvertTransferResult(rc), nullptr, 0)); |
| 734 } else { | 769 } else { |
| 735 SetUpTimeoutCallback(transfer.get(), timeout); | 770 SetUpTimeoutCallback(transfer.get(), timeout); |
| 736 transfers_.push_back(std::move(transfer)); | 771 transfers_.push_back(std::move(transfer)); |
| 737 } | 772 } |
| 738 } | 773 } |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 868 packets[i].length = transfer->urb.iso_frame_desc[i].length; | 903 packets[i].length = transfer->urb.iso_frame_desc[i].length; |
| 869 packets[i].transferred_length = 0; | 904 packets[i].transferred_length = 0; |
| 870 packets[i].status = status; | 905 packets[i].status = status; |
| 871 } | 906 } |
| 872 transfer->RunIsochronousCallback(packets); | 907 transfer->RunIsochronousCallback(packets); |
| 873 } else { | 908 } else { |
| 874 transfer->RunCallback(status, 0); | 909 transfer->RunCallback(status, 0); |
| 875 } | 910 } |
| 876 | 911 |
| 877 blocking_task_runner_->PostTask( | 912 blocking_task_runner_->PostTask( |
| 878 FROM_HERE, | 913 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::DiscardUrb, |
| 879 base::Bind(&UsbDeviceHandleUsbfs::DiscardUrbBlocking, this, transfer)); | 914 base::Unretained(helper_.get()), transfer)); |
| 880 } | 915 } |
| 881 | 916 |
| 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 | 917 |
| 891 void UsbDeviceHandleUsbfs::UrbDiscarded(Transfer* transfer) { | 918 void UsbDeviceHandleUsbfs::UrbDiscarded(Transfer* transfer) { |
| 892 transfer->discarded = true; | 919 transfer->discarded = true; |
| 893 if (transfer->reaped) | 920 if (transfer->reaped) |
| 894 RemoveFromTransferList(transfer); | 921 RemoveFromTransferList(transfer); |
| 895 } | 922 } |
| 896 | 923 |
| 897 } // namespace device | 924 } // namespace device |
| OLD | NEW |