Upstream version 10.39.225.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/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) {
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) {
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       manufacturer_ = value ? value : "";
162       value = udev_device_get_sysattr_value(device.get(), "product");
163       product_ = value ? value : "";
164       value = udev_device_get_sysattr_value(device.get(), "serial");
165       serial_number_ = value ? value : "";
166       break;
167     }
168   }
169 #endif
170 }
171
172 UsbDeviceImpl::~UsbDeviceImpl() {
173   DCHECK(thread_checker_.CalledOnValidThread());
174   for (HandlesVector::iterator it = handles_.begin(); it != handles_.end();
175        ++it) {
176     (*it)->InternalClose();
177   }
178   STLClearObject(&handles_);
179   libusb_unref_device(platform_device_);
180 }
181
182 #if defined(OS_CHROMEOS)
183
184 void UsbDeviceImpl::RequestUsbAccess(
185     int interface_id,
186     const base::Callback<void(bool success)>& callback) {
187   DCHECK(thread_checker_.CalledOnValidThread());
188
189   // ChromeOS builds on non-ChromeOS machines (dev) should not attempt to
190   // use permission broker.
191   if (base::SysInfo::IsRunningOnChromeOS()) {
192     chromeos::PermissionBrokerClient* client =
193         chromeos::DBusThreadManager::Get()->GetPermissionBrokerClient();
194     DCHECK(client) << "Could not get permission broker client.";
195     if (!client) {
196       callback.Run(false);
197       return;
198     }
199
200     ui_task_runner_->PostTask(
201         FROM_HERE,
202         base::Bind(&chromeos::PermissionBrokerClient::RequestUsbAccess,
203                    base::Unretained(client),
204                    vendor_id(),
205                    product_id(),
206                    interface_id,
207                    base::Bind(&OnRequestUsbAccessReplied,
208                               base::ThreadTaskRunnerHandle::Get(),
209                               callback)));
210   }
211 }
212
213 #endif
214
215 scoped_refptr<UsbDeviceHandle> UsbDeviceImpl::Open() {
216   DCHECK(thread_checker_.CalledOnValidThread());
217   PlatformUsbDeviceHandle handle;
218   const int rv = libusb_open(platform_device_, &handle);
219   if (LIBUSB_SUCCESS == rv) {
220     GetConfiguration();
221     if (!current_configuration_cached_) {
222       return NULL;
223     }
224     scoped_refptr<UsbDeviceHandleImpl> device_handle =
225         new UsbDeviceHandleImpl(context_, this, handle, current_configuration_);
226     handles_.push_back(device_handle);
227     return device_handle;
228   } else {
229     VLOG(1) << "Failed to open device: " << ConvertPlatformUsbErrorToString(rv);
230     return NULL;
231   }
232 }
233
234 bool UsbDeviceImpl::Close(scoped_refptr<UsbDeviceHandle> handle) {
235   DCHECK(thread_checker_.CalledOnValidThread());
236
237   for (HandlesVector::iterator it = handles_.begin(); it != handles_.end();
238        ++it) {
239     if (it->get() == handle.get()) {
240       (*it)->InternalClose();
241       handles_.erase(it);
242       return true;
243     }
244   }
245   return false;
246 }
247
248 const UsbConfigDescriptor& UsbDeviceImpl::GetConfiguration() {
249   DCHECK(thread_checker_.CalledOnValidThread());
250
251   if (!current_configuration_cached_) {
252     libusb_config_descriptor* platform_config;
253     const int rv =
254         libusb_get_active_config_descriptor(platform_device_, &platform_config);
255     if (rv != LIBUSB_SUCCESS) {
256       VLOG(1) << "Failed to get config descriptor: "
257               << ConvertPlatformUsbErrorToString(rv);
258       return current_configuration_;
259     }
260
261     current_configuration_.configuration_value =
262         platform_config->bConfigurationValue;
263     current_configuration_.self_powered =
264         (platform_config->bmAttributes & 0x40) != 0;
265     current_configuration_.remote_wakeup =
266         (platform_config->bmAttributes & 0x20) != 0;
267     current_configuration_.maximum_power = platform_config->MaxPower * 2;
268
269     for (size_t i = 0; i < platform_config->bNumInterfaces; ++i) {
270       const struct libusb_interface* platform_interface =
271           &platform_config->interface[i];
272       for (int j = 0; j < platform_interface->num_altsetting; ++j) {
273         const struct libusb_interface_descriptor* platform_alt_setting =
274             &platform_interface->altsetting[j];
275         UsbInterfaceDescriptor interface;
276
277         interface.interface_number = platform_alt_setting->bInterfaceNumber;
278         interface.alternate_setting = platform_alt_setting->bAlternateSetting;
279         interface.interface_class = platform_alt_setting->bInterfaceClass;
280         interface.interface_subclass = platform_alt_setting->bInterfaceSubClass;
281         interface.interface_protocol = platform_alt_setting->bInterfaceProtocol;
282
283         for (size_t k = 0; k < platform_alt_setting->bNumEndpoints; ++k) {
284           const struct libusb_endpoint_descriptor* platform_endpoint =
285               &platform_alt_setting->endpoint[k];
286           UsbEndpointDescriptor endpoint;
287
288           endpoint.address = platform_endpoint->bEndpointAddress;
289           endpoint.direction = GetDirection(platform_endpoint);
290           endpoint.maximum_packet_size = platform_endpoint->wMaxPacketSize;
291           endpoint.synchronization_type =
292               GetSynchronizationType(platform_endpoint);
293           endpoint.transfer_type = GetTransferType(platform_endpoint);
294           endpoint.usage_type = GetUsageType(platform_endpoint);
295           endpoint.polling_interval = platform_endpoint->bInterval;
296           endpoint.extra_data = std::vector<uint8_t>(
297               platform_endpoint->extra,
298               platform_endpoint->extra + platform_endpoint->extra_length);
299
300           interface.endpoints.push_back(endpoint);
301         }
302
303         interface.extra_data = std::vector<uint8_t>(
304             platform_alt_setting->extra,
305             platform_alt_setting->extra + platform_alt_setting->extra_length);
306
307         current_configuration_.interfaces.push_back(interface);
308       }
309     }
310
311     current_configuration_.extra_data = std::vector<uint8_t>(
312         platform_config->extra,
313         platform_config->extra + platform_config->extra_length);
314
315     libusb_free_config_descriptor(platform_config);
316     current_configuration_cached_ = true;
317   }
318
319   return current_configuration_;
320 }
321
322 bool UsbDeviceImpl::GetManufacturer(base::string16* manufacturer) {
323   DCHECK(thread_checker_.CalledOnValidThread());
324
325 #if defined(USE_UDEV)
326   if (manufacturer_.empty()) {
327     return false;
328   }
329   *manufacturer = base::UTF8ToUTF16(manufacturer_);
330   return true;
331 #else
332   // This is a non-blocking call as libusb has the descriptor in memory.
333   libusb_device_descriptor desc;
334   const int rv = libusb_get_device_descriptor(platform_device_, &desc);
335   if (rv != LIBUSB_SUCCESS) {
336     VLOG(1) << "Failed to read device descriptor: "
337             << ConvertPlatformUsbErrorToString(rv);
338     return false;
339   }
340
341   if (desc.iManufacturer == 0) {
342     return false;
343   }
344
345   scoped_refptr<UsbDeviceHandle> device_handle = Open();
346   if (device_handle.get()) {
347     return device_handle->GetStringDescriptor(desc.iManufacturer, manufacturer);
348   }
349   return false;
350 #endif
351 }
352
353 bool UsbDeviceImpl::GetProduct(base::string16* product) {
354   DCHECK(thread_checker_.CalledOnValidThread());
355
356 #if defined(USE_UDEV)
357   if (product_.empty()) {
358     return false;
359   }
360   *product = base::UTF8ToUTF16(product_);
361   return true;
362 #else
363   // This is a non-blocking call as libusb has the descriptor in memory.
364   libusb_device_descriptor desc;
365   const int rv = libusb_get_device_descriptor(platform_device_, &desc);
366   if (rv != LIBUSB_SUCCESS) {
367     VLOG(1) << "Failed to read device descriptor: "
368             << ConvertPlatformUsbErrorToString(rv);
369     return false;
370   }
371
372   if (desc.iProduct == 0) {
373     return false;
374   }
375
376   scoped_refptr<UsbDeviceHandle> device_handle = Open();
377   if (device_handle.get()) {
378     return device_handle->GetStringDescriptor(desc.iProduct, product);
379   }
380   return false;
381 #endif
382 }
383
384 bool UsbDeviceImpl::GetSerialNumber(base::string16* serial_number) {
385   DCHECK(thread_checker_.CalledOnValidThread());
386
387 #if defined(USE_UDEV)
388   if (serial_number_.empty()) {
389     return false;
390   }
391   *serial_number = base::UTF8ToUTF16(serial_number_);
392   return true;
393 #else
394   // This is a non-blocking call as libusb has the descriptor in memory.
395   libusb_device_descriptor desc;
396   const int rv = libusb_get_device_descriptor(platform_device_, &desc);
397   if (rv != LIBUSB_SUCCESS) {
398     VLOG(1) << "Failed to read device descriptor: "
399             << ConvertPlatformUsbErrorToString(rv);
400     return false;
401   }
402
403   if (desc.iSerialNumber == 0) {
404     return false;
405   }
406
407   scoped_refptr<UsbDeviceHandle> device_handle = Open();
408   if (device_handle.get()) {
409     return device_handle->GetStringDescriptor(desc.iSerialNumber,
410                                               serial_number);
411   }
412   return false;
413 #endif
414 }
415
416 void UsbDeviceImpl::OnDisconnect() {
417   DCHECK(thread_checker_.CalledOnValidThread());
418   HandlesVector handles;
419   swap(handles, handles_);
420   for (HandlesVector::iterator it = handles.begin(); it != handles.end(); ++it)
421     (*it)->InternalClose();
422 }
423
424 }  // namespace device