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 |