OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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_impl.h" | 5 #include "device/usb/usb_device_handle_impl.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 << ConvertPlatformUsbErrorToString(rv); | 150 << ConvertPlatformUsbErrorToString(rv); |
151 } | 151 } |
152 return rv == LIBUSB_SUCCESS; | 152 return rv == LIBUSB_SUCCESS; |
153 } | 153 } |
154 | 154 |
155 // This inner class owns the underlying libusb_transfer and may outlast | 155 // This inner class owns the underlying libusb_transfer and may outlast |
156 // the UsbDeviceHandle that created it. | 156 // the UsbDeviceHandle that created it. |
157 class UsbDeviceHandleImpl::Transfer { | 157 class UsbDeviceHandleImpl::Transfer { |
158 public: | 158 public: |
159 static scoped_ptr<Transfer> CreateControlTransfer( | 159 static scoped_ptr<Transfer> CreateControlTransfer( |
| 160 scoped_refptr<UsbDeviceHandleImpl> device_handle, |
160 uint8 type, | 161 uint8 type, |
161 uint8 request, | 162 uint8 request, |
162 uint16 value, | 163 uint16 value, |
163 uint16 index, | 164 uint16 index, |
164 uint16 length, | 165 uint16 length, |
165 scoped_refptr<net::IOBuffer> buffer, | 166 scoped_refptr<net::IOBuffer> buffer, |
166 unsigned int timeout, | 167 unsigned int timeout, |
167 const UsbTransferCallback& callback); | 168 scoped_refptr<base::TaskRunner> callback_task_runner, |
| 169 const TransferCallback& callback); |
168 static scoped_ptr<Transfer> CreateBulkTransfer( | 170 static scoped_ptr<Transfer> CreateBulkTransfer( |
| 171 scoped_refptr<UsbDeviceHandleImpl> device_handle, |
169 uint8 endpoint, | 172 uint8 endpoint, |
170 scoped_refptr<net::IOBuffer> buffer, | 173 scoped_refptr<net::IOBuffer> buffer, |
171 int length, | 174 int length, |
172 unsigned int timeout, | 175 unsigned int timeout, |
173 const UsbTransferCallback& callback); | 176 scoped_refptr<base::TaskRunner> callback_task_runner, |
| 177 const TransferCallback& callback); |
174 static scoped_ptr<Transfer> CreateInterruptTransfer( | 178 static scoped_ptr<Transfer> CreateInterruptTransfer( |
| 179 scoped_refptr<UsbDeviceHandleImpl> device_handle, |
175 uint8 endpoint, | 180 uint8 endpoint, |
176 scoped_refptr<net::IOBuffer> buffer, | 181 scoped_refptr<net::IOBuffer> buffer, |
177 int length, | 182 int length, |
178 unsigned int timeout, | 183 unsigned int timeout, |
179 const UsbTransferCallback& callback); | 184 scoped_refptr<base::TaskRunner> callback_task_runner, |
| 185 const TransferCallback& callback); |
180 static scoped_ptr<Transfer> CreateIsochronousTransfer( | 186 static scoped_ptr<Transfer> CreateIsochronousTransfer( |
| 187 scoped_refptr<UsbDeviceHandleImpl> device_handle, |
181 uint8 endpoint, | 188 uint8 endpoint, |
182 scoped_refptr<net::IOBuffer> buffer, | 189 scoped_refptr<net::IOBuffer> buffer, |
183 size_t length, | 190 size_t length, |
184 unsigned int packets, | 191 unsigned int packets, |
185 unsigned int packet_length, | 192 unsigned int packet_length, |
186 unsigned int timeout, | 193 unsigned int timeout, |
187 const UsbTransferCallback& callback); | 194 scoped_refptr<base::TaskRunner> task_runner, |
| 195 const TransferCallback& callback); |
188 | 196 |
189 ~Transfer(); | 197 ~Transfer(); |
190 | 198 |
191 bool Submit(base::WeakPtr<UsbDeviceHandleImpl> device_handle); | 199 void Submit(); |
192 void Cancel(); | 200 void Cancel(); |
193 void ProcessCompletion(); | 201 void ProcessCompletion(); |
194 void Complete(UsbTransferStatus status, size_t bytes_transferred); | 202 void TransferComplete(UsbTransferStatus status, size_t bytes_transferred); |
195 | 203 |
196 const UsbDeviceHandleImpl::InterfaceClaimer* claimed_interface() const { | 204 const UsbDeviceHandleImpl::InterfaceClaimer* claimed_interface() const { |
197 return claimed_interface_.get(); | 205 return claimed_interface_.get(); |
198 } | 206 } |
199 | 207 |
| 208 scoped_refptr<base::TaskRunner> callback_task_runner() const { |
| 209 return callback_task_runner_; |
| 210 } |
| 211 |
200 private: | 212 private: |
201 Transfer(UsbTransferType transfer_type, | 213 Transfer(scoped_refptr<UsbDeviceHandleImpl> device_handle, |
| 214 scoped_refptr<InterfaceClaimer> claimed_interface, |
| 215 UsbTransferType transfer_type, |
202 scoped_refptr<net::IOBuffer> buffer, | 216 scoped_refptr<net::IOBuffer> buffer, |
203 size_t length, | 217 size_t length, |
204 const UsbTransferCallback& callback); | 218 scoped_refptr<base::TaskRunner> callback_task_runner, |
| 219 const TransferCallback& callback); |
205 | 220 |
206 static void LIBUSB_CALL PlatformCallback(PlatformUsbTransferHandle handle); | 221 static void LIBUSB_CALL PlatformCallback(PlatformUsbTransferHandle handle); |
207 | 222 |
208 UsbTransferType transfer_type_; | 223 UsbTransferType transfer_type_; |
209 base::WeakPtr<UsbDeviceHandleImpl> device_handle_; | 224 scoped_refptr<UsbDeviceHandleImpl> device_handle_; |
210 PlatformUsbTransferHandle platform_transfer_; | 225 PlatformUsbTransferHandle platform_transfer_ = nullptr; |
211 scoped_refptr<net::IOBuffer> buffer_; | 226 scoped_refptr<net::IOBuffer> buffer_; |
212 scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer> claimed_interface_; | 227 scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer> claimed_interface_; |
213 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | |
214 size_t length_; | 228 size_t length_; |
215 bool cancelled_; | 229 bool cancelled_ = false; |
216 UsbTransferCallback callback_; | 230 scoped_refptr<base::SequencedTaskRunner> task_runner_; |
217 scoped_refptr<base::SingleThreadTaskRunner> callback_task_runner_; | 231 scoped_refptr<base::TaskRunner> callback_task_runner_; |
| 232 TransferCallback callback_; |
218 }; | 233 }; |
219 | 234 |
220 // static | 235 // static |
221 scoped_ptr<UsbDeviceHandleImpl::Transfer> | 236 scoped_ptr<UsbDeviceHandleImpl::Transfer> |
222 UsbDeviceHandleImpl::Transfer::CreateControlTransfer( | 237 UsbDeviceHandleImpl::Transfer::CreateControlTransfer( |
| 238 scoped_refptr<UsbDeviceHandleImpl> device_handle, |
223 uint8 type, | 239 uint8 type, |
224 uint8 request, | 240 uint8 request, |
225 uint16 value, | 241 uint16 value, |
226 uint16 index, | 242 uint16 index, |
227 uint16 length, | 243 uint16 length, |
228 scoped_refptr<net::IOBuffer> buffer, | 244 scoped_refptr<net::IOBuffer> buffer, |
229 unsigned int timeout, | 245 unsigned int timeout, |
230 const UsbTransferCallback& callback) { | 246 scoped_refptr<base::TaskRunner> callback_task_runner, |
231 scoped_ptr<Transfer> transfer(new Transfer(USB_TRANSFER_CONTROL, buffer, | 247 const TransferCallback& callback) { |
232 length + LIBUSB_CONTROL_SETUP_SIZE, | 248 scoped_ptr<Transfer> transfer(new Transfer( |
233 callback)); | 249 device_handle, nullptr, USB_TRANSFER_CONTROL, buffer, |
| 250 length + LIBUSB_CONTROL_SETUP_SIZE, callback_task_runner, callback)); |
234 | 251 |
235 transfer->platform_transfer_ = libusb_alloc_transfer(0); | 252 transfer->platform_transfer_ = libusb_alloc_transfer(0); |
236 if (!transfer->platform_transfer_) { | 253 if (!transfer->platform_transfer_) { |
237 USB_LOG(ERROR) << "Failed to allocate control transfer."; | 254 USB_LOG(ERROR) << "Failed to allocate control transfer."; |
238 return nullptr; | 255 return nullptr; |
239 } | 256 } |
240 | 257 |
241 libusb_fill_control_setup(reinterpret_cast<uint8*>(buffer->data()), type, | 258 libusb_fill_control_setup(reinterpret_cast<uint8*>(buffer->data()), type, |
242 request, value, index, length); | 259 request, value, index, length); |
243 libusb_fill_control_transfer(transfer->platform_transfer_, | 260 libusb_fill_control_transfer(transfer->platform_transfer_, |
244 nullptr, /* filled in by Submit() */ | 261 device_handle->handle_, |
245 reinterpret_cast<uint8*>(buffer->data()), | 262 reinterpret_cast<uint8*>(buffer->data()), |
246 &UsbDeviceHandleImpl::Transfer::PlatformCallback, | 263 &UsbDeviceHandleImpl::Transfer::PlatformCallback, |
247 transfer.get(), timeout); | 264 transfer.get(), timeout); |
248 | 265 |
249 return transfer.Pass(); | 266 return transfer.Pass(); |
250 } | 267 } |
251 | 268 |
252 // static | 269 // static |
253 scoped_ptr<UsbDeviceHandleImpl::Transfer> | 270 scoped_ptr<UsbDeviceHandleImpl::Transfer> |
254 UsbDeviceHandleImpl::Transfer::CreateBulkTransfer( | 271 UsbDeviceHandleImpl::Transfer::CreateBulkTransfer( |
| 272 scoped_refptr<UsbDeviceHandleImpl> device_handle, |
255 uint8 endpoint, | 273 uint8 endpoint, |
256 scoped_refptr<net::IOBuffer> buffer, | 274 scoped_refptr<net::IOBuffer> buffer, |
257 int length, | 275 int length, |
258 unsigned int timeout, | 276 unsigned int timeout, |
259 const UsbTransferCallback& callback) { | 277 scoped_refptr<base::TaskRunner> callback_task_runner, |
260 scoped_ptr<Transfer> transfer( | 278 const TransferCallback& callback) { |
261 new Transfer(USB_TRANSFER_BULK, buffer, length, callback)); | 279 scoped_ptr<Transfer> transfer(new Transfer( |
| 280 device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint), |
| 281 USB_TRANSFER_BULK, buffer, length, callback_task_runner, callback)); |
262 | 282 |
263 transfer->platform_transfer_ = libusb_alloc_transfer(0); | 283 transfer->platform_transfer_ = libusb_alloc_transfer(0); |
264 if (!transfer->platform_transfer_) { | 284 if (!transfer->platform_transfer_) { |
265 USB_LOG(ERROR) << "Failed to allocate bulk transfer."; | 285 USB_LOG(ERROR) << "Failed to allocate bulk transfer."; |
266 return nullptr; | 286 return nullptr; |
267 } | 287 } |
268 | 288 |
269 libusb_fill_bulk_transfer(transfer->platform_transfer_, | 289 libusb_fill_bulk_transfer( |
270 nullptr, /* filled in by Submit() */ | 290 transfer->platform_transfer_, device_handle->handle_, endpoint, |
271 endpoint, reinterpret_cast<uint8*>(buffer->data()), | 291 reinterpret_cast<uint8*>(buffer->data()), static_cast<int>(length), |
272 static_cast<int>(length), | 292 &UsbDeviceHandleImpl::Transfer::PlatformCallback, transfer.get(), |
273 &UsbDeviceHandleImpl::Transfer::PlatformCallback, | 293 timeout); |
274 transfer.get(), timeout); | |
275 | 294 |
276 return transfer.Pass(); | 295 return transfer.Pass(); |
277 } | 296 } |
278 | 297 |
279 // static | 298 // static |
280 scoped_ptr<UsbDeviceHandleImpl::Transfer> | 299 scoped_ptr<UsbDeviceHandleImpl::Transfer> |
281 UsbDeviceHandleImpl::Transfer::CreateInterruptTransfer( | 300 UsbDeviceHandleImpl::Transfer::CreateInterruptTransfer( |
| 301 scoped_refptr<UsbDeviceHandleImpl> device_handle, |
282 uint8 endpoint, | 302 uint8 endpoint, |
283 scoped_refptr<net::IOBuffer> buffer, | 303 scoped_refptr<net::IOBuffer> buffer, |
284 int length, | 304 int length, |
285 unsigned int timeout, | 305 unsigned int timeout, |
286 const UsbTransferCallback& callback) { | 306 scoped_refptr<base::TaskRunner> callback_task_runner, |
287 scoped_ptr<Transfer> transfer( | 307 const TransferCallback& callback) { |
288 new Transfer(USB_TRANSFER_INTERRUPT, buffer, length, callback)); | 308 scoped_ptr<Transfer> transfer(new Transfer( |
| 309 device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint), |
| 310 USB_TRANSFER_INTERRUPT, buffer, length, callback_task_runner, callback)); |
289 | 311 |
290 transfer->platform_transfer_ = libusb_alloc_transfer(0); | 312 transfer->platform_transfer_ = libusb_alloc_transfer(0); |
291 if (!transfer->platform_transfer_) { | 313 if (!transfer->platform_transfer_) { |
292 USB_LOG(ERROR) << "Failed to allocate interrupt transfer."; | 314 USB_LOG(ERROR) << "Failed to allocate interrupt transfer."; |
293 return nullptr; | 315 return nullptr; |
294 } | 316 } |
295 | 317 |
296 libusb_fill_interrupt_transfer( | 318 libusb_fill_interrupt_transfer( |
297 transfer->platform_transfer_, nullptr, /* filled in by Submit() */ | 319 transfer->platform_transfer_, device_handle->handle_, endpoint, |
298 endpoint, reinterpret_cast<uint8*>(buffer->data()), | 320 reinterpret_cast<uint8*>(buffer->data()), static_cast<int>(length), |
299 static_cast<int>(length), | |
300 &UsbDeviceHandleImpl::Transfer::PlatformCallback, transfer.get(), | 321 &UsbDeviceHandleImpl::Transfer::PlatformCallback, transfer.get(), |
301 timeout); | 322 timeout); |
302 | 323 |
303 return transfer.Pass(); | 324 return transfer.Pass(); |
304 } | 325 } |
305 | 326 |
306 // static | 327 // static |
307 scoped_ptr<UsbDeviceHandleImpl::Transfer> | 328 scoped_ptr<UsbDeviceHandleImpl::Transfer> |
308 UsbDeviceHandleImpl::Transfer::CreateIsochronousTransfer( | 329 UsbDeviceHandleImpl::Transfer::CreateIsochronousTransfer( |
| 330 scoped_refptr<UsbDeviceHandleImpl> device_handle, |
309 uint8 endpoint, | 331 uint8 endpoint, |
310 scoped_refptr<net::IOBuffer> buffer, | 332 scoped_refptr<net::IOBuffer> buffer, |
311 size_t length, | 333 size_t length, |
312 unsigned int packets, | 334 unsigned int packets, |
313 unsigned int packet_length, | 335 unsigned int packet_length, |
314 unsigned int timeout, | 336 unsigned int timeout, |
315 const UsbTransferCallback& callback) { | 337 scoped_refptr<base::TaskRunner> callback_task_runner, |
| 338 const TransferCallback& callback) { |
316 DCHECK(packets <= length && (packets * packet_length) <= length) | 339 DCHECK(packets <= length && (packets * packet_length) <= length) |
317 << "transfer length is too small"; | 340 << "transfer length is too small"; |
318 | 341 |
319 scoped_ptr<Transfer> transfer( | 342 scoped_ptr<Transfer> transfer(new Transfer( |
320 new Transfer(USB_TRANSFER_ISOCHRONOUS, buffer, length, callback)); | 343 device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint), |
| 344 USB_TRANSFER_ISOCHRONOUS, buffer, length, callback_task_runner, |
| 345 callback)); |
321 | 346 |
322 transfer->platform_transfer_ = libusb_alloc_transfer(packets); | 347 transfer->platform_transfer_ = libusb_alloc_transfer(packets); |
323 if (!transfer->platform_transfer_) { | 348 if (!transfer->platform_transfer_) { |
324 USB_LOG(ERROR) << "Failed to allocate isochronous transfer."; | 349 USB_LOG(ERROR) << "Failed to allocate isochronous transfer."; |
325 return nullptr; | 350 return nullptr; |
326 } | 351 } |
327 | 352 |
328 libusb_fill_iso_transfer( | 353 libusb_fill_iso_transfer( |
329 transfer->platform_transfer_, nullptr, /* filled in by Submit() */ | 354 transfer->platform_transfer_, device_handle->handle_, endpoint, |
330 endpoint, reinterpret_cast<uint8*>(buffer->data()), | 355 reinterpret_cast<uint8*>(buffer->data()), static_cast<int>(length), |
331 static_cast<int>(length), packets, &Transfer::PlatformCallback, | 356 packets, &Transfer::PlatformCallback, transfer.get(), timeout); |
332 transfer.get(), timeout); | |
333 libusb_set_iso_packet_lengths(transfer->platform_transfer_, packet_length); | 357 libusb_set_iso_packet_lengths(transfer->platform_transfer_, packet_length); |
334 | 358 |
335 return transfer.Pass(); | 359 return transfer.Pass(); |
336 } | 360 } |
337 | 361 |
338 UsbDeviceHandleImpl::Transfer::Transfer(UsbTransferType transfer_type, | 362 UsbDeviceHandleImpl::Transfer::Transfer( |
339 scoped_refptr<net::IOBuffer> buffer, | 363 scoped_refptr<UsbDeviceHandleImpl> device_handle, |
340 size_t length, | 364 scoped_refptr<InterfaceClaimer> claimed_interface, |
341 const UsbTransferCallback& callback) | 365 UsbTransferType transfer_type, |
| 366 scoped_refptr<net::IOBuffer> buffer, |
| 367 size_t length, |
| 368 scoped_refptr<base::TaskRunner> callback_task_runner, |
| 369 const TransferCallback& callback) |
342 : transfer_type_(transfer_type), | 370 : transfer_type_(transfer_type), |
| 371 device_handle_(device_handle), |
343 buffer_(buffer), | 372 buffer_(buffer), |
| 373 claimed_interface_(claimed_interface), |
344 length_(length), | 374 length_(length), |
345 cancelled_(false), | 375 callback_task_runner_(callback_task_runner), |
346 callback_(callback) { | 376 callback_(callback) { |
347 // Remember the thread from which this transfer was created so that |callback| | 377 task_runner_ = base::ThreadTaskRunnerHandle::Get(); |
348 // can be dispatched there. | |
349 callback_task_runner_ = base::ThreadTaskRunnerHandle::Get(); | |
350 } | 378 } |
351 | 379 |
352 UsbDeviceHandleImpl::Transfer::~Transfer() { | 380 UsbDeviceHandleImpl::Transfer::~Transfer() { |
353 if (platform_transfer_) { | 381 if (platform_transfer_) { |
354 libusb_free_transfer(platform_transfer_); | 382 libusb_free_transfer(platform_transfer_); |
355 } | 383 } |
356 } | 384 } |
357 | 385 |
358 bool UsbDeviceHandleImpl::Transfer::Submit( | 386 void UsbDeviceHandleImpl::Transfer::Submit() { |
359 base::WeakPtr<UsbDeviceHandleImpl> device_handle) { | |
360 device_handle_ = device_handle; | |
361 // Remember the thread from which this transfer was submitted so that it can | |
362 // be marked complete there. | |
363 task_runner_ = base::ThreadTaskRunnerHandle::Get(); | |
364 // GetClaimedInterfaceForEndpoint may return nullptr. libusb_submit_transfer | |
365 // will fail if it requires an interface we didn't claim. | |
366 claimed_interface_ = device_handle->GetClaimedInterfaceForEndpoint( | |
367 platform_transfer_->endpoint); | |
368 platform_transfer_->dev_handle = device_handle_->handle_; | |
369 | |
370 const int rv = libusb_submit_transfer(platform_transfer_); | 387 const int rv = libusb_submit_transfer(platform_transfer_); |
371 if (rv == LIBUSB_SUCCESS) { | 388 if (rv != LIBUSB_SUCCESS) { |
372 return true; | |
373 } else { | |
374 USB_LOG(EVENT) << "Failed to submit transfer: " | 389 USB_LOG(EVENT) << "Failed to submit transfer: " |
375 << ConvertPlatformUsbErrorToString(rv); | 390 << ConvertPlatformUsbErrorToString(rv); |
376 Complete(USB_TRANSFER_ERROR, 0); | 391 TransferComplete(USB_TRANSFER_ERROR, 0); |
377 return false; | |
378 } | 392 } |
379 } | 393 } |
380 | 394 |
381 void UsbDeviceHandleImpl::Transfer::Cancel() { | 395 void UsbDeviceHandleImpl::Transfer::Cancel() { |
382 if (!cancelled_) { | 396 if (!cancelled_) { |
383 libusb_cancel_transfer(platform_transfer_); | 397 libusb_cancel_transfer(platform_transfer_); |
384 claimed_interface_ = nullptr; | 398 claimed_interface_ = nullptr; |
385 } | 399 } |
386 cancelled_ = true; | 400 cancelled_ = true; |
387 } | 401 } |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
446 | 460 |
447 case USB_TRANSFER_BULK: | 461 case USB_TRANSFER_BULK: |
448 case USB_TRANSFER_INTERRUPT: | 462 case USB_TRANSFER_INTERRUPT: |
449 break; | 463 break; |
450 | 464 |
451 default: | 465 default: |
452 NOTREACHED() << "Invalid usb transfer type"; | 466 NOTREACHED() << "Invalid usb transfer type"; |
453 break; | 467 break; |
454 } | 468 } |
455 | 469 |
456 Complete(ConvertTransferStatus(platform_transfer_->status), actual_length); | 470 TransferComplete(ConvertTransferStatus(platform_transfer_->status), |
457 } | 471 actual_length); |
458 | |
459 void UsbDeviceHandleImpl::Transfer::Complete(UsbTransferStatus status, | |
460 size_t bytes_transferred) { | |
461 if (callback_task_runner_->RunsTasksOnCurrentThread()) { | |
462 callback_.Run(status, buffer_, bytes_transferred); | |
463 } else { | |
464 callback_task_runner_->PostTask( | |
465 FROM_HERE, base::Bind(callback_, status, buffer_, bytes_transferred)); | |
466 } | |
467 } | 472 } |
468 | 473 |
469 /* static */ | 474 /* static */ |
470 void LIBUSB_CALL UsbDeviceHandleImpl::Transfer::PlatformCallback( | 475 void LIBUSB_CALL UsbDeviceHandleImpl::Transfer::PlatformCallback( |
471 PlatformUsbTransferHandle platform_transfer) { | 476 PlatformUsbTransferHandle platform_transfer) { |
472 scoped_ptr<Transfer> transfer( | 477 Transfer* transfer = |
473 reinterpret_cast<Transfer*>(platform_transfer->user_data)); | 478 reinterpret_cast<Transfer*>(platform_transfer->user_data); |
474 DCHECK(transfer->platform_transfer_ == platform_transfer); | 479 DCHECK(transfer->platform_transfer_ == platform_transfer); |
475 | 480 transfer->ProcessCompletion(); |
476 // Because device_handle_ is a weak pointer it is guaranteed that the callback | |
477 // will be discarded if the handle has been freed. | |
478 Transfer* tmp_transfer = transfer.get(); // base::Passed invalidates transfer | |
479 tmp_transfer->task_runner_->PostTask( | |
480 FROM_HERE, base::Bind(&UsbDeviceHandleImpl::CompleteTransfer, | |
481 tmp_transfer->device_handle_, | |
482 base::Passed(&transfer))); | |
483 } | 481 } |
484 | 482 |
485 UsbDeviceHandleImpl::UsbDeviceHandleImpl(scoped_refptr<UsbContext> context, | 483 void UsbDeviceHandleImpl::Transfer::TransferComplete(UsbTransferStatus status, |
486 scoped_refptr<UsbDeviceImpl> device, | 484 size_t bytes_transferred) { |
487 PlatformUsbDeviceHandle handle) | 485 task_runner_->PostTask( |
488 : device_(device), | 486 FROM_HERE, |
489 handle_(handle), | 487 base::Bind(&UsbDeviceHandleImpl::TransferComplete, device_handle_, |
490 context_(context), | 488 base::Owned(this), |
491 task_runner_(base::ThreadTaskRunnerHandle::Get()), | 489 base::Bind(callback_, status, buffer_, bytes_transferred))); |
492 weak_factory_(this) { | |
493 DCHECK(handle) << "Cannot create device with NULL handle."; | |
494 } | |
495 | |
496 UsbDeviceHandleImpl::~UsbDeviceHandleImpl() { | |
497 DCHECK(thread_checker_.CalledOnValidThread()); | |
498 | |
499 libusb_close(handle_); | |
500 handle_ = NULL; | |
501 } | 490 } |
502 | 491 |
503 scoped_refptr<UsbDevice> UsbDeviceHandleImpl::GetDevice() const { | 492 scoped_refptr<UsbDevice> UsbDeviceHandleImpl::GetDevice() const { |
504 return device_; | 493 return device_; |
505 } | 494 } |
506 | 495 |
507 void UsbDeviceHandleImpl::Close() { | 496 void UsbDeviceHandleImpl::Close() { |
508 DCHECK(thread_checker_.CalledOnValidThread()); | 497 DCHECK(thread_checker_.CalledOnValidThread()); |
509 if (device_) | 498 if (device_) |
510 device_->Close(this); | 499 device_->Close(this); |
511 } | 500 } |
512 | 501 |
513 bool UsbDeviceHandleImpl::SetConfiguration(int configuration_value) { | 502 void UsbDeviceHandleImpl::SetConfiguration(int configuration_value, |
| 503 const ResultCallback& callback) { |
514 DCHECK(thread_checker_.CalledOnValidThread()); | 504 DCHECK(thread_checker_.CalledOnValidThread()); |
515 if (!device_) { | 505 if (!device_) { |
516 return false; | 506 callback.Run(false); |
| 507 return; |
517 } | 508 } |
518 | 509 |
519 for (Transfer* transfer : transfers_) { | 510 for (Transfer* transfer : transfers_) { |
520 transfer->Cancel(); | 511 transfer->Cancel(); |
521 } | 512 } |
522 claimed_interfaces_.clear(); | 513 claimed_interfaces_.clear(); |
523 | 514 |
524 int rv = libusb_set_configuration(handle_, configuration_value); | 515 blocking_task_runner_->PostTask( |
525 if (rv == LIBUSB_SUCCESS) { | 516 FROM_HERE, |
526 device_->RefreshConfiguration(); | 517 base::Bind(&UsbDeviceHandleImpl::SetConfigurationOnBlockingThread, this, |
527 RefreshEndpointMap(); | 518 handle_, configuration_value, callback)); |
528 } else { | |
529 USB_LOG(EVENT) << "Failed to set configuration " << configuration_value | |
530 << ": " << ConvertPlatformUsbErrorToString(rv); | |
531 } | |
532 return rv == LIBUSB_SUCCESS; | |
533 } | 519 } |
534 | 520 |
535 bool UsbDeviceHandleImpl::ClaimInterface(const int interface_number) { | 521 void UsbDeviceHandleImpl::ClaimInterface(int interface_number, |
| 522 const ResultCallback& callback) { |
| 523 DCHECK(thread_checker_.CalledOnValidThread()); |
| 524 if (!device_) { |
| 525 callback.Run(false); |
| 526 return; |
| 527 } |
| 528 if (ContainsKey(claimed_interfaces_, interface_number)) { |
| 529 callback.Run(true); |
| 530 return; |
| 531 } |
| 532 |
| 533 blocking_task_runner_->PostTask( |
| 534 FROM_HERE, |
| 535 base::Bind(&UsbDeviceHandleImpl::ClaimInterfaceOnBlockingThread, this, |
| 536 handle_, interface_number, callback)); |
| 537 } |
| 538 |
| 539 bool UsbDeviceHandleImpl::ReleaseInterface(int interface_number) { |
536 DCHECK(thread_checker_.CalledOnValidThread()); | 540 DCHECK(thread_checker_.CalledOnValidThread()); |
537 if (!device_) | 541 if (!device_) |
538 return false; | 542 return false; |
539 if (ContainsKey(claimed_interfaces_, interface_number)) | |
540 return true; | |
541 | |
542 scoped_refptr<InterfaceClaimer> claimer = | |
543 new InterfaceClaimer(this, interface_number); | |
544 | |
545 if (claimer->Claim()) { | |
546 claimed_interfaces_[interface_number] = claimer; | |
547 RefreshEndpointMap(); | |
548 return true; | |
549 } | |
550 return false; | |
551 } | |
552 | |
553 bool UsbDeviceHandleImpl::ReleaseInterface(const int interface_number) { | |
554 DCHECK(thread_checker_.CalledOnValidThread()); | |
555 if (!device_) | |
556 return false; | |
557 if (!ContainsKey(claimed_interfaces_, interface_number)) | 543 if (!ContainsKey(claimed_interfaces_, interface_number)) |
558 return false; | 544 return false; |
559 | 545 |
560 // Cancel all the transfers on that interface. | 546 // Cancel all the transfers on that interface. |
561 InterfaceClaimer* interface_claimer = | 547 InterfaceClaimer* interface_claimer = |
562 claimed_interfaces_[interface_number].get(); | 548 claimed_interfaces_[interface_number].get(); |
563 for (Transfer* transfer : transfers_) { | 549 for (Transfer* transfer : transfers_) { |
564 if (transfer->claimed_interface() == interface_claimer) { | 550 if (transfer->claimed_interface() == interface_claimer) { |
565 transfer->Cancel(); | 551 transfer->Cancel(); |
566 } | 552 } |
567 } | 553 } |
568 claimed_interfaces_.erase(interface_number); | 554 claimed_interfaces_.erase(interface_number); |
569 | 555 |
570 RefreshEndpointMap(); | 556 RefreshEndpointMap(); |
571 return true; | 557 return true; |
572 } | 558 } |
573 | 559 |
574 bool UsbDeviceHandleImpl::SetInterfaceAlternateSetting( | 560 void UsbDeviceHandleImpl::SetInterfaceAlternateSetting( |
575 const int interface_number, | 561 int interface_number, |
576 const int alternate_setting) { | 562 int alternate_setting, |
577 DCHECK(thread_checker_.CalledOnValidThread()); | 563 const ResultCallback& callback) { |
578 if (!device_) | 564 DCHECK(thread_checker_.CalledOnValidThread()); |
579 return false; | 565 if (!device_ || !ContainsKey(claimed_interfaces_, interface_number)) { |
580 if (!ContainsKey(claimed_interfaces_, interface_number)) | 566 callback.Run(false); |
581 return false; | 567 return; |
582 const int rv = libusb_set_interface_alt_setting( | 568 } |
583 handle_, interface_number, alternate_setting); | 569 |
584 if (rv == LIBUSB_SUCCESS) { | 570 blocking_task_runner_->PostTask( |
585 claimed_interfaces_[interface_number]->set_alternate_setting( | 571 FROM_HERE, |
586 alternate_setting); | 572 base::Bind( |
587 RefreshEndpointMap(); | 573 &UsbDeviceHandleImpl::SetInterfaceAlternateSettingOnBlockingThread, |
588 } else { | 574 this, handle_, interface_number, alternate_setting, callback)); |
589 USB_LOG(EVENT) << "Failed to set interface " << interface_number | 575 } |
590 << " to alternate setting " << alternate_setting << ": " | 576 |
591 << ConvertPlatformUsbErrorToString(rv); | 577 void UsbDeviceHandleImpl::ResetDevice(const ResultCallback& callback) { |
592 } | 578 DCHECK(thread_checker_.CalledOnValidThread()); |
593 return rv == LIBUSB_SUCCESS; | 579 if (!device_) { |
594 } | 580 callback.Run(false); |
595 | 581 return; |
596 bool UsbDeviceHandleImpl::ResetDevice() { | 582 } |
597 DCHECK(thread_checker_.CalledOnValidThread()); | 583 |
598 if (!device_) | 584 blocking_task_runner_->PostTask( |
599 return false; | 585 FROM_HERE, base::Bind(&UsbDeviceHandleImpl::ResetDeviceOnBlockingThread, |
600 | 586 this, handle_, callback)); |
601 const int rv = libusb_reset_device(handle_); | |
602 if (rv != LIBUSB_SUCCESS) { | |
603 USB_LOG(EVENT) << "Failed to reset device: " | |
604 << ConvertPlatformUsbErrorToString(rv); | |
605 } | |
606 return rv == LIBUSB_SUCCESS; | |
607 } | |
608 | |
609 bool UsbDeviceHandleImpl::GetStringDescriptor(uint8 string_id, | |
610 base::string16* string) { | |
611 if (!GetSupportedLanguages()) { | |
612 return false; | |
613 } | |
614 | |
615 std::map<uint8, base::string16>::const_iterator it = strings_.find(string_id); | |
616 if (it != strings_.end()) { | |
617 *string = it->second; | |
618 return true; | |
619 } | |
620 | |
621 for (size_t i = 0; i < languages_.size(); ++i) { | |
622 // Get the string using language ID. | |
623 uint16 language_id = languages_[i]; | |
624 // The 1-byte length field limits the descriptor to 256-bytes (128 char16s). | |
625 base::char16 text[128]; | |
626 int size = | |
627 libusb_get_string_descriptor(handle_, | |
628 string_id, | |
629 language_id, | |
630 reinterpret_cast<unsigned char*>(&text[0]), | |
631 sizeof(text)); | |
632 if (size < 0) { | |
633 USB_LOG(EVENT) << "Failed to get string descriptor " << string_id | |
634 << " (langid " << language_id | |
635 << "): " << ConvertPlatformUsbErrorToString(size); | |
636 continue; | |
637 } else if (size < 2) { | |
638 USB_LOG(EVENT) << "String descriptor " << string_id << " (langid " | |
639 << language_id << ") has no header."; | |
640 continue; | |
641 // The first 2 bytes of the descriptor are the total length and type tag. | |
642 } else if ((text[0] & 0xff) != size) { | |
643 USB_LOG(EVENT) << "String descriptor " << string_id << " (langid " | |
644 << language_id << ") size mismatch: " << (text[0] & 0xff) | |
645 << " != " << size; | |
646 continue; | |
647 } else if ((text[0] >> 8) != LIBUSB_DT_STRING) { | |
648 USB_LOG(EVENT) << "String descriptor " << string_id << " (langid " | |
649 << language_id << ") is not a string descriptor."; | |
650 continue; | |
651 } | |
652 | |
653 *string = base::string16(text + 1, (size - 2) / 2); | |
654 strings_[string_id] = *string; | |
655 return true; | |
656 } | |
657 | |
658 return false; | |
659 } | 587 } |
660 | 588 |
661 void UsbDeviceHandleImpl::ControlTransfer(UsbEndpointDirection direction, | 589 void UsbDeviceHandleImpl::ControlTransfer(UsbEndpointDirection direction, |
662 TransferRequestType request_type, | 590 TransferRequestType request_type, |
663 TransferRecipient recipient, | 591 TransferRecipient recipient, |
664 uint8 request, | 592 uint8 request, |
665 uint16 value, | 593 uint16 value, |
666 uint16 index, | 594 uint16 index, |
667 net::IOBuffer* buffer, | 595 scoped_refptr<net::IOBuffer> buffer, |
668 size_t length, | 596 size_t length, |
669 unsigned int timeout, | 597 unsigned int timeout, |
670 const UsbTransferCallback& callback) { | 598 const TransferCallback& callback) { |
| 599 if (task_runner_->BelongsToCurrentThread()) { |
| 600 ControlTransferInternal(direction, request_type, recipient, request, value, |
| 601 index, buffer, length, timeout, task_runner_, |
| 602 callback); |
| 603 } else { |
| 604 task_runner_->PostTask( |
| 605 FROM_HERE, base::Bind(&UsbDeviceHandleImpl::ControlTransferInternal, |
| 606 this, direction, request_type, recipient, request, |
| 607 value, index, buffer, length, timeout, |
| 608 base::ThreadTaskRunnerHandle::Get(), callback)); |
| 609 } |
| 610 } |
| 611 |
| 612 void UsbDeviceHandleImpl::BulkTransfer(UsbEndpointDirection direction, |
| 613 uint8 endpoint, |
| 614 scoped_refptr<net::IOBuffer> buffer, |
| 615 size_t length, |
| 616 unsigned int timeout, |
| 617 const TransferCallback& callback) { |
| 618 if (task_runner_->BelongsToCurrentThread()) { |
| 619 BulkTransferInternal(direction, endpoint, buffer, length, timeout, |
| 620 task_runner_, callback); |
| 621 } else { |
| 622 task_runner_->PostTask( |
| 623 FROM_HERE, base::Bind(&UsbDeviceHandleImpl::BulkTransferInternal, this, |
| 624 direction, endpoint, buffer, length, timeout, |
| 625 base::ThreadTaskRunnerHandle::Get(), callback)); |
| 626 } |
| 627 } |
| 628 |
| 629 void UsbDeviceHandleImpl::InterruptTransfer(UsbEndpointDirection direction, |
| 630 uint8 endpoint, |
| 631 scoped_refptr<net::IOBuffer> buffer, |
| 632 size_t length, |
| 633 unsigned int timeout, |
| 634 const TransferCallback& callback) { |
| 635 if (task_runner_->BelongsToCurrentThread()) { |
| 636 InterruptTransferInternal(direction, endpoint, buffer, length, timeout, |
| 637 task_runner_, callback); |
| 638 } else { |
| 639 task_runner_->PostTask( |
| 640 FROM_HERE, |
| 641 base::Bind(&UsbDeviceHandleImpl::InterruptTransferInternal, this, |
| 642 direction, endpoint, buffer, length, timeout, |
| 643 base::ThreadTaskRunnerHandle::Get(), callback)); |
| 644 } |
| 645 } |
| 646 |
| 647 void UsbDeviceHandleImpl::IsochronousTransfer( |
| 648 UsbEndpointDirection direction, |
| 649 uint8 endpoint, |
| 650 scoped_refptr<net::IOBuffer> buffer, |
| 651 size_t length, |
| 652 unsigned int packets, |
| 653 unsigned int packet_length, |
| 654 unsigned int timeout, |
| 655 const TransferCallback& callback) { |
| 656 if (task_runner_->BelongsToCurrentThread()) { |
| 657 IsochronousTransferInternal(direction, endpoint, buffer, length, packets, |
| 658 packet_length, timeout, task_runner_, callback); |
| 659 } else { |
| 660 task_runner_->PostTask( |
| 661 FROM_HERE, |
| 662 base::Bind(&UsbDeviceHandleImpl::IsochronousTransferInternal, this, |
| 663 direction, endpoint, buffer, length, packets, packet_length, |
| 664 timeout, base::ThreadTaskRunnerHandle::Get(), callback)); |
| 665 } |
| 666 } |
| 667 |
| 668 UsbDeviceHandleImpl::UsbDeviceHandleImpl( |
| 669 scoped_refptr<UsbContext> context, |
| 670 scoped_refptr<UsbDeviceImpl> device, |
| 671 PlatformUsbDeviceHandle handle, |
| 672 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) |
| 673 : device_(device), |
| 674 handle_(handle), |
| 675 context_(context), |
| 676 task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 677 blocking_task_runner_(blocking_task_runner) { |
| 678 DCHECK(handle) << "Cannot create device with NULL handle."; |
| 679 } |
| 680 |
| 681 UsbDeviceHandleImpl::~UsbDeviceHandleImpl() { |
| 682 DCHECK(thread_checker_.CalledOnValidThread()); |
| 683 |
| 684 libusb_close(handle_); |
| 685 handle_ = NULL; |
| 686 } |
| 687 |
| 688 void UsbDeviceHandleImpl::SetConfigurationOnBlockingThread( |
| 689 PlatformUsbDeviceHandle handle, |
| 690 int configuration_value, |
| 691 const ResultCallback& callback) { |
| 692 int rv = libusb_set_configuration(handle_, configuration_value); |
| 693 if (rv != LIBUSB_SUCCESS) { |
| 694 USB_LOG(EVENT) << "Failed to set configuration " << configuration_value |
| 695 << ": " << ConvertPlatformUsbErrorToString(rv); |
| 696 } |
| 697 task_runner_->PostTask( |
| 698 FROM_HERE, base::Bind(&UsbDeviceHandleImpl::SetConfigurationComplete, |
| 699 this, rv == LIBUSB_SUCCESS, callback)); |
| 700 } |
| 701 |
| 702 void UsbDeviceHandleImpl::SetConfigurationComplete( |
| 703 bool success, |
| 704 const ResultCallback& callback) { |
| 705 if (success) { |
| 706 device_->RefreshConfiguration(); |
| 707 RefreshEndpointMap(); |
| 708 } |
| 709 callback.Run(success); |
| 710 } |
| 711 |
| 712 void UsbDeviceHandleImpl::ClaimInterfaceOnBlockingThread( |
| 713 PlatformUsbDeviceHandle handle, |
| 714 int interface_number, |
| 715 const ResultCallback& callback) { |
| 716 int rv = libusb_claim_interface(handle, interface_number); |
| 717 if (rv != LIBUSB_SUCCESS) { |
| 718 VLOG(1) << "Failed to claim interface: " |
| 719 << ConvertPlatformUsbErrorToString(rv); |
| 720 } |
| 721 task_runner_->PostTask( |
| 722 FROM_HERE, base::Bind(&UsbDeviceHandleImpl::ClaimInterfaceComplete, this, |
| 723 interface_number, rv == LIBUSB_SUCCESS, callback)); |
| 724 } |
| 725 |
| 726 void UsbDeviceHandleImpl::ClaimInterfaceComplete( |
| 727 int interface_number, |
| 728 bool success, |
| 729 const ResultCallback& callback) { |
| 730 if (success) { |
| 731 claimed_interfaces_[interface_number] = |
| 732 new InterfaceClaimer(this, interface_number); |
| 733 RefreshEndpointMap(); |
| 734 } |
| 735 callback.Run(success); |
| 736 } |
| 737 |
| 738 void UsbDeviceHandleImpl::SetInterfaceAlternateSettingOnBlockingThread( |
| 739 PlatformUsbDeviceHandle handle, |
| 740 int interface_number, |
| 741 int alternate_setting, |
| 742 const ResultCallback& callback) { |
| 743 int rv = libusb_set_interface_alt_setting(handle, interface_number, |
| 744 alternate_setting); |
| 745 if (rv != LIBUSB_SUCCESS) { |
| 746 USB_LOG(EVENT) << "Failed to set interface " << interface_number |
| 747 << " to alternate setting " << alternate_setting << ": " |
| 748 << ConvertPlatformUsbErrorToString(rv); |
| 749 } |
| 750 task_runner_->PostTask( |
| 751 FROM_HERE, |
| 752 base::Bind(&UsbDeviceHandleImpl::SetInterfaceAlternateSettingComplete, |
| 753 this, interface_number, alternate_setting, |
| 754 rv == LIBUSB_SUCCESS, callback)); |
| 755 } |
| 756 |
| 757 void UsbDeviceHandleImpl::SetInterfaceAlternateSettingComplete( |
| 758 int interface_number, |
| 759 int alternate_setting, |
| 760 bool success, |
| 761 const ResultCallback& callback) { |
| 762 if (success) { |
| 763 claimed_interfaces_[interface_number]->set_alternate_setting( |
| 764 alternate_setting); |
| 765 RefreshEndpointMap(); |
| 766 } |
| 767 callback.Run(success); |
| 768 } |
| 769 |
| 770 void UsbDeviceHandleImpl::ResetDeviceOnBlockingThread( |
| 771 PlatformUsbDeviceHandle handle, |
| 772 const ResultCallback& callback) { |
| 773 int rv = libusb_reset_device(handle); |
| 774 if (rv != LIBUSB_SUCCESS) { |
| 775 USB_LOG(EVENT) << "Failed to reset device: " |
| 776 << ConvertPlatformUsbErrorToString(rv); |
| 777 } |
| 778 task_runner_->PostTask( |
| 779 FROM_HERE, base::Bind(&UsbDeviceHandleImpl::ResetDeviceComplete, this, |
| 780 rv == LIBUSB_SUCCESS, callback)); |
| 781 } |
| 782 |
| 783 void UsbDeviceHandleImpl::ResetDeviceComplete(bool success, |
| 784 const ResultCallback& callback) { |
| 785 callback.Run(success); |
| 786 } |
| 787 |
| 788 void UsbDeviceHandleImpl::RefreshEndpointMap() { |
| 789 DCHECK(thread_checker_.CalledOnValidThread()); |
| 790 endpoint_map_.clear(); |
| 791 const UsbConfigDescriptor* config = device_->GetConfiguration(); |
| 792 if (config) { |
| 793 for (const auto& map_entry : claimed_interfaces_) { |
| 794 int interface_number = map_entry.first; |
| 795 const scoped_refptr<InterfaceClaimer>& claimed_iface = map_entry.second; |
| 796 |
| 797 for (const UsbInterfaceDescriptor& iface : config->interfaces) { |
| 798 if (iface.interface_number == interface_number && |
| 799 iface.alternate_setting == claimed_iface->alternate_setting()) { |
| 800 for (const UsbEndpointDescriptor& endpoint : iface.endpoints) { |
| 801 endpoint_map_[endpoint.address] = interface_number; |
| 802 } |
| 803 break; |
| 804 } |
| 805 } |
| 806 } |
| 807 } |
| 808 } |
| 809 |
| 810 scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer> |
| 811 UsbDeviceHandleImpl::GetClaimedInterfaceForEndpoint(unsigned char endpoint) { |
| 812 if (ContainsKey(endpoint_map_, endpoint)) |
| 813 return claimed_interfaces_[endpoint_map_[endpoint]]; |
| 814 return NULL; |
| 815 } |
| 816 |
| 817 void UsbDeviceHandleImpl::ControlTransferInternal( |
| 818 UsbEndpointDirection direction, |
| 819 TransferRequestType request_type, |
| 820 TransferRecipient recipient, |
| 821 uint8 request, |
| 822 uint16 value, |
| 823 uint16 index, |
| 824 scoped_refptr<net::IOBuffer> buffer, |
| 825 size_t length, |
| 826 unsigned int timeout, |
| 827 scoped_refptr<base::TaskRunner> callback_task_runner, |
| 828 const TransferCallback& callback) { |
| 829 DCHECK(thread_checker_.CalledOnValidThread()); |
| 830 |
| 831 if (!device_) { |
| 832 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); |
| 833 return; |
| 834 } |
| 835 |
671 if (length > UINT16_MAX) { | 836 if (length > UINT16_MAX) { |
672 USB_LOG(USER) << "Transfer too long."; | 837 USB_LOG(USER) << "Transfer too long."; |
673 callback.Run(USB_TRANSFER_ERROR, buffer, 0); | 838 callback.Run(USB_TRANSFER_ERROR, buffer, 0); |
674 return; | 839 return; |
675 } | 840 } |
676 | 841 |
677 const size_t resized_length = LIBUSB_CONTROL_SETUP_SIZE + length; | 842 const size_t resized_length = LIBUSB_CONTROL_SETUP_SIZE + length; |
678 scoped_refptr<net::IOBuffer> resized_buffer( | 843 scoped_refptr<net::IOBuffer> resized_buffer( |
679 new net::IOBufferWithSize(static_cast<int>(resized_length))); | 844 new net::IOBufferWithSize(static_cast<int>(resized_length))); |
680 if (!resized_buffer.get()) { | 845 if (!resized_buffer.get()) { |
681 callback.Run(USB_TRANSFER_ERROR, buffer, 0); | 846 callback.Run(USB_TRANSFER_ERROR, buffer, 0); |
682 return; | 847 return; |
683 } | 848 } |
684 memcpy(resized_buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, buffer->data(), | 849 memcpy(resized_buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, buffer->data(), |
685 length); | 850 length); |
686 | 851 |
687 scoped_ptr<Transfer> transfer = Transfer::CreateControlTransfer( | 852 scoped_ptr<Transfer> transfer = Transfer::CreateControlTransfer( |
688 CreateRequestType(direction, request_type, recipient), request, value, | 853 this, CreateRequestType(direction, request_type, recipient), request, |
689 index, static_cast<uint16>(length), resized_buffer, timeout, callback); | 854 value, index, static_cast<uint16>(length), resized_buffer, timeout, |
| 855 callback_task_runner, callback); |
690 if (!transfer) { | 856 if (!transfer) { |
691 callback.Run(USB_TRANSFER_ERROR, buffer, 0); | 857 callback.Run(USB_TRANSFER_ERROR, buffer, 0); |
692 return; | 858 return; |
693 } | 859 } |
694 | 860 |
695 PostOrSubmitTransfer(transfer.Pass()); | 861 SubmitTransfer(transfer.Pass()); |
696 } | 862 } |
697 | 863 |
698 void UsbDeviceHandleImpl::BulkTransfer(const UsbEndpointDirection direction, | 864 void UsbDeviceHandleImpl::BulkTransferInternal( |
699 const uint8 endpoint, | 865 const UsbEndpointDirection direction, |
700 net::IOBuffer* buffer, | 866 const uint8 endpoint, |
701 const size_t length, | 867 scoped_refptr<net::IOBuffer> buffer, |
702 const unsigned int timeout, | 868 const size_t length, |
703 const UsbTransferCallback& callback) { | 869 const unsigned int timeout, |
| 870 scoped_refptr<base::TaskRunner> callback_task_runner, |
| 871 const TransferCallback& callback) { |
| 872 DCHECK(thread_checker_.CalledOnValidThread()); |
| 873 |
| 874 if (!device_) { |
| 875 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); |
| 876 return; |
| 877 } |
| 878 |
704 if (length > INT_MAX) { | 879 if (length > INT_MAX) { |
705 USB_LOG(USER) << "Transfer too long."; | 880 USB_LOG(USER) << "Transfer too long."; |
706 callback.Run(USB_TRANSFER_ERROR, buffer, 0); | 881 callback.Run(USB_TRANSFER_ERROR, buffer, 0); |
707 return; | 882 return; |
708 } | 883 } |
709 | 884 |
710 scoped_ptr<Transfer> transfer = Transfer::CreateBulkTransfer( | 885 scoped_ptr<Transfer> transfer = Transfer::CreateBulkTransfer( |
711 ConvertTransferDirection(direction) | endpoint, buffer, | 886 this, ConvertTransferDirection(direction) | endpoint, buffer, |
712 static_cast<int>(length), timeout, callback); | 887 static_cast<int>(length), timeout, callback_task_runner, callback); |
713 | 888 |
714 PostOrSubmitTransfer(transfer.Pass()); | 889 SubmitTransfer(transfer.Pass()); |
715 } | 890 } |
716 | 891 |
717 void UsbDeviceHandleImpl::InterruptTransfer( | 892 void UsbDeviceHandleImpl::InterruptTransferInternal( |
718 UsbEndpointDirection direction, | 893 UsbEndpointDirection direction, |
719 uint8 endpoint, | 894 uint8 endpoint, |
720 net::IOBuffer* buffer, | 895 scoped_refptr<net::IOBuffer> buffer, |
721 size_t length, | 896 size_t length, |
722 unsigned int timeout, | 897 unsigned int timeout, |
723 const UsbTransferCallback& callback) { | 898 scoped_refptr<base::TaskRunner> callback_task_runner, |
| 899 const TransferCallback& callback) { |
| 900 DCHECK(thread_checker_.CalledOnValidThread()); |
| 901 |
| 902 if (!device_) { |
| 903 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); |
| 904 return; |
| 905 } |
| 906 |
724 if (length > INT_MAX) { | 907 if (length > INT_MAX) { |
725 USB_LOG(USER) << "Transfer too long."; | 908 USB_LOG(USER) << "Transfer too long."; |
726 callback.Run(USB_TRANSFER_ERROR, buffer, 0); | 909 callback.Run(USB_TRANSFER_ERROR, buffer, 0); |
727 return; | 910 return; |
728 } | 911 } |
729 | 912 |
730 scoped_ptr<Transfer> transfer = Transfer::CreateInterruptTransfer( | 913 scoped_ptr<Transfer> transfer = Transfer::CreateInterruptTransfer( |
731 ConvertTransferDirection(direction) | endpoint, buffer, | 914 this, ConvertTransferDirection(direction) | endpoint, buffer, |
732 static_cast<int>(length), timeout, callback); | 915 static_cast<int>(length), timeout, callback_task_runner, callback); |
733 | 916 |
734 PostOrSubmitTransfer(transfer.Pass()); | 917 SubmitTransfer(transfer.Pass()); |
735 } | 918 } |
736 | 919 |
737 void UsbDeviceHandleImpl::IsochronousTransfer( | 920 void UsbDeviceHandleImpl::IsochronousTransferInternal( |
738 const UsbEndpointDirection direction, | 921 const UsbEndpointDirection direction, |
739 const uint8 endpoint, | 922 uint8 endpoint, |
740 net::IOBuffer* buffer, | 923 scoped_refptr<net::IOBuffer> buffer, |
741 const size_t length, | 924 size_t length, |
742 const unsigned int packets, | 925 unsigned int packets, |
743 const unsigned int packet_length, | 926 unsigned int packet_length, |
744 const unsigned int timeout, | 927 unsigned int timeout, |
745 const UsbTransferCallback& callback) { | 928 scoped_refptr<base::TaskRunner> callback_task_runner, |
| 929 const TransferCallback& callback) { |
| 930 DCHECK(thread_checker_.CalledOnValidThread()); |
| 931 |
| 932 if (!device_) { |
| 933 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); |
| 934 return; |
| 935 } |
| 936 |
746 if (length > INT_MAX) { | 937 if (length > INT_MAX) { |
747 USB_LOG(USER) << "Transfer too long."; | 938 USB_LOG(USER) << "Transfer too long."; |
748 callback.Run(USB_TRANSFER_ERROR, buffer, 0); | 939 callback.Run(USB_TRANSFER_ERROR, buffer, 0); |
749 return; | 940 return; |
750 } | 941 } |
751 | 942 |
752 scoped_ptr<Transfer> transfer = Transfer::CreateIsochronousTransfer( | 943 scoped_ptr<Transfer> transfer = Transfer::CreateIsochronousTransfer( |
753 ConvertTransferDirection(direction) | endpoint, buffer, | 944 this, ConvertTransferDirection(direction) | endpoint, buffer, |
754 static_cast<int>(length), packets, packet_length, timeout, callback); | 945 static_cast<int>(length), packets, packet_length, timeout, |
| 946 callback_task_runner, callback); |
755 | 947 |
756 PostOrSubmitTransfer(transfer.Pass()); | 948 SubmitTransfer(transfer.Pass()); |
757 } | |
758 | |
759 void UsbDeviceHandleImpl::RefreshEndpointMap() { | |
760 DCHECK(thread_checker_.CalledOnValidThread()); | |
761 endpoint_map_.clear(); | |
762 const UsbConfigDescriptor* config = device_->GetConfiguration(); | |
763 if (config) { | |
764 for (const auto& map_entry : claimed_interfaces_) { | |
765 int interface_number = map_entry.first; | |
766 const scoped_refptr<InterfaceClaimer>& claimed_iface = map_entry.second; | |
767 | |
768 for (const UsbInterfaceDescriptor& iface : config->interfaces) { | |
769 if (iface.interface_number == interface_number && | |
770 iface.alternate_setting == claimed_iface->alternate_setting()) { | |
771 for (const UsbEndpointDescriptor& endpoint : iface.endpoints) { | |
772 endpoint_map_[endpoint.address] = interface_number; | |
773 } | |
774 break; | |
775 } | |
776 } | |
777 } | |
778 } | |
779 } | |
780 | |
781 scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer> | |
782 UsbDeviceHandleImpl::GetClaimedInterfaceForEndpoint(unsigned char endpoint) { | |
783 if (ContainsKey(endpoint_map_, endpoint)) | |
784 return claimed_interfaces_[endpoint_map_[endpoint]]; | |
785 return NULL; | |
786 } | |
787 | |
788 void UsbDeviceHandleImpl::PostOrSubmitTransfer(scoped_ptr<Transfer> transfer) { | |
789 if (task_runner_->RunsTasksOnCurrentThread()) { | |
790 SubmitTransfer(transfer.Pass()); | |
791 } else { | |
792 task_runner_->PostTask( | |
793 FROM_HERE, base::Bind(&UsbDeviceHandleImpl::SubmitTransfer, this, | |
794 base::Passed(&transfer))); | |
795 } | |
796 } | 949 } |
797 | 950 |
798 void UsbDeviceHandleImpl::SubmitTransfer(scoped_ptr<Transfer> transfer) { | 951 void UsbDeviceHandleImpl::SubmitTransfer(scoped_ptr<Transfer> transfer) { |
799 DCHECK(thread_checker_.CalledOnValidThread()); | 952 DCHECK(thread_checker_.CalledOnValidThread()); |
800 | 953 |
801 if (device_) { | 954 // Transfer is owned by libusb until its completion callback is run. This |
802 if (transfer->Submit(weak_factory_.GetWeakPtr())) { | 955 // object holds a weak reference. |
803 // Transfer is now owned by libusb until its completion callback is run. | 956 transfers_.insert(transfer.get()); |
804 // This object holds a weak reference. | 957 blocking_task_runner_->PostTask( |
805 transfers_.insert(transfer.release()); | 958 FROM_HERE, |
806 } | 959 base::Bind(&Transfer::Submit, base::Unretained(transfer.release()))); |
| 960 } |
| 961 |
| 962 void UsbDeviceHandleImpl::TransferComplete(Transfer* transfer, |
| 963 const base::Closure& callback) { |
| 964 DCHECK(thread_checker_.CalledOnValidThread()); |
| 965 DCHECK(ContainsKey(transfers_, transfer)) << "Missing transfer completed"; |
| 966 transfers_.erase(transfer); |
| 967 |
| 968 if (transfer->callback_task_runner()->RunsTasksOnCurrentThread()) { |
| 969 callback.Run(); |
807 } else { | 970 } else { |
808 transfer->Complete(USB_TRANSFER_DISCONNECT, 0); | 971 transfer->callback_task_runner()->PostTask(FROM_HERE, callback); |
809 } | 972 } |
810 } | 973 } |
811 | 974 |
812 void UsbDeviceHandleImpl::CompleteTransfer(scoped_ptr<Transfer> transfer) { | |
813 DCHECK(ContainsKey(transfers_, transfer.get())) | |
814 << "Missing transfer completed"; | |
815 transfers_.erase(transfer.get()); | |
816 transfer->ProcessCompletion(); | |
817 } | |
818 | |
819 bool UsbDeviceHandleImpl::GetSupportedLanguages() { | |
820 if (!languages_.empty()) { | |
821 return true; | |
822 } | |
823 | |
824 // The 1-byte length field limits the descriptor to 256-bytes (128 uint16s). | |
825 uint16 languages[128]; | |
826 int size = libusb_get_string_descriptor( | |
827 handle_, | |
828 0, | |
829 0, | |
830 reinterpret_cast<unsigned char*>(&languages[0]), | |
831 sizeof(languages)); | |
832 if (size < 0) { | |
833 USB_LOG(EVENT) << "Failed to get list of supported languages: " | |
834 << ConvertPlatformUsbErrorToString(size); | |
835 return false; | |
836 } else if (size < 2) { | |
837 USB_LOG(EVENT) << "String descriptor zero has no header."; | |
838 return false; | |
839 // The first 2 bytes of the descriptor are the total length and type tag. | |
840 } else if ((languages[0] & 0xff) != size) { | |
841 USB_LOG(EVENT) << "String descriptor zero size mismatch: " | |
842 << (languages[0] & 0xff) << " != " << size; | |
843 return false; | |
844 } else if ((languages[0] >> 8) != LIBUSB_DT_STRING) { | |
845 USB_LOG(EVENT) << "String descriptor zero is not a string descriptor."; | |
846 return false; | |
847 } | |
848 | |
849 languages_.assign(languages[1], languages[(size - 2) / 2]); | |
850 return true; | |
851 } | |
852 | |
853 void UsbDeviceHandleImpl::InternalClose() { | 975 void UsbDeviceHandleImpl::InternalClose() { |
854 DCHECK(thread_checker_.CalledOnValidThread()); | 976 DCHECK(thread_checker_.CalledOnValidThread()); |
855 if (!device_) | 977 if (!device_) |
856 return; | 978 return; |
857 | 979 |
858 // Cancel all the transfers. | 980 // Cancel all the transfers. |
859 for (Transfer* transfer : transfers_) { | 981 for (Transfer* transfer : transfers_) { |
860 // The callback will be called some time later. | 982 // The callback will be called some time later. |
861 transfer->Cancel(); | 983 transfer->Cancel(); |
862 } | 984 } |
863 | 985 |
864 // Attempt-release all the interfaces. | 986 // Attempt-release all the interfaces. |
865 // It will be retained until the transfer cancellation is finished. | 987 // It will be retained until the transfer cancellation is finished. |
866 claimed_interfaces_.clear(); | 988 claimed_interfaces_.clear(); |
867 | 989 |
868 // Cannot close device handle here. Need to wait for libusb_cancel_transfer to | 990 // Cannot close device handle here. Need to wait for libusb_cancel_transfer to |
869 // finish. | 991 // finish. |
870 device_ = NULL; | 992 device_ = NULL; |
871 } | 993 } |
872 | 994 |
873 } // namespace device | 995 } // namespace device |
OLD | NEW |