OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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 "chrome/browser/usb/usb_device_handle.h" | 5 #include "components/usb_service/usb_device_handle.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
11 #include "base/stl_util.h" | 11 #include "base/stl_util.h" |
12 #include "base/strings/string16.h" | 12 #include "base/strings/string16.h" |
13 #include "base/synchronization/lock.h" | 13 #include "base/synchronization/lock.h" |
14 #include "chrome/browser/usb/usb_context.h" | 14 #include "components/usb_service/usb_context.h" |
15 #include "chrome/browser/usb/usb_device.h" | 15 #include "components/usb_service/usb_device.h" |
16 #include "chrome/browser/usb/usb_interface.h" | 16 #include "components/usb_service/usb_interface.h" |
17 #include "chrome/browser/usb/usb_service.h" | 17 #include "components/usb_service/usb_service.h" |
18 #include "content/public/browser/browser_thread.h" | 18 #include "content/public/browser/browser_thread.h" |
19 #include "third_party/libusb/src/libusb/libusb.h" | 19 #include "third_party/libusb/src/libusb/libusb.h" |
20 | 20 |
21 using content::BrowserThread; | 21 using content::BrowserThread; |
22 void HandleTransferCompletion(PlatformUsbTransferHandle transfer); | 22 |
| 23 namespace usb_service { |
| 24 |
| 25 void HandleTransferCompletion(usb_service::PlatformUsbTransferHandle transfer); |
23 | 26 |
24 namespace { | 27 namespace { |
25 | 28 |
26 static uint8 ConvertTransferDirection( | 29 static uint8 ConvertTransferDirection(const UsbEndpointDirection direction) { |
27 const UsbEndpointDirection direction) { | |
28 switch (direction) { | 30 switch (direction) { |
29 case USB_DIRECTION_INBOUND: | 31 case USB_DIRECTION_INBOUND: |
30 return LIBUSB_ENDPOINT_IN; | 32 return LIBUSB_ENDPOINT_IN; |
31 case USB_DIRECTION_OUTBOUND: | 33 case USB_DIRECTION_OUTBOUND: |
32 return LIBUSB_ENDPOINT_OUT; | 34 return LIBUSB_ENDPOINT_OUT; |
33 default: | 35 default: |
34 NOTREACHED(); | 36 NOTREACHED(); |
35 return LIBUSB_ENDPOINT_IN; | 37 return LIBUSB_ENDPOINT_IN; |
36 } | 38 } |
37 } | 39 } |
38 | 40 |
39 static uint8 CreateRequestType(const UsbEndpointDirection direction, | 41 static uint8 CreateRequestType( |
| 42 const UsbEndpointDirection direction, |
40 const UsbDeviceHandle::TransferRequestType request_type, | 43 const UsbDeviceHandle::TransferRequestType request_type, |
41 const UsbDeviceHandle::TransferRecipient recipient) { | 44 const UsbDeviceHandle::TransferRecipient recipient) { |
42 uint8 result = ConvertTransferDirection(direction); | 45 uint8 result = ConvertTransferDirection(direction); |
43 | 46 |
44 switch (request_type) { | 47 switch (request_type) { |
45 case UsbDeviceHandle::STANDARD: | 48 case UsbDeviceHandle::STANDARD: |
46 result |= LIBUSB_REQUEST_TYPE_STANDARD; | 49 result |= LIBUSB_REQUEST_TYPE_STANDARD; |
47 break; | 50 break; |
48 case UsbDeviceHandle::CLASS: | 51 case UsbDeviceHandle::CLASS: |
49 result |= LIBUSB_REQUEST_TYPE_CLASS; | 52 result |= LIBUSB_REQUEST_TYPE_CLASS; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 case LIBUSB_TRANSFER_OVERFLOW: | 93 case LIBUSB_TRANSFER_OVERFLOW: |
91 return USB_TRANSFER_OVERFLOW; | 94 return USB_TRANSFER_OVERFLOW; |
92 case LIBUSB_TRANSFER_CANCELLED: | 95 case LIBUSB_TRANSFER_CANCELLED: |
93 return USB_TRANSFER_CANCELLED; | 96 return USB_TRANSFER_CANCELLED; |
94 default: | 97 default: |
95 NOTREACHED(); | 98 NOTREACHED(); |
96 return USB_TRANSFER_ERROR; | 99 return USB_TRANSFER_ERROR; |
97 } | 100 } |
98 } | 101 } |
99 | 102 |
100 static void LIBUSB_CALL PlatformTransferCompletionCallback( | 103 static void LIBUSB_CALL |
101 PlatformUsbTransferHandle transfer) { | 104 PlatformTransferCompletionCallback(PlatformUsbTransferHandle transfer) { |
102 BrowserThread::PostTask(BrowserThread::FILE, | 105 BrowserThread::PostTask(BrowserThread::FILE, |
103 FROM_HERE, | 106 FROM_HERE, |
104 base::Bind(HandleTransferCompletion, transfer)); | 107 base::Bind(HandleTransferCompletion, transfer)); |
105 } | 108 } |
106 | 109 |
107 } // namespace | 110 } // namespace |
108 | 111 |
109 void HandleTransferCompletion(PlatformUsbTransferHandle transfer) { | 112 void HandleTransferCompletion(PlatformUsbTransferHandle transfer) { |
110 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 113 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
111 UsbDeviceHandle* const device_handle = | 114 UsbDeviceHandle* const device_handle = |
112 reinterpret_cast<UsbDeviceHandle*>(transfer->user_data); | 115 reinterpret_cast<UsbDeviceHandle*>(transfer->user_data); |
113 CHECK(device_handle) << "Device handle is closed before transfer finishes."; | 116 CHECK(device_handle) << "Device handle is closed before transfer finishes."; |
114 device_handle->TransferComplete(transfer); | 117 device_handle->TransferComplete(transfer); |
115 libusb_free_transfer(transfer); | 118 libusb_free_transfer(transfer); |
116 } | 119 } |
117 | 120 |
118 | |
119 class UsbDeviceHandle::InterfaceClaimer | 121 class UsbDeviceHandle::InterfaceClaimer |
120 : public base::RefCountedThreadSafe<UsbDeviceHandle::InterfaceClaimer> { | 122 : public base::RefCountedThreadSafe<UsbDeviceHandle::InterfaceClaimer> { |
121 public: | 123 public: |
122 InterfaceClaimer(const scoped_refptr<UsbDeviceHandle> handle, | 124 InterfaceClaimer(const scoped_refptr<UsbDeviceHandle> handle, |
123 const int interface_number); | 125 const int interface_number); |
124 | 126 |
125 bool Claim() const; | 127 bool Claim() const; |
126 | 128 |
127 int alternate_setting() const { return alternate_setting_; } | 129 int alternate_setting() const { return alternate_setting_; } |
128 void set_alternate_setting(const int alternate_setting) { | 130 void set_alternate_setting(const int alternate_setting) { |
129 alternate_setting_ = alternate_setting; | 131 alternate_setting_ = alternate_setting; |
130 } | 132 } |
131 | 133 |
132 private: | 134 private: |
133 friend class UsbDevice; | 135 friend class UsbDevice; |
134 friend class base::RefCountedThreadSafe<InterfaceClaimer>; | 136 friend class base::RefCountedThreadSafe<InterfaceClaimer>; |
135 ~InterfaceClaimer(); | 137 ~InterfaceClaimer(); |
136 | 138 |
137 const scoped_refptr<UsbDeviceHandle> handle_; | 139 const scoped_refptr<UsbDeviceHandle> handle_; |
138 const int interface_number_; | 140 const int interface_number_; |
139 int alternate_setting_; | 141 int alternate_setting_; |
140 | 142 |
141 DISALLOW_COPY_AND_ASSIGN(InterfaceClaimer); | 143 DISALLOW_COPY_AND_ASSIGN(InterfaceClaimer); |
142 }; | 144 }; |
143 | 145 |
144 UsbDeviceHandle::InterfaceClaimer::InterfaceClaimer( | 146 UsbDeviceHandle::InterfaceClaimer::InterfaceClaimer( |
145 const scoped_refptr<UsbDeviceHandle> handle, const int interface_number) | 147 const scoped_refptr<UsbDeviceHandle> handle, |
| 148 const int interface_number) |
146 : handle_(handle), | 149 : handle_(handle), |
147 interface_number_(interface_number), | 150 interface_number_(interface_number), |
148 alternate_setting_(0) { | 151 alternate_setting_(0) { |
149 } | 152 } |
150 | 153 |
151 UsbDeviceHandle::InterfaceClaimer::~InterfaceClaimer() { | 154 UsbDeviceHandle::InterfaceClaimer::~InterfaceClaimer() { |
152 libusb_release_interface(handle_->handle(), interface_number_); | 155 libusb_release_interface(handle_->handle(), interface_number_); |
153 } | 156 } |
154 | 157 |
155 bool UsbDeviceHandle::InterfaceClaimer::Claim() const { | 158 bool UsbDeviceHandle::InterfaceClaimer::Claim() const { |
156 return libusb_claim_interface(handle_->handle(), interface_number_) == 0; | 159 return libusb_claim_interface(handle_->handle(), interface_number_) == 0; |
157 } | 160 } |
158 | 161 |
159 struct UsbDeviceHandle::Transfer { | 162 struct UsbDeviceHandle::Transfer { |
160 Transfer(); | 163 Transfer(); |
161 ~Transfer(); | 164 ~Transfer(); |
162 | 165 |
163 UsbTransferType transfer_type; | 166 UsbTransferType transfer_type; |
164 scoped_refptr<net::IOBuffer> buffer; | 167 scoped_refptr<net::IOBuffer> buffer; |
165 scoped_refptr<UsbDeviceHandle::InterfaceClaimer> claimed_interface; | 168 scoped_refptr<UsbDeviceHandle::InterfaceClaimer> claimed_interface; |
166 scoped_refptr<base::MessageLoopProxy> message_loop_proxy; | 169 scoped_refptr<base::MessageLoopProxy> message_loop_proxy; |
167 size_t length; | 170 size_t length; |
168 UsbTransferCallback callback; | 171 UsbTransferCallback callback; |
169 }; | 172 }; |
170 | 173 |
171 UsbDeviceHandle::Transfer::Transfer() | 174 UsbDeviceHandle::Transfer::Transfer() |
172 : transfer_type(USB_TRANSFER_CONTROL), | 175 : transfer_type(USB_TRANSFER_CONTROL), length(0) { |
173 length(0) { | |
174 } | 176 } |
175 | 177 |
176 UsbDeviceHandle::Transfer::~Transfer() {} | 178 UsbDeviceHandle::Transfer::~Transfer() { |
| 179 } |
177 | 180 |
178 UsbDeviceHandle::UsbDeviceHandle( | 181 UsbDeviceHandle::UsbDeviceHandle(scoped_refptr<UsbContext> context, |
179 scoped_refptr<UsbContext> context, | 182 UsbDevice* device, |
180 UsbDevice* device, | 183 PlatformUsbDeviceHandle handle, |
181 PlatformUsbDeviceHandle handle, | 184 scoped_refptr<UsbConfigDescriptor> interfaces) |
182 scoped_refptr<UsbConfigDescriptor> interfaces) | |
183 : device_(device), | 185 : device_(device), |
184 handle_(handle), | 186 handle_(handle), |
185 interfaces_(interfaces), | 187 interfaces_(interfaces), |
186 context_(context) { | 188 context_(context) { |
187 DCHECK(thread_checker_.CalledOnValidThread()); | 189 DCHECK(thread_checker_.CalledOnValidThread()); |
188 DCHECK(handle) << "Cannot create device with NULL handle."; | 190 DCHECK(handle) << "Cannot create device with NULL handle."; |
189 DCHECK(interfaces_) << "Unabled to list interfaces"; | 191 DCHECK(interfaces_) << "Unabled to list interfaces"; |
190 } | 192 } |
191 | 193 |
192 UsbDeviceHandle::UsbDeviceHandle() : device_(NULL), handle_(NULL) { | 194 UsbDeviceHandle::UsbDeviceHandle() : device_(NULL), handle_(NULL) { |
(...skipping 19 matching lines...) Expand all Loading... |
212 void UsbDeviceHandle::TransferComplete(PlatformUsbTransferHandle handle) { | 214 void UsbDeviceHandle::TransferComplete(PlatformUsbTransferHandle handle) { |
213 DCHECK(ContainsKey(transfers_, handle)) << "Missing transfer completed"; | 215 DCHECK(ContainsKey(transfers_, handle)) << "Missing transfer completed"; |
214 | 216 |
215 Transfer transfer = transfers_[handle]; | 217 Transfer transfer = transfers_[handle]; |
216 transfers_.erase(handle); | 218 transfers_.erase(handle); |
217 | 219 |
218 DCHECK_GE(handle->actual_length, 0) << "Negative actual length received"; | 220 DCHECK_GE(handle->actual_length, 0) << "Negative actual length received"; |
219 size_t actual_length = | 221 size_t actual_length = |
220 static_cast<size_t>(std::max(handle->actual_length, 0)); | 222 static_cast<size_t>(std::max(handle->actual_length, 0)); |
221 | 223 |
222 DCHECK(transfer.length >= actual_length) << | 224 DCHECK(transfer.length >= actual_length) |
223 "data too big for our buffer (libusb failure?)"; | 225 << "data too big for our buffer (libusb failure?)"; |
224 | 226 |
225 scoped_refptr<net::IOBuffer> buffer = transfer.buffer; | 227 scoped_refptr<net::IOBuffer> buffer = transfer.buffer; |
226 switch (transfer.transfer_type) { | 228 switch (transfer.transfer_type) { |
227 case USB_TRANSFER_CONTROL: | 229 case USB_TRANSFER_CONTROL: |
228 // If the transfer is a control transfer we do not expose the control | 230 // If the transfer is a control transfer we do not expose the control |
229 // setup header to the caller. This logic strips off the header if | 231 // setup header to the caller. This logic strips off the header if |
230 // present before invoking the callback provided with the transfer. | 232 // present before invoking the callback provided with the transfer. |
231 if (actual_length > 0) { | 233 if (actual_length > 0) { |
232 CHECK(transfer.length >= LIBUSB_CONTROL_SETUP_SIZE) << | 234 CHECK(transfer.length >= LIBUSB_CONTROL_SETUP_SIZE) |
233 "buffer was not correctly set: too small for the control header"; | 235 << "buffer was not correctly set: too small for the control header"; |
234 | 236 |
235 if (transfer.length >= actual_length && | 237 if (transfer.length >= actual_length && |
236 actual_length >= LIBUSB_CONTROL_SETUP_SIZE) { | 238 actual_length >= LIBUSB_CONTROL_SETUP_SIZE) { |
237 // If the payload is zero bytes long, pad out the allocated buffer | 239 // If the payload is zero bytes long, pad out the allocated buffer |
238 // size to one byte so that an IOBuffer of that size can be allocated. | 240 // size to one byte so that an IOBuffer of that size can be allocated. |
239 scoped_refptr<net::IOBuffer> resized_buffer = new net::IOBuffer( | 241 scoped_refptr<net::IOBuffer> resized_buffer = |
240 std::max(actual_length, static_cast<size_t>(1))); | 242 new net::IOBuffer(static_cast<int>( |
| 243 std::max(actual_length, static_cast<size_t>(1)))); |
241 memcpy(resized_buffer->data(), | 244 memcpy(resized_buffer->data(), |
242 buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, | 245 buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, |
243 actual_length); | 246 actual_length); |
244 buffer = resized_buffer; | 247 buffer = resized_buffer; |
245 } | 248 } |
246 } | 249 } |
247 break; | 250 break; |
248 | 251 |
249 case USB_TRANSFER_ISOCHRONOUS: | 252 case USB_TRANSFER_ISOCHRONOUS: |
250 // Isochronous replies might carry data in the different isoc packets even | 253 // Isochronous replies might carry data in the different isoc packets even |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 ConvertTransferStatus(handle->status), | 291 ConvertTransferStatus(handle->status), |
289 buffer, | 292 buffer, |
290 actual_length)); | 293 actual_length)); |
291 | 294 |
292 // Must release interface first before actually delete this. | 295 // Must release interface first before actually delete this. |
293 transfer.claimed_interface = NULL; | 296 transfer.claimed_interface = NULL; |
294 } | 297 } |
295 | 298 |
296 bool UsbDeviceHandle::ClaimInterface(const int interface_number) { | 299 bool UsbDeviceHandle::ClaimInterface(const int interface_number) { |
297 DCHECK(thread_checker_.CalledOnValidThread()); | 300 DCHECK(thread_checker_.CalledOnValidThread()); |
298 if (!device_) return false; | 301 if (!device_) |
299 if (ContainsKey(claimed_interfaces_, interface_number)) return true; | 302 return false; |
| 303 if (ContainsKey(claimed_interfaces_, interface_number)) |
| 304 return true; |
300 | 305 |
301 scoped_refptr<InterfaceClaimer> claimer = | 306 scoped_refptr<InterfaceClaimer> claimer = |
302 new InterfaceClaimer(this, interface_number); | 307 new InterfaceClaimer(this, interface_number); |
303 | 308 |
304 if (claimer->Claim()) { | 309 if (claimer->Claim()) { |
305 claimed_interfaces_[interface_number]= claimer; | 310 claimed_interfaces_[interface_number] = claimer; |
306 RefreshEndpointMap(); | 311 RefreshEndpointMap(); |
307 return true; | 312 return true; |
308 } | 313 } |
309 return false; | 314 return false; |
310 } | 315 } |
311 | 316 |
312 bool UsbDeviceHandle::ReleaseInterface(const int interface_number) { | 317 bool UsbDeviceHandle::ReleaseInterface(const int interface_number) { |
313 DCHECK(thread_checker_.CalledOnValidThread()); | 318 DCHECK(thread_checker_.CalledOnValidThread()); |
314 if (!device_) return false; | 319 if (!device_) |
315 if (!ContainsKey(claimed_interfaces_, interface_number)) return false; | 320 return false; |
| 321 if (!ContainsKey(claimed_interfaces_, interface_number)) |
| 322 return false; |
316 | 323 |
317 // Cancel all the transfers on that interface. | 324 // Cancel all the transfers on that interface. |
318 InterfaceClaimer* interface_claimer = | 325 InterfaceClaimer* interface_claimer = |
319 claimed_interfaces_[interface_number].get(); | 326 claimed_interfaces_[interface_number].get(); |
320 for (TransferMap::iterator it = transfers_.begin(); | 327 for (TransferMap::iterator it = transfers_.begin(); it != transfers_.end(); |
321 it != transfers_.end(); ++it) { | 328 ++it) { |
322 if (it->second.claimed_interface.get() == interface_claimer) | 329 if (it->second.claimed_interface.get() == interface_claimer) |
323 libusb_cancel_transfer(it->first); | 330 libusb_cancel_transfer(it->first); |
324 } | 331 } |
325 claimed_interfaces_.erase(interface_number); | 332 claimed_interfaces_.erase(interface_number); |
326 | 333 |
327 RefreshEndpointMap(); | 334 RefreshEndpointMap(); |
328 return true; | 335 return true; |
329 } | 336 } |
330 | 337 |
331 bool UsbDeviceHandle::SetInterfaceAlternateSetting( | 338 bool UsbDeviceHandle::SetInterfaceAlternateSetting( |
332 const int interface_number, | 339 const int interface_number, |
333 const int alternate_setting) { | 340 const int alternate_setting) { |
334 DCHECK(thread_checker_.CalledOnValidThread()); | 341 DCHECK(thread_checker_.CalledOnValidThread()); |
335 if (!device_) return false; | 342 if (!device_) |
336 if (!ContainsKey(claimed_interfaces_, interface_number)) return false; | 343 return false; |
337 const int rv = libusb_set_interface_alt_setting(handle_, | 344 if (!ContainsKey(claimed_interfaces_, interface_number)) |
338 interface_number, alternate_setting); | 345 return false; |
| 346 const int rv = libusb_set_interface_alt_setting( |
| 347 handle_, interface_number, alternate_setting); |
339 if (rv == 0) { | 348 if (rv == 0) { |
340 claimed_interfaces_[interface_number]-> | 349 claimed_interfaces_[interface_number]->set_alternate_setting( |
341 set_alternate_setting(alternate_setting); | 350 alternate_setting); |
342 RefreshEndpointMap(); | 351 RefreshEndpointMap(); |
343 return true; | 352 return true; |
344 } | 353 } |
345 return false; | 354 return false; |
346 } | 355 } |
347 | 356 |
348 bool UsbDeviceHandle::ResetDevice() { | 357 bool UsbDeviceHandle::ResetDevice() { |
349 DCHECK(thread_checker_.CalledOnValidThread()); | 358 DCHECK(thread_checker_.CalledOnValidThread()); |
350 if (!device_) return false; | 359 if (!device_) |
| 360 return false; |
351 | 361 |
352 return libusb_reset_device(handle_) == 0; | 362 return libusb_reset_device(handle_) == 0; |
353 } | 363 } |
354 | 364 |
355 bool UsbDeviceHandle::GetSerial(base::string16* serial) { | 365 bool UsbDeviceHandle::GetSerial(base::string16* serial) { |
356 DCHECK(thread_checker_.CalledOnValidThread()); | 366 DCHECK(thread_checker_.CalledOnValidThread()); |
357 PlatformUsbDevice device = libusb_get_device(handle_); | 367 PlatformUsbDevice device = libusb_get_device(handle_); |
358 libusb_device_descriptor desc; | 368 libusb_device_descriptor desc; |
359 | 369 |
360 if (libusb_get_device_descriptor(device, &desc) != LIBUSB_SUCCESS) | 370 if (libusb_get_device_descriptor(device, &desc) != LIBUSB_SUCCESS) |
361 return false; | 371 return false; |
362 | 372 |
363 if (desc.iSerialNumber == 0) | 373 if (desc.iSerialNumber == 0) |
364 return false; | 374 return false; |
365 | 375 |
366 // Getting supported language ID. | 376 // Getting supported language ID. |
367 uint16 langid[128] = { 0 }; | 377 uint16 langid[128] = {0}; |
368 | 378 |
369 int size = libusb_get_string_descriptor( | 379 int size = |
370 handle_, 0, 0, | 380 libusb_get_string_descriptor(handle_, |
371 reinterpret_cast<unsigned char*>(&langid[0]), sizeof(langid)); | 381 0, |
| 382 0, |
| 383 reinterpret_cast<unsigned char*>(&langid[0]), |
| 384 sizeof(langid)); |
372 if (size < 0) | 385 if (size < 0) |
373 return false; | 386 return false; |
374 | 387 |
375 int language_count = (size - 2) / 2; | 388 int language_count = (size - 2) / 2; |
376 | 389 |
377 for (int i = 1; i <= language_count; ++i) { | 390 for (int i = 1; i <= language_count; ++i) { |
378 // Get the string using language ID. | 391 // Get the string using language ID. |
379 base::char16 text[256] = { 0 }; | 392 base::char16 text[256] = {0}; |
380 size = libusb_get_string_descriptor( | 393 size = |
381 handle_, desc.iSerialNumber, langid[i], | 394 libusb_get_string_descriptor(handle_, |
382 reinterpret_cast<unsigned char*>(&text[0]), sizeof(text)); | 395 desc.iSerialNumber, |
| 396 langid[i], |
| 397 reinterpret_cast<unsigned char*>(&text[0]), |
| 398 sizeof(text)); |
383 if (size <= 2) | 399 if (size <= 2) |
384 continue; | 400 continue; |
385 if ((text[0] >> 8) != LIBUSB_DT_STRING) | 401 if ((text[0] >> 8) != LIBUSB_DT_STRING) |
386 continue; | 402 continue; |
387 if ((text[0] & 255) > size) | 403 if ((text[0] & 255) > size) |
388 continue; | 404 continue; |
389 | 405 |
390 size = size / 2 - 1; | 406 size = size / 2 - 1; |
391 *serial = base::string16(text + 1, size); | 407 *serial = base::string16(text + 1, size); |
392 return true; | 408 return true; |
393 } | 409 } |
394 return false; | 410 return false; |
395 } | 411 } |
396 | 412 |
397 void UsbDeviceHandle::ControlTransfer(const UsbEndpointDirection direction, | 413 void UsbDeviceHandle::ControlTransfer(const UsbEndpointDirection direction, |
398 const TransferRequestType request_type, const TransferRecipient recipient, | 414 const TransferRequestType request_type, |
399 const uint8 request, const uint16 value, const uint16 index, | 415 const TransferRecipient recipient, |
400 net::IOBuffer* buffer, const size_t length, const unsigned int timeout, | 416 const uint8 request, |
401 const UsbTransferCallback& callback) { | 417 const uint16 value, |
| 418 const uint16 index, |
| 419 net::IOBuffer* buffer, |
| 420 const size_t length, |
| 421 const unsigned int timeout, |
| 422 const UsbTransferCallback& callback) { |
402 if (!device_) { | 423 if (!device_) { |
403 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); | 424 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); |
404 return; | 425 return; |
405 } | 426 } |
406 | 427 |
407 const size_t resized_length = LIBUSB_CONTROL_SETUP_SIZE + length; | 428 const size_t resized_length = LIBUSB_CONTROL_SETUP_SIZE + length; |
408 scoped_refptr<net::IOBuffer> resized_buffer(new net::IOBufferWithSize( | 429 scoped_refptr<net::IOBuffer> resized_buffer( |
409 resized_length)); | 430 new net::IOBufferWithSize(static_cast<int>(resized_length))); |
410 memcpy(resized_buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, buffer->data(), | 431 if (!resized_buffer) { |
411 length); | 432 callback.Run(USB_TRANSFER_ERROR, buffer, 0); |
| 433 return; |
| 434 } |
| 435 memcpy(resized_buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, |
| 436 buffer->data(), |
| 437 static_cast<int>(length)); |
412 | 438 |
413 PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(0); | 439 PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(0); |
414 const uint8 converted_type = CreateRequestType(direction, request_type, | 440 const uint8 converted_type = |
415 recipient); | 441 CreateRequestType(direction, request_type, recipient); |
416 libusb_fill_control_setup(reinterpret_cast<uint8*>(resized_buffer->data()), | 442 libusb_fill_control_setup(reinterpret_cast<uint8*>(resized_buffer->data()), |
417 converted_type, request, value, index, length); | 443 converted_type, |
418 libusb_fill_control_transfer( | 444 request, |
419 transfer, | 445 value, |
420 handle_, | 446 index, |
421 reinterpret_cast<uint8*>(resized_buffer->data()), | 447 static_cast<int16>(length)); |
422 PlatformTransferCompletionCallback, | 448 libusb_fill_control_transfer(transfer, |
423 this, | 449 handle_, |
424 timeout); | 450 reinterpret_cast<uint8*>(resized_buffer->data()), |
| 451 PlatformTransferCompletionCallback, |
| 452 this, |
| 453 timeout); |
425 | 454 |
426 BrowserThread::PostTask( | 455 BrowserThread::PostTask(BrowserThread::FILE, |
427 BrowserThread::FILE, | 456 FROM_HERE, |
428 FROM_HERE, | 457 base::Bind(&UsbDeviceHandle::SubmitTransfer, |
429 base::Bind(&UsbDeviceHandle::SubmitTransfer, | 458 this, |
430 this, | 459 transfer, |
431 transfer, | 460 USB_TRANSFER_CONTROL, |
432 USB_TRANSFER_CONTROL, | 461 resized_buffer, |
433 resized_buffer, | 462 resized_length, |
434 resized_length, | 463 base::MessageLoopProxy::current(), |
435 base::MessageLoopProxy::current(), | 464 callback)); |
436 callback)); | |
437 } | 465 } |
438 | 466 |
439 void UsbDeviceHandle::BulkTransfer(const UsbEndpointDirection direction, | 467 void UsbDeviceHandle::BulkTransfer(const UsbEndpointDirection direction, |
440 const uint8 endpoint, net::IOBuffer* buffer, const size_t length, | 468 const uint8 endpoint, |
441 const unsigned int timeout, const UsbTransferCallback& callback) { | 469 net::IOBuffer* buffer, |
| 470 const size_t length, |
| 471 const unsigned int timeout, |
| 472 const UsbTransferCallback& callback) { |
442 if (!device_) { | 473 if (!device_) { |
443 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); | 474 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); |
444 return; | 475 return; |
445 } | 476 } |
446 | 477 |
447 PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(0); | 478 PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(0); |
448 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; | 479 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; |
449 libusb_fill_bulk_transfer(transfer, handle_, new_endpoint, | 480 libusb_fill_bulk_transfer(transfer, |
450 reinterpret_cast<uint8*>(buffer->data()), length, | 481 handle_, |
451 PlatformTransferCompletionCallback, this, timeout); | 482 new_endpoint, |
| 483 reinterpret_cast<uint8*>(buffer->data()), |
| 484 static_cast<int>(length), |
| 485 PlatformTransferCompletionCallback, |
| 486 this, |
| 487 timeout); |
452 | 488 |
453 BrowserThread::PostTask( | 489 BrowserThread::PostTask(BrowserThread::FILE, |
454 BrowserThread::FILE, | 490 FROM_HERE, |
455 FROM_HERE, | 491 base::Bind(&UsbDeviceHandle::SubmitTransfer, |
456 base::Bind(&UsbDeviceHandle::SubmitTransfer, | 492 this, |
457 this, | 493 transfer, |
458 transfer, | 494 USB_TRANSFER_BULK, |
459 USB_TRANSFER_BULK, | 495 make_scoped_refptr(buffer), |
460 make_scoped_refptr(buffer), | 496 length, |
461 length, | 497 base::MessageLoopProxy::current(), |
462 base::MessageLoopProxy::current(), | 498 callback)); |
463 callback)); | |
464 } | 499 } |
465 | 500 |
466 void UsbDeviceHandle::InterruptTransfer(const UsbEndpointDirection direction, | 501 void UsbDeviceHandle::InterruptTransfer(const UsbEndpointDirection direction, |
467 const uint8 endpoint, net::IOBuffer* buffer, const size_t length, | 502 const uint8 endpoint, |
468 const unsigned int timeout, const UsbTransferCallback& callback) { | 503 net::IOBuffer* buffer, |
| 504 const size_t length, |
| 505 const unsigned int timeout, |
| 506 const UsbTransferCallback& callback) { |
469 if (!device_) { | 507 if (!device_) { |
470 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); | 508 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); |
471 return; | 509 return; |
472 } | 510 } |
473 | 511 |
474 PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(0); | 512 PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(0); |
475 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; | 513 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; |
476 libusb_fill_interrupt_transfer(transfer, handle_, new_endpoint, | 514 libusb_fill_interrupt_transfer(transfer, |
477 reinterpret_cast<uint8*>(buffer->data()), length, | 515 handle_, |
478 PlatformTransferCompletionCallback, this, timeout); | 516 new_endpoint, |
479 BrowserThread::PostTask( | 517 reinterpret_cast<uint8*>(buffer->data()), |
480 BrowserThread::FILE, | 518 static_cast<int>(length), |
481 FROM_HERE, | 519 PlatformTransferCompletionCallback, |
482 base::Bind(&UsbDeviceHandle::SubmitTransfer, | 520 this, |
483 this, | 521 timeout); |
484 transfer, | 522 BrowserThread::PostTask(BrowserThread::FILE, |
485 USB_TRANSFER_INTERRUPT, | 523 FROM_HERE, |
486 make_scoped_refptr(buffer), | 524 base::Bind(&UsbDeviceHandle::SubmitTransfer, |
487 length, | 525 this, |
488 base::MessageLoopProxy::current(), | 526 transfer, |
489 callback)); | 527 USB_TRANSFER_INTERRUPT, |
| 528 make_scoped_refptr(buffer), |
| 529 length, |
| 530 base::MessageLoopProxy::current(), |
| 531 callback)); |
490 } | 532 } |
491 | 533 |
492 void UsbDeviceHandle::IsochronousTransfer(const UsbEndpointDirection direction, | 534 void UsbDeviceHandle::IsochronousTransfer(const UsbEndpointDirection direction, |
493 const uint8 endpoint, net::IOBuffer* buffer, const size_t length, | 535 const uint8 endpoint, |
494 const unsigned int packets, const unsigned int packet_length, | 536 net::IOBuffer* buffer, |
495 const unsigned int timeout, const UsbTransferCallback& callback) { | 537 const size_t length, |
| 538 const unsigned int packets, |
| 539 const unsigned int packet_length, |
| 540 const unsigned int timeout, |
| 541 const UsbTransferCallback& callback) { |
496 if (!device_) { | 542 if (!device_) { |
497 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); | 543 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); |
498 return; | 544 return; |
499 } | 545 } |
500 | 546 |
501 const uint64 total_length = packets * packet_length; | 547 const uint64 total_length = packets * packet_length; |
502 CHECK(packets <= length && total_length <= length) << | 548 CHECK(packets <= length && total_length <= length) |
503 "transfer length is too small"; | 549 << "transfer length is too small"; |
504 | 550 |
505 PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(packets); | 551 PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(packets); |
506 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; | 552 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; |
507 libusb_fill_iso_transfer(transfer, handle_, new_endpoint, | 553 libusb_fill_iso_transfer(transfer, |
508 reinterpret_cast<uint8*>(buffer->data()), length, packets, | 554 handle_, |
509 PlatformTransferCompletionCallback, this, timeout); | 555 new_endpoint, |
| 556 reinterpret_cast<uint8*>(buffer->data()), |
| 557 static_cast<int>(length), |
| 558 packets, |
| 559 PlatformTransferCompletionCallback, |
| 560 this, |
| 561 timeout); |
510 libusb_set_iso_packet_lengths(transfer, packet_length); | 562 libusb_set_iso_packet_lengths(transfer, packet_length); |
511 | 563 |
512 BrowserThread::PostTask( | 564 BrowserThread::PostTask(BrowserThread::FILE, |
513 BrowserThread::FILE, | 565 FROM_HERE, |
514 FROM_HERE, | 566 base::Bind(&UsbDeviceHandle::SubmitTransfer, |
515 base::Bind(&UsbDeviceHandle::SubmitTransfer, | 567 this, |
516 this, | 568 transfer, |
517 transfer, | 569 USB_TRANSFER_ISOCHRONOUS, |
518 USB_TRANSFER_ISOCHRONOUS, | 570 make_scoped_refptr(buffer), |
519 make_scoped_refptr(buffer), | 571 length, |
520 length, | 572 base::MessageLoopProxy::current(), |
521 base::MessageLoopProxy::current(), | 573 callback)); |
522 callback)); | |
523 } | 574 } |
524 | 575 |
525 void UsbDeviceHandle::RefreshEndpointMap() { | 576 void UsbDeviceHandle::RefreshEndpointMap() { |
526 DCHECK(thread_checker_.CalledOnValidThread()); | 577 DCHECK(thread_checker_.CalledOnValidThread()); |
527 endpoint_map_.clear(); | 578 endpoint_map_.clear(); |
528 for (ClaimedInterfaceMap::iterator it = claimed_interfaces_.begin(); | 579 for (ClaimedInterfaceMap::iterator it = claimed_interfaces_.begin(); |
529 it != claimed_interfaces_.end(); ++it) { | 580 it != claimed_interfaces_.end(); |
| 581 ++it) { |
530 scoped_refptr<const UsbInterfaceAltSettingDescriptor> interface_desc = | 582 scoped_refptr<const UsbInterfaceAltSettingDescriptor> interface_desc = |
531 interfaces_->GetInterface(it->first)->GetAltSetting( | 583 interfaces_->GetInterface(it->first) |
532 it->second->alternate_setting()); | 584 ->GetAltSetting(it->second->alternate_setting()); |
533 for (size_t i = 0; i < interface_desc->GetNumEndpoints(); i++) { | 585 for (size_t i = 0; i < interface_desc->GetNumEndpoints(); i++) { |
534 scoped_refptr<const UsbEndpointDescriptor> endpoint = | 586 scoped_refptr<const UsbEndpointDescriptor> endpoint = |
535 interface_desc->GetEndpoint(i); | 587 interface_desc->GetEndpoint(i); |
536 endpoint_map_[endpoint->GetAddress()] = it->first; | 588 endpoint_map_[endpoint->GetAddress()] = it->first; |
537 } | 589 } |
538 } | 590 } |
539 } | 591 } |
540 | 592 |
541 scoped_refptr<UsbDeviceHandle::InterfaceClaimer> | 593 scoped_refptr<UsbDeviceHandle::InterfaceClaimer> |
542 UsbDeviceHandle::GetClaimedInterfaceForEndpoint(unsigned char endpoint) { | 594 UsbDeviceHandle::GetClaimedInterfaceForEndpoint(unsigned char endpoint) { |
543 unsigned char address = endpoint & LIBUSB_ENDPOINT_ADDRESS_MASK; | 595 unsigned char address = endpoint & LIBUSB_ENDPOINT_ADDRESS_MASK; |
544 if (ContainsKey(endpoint_map_, address)) | 596 if (ContainsKey(endpoint_map_, address)) |
545 return claimed_interfaces_[endpoint_map_[address]]; | 597 return claimed_interfaces_[endpoint_map_[address]]; |
546 return NULL; | 598 return NULL; |
547 } | 599 } |
548 | 600 |
549 void UsbDeviceHandle::SubmitTransfer( | 601 void UsbDeviceHandle::SubmitTransfer( |
550 PlatformUsbTransferHandle handle, | 602 PlatformUsbTransferHandle handle, |
551 UsbTransferType transfer_type, | 603 UsbTransferType transfer_type, |
552 net::IOBuffer* buffer, | 604 net::IOBuffer* buffer, |
553 const size_t length, | 605 const size_t length, |
554 scoped_refptr<base::MessageLoopProxy> message_loop_proxy, | 606 scoped_refptr<base::MessageLoopProxy> message_loop_proxy, |
555 const UsbTransferCallback& callback) { | 607 const UsbTransferCallback& callback) { |
556 DCHECK(thread_checker_.CalledOnValidThread()); | 608 DCHECK(thread_checker_.CalledOnValidThread()); |
557 if (!device_) { | 609 if (!device_) { |
558 message_loop_proxy->PostTask( | 610 message_loop_proxy->PostTask( |
559 FROM_HERE, | 611 FROM_HERE, |
560 base::Bind(callback, USB_TRANSFER_DISCONNECT, | 612 base::Bind( |
561 make_scoped_refptr(buffer), 0)); | 613 callback, USB_TRANSFER_DISCONNECT, make_scoped_refptr(buffer), 0)); |
562 } | 614 } |
563 | 615 |
564 Transfer transfer; | 616 Transfer transfer; |
565 transfer.transfer_type = transfer_type; | 617 transfer.transfer_type = transfer_type; |
566 transfer.buffer = buffer; | 618 transfer.buffer = buffer; |
567 transfer.length = length; | 619 transfer.length = length; |
568 transfer.callback = callback; | 620 transfer.callback = callback; |
569 transfer.message_loop_proxy = message_loop_proxy; | 621 transfer.message_loop_proxy = message_loop_proxy; |
570 | 622 |
571 // It's OK for this method to return NULL. libusb_submit_transfer will fail if | 623 // It's OK for this method to return NULL. libusb_submit_transfer will fail if |
572 // it requires an interface we didn't claim. | 624 // it requires an interface we didn't claim. |
573 transfer.claimed_interface = GetClaimedInterfaceForEndpoint(handle->endpoint); | 625 transfer.claimed_interface = GetClaimedInterfaceForEndpoint(handle->endpoint); |
574 | 626 |
575 if (libusb_submit_transfer(handle) == LIBUSB_SUCCESS) { | 627 if (libusb_submit_transfer(handle) == LIBUSB_SUCCESS) { |
576 transfers_[handle] = transfer; | 628 transfers_[handle] = transfer; |
577 } else { | 629 } else { |
578 message_loop_proxy->PostTask( | 630 message_loop_proxy->PostTask( |
579 FROM_HERE, | 631 FROM_HERE, |
580 base::Bind(callback, USB_TRANSFER_ERROR, | 632 base::Bind( |
581 make_scoped_refptr(buffer), 0)); | 633 callback, USB_TRANSFER_ERROR, make_scoped_refptr(buffer), 0)); |
582 } | 634 } |
583 } | 635 } |
584 | 636 |
585 void UsbDeviceHandle::InternalClose() { | 637 void UsbDeviceHandle::InternalClose() { |
586 DCHECK(thread_checker_.CalledOnValidThread()); | 638 DCHECK(thread_checker_.CalledOnValidThread()); |
587 if (!device_) return; | 639 if (!device_) |
| 640 return; |
588 | 641 |
589 // Cancel all the transfers. | 642 // Cancel all the transfers. |
590 for (TransferMap::iterator it = transfers_.begin(); | 643 for (TransferMap::iterator it = transfers_.begin(); it != transfers_.end(); |
591 it != transfers_.end(); ++it) { | 644 ++it) { |
592 // The callback will be called some time later. | 645 // The callback will be called some time later. |
593 libusb_cancel_transfer(it->first); | 646 libusb_cancel_transfer(it->first); |
594 } | 647 } |
595 | 648 |
596 // Attempt-release all the interfaces. | 649 // Attempt-release all the interfaces. |
597 // It will be retained until the transfer cancellation is finished. | 650 // It will be retained until the transfer cancellation is finished. |
598 claimed_interfaces_.clear(); | 651 claimed_interfaces_.clear(); |
599 | 652 |
600 // Cannot close device handle here. Need to wait for libusb_cancel_transfer to | 653 // Cannot close device handle here. Need to wait for libusb_cancel_transfer to |
601 // finish. | 654 // finish. |
602 device_ = NULL; | 655 device_ = NULL; |
603 } | 656 } |
| 657 |
| 658 } // namespace usb_service |
OLD | NEW |