seccomp-bpf: Remove legacy SandboxBPFPolicy class
[chromium-blink-merge.git] / device / usb / usb_device_impl.cc
blobb1beeb24736955d0bff5d174500a091ab756c029
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.
5 #include "device/usb/usb_device_impl.h"
7 #include <algorithm>
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"
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)
28 #if defined(USE_UDEV)
29 #include "device/udev_linux/udev.h"
30 #endif // defined(USE_UDEV)
32 namespace device {
34 namespace {
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));
43 #endif // defined(OS_CHROMEOS)
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;
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;
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;
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;
105 } // namespace
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) {
111 UsbDevice::~UsbDevice() {
114 void UsbDevice::NotifyDisconnect() {
115 FOR_EACH_OBSERVER(Observer, observer_list_, OnDisconnect(this));
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);
133 #if defined(USE_UDEV)
134 ScopedUdevPtr udev(udev_new());
135 ScopedUdevEnumeratePtr enumerate(udev_enumerate_new(udev.get()));
137 udev_enumerate_add_match_subsystem(enumerate.get(), "usb");
138 if (udev_enumerate_scan_devices(enumerate.get()) != 0) {
139 return;
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;
155 value = udev_device_get_sysattr_value(device.get(), "devnum");
156 if (!value || device_address != value) {
157 continue;
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;
169 #endif
172 UsbDeviceImpl::~UsbDeviceImpl() {
173 DCHECK(thread_checker_.CalledOnValidThread());
174 for (HandlesVector::iterator it = handles_.begin(); it != handles_.end();
175 ++it) {
176 (*it)->InternalClose();
178 STLClearObject(&handles_);
179 libusb_unref_device(platform_device_);
182 #if defined(OS_CHROMEOS)
184 void UsbDeviceImpl::RequestUsbAccess(
185 int interface_id,
186 const base::Callback<void(bool success)>& callback) {
187 DCHECK(thread_checker_.CalledOnValidThread());
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;
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)));
213 #endif
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;
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;
234 bool UsbDeviceImpl::Close(scoped_refptr<UsbDeviceHandle> handle) {
235 DCHECK(thread_checker_.CalledOnValidThread());
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;
245 return false;
248 const UsbConfigDescriptor& UsbDeviceImpl::GetConfiguration() {
249 DCHECK(thread_checker_.CalledOnValidThread());
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_;
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;
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;
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;
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;
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);
300 interface.endpoints.push_back(endpoint);
303 interface.extra_data = std::vector<uint8_t>(
304 platform_alt_setting->extra,
305 platform_alt_setting->extra + platform_alt_setting->extra_length);
307 current_configuration_.interfaces.push_back(interface);
311 current_configuration_.extra_data = std::vector<uint8_t>(
312 platform_config->extra,
313 platform_config->extra + platform_config->extra_length);
315 libusb_free_config_descriptor(platform_config);
316 current_configuration_cached_ = true;
319 return current_configuration_;
322 bool UsbDeviceImpl::GetManufacturer(base::string16* manufacturer) {
323 DCHECK(thread_checker_.CalledOnValidThread());
325 #if defined(USE_UDEV)
326 if (manufacturer_.empty()) {
327 return false;
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;
341 if (desc.iManufacturer == 0) {
342 return false;
345 scoped_refptr<UsbDeviceHandle> device_handle = Open();
346 if (device_handle.get()) {
347 return device_handle->GetStringDescriptor(desc.iManufacturer, manufacturer);
349 return false;
350 #endif
353 bool UsbDeviceImpl::GetProduct(base::string16* product) {
354 DCHECK(thread_checker_.CalledOnValidThread());
356 #if defined(USE_UDEV)
357 if (product_.empty()) {
358 return false;
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;
372 if (desc.iProduct == 0) {
373 return false;
376 scoped_refptr<UsbDeviceHandle> device_handle = Open();
377 if (device_handle.get()) {
378 return device_handle->GetStringDescriptor(desc.iProduct, product);
380 return false;
381 #endif
384 bool UsbDeviceImpl::GetSerialNumber(base::string16* serial_number) {
385 DCHECK(thread_checker_.CalledOnValidThread());
387 #if defined(USE_UDEV)
388 if (serial_number_.empty()) {
389 return false;
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;
403 if (desc.iSerialNumber == 0) {
404 return false;
407 scoped_refptr<UsbDeviceHandle> device_handle = Open();
408 if (device_handle.get()) {
409 return device_handle->GetStringDescriptor(desc.iSerialNumber,
410 serial_number);
412 return false;
413 #endif
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();
424 } // namespace device