Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / device / usb / usb_device_impl.cc
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
3 // found in the LICENSE file.
4
5 #include "device/usb/usb_device_impl.h"
6
7 #include <algorithm>
8
9 #include "base/bind.h"
10 #include "base/location.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/stl_util.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "device/usb/usb_context.h"
17 #include "device/usb/usb_descriptors.h"
18 #include "device/usb/usb_device_handle_impl.h"
19 #include "device/usb/usb_error.h"
20 #include "third_party/libusb/src/libusb/libusb.h"
21
22 #if defined(OS_CHROMEOS)
23 #include "base/sys_info.h"
24 #include "chromeos/dbus/dbus_thread_manager.h"
25 #include "chromeos/dbus/permission_broker_client.h"
26 #endif  // defined(OS_CHROMEOS)
27
28 #if defined(USE_UDEV)
29 #include "device/udev_linux/scoped_udev.h"
30 #endif  // defined(USE_UDEV)
31
32 namespace device {
33
34 namespace {
35
36 #if defined(OS_CHROMEOS)
37 void OnRequestUsbAccessReplied(
38     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
39     const base::Callback<void(bool success)>& callback,
40     bool success) {
41   task_runner->PostTask(FROM_HERE, base::Bind(callback, success));
42 }
43 #endif  // defined(OS_CHROMEOS)
44
45 UsbEndpointDirection GetDirection(
46     const libusb_endpoint_descriptor* descriptor) {
47   switch (descriptor->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) {
48     case LIBUSB_ENDPOINT_IN:
49       return USB_DIRECTION_INBOUND;
50     case LIBUSB_ENDPOINT_OUT:
51       return USB_DIRECTION_OUTBOUND;
52     default:
53       NOTREACHED();
54       return USB_DIRECTION_INBOUND;
55   }
56 }
57
58 UsbSynchronizationType GetSynchronizationType(
59     const libusb_endpoint_descriptor* descriptor) {
60   switch ((descriptor->bmAttributes & LIBUSB_ISO_SYNC_TYPE_MASK) >> 2) {
61     case LIBUSB_ISO_SYNC_TYPE_NONE:
62       return USB_SYNCHRONIZATION_NONE;
63     case LIBUSB_ISO_SYNC_TYPE_ASYNC:
64       return USB_SYNCHRONIZATION_ASYNCHRONOUS;
65     case LIBUSB_ISO_SYNC_TYPE_ADAPTIVE:
66       return USB_SYNCHRONIZATION_ADAPTIVE;
67     case LIBUSB_ISO_SYNC_TYPE_SYNC:
68       return USB_SYNCHRONIZATION_SYNCHRONOUS;
69     default:
70       NOTREACHED();
71       return USB_SYNCHRONIZATION_NONE;
72   }
73 }
74
75 UsbTransferType GetTransferType(const libusb_endpoint_descriptor* descriptor) {
76   switch (descriptor->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) {
77     case LIBUSB_TRANSFER_TYPE_CONTROL:
78       return USB_TRANSFER_CONTROL;
79     case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
80       return USB_TRANSFER_ISOCHRONOUS;
81     case LIBUSB_TRANSFER_TYPE_BULK:
82       return USB_TRANSFER_BULK;
83     case LIBUSB_TRANSFER_TYPE_INTERRUPT:
84       return USB_TRANSFER_INTERRUPT;
85     default:
86       NOTREACHED();
87       return USB_TRANSFER_CONTROL;
88   }
89 }
90
91 UsbUsageType GetUsageType(const libusb_endpoint_descriptor* descriptor) {
92   switch ((descriptor->bmAttributes & LIBUSB_ISO_USAGE_TYPE_MASK) >> 4) {
93     case LIBUSB_ISO_USAGE_TYPE_DATA:
94       return USB_USAGE_DATA;
95     case LIBUSB_ISO_USAGE_TYPE_FEEDBACK:
96       return USB_USAGE_FEEDBACK;
97     case LIBUSB_ISO_USAGE_TYPE_IMPLICIT:
98       return USB_USAGE_EXPLICIT_FEEDBACK;
99     default:
100       NOTREACHED();
101       return USB_USAGE_DATA;
102   }
103 }
104
105 }  // namespace
106
107 UsbDevice::UsbDevice(uint16 vendor_id, uint16 product_id, uint32 unique_id)
108     : vendor_id_(vendor_id), product_id_(product_id), unique_id_(unique_id) {
109 }
110
111 UsbDevice::~UsbDevice() {
112 }
113
114 void UsbDevice::NotifyDisconnect() {
115   FOR_EACH_OBSERVER(Observer, observer_list_, OnDisconnect(this));
116 }
117
118 UsbDeviceImpl::UsbDeviceImpl(
119     scoped_refptr<UsbContext> context,
120     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
121     PlatformUsbDevice platform_device,
122     uint16 vendor_id,
123     uint16 product_id,
124     uint32 unique_id)
125     : UsbDevice(vendor_id, product_id, unique_id),
126       platform_device_(platform_device),
127       current_configuration_cached_(false),
128       context_(context),
129       ui_task_runner_(ui_task_runner) {
130   CHECK(platform_device) << "platform_device cannot be NULL";
131   libusb_ref_device(platform_device);
132
133 #if defined(USE_UDEV)
134   ScopedUdevPtr udev(udev_new());
135   ScopedUdevEnumeratePtr enumerate(udev_enumerate_new(udev.get()));
136
137   udev_enumerate_add_match_subsystem(enumerate.get(), "usb");
138   if (udev_enumerate_scan_devices(enumerate.get()) != 0) {
139     return;
140   }
141   std::string bus_number =
142       base::IntToString(libusb_get_bus_number(platform_device));
143   std::string device_address =
144       base::IntToString(libusb_get_device_address(platform_device));
145   udev_list_entry* devices = udev_enumerate_get_list_entry(enumerate.get());
146   for (udev_list_entry* i = devices; i != NULL;
147        i = udev_list_entry_get_next(i)) {
148     ScopedUdevDevicePtr device(
149         udev_device_new_from_syspath(udev.get(), udev_list_entry_get_name(i)));
150     if (device) {
151       const char* value = udev_device_get_sysattr_value(device.get(), "busnum");
152       if (!value || bus_number != value) {
153         continue;
154       }
155       value = udev_device_get_sysattr_value(device.get(), "devnum");
156       if (!value || device_address != value) {
157         continue;
158       }
159
160       value = udev_device_get_sysattr_value(device.get(), "manufacturer");
161       if (value) {
162         manufacturer_ = base::UTF8ToUTF16(value);
163       }
164       value = udev_device_get_sysattr_value(device.get(), "product");
165       if (value) {
166         product_ = base::UTF8ToUTF16(value);
167       }
168       value = udev_device_get_sysattr_value(device.get(), "serial");
169       if (value) {
170         serial_number_ = base::UTF8ToUTF16(value);
171       }
172       break;
173     }
174   }
175 #else
176   strings_cached_ = false;
177 #endif
178 }
179
180 UsbDeviceImpl::~UsbDeviceImpl() {
181   DCHECK(thread_checker_.CalledOnValidThread());
182   for (HandlesVector::iterator it = handles_.begin(); it != handles_.end();
183        ++it) {
184     (*it)->InternalClose();
185   }
186   STLClearObject(&handles_);
187   libusb_unref_device(platform_device_);
188 }
189
190 #if defined(OS_CHROMEOS)
191
192 void UsbDeviceImpl::RequestUsbAccess(
193     int interface_id,
194     const base::Callback<void(bool success)>& callback) {
195   DCHECK(thread_checker_.CalledOnValidThread());
196
197   // ChromeOS builds on non-ChromeOS machines (dev) should not attempt to
198   // use permission broker.
199   if (base::SysInfo::IsRunningOnChromeOS()) {
200     chromeos::PermissionBrokerClient* client =
201         chromeos::DBusThreadManager::Get()->GetPermissionBrokerClient();
202     DCHECK(client) << "Could not get permission broker client.";
203     if (!client) {
204       callback.Run(false);
205       return;
206     }
207
208     ui_task_runner_->PostTask(
209         FROM_HERE,
210         base::Bind(&chromeos::PermissionBrokerClient::RequestUsbAccess,
211                    base::Unretained(client),
212                    vendor_id(),
213                    product_id(),
214                    interface_id,
215                    base::Bind(&OnRequestUsbAccessReplied,
216                               base::ThreadTaskRunnerHandle::Get(),
217                               callback)));
218   }
219 }
220
221 #endif
222
223 scoped_refptr<UsbDeviceHandle> UsbDeviceImpl::Open() {
224   DCHECK(thread_checker_.CalledOnValidThread());
225   PlatformUsbDeviceHandle handle;
226   const int rv = libusb_open(platform_device_, &handle);
227   if (LIBUSB_SUCCESS == rv) {
228     GetConfiguration();
229     if (!current_configuration_cached_) {
230       libusb_close(handle);
231       return NULL;
232     }
233     scoped_refptr<UsbDeviceHandleImpl> device_handle =
234         new UsbDeviceHandleImpl(context_, this, handle, current_configuration_);
235     handles_.push_back(device_handle);
236     return device_handle;
237   } else {
238     VLOG(1) << "Failed to open device: " << ConvertPlatformUsbErrorToString(rv);
239     return NULL;
240   }
241 }
242
243 bool UsbDeviceImpl::Close(scoped_refptr<UsbDeviceHandle> handle) {
244   DCHECK(thread_checker_.CalledOnValidThread());
245
246   for (HandlesVector::iterator it = handles_.begin(); it != handles_.end();
247        ++it) {
248     if (it->get() == handle.get()) {
249       (*it)->InternalClose();
250       handles_.erase(it);
251       return true;
252     }
253   }
254   return false;
255 }
256
257 const UsbConfigDescriptor& UsbDeviceImpl::GetConfiguration() {
258   DCHECK(thread_checker_.CalledOnValidThread());
259
260   if (!current_configuration_cached_) {
261     libusb_config_descriptor* platform_config;
262     const int rv =
263         libusb_get_active_config_descriptor(platform_device_, &platform_config);
264     if (rv != LIBUSB_SUCCESS) {
265       VLOG(1) << "Failed to get config descriptor: "
266               << ConvertPlatformUsbErrorToString(rv);
267       return current_configuration_;
268     }
269
270     current_configuration_.configuration_value =
271         platform_config->bConfigurationValue;
272     current_configuration_.self_powered =
273         (platform_config->bmAttributes & 0x40) != 0;
274     current_configuration_.remote_wakeup =
275         (platform_config->bmAttributes & 0x20) != 0;
276     current_configuration_.maximum_power = platform_config->MaxPower * 2;
277
278     for (size_t i = 0; i < platform_config->bNumInterfaces; ++i) {
279       const struct libusb_interface* platform_interface =
280           &platform_config->interface[i];
281       for (int j = 0; j < platform_interface->num_altsetting; ++j) {
282         const struct libusb_interface_descriptor* platform_alt_setting =
283             &platform_interface->altsetting[j];
284         UsbInterfaceDescriptor interface;
285
286         interface.interface_number = platform_alt_setting->bInterfaceNumber;
287         interface.alternate_setting = platform_alt_setting->bAlternateSetting;
288         interface.interface_class = platform_alt_setting->bInterfaceClass;
289         interface.interface_subclass = platform_alt_setting->bInterfaceSubClass;
290         interface.interface_protocol = platform_alt_setting->bInterfaceProtocol;
291
292         for (size_t k = 0; k < platform_alt_setting->bNumEndpoints; ++k) {
293           const struct libusb_endpoint_descriptor* platform_endpoint =
294               &platform_alt_setting->endpoint[k];
295           UsbEndpointDescriptor endpoint;
296
297           endpoint.address = platform_endpoint->bEndpointAddress;
298           endpoint.direction = GetDirection(platform_endpoint);
299           endpoint.maximum_packet_size = platform_endpoint->wMaxPacketSize;
300           endpoint.synchronization_type =
301               GetSynchronizationType(platform_endpoint);
302           endpoint.transfer_type = GetTransferType(platform_endpoint);
303           endpoint.usage_type = GetUsageType(platform_endpoint);
304           endpoint.polling_interval = platform_endpoint->bInterval;
305           endpoint.extra_data = std::vector<uint8_t>(
306               platform_endpoint->extra,
307               platform_endpoint->extra + platform_endpoint->extra_length);
308
309           interface.endpoints.push_back(endpoint);
310         }
311
312         interface.extra_data = std::vector<uint8_t>(
313             platform_alt_setting->extra,
314             platform_alt_setting->extra + platform_alt_setting->extra_length);
315
316         current_configuration_.interfaces.push_back(interface);
317       }
318     }
319
320     current_configuration_.extra_data = std::vector<uint8_t>(
321         platform_config->extra,
322         platform_config->extra + platform_config->extra_length);
323
324     libusb_free_config_descriptor(platform_config);
325     current_configuration_cached_ = true;
326   }
327
328   return current_configuration_;
329 }
330
331 bool UsbDeviceImpl::GetManufacturer(base::string16* manufacturer) {
332   DCHECK(thread_checker_.CalledOnValidThread());
333
334 #if !defined(USE_UDEV)
335   if (!strings_cached_) {
336     CacheStrings();
337   }
338 #endif
339
340   *manufacturer = manufacturer_;
341   return !manufacturer_.empty();
342 }
343
344 bool UsbDeviceImpl::GetProduct(base::string16* product) {
345   DCHECK(thread_checker_.CalledOnValidThread());
346
347 #if !defined(USE_UDEV)
348   if (!strings_cached_) {
349     CacheStrings();
350   }
351 #endif
352
353   *product = product_;
354   return !product_.empty();
355 }
356
357 bool UsbDeviceImpl::GetSerialNumber(base::string16* serial_number) {
358   DCHECK(thread_checker_.CalledOnValidThread());
359
360 #if !defined(USE_UDEV)
361   if (!strings_cached_) {
362     CacheStrings();
363   }
364 #endif
365
366   *serial_number = serial_number_;
367   return !serial_number_.empty();
368 }
369
370 void UsbDeviceImpl::OnDisconnect() {
371   DCHECK(thread_checker_.CalledOnValidThread());
372   HandlesVector handles;
373   swap(handles, handles_);
374   for (HandlesVector::iterator it = handles.begin(); it != handles.end(); ++it)
375     (*it)->InternalClose();
376 }
377
378 #if !defined(USE_UDEV)
379 void UsbDeviceImpl::CacheStrings() {
380   DCHECK(thread_checker_.CalledOnValidThread());
381   // This is a non-blocking call as libusb has the descriptor in memory.
382   libusb_device_descriptor desc;
383   const int rv = libusb_get_device_descriptor(platform_device_, &desc);
384   if (rv == LIBUSB_SUCCESS) {
385     scoped_refptr<UsbDeviceHandle> device_handle = Open();
386     if (device_handle.get()) {
387       if (desc.iManufacturer != 0) {
388         device_handle->GetStringDescriptor(desc.iManufacturer, &manufacturer_);
389       }
390       if (desc.iProduct != 0) {
391         device_handle->GetStringDescriptor(desc.iProduct, &product_);
392       }
393       if (desc.iSerialNumber != 0) {
394         device_handle->GetStringDescriptor(desc.iSerialNumber, &serial_number_);
395       }
396       device_handle->Close();
397     } else {
398       VLOG(1) << "Failed to open device to cache string descriptors.";
399     }
400   } else {
401     VLOG(1) << "Failed to read device descriptor to cache string descriptors: "
402             << ConvertPlatformUsbErrorToString(rv);
403   }
404   strings_cached_ = true;
405 }
406 #endif  // !defined(USE_UDEV)
407
408 }  // namespace device