Chromium Code Reviews| 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, |
| 168 scoped_refptr<base::SequencedTaskRunner> task_runner, | |
| 167 const UsbTransferCallback& callback); | 169 const UsbTransferCallback& 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, |
| 176 scoped_refptr<base::SequencedTaskRunner> task_runner, | |
| 173 const UsbTransferCallback& callback); | 177 const UsbTransferCallback& 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, |
| 184 scoped_refptr<base::SequencedTaskRunner> task_runner, | |
| 179 const UsbTransferCallback& callback); | 185 const UsbTransferCallback& 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, |
| 194 scoped_refptr<base::SequencedTaskRunner> task_runner, | |
| 187 const UsbTransferCallback& callback); | 195 const UsbTransferCallback& 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 |
| 200 private: | 208 private: |
| 201 Transfer(UsbTransferType transfer_type, | 209 Transfer(scoped_refptr<UsbDeviceHandleImpl> device_handle, |
| 210 scoped_refptr<InterfaceClaimer> claimed_interface, | |
| 211 UsbTransferType transfer_type, | |
| 202 scoped_refptr<net::IOBuffer> buffer, | 212 scoped_refptr<net::IOBuffer> buffer, |
| 203 size_t length, | 213 size_t length, |
| 214 scoped_refptr<base::SequencedTaskRunner> task_runner, | |
| 204 const UsbTransferCallback& callback); | 215 const UsbTransferCallback& callback); |
| 205 | 216 |
| 206 static void LIBUSB_CALL PlatformCallback(PlatformUsbTransferHandle handle); | 217 static void LIBUSB_CALL PlatformCallback(PlatformUsbTransferHandle handle); |
| 207 | 218 |
| 208 UsbTransferType transfer_type_; | 219 UsbTransferType transfer_type_; |
| 209 base::WeakPtr<UsbDeviceHandleImpl> device_handle_; | 220 scoped_refptr<UsbDeviceHandleImpl> device_handle_; |
| 210 PlatformUsbTransferHandle platform_transfer_; | 221 PlatformUsbTransferHandle platform_transfer_; |
| 211 scoped_refptr<net::IOBuffer> buffer_; | 222 scoped_refptr<net::IOBuffer> buffer_; |
| 212 scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer> claimed_interface_; | 223 scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer> claimed_interface_; |
| 213 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | |
| 214 size_t length_; | 224 size_t length_; |
| 215 bool cancelled_; | 225 bool cancelled_; |
| 226 scoped_refptr<base::SequencedTaskRunner> task_runner_; | |
| 216 UsbTransferCallback callback_; | 227 UsbTransferCallback callback_; |
| 217 scoped_refptr<base::SingleThreadTaskRunner> callback_task_runner_; | |
| 218 }; | 228 }; |
| 219 | 229 |
| 220 // static | 230 // static |
| 221 scoped_ptr<UsbDeviceHandleImpl::Transfer> | 231 scoped_ptr<UsbDeviceHandleImpl::Transfer> |
| 222 UsbDeviceHandleImpl::Transfer::CreateControlTransfer( | 232 UsbDeviceHandleImpl::Transfer::CreateControlTransfer( |
| 233 scoped_refptr<UsbDeviceHandleImpl> device_handle, | |
| 223 uint8 type, | 234 uint8 type, |
| 224 uint8 request, | 235 uint8 request, |
| 225 uint16 value, | 236 uint16 value, |
| 226 uint16 index, | 237 uint16 index, |
| 227 uint16 length, | 238 uint16 length, |
| 228 scoped_refptr<net::IOBuffer> buffer, | 239 scoped_refptr<net::IOBuffer> buffer, |
| 229 unsigned int timeout, | 240 unsigned int timeout, |
| 241 scoped_refptr<base::SequencedTaskRunner> task_runner, | |
| 230 const UsbTransferCallback& callback) { | 242 const UsbTransferCallback& callback) { |
| 231 scoped_ptr<Transfer> transfer(new Transfer(USB_TRANSFER_CONTROL, buffer, | 243 scoped_ptr<Transfer> transfer( |
| 232 length + LIBUSB_CONTROL_SETUP_SIZE, | 244 new Transfer(device_handle, nullptr, USB_TRANSFER_CONTROL, buffer, |
| 233 callback)); | 245 length + LIBUSB_CONTROL_SETUP_SIZE, task_runner, callback)); |
| 234 | 246 |
| 235 transfer->platform_transfer_ = libusb_alloc_transfer(0); | 247 transfer->platform_transfer_ = libusb_alloc_transfer(0); |
| 236 if (!transfer->platform_transfer_) { | 248 if (!transfer->platform_transfer_) { |
| 237 USB_LOG(ERROR) << "Failed to allocate control transfer."; | 249 USB_LOG(ERROR) << "Failed to allocate control transfer."; |
| 238 return nullptr; | 250 return nullptr; |
| 239 } | 251 } |
| 240 | 252 |
| 241 libusb_fill_control_setup(reinterpret_cast<uint8*>(buffer->data()), type, | 253 libusb_fill_control_setup(reinterpret_cast<uint8*>(buffer->data()), type, |
| 242 request, value, index, length); | 254 request, value, index, length); |
| 243 libusb_fill_control_transfer(transfer->platform_transfer_, | 255 libusb_fill_control_transfer(transfer->platform_transfer_, |
| 244 nullptr, /* filled in by Submit() */ | 256 device_handle->handle_, |
| 245 reinterpret_cast<uint8*>(buffer->data()), | 257 reinterpret_cast<uint8*>(buffer->data()), |
| 246 &UsbDeviceHandleImpl::Transfer::PlatformCallback, | 258 &UsbDeviceHandleImpl::Transfer::PlatformCallback, |
| 247 transfer.get(), timeout); | 259 transfer.get(), timeout); |
| 248 | 260 |
| 249 return transfer.Pass(); | 261 return transfer.Pass(); |
| 250 } | 262 } |
| 251 | 263 |
| 252 // static | 264 // static |
| 253 scoped_ptr<UsbDeviceHandleImpl::Transfer> | 265 scoped_ptr<UsbDeviceHandleImpl::Transfer> |
| 254 UsbDeviceHandleImpl::Transfer::CreateBulkTransfer( | 266 UsbDeviceHandleImpl::Transfer::CreateBulkTransfer( |
| 267 scoped_refptr<UsbDeviceHandleImpl> device_handle, | |
| 255 uint8 endpoint, | 268 uint8 endpoint, |
| 256 scoped_refptr<net::IOBuffer> buffer, | 269 scoped_refptr<net::IOBuffer> buffer, |
| 257 int length, | 270 int length, |
| 258 unsigned int timeout, | 271 unsigned int timeout, |
| 272 scoped_refptr<base::SequencedTaskRunner> task_runner, | |
| 259 const UsbTransferCallback& callback) { | 273 const UsbTransferCallback& callback) { |
| 260 scoped_ptr<Transfer> transfer( | 274 scoped_ptr<Transfer> transfer(new Transfer( |
| 261 new Transfer(USB_TRANSFER_BULK, buffer, length, callback)); | 275 device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint), |
| 276 USB_TRANSFER_BULK, buffer, length, task_runner, callback)); | |
| 262 | 277 |
| 263 transfer->platform_transfer_ = libusb_alloc_transfer(0); | 278 transfer->platform_transfer_ = libusb_alloc_transfer(0); |
| 264 if (!transfer->platform_transfer_) { | 279 if (!transfer->platform_transfer_) { |
| 265 USB_LOG(ERROR) << "Failed to allocate bulk transfer."; | 280 USB_LOG(ERROR) << "Failed to allocate bulk transfer."; |
| 266 return nullptr; | 281 return nullptr; |
| 267 } | 282 } |
| 268 | 283 |
| 269 libusb_fill_bulk_transfer(transfer->platform_transfer_, | 284 libusb_fill_bulk_transfer( |
| 270 nullptr, /* filled in by Submit() */ | 285 transfer->platform_transfer_, device_handle->handle_, endpoint, |
| 271 endpoint, reinterpret_cast<uint8*>(buffer->data()), | 286 reinterpret_cast<uint8*>(buffer->data()), static_cast<int>(length), |
| 272 static_cast<int>(length), | 287 &UsbDeviceHandleImpl::Transfer::PlatformCallback, transfer.get(), |
| 273 &UsbDeviceHandleImpl::Transfer::PlatformCallback, | 288 timeout); |
| 274 transfer.get(), timeout); | |
| 275 | 289 |
| 276 return transfer.Pass(); | 290 return transfer.Pass(); |
| 277 } | 291 } |
| 278 | 292 |
| 279 // static | 293 // static |
| 280 scoped_ptr<UsbDeviceHandleImpl::Transfer> | 294 scoped_ptr<UsbDeviceHandleImpl::Transfer> |
| 281 UsbDeviceHandleImpl::Transfer::CreateInterruptTransfer( | 295 UsbDeviceHandleImpl::Transfer::CreateInterruptTransfer( |
| 296 scoped_refptr<UsbDeviceHandleImpl> device_handle, | |
| 282 uint8 endpoint, | 297 uint8 endpoint, |
| 283 scoped_refptr<net::IOBuffer> buffer, | 298 scoped_refptr<net::IOBuffer> buffer, |
| 284 int length, | 299 int length, |
| 285 unsigned int timeout, | 300 unsigned int timeout, |
| 301 scoped_refptr<base::SequencedTaskRunner> task_runner, | |
| 286 const UsbTransferCallback& callback) { | 302 const UsbTransferCallback& callback) { |
| 287 scoped_ptr<Transfer> transfer( | 303 scoped_ptr<Transfer> transfer(new Transfer( |
| 288 new Transfer(USB_TRANSFER_INTERRUPT, buffer, length, callback)); | 304 device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint), |
| 305 USB_TRANSFER_INTERRUPT, buffer, length, task_runner, callback)); | |
| 289 | 306 |
| 290 transfer->platform_transfer_ = libusb_alloc_transfer(0); | 307 transfer->platform_transfer_ = libusb_alloc_transfer(0); |
| 291 if (!transfer->platform_transfer_) { | 308 if (!transfer->platform_transfer_) { |
| 292 USB_LOG(ERROR) << "Failed to allocate interrupt transfer."; | 309 USB_LOG(ERROR) << "Failed to allocate interrupt transfer."; |
| 293 return nullptr; | 310 return nullptr; |
| 294 } | 311 } |
| 295 | 312 |
| 296 libusb_fill_interrupt_transfer( | 313 libusb_fill_interrupt_transfer( |
| 297 transfer->platform_transfer_, nullptr, /* filled in by Submit() */ | 314 transfer->platform_transfer_, device_handle->handle_, endpoint, |
| 298 endpoint, reinterpret_cast<uint8*>(buffer->data()), | 315 reinterpret_cast<uint8*>(buffer->data()), static_cast<int>(length), |
| 299 static_cast<int>(length), | |
| 300 &UsbDeviceHandleImpl::Transfer::PlatformCallback, transfer.get(), | 316 &UsbDeviceHandleImpl::Transfer::PlatformCallback, transfer.get(), |
| 301 timeout); | 317 timeout); |
| 302 | 318 |
| 303 return transfer.Pass(); | 319 return transfer.Pass(); |
| 304 } | 320 } |
| 305 | 321 |
| 306 // static | 322 // static |
| 307 scoped_ptr<UsbDeviceHandleImpl::Transfer> | 323 scoped_ptr<UsbDeviceHandleImpl::Transfer> |
| 308 UsbDeviceHandleImpl::Transfer::CreateIsochronousTransfer( | 324 UsbDeviceHandleImpl::Transfer::CreateIsochronousTransfer( |
| 325 scoped_refptr<UsbDeviceHandleImpl> device_handle, | |
| 309 uint8 endpoint, | 326 uint8 endpoint, |
| 310 scoped_refptr<net::IOBuffer> buffer, | 327 scoped_refptr<net::IOBuffer> buffer, |
| 311 size_t length, | 328 size_t length, |
| 312 unsigned int packets, | 329 unsigned int packets, |
| 313 unsigned int packet_length, | 330 unsigned int packet_length, |
| 314 unsigned int timeout, | 331 unsigned int timeout, |
| 332 scoped_refptr<base::SequencedTaskRunner> task_runner, | |
| 315 const UsbTransferCallback& callback) { | 333 const UsbTransferCallback& callback) { |
| 316 DCHECK(packets <= length && (packets * packet_length) <= length) | 334 DCHECK(packets <= length && (packets * packet_length) <= length) |
| 317 << "transfer length is too small"; | 335 << "transfer length is too small"; |
| 318 | 336 |
| 319 scoped_ptr<Transfer> transfer( | 337 scoped_ptr<Transfer> transfer(new Transfer( |
| 320 new Transfer(USB_TRANSFER_ISOCHRONOUS, buffer, length, callback)); | 338 device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint), |
| 339 USB_TRANSFER_ISOCHRONOUS, buffer, length, task_runner, callback)); | |
| 321 | 340 |
| 322 transfer->platform_transfer_ = libusb_alloc_transfer(packets); | 341 transfer->platform_transfer_ = libusb_alloc_transfer(packets); |
| 323 if (!transfer->platform_transfer_) { | 342 if (!transfer->platform_transfer_) { |
| 324 USB_LOG(ERROR) << "Failed to allocate isochronous transfer."; | 343 USB_LOG(ERROR) << "Failed to allocate isochronous transfer."; |
| 325 return nullptr; | 344 return nullptr; |
| 326 } | 345 } |
| 327 | 346 |
| 328 libusb_fill_iso_transfer( | 347 libusb_fill_iso_transfer( |
| 329 transfer->platform_transfer_, nullptr, /* filled in by Submit() */ | 348 transfer->platform_transfer_, device_handle->handle_, endpoint, |
| 330 endpoint, reinterpret_cast<uint8*>(buffer->data()), | 349 reinterpret_cast<uint8*>(buffer->data()), static_cast<int>(length), |
| 331 static_cast<int>(length), packets, &Transfer::PlatformCallback, | 350 packets, &Transfer::PlatformCallback, transfer.get(), timeout); |
| 332 transfer.get(), timeout); | |
| 333 libusb_set_iso_packet_lengths(transfer->platform_transfer_, packet_length); | 351 libusb_set_iso_packet_lengths(transfer->platform_transfer_, packet_length); |
| 334 | 352 |
| 335 return transfer.Pass(); | 353 return transfer.Pass(); |
| 336 } | 354 } |
| 337 | 355 |
| 338 UsbDeviceHandleImpl::Transfer::Transfer(UsbTransferType transfer_type, | 356 UsbDeviceHandleImpl::Transfer::Transfer( |
| 339 scoped_refptr<net::IOBuffer> buffer, | 357 scoped_refptr<UsbDeviceHandleImpl> device_handle, |
| 340 size_t length, | 358 scoped_refptr<InterfaceClaimer> claimed_interface, |
| 341 const UsbTransferCallback& callback) | 359 UsbTransferType transfer_type, |
| 360 scoped_refptr<net::IOBuffer> buffer, | |
| 361 size_t length, | |
| 362 scoped_refptr<base::SequencedTaskRunner> task_runner, | |
| 363 const UsbTransferCallback& callback) | |
| 342 : transfer_type_(transfer_type), | 364 : transfer_type_(transfer_type), |
| 365 device_handle_(device_handle), | |
| 366 platform_transfer_(NULL), | |
| 343 buffer_(buffer), | 367 buffer_(buffer), |
| 368 claimed_interface_(claimed_interface), | |
| 344 length_(length), | 369 length_(length), |
| 345 cancelled_(false), | 370 cancelled_(false), |
| 371 task_runner_(task_runner), | |
| 346 callback_(callback) { | 372 callback_(callback) { |
| 347 // Remember the thread from which this transfer was created so that |callback| | |
| 348 // can be dispatched there. | |
| 349 callback_task_runner_ = base::ThreadTaskRunnerHandle::Get(); | |
| 350 } | 373 } |
| 351 | 374 |
| 352 UsbDeviceHandleImpl::Transfer::~Transfer() { | 375 UsbDeviceHandleImpl::Transfer::~Transfer() { |
| 353 if (platform_transfer_) { | 376 if (platform_transfer_) { |
| 354 libusb_free_transfer(platform_transfer_); | 377 libusb_free_transfer(platform_transfer_); |
| 355 } | 378 } |
| 356 } | 379 } |
| 357 | 380 |
| 358 bool UsbDeviceHandleImpl::Transfer::Submit( | 381 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_); | 382 const int rv = libusb_submit_transfer(platform_transfer_); |
| 371 if (rv == LIBUSB_SUCCESS) { | 383 if (rv != LIBUSB_SUCCESS) { |
| 372 return true; | |
| 373 } else { | |
| 374 USB_LOG(EVENT) << "Failed to submit transfer: " | 384 USB_LOG(EVENT) << "Failed to submit transfer: " |
| 375 << ConvertPlatformUsbErrorToString(rv); | 385 << ConvertPlatformUsbErrorToString(rv); |
| 376 Complete(USB_TRANSFER_ERROR, 0); | 386 TransferComplete(USB_TRANSFER_ERROR, 0); |
| 377 return false; | |
| 378 } | 387 } |
| 379 } | 388 } |
| 380 | 389 |
| 381 void UsbDeviceHandleImpl::Transfer::Cancel() { | 390 void UsbDeviceHandleImpl::Transfer::Cancel() { |
| 382 if (!cancelled_) { | 391 if (!cancelled_) { |
| 383 libusb_cancel_transfer(platform_transfer_); | 392 libusb_cancel_transfer(platform_transfer_); |
| 384 claimed_interface_ = nullptr; | 393 claimed_interface_ = nullptr; |
| 385 } | 394 } |
| 386 cancelled_ = true; | 395 cancelled_ = true; |
| 387 } | 396 } |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 446 | 455 |
| 447 case USB_TRANSFER_BULK: | 456 case USB_TRANSFER_BULK: |
| 448 case USB_TRANSFER_INTERRUPT: | 457 case USB_TRANSFER_INTERRUPT: |
| 449 break; | 458 break; |
| 450 | 459 |
| 451 default: | 460 default: |
| 452 NOTREACHED() << "Invalid usb transfer type"; | 461 NOTREACHED() << "Invalid usb transfer type"; |
| 453 break; | 462 break; |
| 454 } | 463 } |
| 455 | 464 |
| 456 Complete(ConvertTransferStatus(platform_transfer_->status), actual_length); | 465 TransferComplete(ConvertTransferStatus(platform_transfer_->status), |
| 457 } | 466 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 } | 467 } |
| 468 | 468 |
| 469 /* static */ | 469 /* static */ |
| 470 void LIBUSB_CALL UsbDeviceHandleImpl::Transfer::PlatformCallback( | 470 void LIBUSB_CALL UsbDeviceHandleImpl::Transfer::PlatformCallback( |
| 471 PlatformUsbTransferHandle platform_transfer) { | 471 PlatformUsbTransferHandle platform_transfer) { |
| 472 scoped_ptr<Transfer> transfer( | 472 Transfer* transfer = |
| 473 reinterpret_cast<Transfer*>(platform_transfer->user_data)); | 473 reinterpret_cast<Transfer*>(platform_transfer->user_data); |
| 474 DCHECK(transfer->platform_transfer_ == platform_transfer); | 474 DCHECK(transfer->platform_transfer_ == platform_transfer); |
| 475 | 475 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 } | 476 } |
| 484 | 477 |
| 485 UsbDeviceHandleImpl::UsbDeviceHandleImpl(scoped_refptr<UsbContext> context, | 478 void UsbDeviceHandleImpl::Transfer::TransferComplete(UsbTransferStatus status, |
| 486 scoped_refptr<UsbDeviceImpl> device, | 479 size_t bytes_transferred) { |
| 487 PlatformUsbDeviceHandle handle) | 480 task_runner_->PostTask( |
| 481 FROM_HERE, | |
| 482 base::Bind(&UsbDeviceHandleImpl::TransferComplete, device_handle_, | |
| 483 base::Owned(this), | |
| 484 base::Bind(callback_, status, buffer_, bytes_transferred))); | |
| 485 } | |
| 486 | |
| 487 UsbDeviceHandleImpl::UsbDeviceHandleImpl( | |
| 488 scoped_refptr<UsbContext> context, | |
| 489 scoped_refptr<UsbDeviceImpl> device, | |
| 490 PlatformUsbDeviceHandle handle, | |
| 491 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) | |
| 488 : device_(device), | 492 : device_(device), |
| 489 handle_(handle), | 493 handle_(handle), |
| 490 context_(context), | 494 context_(context), |
| 491 task_runner_(base::ThreadTaskRunnerHandle::Get()), | 495 task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 492 weak_factory_(this) { | 496 blocking_task_runner_(blocking_task_runner) { |
| 493 DCHECK(handle) << "Cannot create device with NULL handle."; | 497 DCHECK(handle) << "Cannot create device with NULL handle."; |
| 494 } | 498 } |
| 495 | 499 |
| 496 UsbDeviceHandleImpl::~UsbDeviceHandleImpl() { | 500 UsbDeviceHandleImpl::~UsbDeviceHandleImpl() { |
| 497 DCHECK(thread_checker_.CalledOnValidThread()); | 501 DCHECK(thread_checker_.CalledOnValidThread()); |
| 498 | 502 |
| 499 libusb_close(handle_); | 503 libusb_close(handle_); |
| 500 handle_ = NULL; | 504 handle_ = NULL; |
| 501 } | 505 } |
| 502 | 506 |
| 503 scoped_refptr<UsbDevice> UsbDeviceHandleImpl::GetDevice() const { | 507 scoped_refptr<UsbDevice> UsbDeviceHandleImpl::GetDevice() const { |
| 504 return device_; | 508 return device_; |
| 505 } | 509 } |
| 506 | 510 |
| 507 void UsbDeviceHandleImpl::Close() { | 511 void UsbDeviceHandleImpl::Close() { |
| 508 DCHECK(thread_checker_.CalledOnValidThread()); | 512 DCHECK(thread_checker_.CalledOnValidThread()); |
| 509 if (device_) | 513 if (device_) |
| 510 device_->Close(this); | 514 device_->Close(this); |
| 511 } | 515 } |
| 512 | 516 |
| 513 bool UsbDeviceHandleImpl::SetConfiguration(int configuration_value) { | 517 void UsbDeviceHandleImpl::SetConfiguration(int configuration_value, |
| 518 const UsbSuccessCallback& callback) { | |
| 514 DCHECK(thread_checker_.CalledOnValidThread()); | 519 DCHECK(thread_checker_.CalledOnValidThread()); |
| 515 if (!device_) { | 520 if (!device_) { |
| 516 return false; | 521 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
| 522 return; | |
| 517 } | 523 } |
| 518 | 524 |
| 519 for (Transfer* transfer : transfers_) { | 525 for (Transfer* transfer : transfers_) { |
| 520 transfer->Cancel(); | 526 transfer->Cancel(); |
| 521 } | 527 } |
| 522 claimed_interfaces_.clear(); | 528 claimed_interfaces_.clear(); |
| 523 | 529 |
| 524 int rv = libusb_set_configuration(handle_, configuration_value); | 530 blocking_task_runner_->PostTask( |
| 525 if (rv == LIBUSB_SUCCESS) { | 531 FROM_HERE, |
| 526 device_->RefreshConfiguration(); | 532 base::Bind(&UsbDeviceHandleImpl::SetConfigurationOnBlockingThread, this, |
| 527 RefreshEndpointMap(); | 533 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 } | 534 } |
| 534 | 535 |
| 535 bool UsbDeviceHandleImpl::ClaimInterface(const int interface_number) { | 536 void UsbDeviceHandleImpl::ClaimInterface(int interface_number, |
| 537 const UsbSuccessCallback& callback) { | |
| 538 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 539 if (!device_) { | |
| 540 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); | |
| 541 return; | |
| 542 } | |
| 543 if (ContainsKey(claimed_interfaces_, interface_number)) { | |
| 544 task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); | |
|
Ken Rockot(use gerrit already)
2015/04/07 22:09:43
nit: Maybe it doesn't matter, but is there realist
Reilly Grant (use Gerrit)
2015/04/08 21:39:03
I'll change it because I've recently decided that
| |
| 545 return; | |
| 546 } | |
| 547 | |
| 548 blocking_task_runner_->PostTask( | |
| 549 FROM_HERE, | |
| 550 base::Bind(&UsbDeviceHandleImpl::ClaimInterfaceOnBlockingThread, this, | |
| 551 handle_, interface_number, callback)); | |
| 552 } | |
| 553 | |
| 554 bool UsbDeviceHandleImpl::ReleaseInterface(int interface_number) { | |
| 536 DCHECK(thread_checker_.CalledOnValidThread()); | 555 DCHECK(thread_checker_.CalledOnValidThread()); |
| 537 if (!device_) | 556 if (!device_) |
| 538 return false; | 557 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)) | 558 if (!ContainsKey(claimed_interfaces_, interface_number)) |
| 558 return false; | 559 return false; |
| 559 | 560 |
| 560 // Cancel all the transfers on that interface. | 561 // Cancel all the transfers on that interface. |
| 561 InterfaceClaimer* interface_claimer = | 562 InterfaceClaimer* interface_claimer = |
| 562 claimed_interfaces_[interface_number].get(); | 563 claimed_interfaces_[interface_number].get(); |
| 563 for (Transfer* transfer : transfers_) { | 564 for (Transfer* transfer : transfers_) { |
| 564 if (transfer->claimed_interface() == interface_claimer) { | 565 if (transfer->claimed_interface() == interface_claimer) { |
| 565 transfer->Cancel(); | 566 transfer->Cancel(); |
| 566 } | 567 } |
| 567 } | 568 } |
| 568 claimed_interfaces_.erase(interface_number); | 569 claimed_interfaces_.erase(interface_number); |
| 569 | 570 |
| 570 RefreshEndpointMap(); | 571 RefreshEndpointMap(); |
| 571 return true; | 572 return true; |
| 572 } | 573 } |
| 573 | 574 |
| 574 bool UsbDeviceHandleImpl::SetInterfaceAlternateSetting( | 575 void UsbDeviceHandleImpl::SetInterfaceAlternateSetting( |
| 575 const int interface_number, | 576 int interface_number, |
| 576 const int alternate_setting) { | 577 int alternate_setting, |
| 578 const UsbSuccessCallback& callback) { | |
| 577 DCHECK(thread_checker_.CalledOnValidThread()); | 579 DCHECK(thread_checker_.CalledOnValidThread()); |
| 578 if (!device_) | 580 if (!device_ || !ContainsKey(claimed_interfaces_, interface_number)) { |
| 579 return false; | 581 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
| 580 if (!ContainsKey(claimed_interfaces_, interface_number)) | 582 return; |
| 581 return false; | |
| 582 const int rv = libusb_set_interface_alt_setting( | |
| 583 handle_, interface_number, alternate_setting); | |
| 584 if (rv == LIBUSB_SUCCESS) { | |
| 585 claimed_interfaces_[interface_number]->set_alternate_setting( | |
| 586 alternate_setting); | |
| 587 RefreshEndpointMap(); | |
| 588 } else { | |
| 589 USB_LOG(EVENT) << "Failed to set interface " << interface_number | |
| 590 << " to alternate setting " << alternate_setting << ": " | |
| 591 << ConvertPlatformUsbErrorToString(rv); | |
| 592 } | 583 } |
| 593 return rv == LIBUSB_SUCCESS; | 584 |
| 585 blocking_task_runner_->PostTask( | |
| 586 FROM_HERE, | |
| 587 base::Bind( | |
| 588 &UsbDeviceHandleImpl::SetInterfaceAlternateSettingOnBlockingThread, | |
| 589 this, handle_, interface_number, alternate_setting, callback)); | |
| 594 } | 590 } |
| 595 | 591 |
| 596 bool UsbDeviceHandleImpl::ResetDevice() { | 592 void UsbDeviceHandleImpl::ResetDevice(const UsbSuccessCallback& callback) { |
| 597 DCHECK(thread_checker_.CalledOnValidThread()); | 593 DCHECK(thread_checker_.CalledOnValidThread()); |
| 598 if (!device_) | 594 if (!device_) { |
| 599 return false; | 595 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
| 600 | 596 return; |
| 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 } | 597 } |
| 614 | 598 |
| 615 std::map<uint8, base::string16>::const_iterator it = strings_.find(string_id); | 599 blocking_task_runner_->PostTask( |
| 616 if (it != strings_.end()) { | 600 FROM_HERE, base::Bind(&UsbDeviceHandleImpl::ResetDeviceOnBlockingThread, |
| 617 *string = it->second; | 601 this, handle_, callback)); |
| 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 } | 602 } |
| 660 | 603 |
| 661 void UsbDeviceHandleImpl::ControlTransfer(UsbEndpointDirection direction, | 604 void UsbDeviceHandleImpl::ControlTransfer(UsbEndpointDirection direction, |
| 662 TransferRequestType request_type, | 605 TransferRequestType request_type, |
| 663 TransferRecipient recipient, | 606 TransferRecipient recipient, |
| 664 uint8 request, | 607 uint8 request, |
| 665 uint16 value, | 608 uint16 value, |
| 666 uint16 index, | 609 uint16 index, |
| 667 net::IOBuffer* buffer, | 610 net::IOBuffer* buffer, |
| 668 size_t length, | 611 size_t length, |
| 669 unsigned int timeout, | 612 unsigned int timeout, |
| 670 const UsbTransferCallback& callback) { | 613 const UsbTransferCallback& callback) { |
| 614 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 615 | |
| 616 if (!device_) { | |
| 617 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); | |
| 618 return; | |
| 619 } | |
| 620 | |
| 671 if (length > UINT16_MAX) { | 621 if (length > UINT16_MAX) { |
| 672 USB_LOG(USER) << "Transfer too long."; | 622 USB_LOG(USER) << "Transfer too long."; |
| 673 callback.Run(USB_TRANSFER_ERROR, buffer, 0); | 623 callback.Run(USB_TRANSFER_ERROR, buffer, 0); |
| 674 return; | 624 return; |
| 675 } | 625 } |
| 676 | 626 |
| 677 const size_t resized_length = LIBUSB_CONTROL_SETUP_SIZE + length; | 627 const size_t resized_length = LIBUSB_CONTROL_SETUP_SIZE + length; |
| 678 scoped_refptr<net::IOBuffer> resized_buffer( | 628 scoped_refptr<net::IOBuffer> resized_buffer( |
| 679 new net::IOBufferWithSize(static_cast<int>(resized_length))); | 629 new net::IOBufferWithSize(static_cast<int>(resized_length))); |
| 680 if (!resized_buffer.get()) { | 630 if (!resized_buffer.get()) { |
| 681 callback.Run(USB_TRANSFER_ERROR, buffer, 0); | 631 callback.Run(USB_TRANSFER_ERROR, buffer, 0); |
| 682 return; | 632 return; |
| 683 } | 633 } |
| 684 memcpy(resized_buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, buffer->data(), | 634 memcpy(resized_buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, buffer->data(), |
| 685 length); | 635 length); |
| 686 | 636 |
| 687 scoped_ptr<Transfer> transfer = Transfer::CreateControlTransfer( | 637 scoped_ptr<Transfer> transfer = Transfer::CreateControlTransfer( |
| 688 CreateRequestType(direction, request_type, recipient), request, value, | 638 this, CreateRequestType(direction, request_type, recipient), request, |
| 689 index, static_cast<uint16>(length), resized_buffer, timeout, callback); | 639 value, index, static_cast<uint16>(length), resized_buffer, timeout, |
| 640 task_runner_, callback); | |
| 690 if (!transfer) { | 641 if (!transfer) { |
| 691 callback.Run(USB_TRANSFER_ERROR, buffer, 0); | 642 callback.Run(USB_TRANSFER_ERROR, buffer, 0); |
| 692 return; | 643 return; |
| 693 } | 644 } |
| 694 | 645 |
| 695 PostOrSubmitTransfer(transfer.Pass()); | 646 SubmitTransfer(transfer.Pass()); |
| 696 } | 647 } |
| 697 | 648 |
| 698 void UsbDeviceHandleImpl::BulkTransfer(const UsbEndpointDirection direction, | 649 void UsbDeviceHandleImpl::BulkTransfer(const UsbEndpointDirection direction, |
| 699 const uint8 endpoint, | 650 const uint8 endpoint, |
| 700 net::IOBuffer* buffer, | 651 net::IOBuffer* buffer, |
| 701 const size_t length, | 652 const size_t length, |
| 702 const unsigned int timeout, | 653 const unsigned int timeout, |
| 703 const UsbTransferCallback& callback) { | 654 const UsbTransferCallback& callback) { |
| 655 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 656 | |
| 657 if (!device_) { | |
| 658 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); | |
| 659 return; | |
| 660 } | |
| 661 | |
| 704 if (length > INT_MAX) { | 662 if (length > INT_MAX) { |
| 705 USB_LOG(USER) << "Transfer too long."; | 663 USB_LOG(USER) << "Transfer too long."; |
| 706 callback.Run(USB_TRANSFER_ERROR, buffer, 0); | 664 callback.Run(USB_TRANSFER_ERROR, buffer, 0); |
| 707 return; | 665 return; |
| 708 } | 666 } |
| 709 | 667 |
| 710 scoped_ptr<Transfer> transfer = Transfer::CreateBulkTransfer( | 668 scoped_ptr<Transfer> transfer = Transfer::CreateBulkTransfer( |
| 711 ConvertTransferDirection(direction) | endpoint, buffer, | 669 this, ConvertTransferDirection(direction) | endpoint, buffer, |
| 712 static_cast<int>(length), timeout, callback); | 670 static_cast<int>(length), timeout, task_runner_, callback); |
| 713 | 671 |
| 714 PostOrSubmitTransfer(transfer.Pass()); | 672 SubmitTransfer(transfer.Pass()); |
| 715 } | 673 } |
| 716 | 674 |
| 717 void UsbDeviceHandleImpl::InterruptTransfer( | 675 void UsbDeviceHandleImpl::InterruptTransfer( |
| 718 UsbEndpointDirection direction, | 676 UsbEndpointDirection direction, |
| 719 uint8 endpoint, | 677 uint8 endpoint, |
| 720 net::IOBuffer* buffer, | 678 net::IOBuffer* buffer, |
| 721 size_t length, | 679 size_t length, |
| 722 unsigned int timeout, | 680 unsigned int timeout, |
| 723 const UsbTransferCallback& callback) { | 681 const UsbTransferCallback& callback) { |
| 682 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 683 | |
| 684 if (!device_) { | |
| 685 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); | |
| 686 return; | |
| 687 } | |
| 688 | |
| 724 if (length > INT_MAX) { | 689 if (length > INT_MAX) { |
| 725 USB_LOG(USER) << "Transfer too long."; | 690 USB_LOG(USER) << "Transfer too long."; |
| 726 callback.Run(USB_TRANSFER_ERROR, buffer, 0); | 691 callback.Run(USB_TRANSFER_ERROR, buffer, 0); |
| 727 return; | 692 return; |
| 728 } | 693 } |
| 729 | 694 |
| 730 scoped_ptr<Transfer> transfer = Transfer::CreateInterruptTransfer( | 695 scoped_ptr<Transfer> transfer = Transfer::CreateInterruptTransfer( |
| 731 ConvertTransferDirection(direction) | endpoint, buffer, | 696 this, ConvertTransferDirection(direction) | endpoint, buffer, |
| 732 static_cast<int>(length), timeout, callback); | 697 static_cast<int>(length), timeout, task_runner_, callback); |
| 733 | 698 |
| 734 PostOrSubmitTransfer(transfer.Pass()); | 699 SubmitTransfer(transfer.Pass()); |
| 735 } | 700 } |
| 736 | 701 |
| 737 void UsbDeviceHandleImpl::IsochronousTransfer( | 702 void UsbDeviceHandleImpl::IsochronousTransfer( |
| 738 const UsbEndpointDirection direction, | 703 const UsbEndpointDirection direction, |
| 739 const uint8 endpoint, | 704 const uint8 endpoint, |
| 740 net::IOBuffer* buffer, | 705 net::IOBuffer* buffer, |
| 741 const size_t length, | 706 const size_t length, |
| 742 const unsigned int packets, | 707 const unsigned int packets, |
| 743 const unsigned int packet_length, | 708 const unsigned int packet_length, |
| 744 const unsigned int timeout, | 709 const unsigned int timeout, |
| 745 const UsbTransferCallback& callback) { | 710 const UsbTransferCallback& callback) { |
| 711 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 712 | |
| 713 if (!device_) { | |
| 714 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); | |
| 715 return; | |
| 716 } | |
| 717 | |
| 746 if (length > INT_MAX) { | 718 if (length > INT_MAX) { |
| 747 USB_LOG(USER) << "Transfer too long."; | 719 USB_LOG(USER) << "Transfer too long."; |
| 748 callback.Run(USB_TRANSFER_ERROR, buffer, 0); | 720 callback.Run(USB_TRANSFER_ERROR, buffer, 0); |
| 749 return; | 721 return; |
| 750 } | 722 } |
| 751 | 723 |
| 752 scoped_ptr<Transfer> transfer = Transfer::CreateIsochronousTransfer( | 724 scoped_ptr<Transfer> transfer = Transfer::CreateIsochronousTransfer( |
| 753 ConvertTransferDirection(direction) | endpoint, buffer, | 725 this, ConvertTransferDirection(direction) | endpoint, buffer, |
| 754 static_cast<int>(length), packets, packet_length, timeout, callback); | 726 static_cast<int>(length), packets, packet_length, timeout, task_runner_, |
| 727 callback); | |
| 755 | 728 |
| 756 PostOrSubmitTransfer(transfer.Pass()); | 729 SubmitTransfer(transfer.Pass()); |
| 730 } | |
| 731 | |
| 732 void UsbDeviceHandleImpl::SetConfigurationOnBlockingThread( | |
| 733 PlatformUsbDeviceHandle handle, | |
| 734 int configuration_value, | |
| 735 const UsbSuccessCallback& callback) { | |
| 736 int rv = libusb_set_configuration(handle_, configuration_value); | |
| 737 if (rv != LIBUSB_SUCCESS) { | |
| 738 USB_LOG(EVENT) << "Failed to set configuration " << configuration_value | |
| 739 << ": " << ConvertPlatformUsbErrorToString(rv); | |
| 740 } | |
| 741 task_runner_->PostTask( | |
| 742 FROM_HERE, base::Bind(&UsbDeviceHandleImpl::SetConfigurationComplete, | |
| 743 this, rv == LIBUSB_SUCCESS, callback)); | |
| 744 } | |
| 745 | |
| 746 void UsbDeviceHandleImpl::SetConfigurationComplete( | |
| 747 bool success, | |
| 748 const UsbSuccessCallback& callback) { | |
| 749 if (success) { | |
| 750 device_->RefreshConfiguration(); | |
| 751 RefreshEndpointMap(); | |
| 752 } | |
| 753 callback.Run(success); | |
| 754 } | |
| 755 | |
| 756 void UsbDeviceHandleImpl::ClaimInterfaceOnBlockingThread( | |
| 757 PlatformUsbDeviceHandle handle, | |
| 758 int interface_number, | |
| 759 const UsbSuccessCallback& callback) { | |
| 760 int rv = libusb_claim_interface(handle, interface_number); | |
| 761 if (rv != LIBUSB_SUCCESS) { | |
| 762 VLOG(1) << "Failed to claim interface: " | |
| 763 << ConvertPlatformUsbErrorToString(rv); | |
| 764 } | |
| 765 task_runner_->PostTask( | |
| 766 FROM_HERE, base::Bind(&UsbDeviceHandleImpl::ClaimInterfaceComplete, this, | |
| 767 interface_number, rv == LIBUSB_SUCCESS, callback)); | |
| 768 } | |
| 769 | |
| 770 void UsbDeviceHandleImpl::ClaimInterfaceComplete( | |
| 771 int interface_number, | |
| 772 bool success, | |
| 773 const UsbSuccessCallback& callback) { | |
| 774 if (success) { | |
| 775 claimed_interfaces_[interface_number] = | |
| 776 new InterfaceClaimer(this, interface_number); | |
| 777 RefreshEndpointMap(); | |
| 778 } | |
| 779 callback.Run(success); | |
| 780 } | |
| 781 | |
| 782 void UsbDeviceHandleImpl::SetInterfaceAlternateSettingOnBlockingThread( | |
| 783 PlatformUsbDeviceHandle handle, | |
| 784 int interface_number, | |
| 785 int alternate_setting, | |
| 786 const UsbSuccessCallback& callback) { | |
| 787 int rv = libusb_set_interface_alt_setting(handle, interface_number, | |
| 788 alternate_setting); | |
| 789 if (rv != LIBUSB_SUCCESS) { | |
| 790 USB_LOG(EVENT) << "Failed to set interface " << interface_number | |
| 791 << " to alternate setting " << alternate_setting << ": " | |
| 792 << ConvertPlatformUsbErrorToString(rv); | |
| 793 } | |
| 794 task_runner_->PostTask( | |
| 795 FROM_HERE, | |
| 796 base::Bind(&UsbDeviceHandleImpl::SetInterfaceAlternateSettingComplete, | |
| 797 this, interface_number, alternate_setting, | |
| 798 rv == LIBUSB_SUCCESS, callback)); | |
| 799 } | |
| 800 | |
| 801 void UsbDeviceHandleImpl::SetInterfaceAlternateSettingComplete( | |
| 802 int interface_number, | |
| 803 int alternate_setting, | |
| 804 bool success, | |
| 805 const UsbSuccessCallback& callback) { | |
| 806 if (success) { | |
| 807 claimed_interfaces_[interface_number]->set_alternate_setting( | |
| 808 alternate_setting); | |
| 809 RefreshEndpointMap(); | |
| 810 } | |
| 811 callback.Run(success); | |
| 812 } | |
| 813 | |
| 814 void UsbDeviceHandleImpl::ResetDeviceOnBlockingThread( | |
| 815 PlatformUsbDeviceHandle handle, | |
| 816 const UsbSuccessCallback& callback) { | |
| 817 int rv = libusb_reset_device(handle); | |
| 818 if (rv != LIBUSB_SUCCESS) { | |
| 819 USB_LOG(EVENT) << "Failed to reset device: " | |
| 820 << ConvertPlatformUsbErrorToString(rv); | |
| 821 } | |
| 822 task_runner_->PostTask( | |
| 823 FROM_HERE, base::Bind(&UsbDeviceHandleImpl::ResetDeviceComplete, this, | |
| 824 rv == LIBUSB_SUCCESS, callback)); | |
| 825 } | |
| 826 | |
| 827 void UsbDeviceHandleImpl::ResetDeviceComplete( | |
| 828 bool success, | |
| 829 const UsbSuccessCallback& callback) { | |
| 830 callback.Run(success); | |
| 757 } | 831 } |
| 758 | 832 |
| 759 void UsbDeviceHandleImpl::RefreshEndpointMap() { | 833 void UsbDeviceHandleImpl::RefreshEndpointMap() { |
| 760 DCHECK(thread_checker_.CalledOnValidThread()); | 834 DCHECK(thread_checker_.CalledOnValidThread()); |
| 761 endpoint_map_.clear(); | 835 endpoint_map_.clear(); |
| 762 const UsbConfigDescriptor* config = device_->GetConfiguration(); | 836 const UsbConfigDescriptor* config = device_->GetConfiguration(); |
| 763 if (config) { | 837 if (config) { |
| 764 for (const auto& map_entry : claimed_interfaces_) { | 838 for (const auto& map_entry : claimed_interfaces_) { |
| 765 int interface_number = map_entry.first; | 839 int interface_number = map_entry.first; |
| 766 const scoped_refptr<InterfaceClaimer>& claimed_iface = map_entry.second; | 840 const scoped_refptr<InterfaceClaimer>& claimed_iface = map_entry.second; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 778 } | 852 } |
| 779 } | 853 } |
| 780 | 854 |
| 781 scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer> | 855 scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer> |
| 782 UsbDeviceHandleImpl::GetClaimedInterfaceForEndpoint(unsigned char endpoint) { | 856 UsbDeviceHandleImpl::GetClaimedInterfaceForEndpoint(unsigned char endpoint) { |
| 783 if (ContainsKey(endpoint_map_, endpoint)) | 857 if (ContainsKey(endpoint_map_, endpoint)) |
| 784 return claimed_interfaces_[endpoint_map_[endpoint]]; | 858 return claimed_interfaces_[endpoint_map_[endpoint]]; |
| 785 return NULL; | 859 return NULL; |
| 786 } | 860 } |
| 787 | 861 |
| 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 } | |
| 797 | |
| 798 void UsbDeviceHandleImpl::SubmitTransfer(scoped_ptr<Transfer> transfer) { | 862 void UsbDeviceHandleImpl::SubmitTransfer(scoped_ptr<Transfer> transfer) { |
| 799 DCHECK(thread_checker_.CalledOnValidThread()); | 863 DCHECK(thread_checker_.CalledOnValidThread()); |
| 800 | 864 |
| 801 if (device_) { | 865 // Transfer is owned by libusb until its completion callback is run. This |
| 802 if (transfer->Submit(weak_factory_.GetWeakPtr())) { | 866 // object holds a weak reference. |
| 803 // Transfer is now owned by libusb until its completion callback is run. | 867 transfers_.insert(transfer.get()); |
| 804 // This object holds a weak reference. | 868 blocking_task_runner_->PostTask( |
| 805 transfers_.insert(transfer.release()); | 869 FROM_HERE, |
| 806 } | 870 base::Bind(&Transfer::Submit, base::Unretained(transfer.release()))); |
| 807 } else { | |
| 808 transfer->Complete(USB_TRANSFER_DISCONNECT, 0); | |
| 809 } | |
| 810 } | 871 } |
| 811 | 872 |
| 812 void UsbDeviceHandleImpl::CompleteTransfer(scoped_ptr<Transfer> transfer) { | 873 void UsbDeviceHandleImpl::TransferComplete(Transfer* transfer, |
| 813 DCHECK(ContainsKey(transfers_, transfer.get())) | 874 const base::Closure& callback) { |
| 814 << "Missing transfer completed"; | 875 DCHECK(thread_checker_.CalledOnValidThread()); |
| 815 transfers_.erase(transfer.get()); | 876 DCHECK(ContainsKey(transfers_, transfer)) << "Missing transfer completed"; |
| 816 transfer->ProcessCompletion(); | 877 transfers_.erase(transfer); |
| 817 } | 878 callback.Run(); |
| 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 } | 879 } |
| 852 | 880 |
| 853 void UsbDeviceHandleImpl::InternalClose() { | 881 void UsbDeviceHandleImpl::InternalClose() { |
| 854 DCHECK(thread_checker_.CalledOnValidThread()); | 882 DCHECK(thread_checker_.CalledOnValidThread()); |
| 855 if (!device_) | 883 if (!device_) |
| 856 return; | 884 return; |
| 857 | 885 |
| 858 // Cancel all the transfers. | 886 // Cancel all the transfers. |
| 859 for (Transfer* transfer : transfers_) { | 887 for (Transfer* transfer : transfers_) { |
| 860 // The callback will be called some time later. | 888 // The callback will be called some time later. |
| 861 transfer->Cancel(); | 889 transfer->Cancel(); |
| 862 } | 890 } |
| 863 | 891 |
| 864 // Attempt-release all the interfaces. | 892 // Attempt-release all the interfaces. |
| 865 // It will be retained until the transfer cancellation is finished. | 893 // It will be retained until the transfer cancellation is finished. |
| 866 claimed_interfaces_.clear(); | 894 claimed_interfaces_.clear(); |
| 867 | 895 |
| 868 // Cannot close device handle here. Need to wait for libusb_cancel_transfer to | 896 // Cannot close device handle here. Need to wait for libusb_cancel_transfer to |
| 869 // finish. | 897 // finish. |
| 870 device_ = NULL; | 898 device_ = NULL; |
| 871 } | 899 } |
| 872 | 900 |
| 873 } // namespace device | 901 } // namespace device |
| OLD | NEW |