// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "components/usb_service/usb_device_impl.h" #include #include "base/stl_util.h" #include "components/usb_service/usb_context.h" #include "components/usb_service/usb_device_handle_impl.h" #include "components/usb_service/usb_interface_impl.h" #include "content/public/browser/browser_thread.h" #include "third_party/libusb/src/libusb/libusb.h" #if defined(OS_CHROMEOS) #include "base/sys_info.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/permission_broker_client.h" #endif // defined(OS_CHROMEOS) using content::BrowserThread; namespace { #if defined(OS_CHROMEOS) void OnRequestUsbAccessReplied( const base::Callback& callback, bool success) { BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, base::Bind(callback, success)); } #endif // defined(OS_CHROMEOS) } // namespace namespace usb_service { UsbDeviceImpl::UsbDeviceImpl(scoped_refptr context, PlatformUsbDevice platform_device, uint16 vendor_id, uint16 product_id, uint32 unique_id) : UsbDevice(vendor_id, product_id, unique_id), platform_device_(platform_device), context_(context) { CHECK(platform_device) << "platform_device cannot be NULL"; libusb_ref_device(platform_device); } UsbDeviceImpl::~UsbDeviceImpl() { DCHECK(thread_checker_.CalledOnValidThread()); for (HandlesVector::iterator it = handles_.begin(); it != handles_.end(); ++it) { (*it)->InternalClose(); } STLClearObject(&handles_); libusb_unref_device(platform_device_); } #if defined(OS_CHROMEOS) void UsbDeviceImpl::RequestUsbAcess( int interface_id, const base::Callback& callback) { DCHECK(thread_checker_.CalledOnValidThread()); // ChromeOS builds on non-ChromeOS machines (dev) should not attempt to // use permission broker. if (base::SysInfo::IsRunningOnChromeOS()) { chromeos::PermissionBrokerClient* client = chromeos::DBusThreadManager::Get()->GetPermissionBrokerClient(); DCHECK(client) << "Could not get permission broker client."; if (!client) { callback.Run(false); return; } BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind(&chromeos::PermissionBrokerClient::RequestUsbAccess, base::Unretained(client), vendor_id(), product_id(), interface_id, base::Bind(&OnRequestUsbAccessReplied, callback))); } } #endif scoped_refptr UsbDeviceImpl::Open() { DCHECK(thread_checker_.CalledOnValidThread()); PlatformUsbDeviceHandle handle; int rv = libusb_open(platform_device_, &handle); if (LIBUSB_SUCCESS == rv) { scoped_refptr interfaces = ListInterfaces(); if (!interfaces) return NULL; scoped_refptr device_handle = new UsbDeviceHandleImpl(context_, this, handle, interfaces); handles_.push_back(device_handle); return device_handle; } return NULL; } bool UsbDeviceImpl::Close(scoped_refptr handle) { DCHECK(thread_checker_.CalledOnValidThread()); for (HandlesVector::iterator it = handles_.begin(); it != handles_.end(); ++it) { if (*it == handle) { (*it)->InternalClose(); handles_.erase(it); return true; } } return false; } scoped_refptr UsbDeviceImpl::ListInterfaces() { DCHECK(thread_checker_.CalledOnValidThread()); PlatformUsbConfigDescriptor platform_config; const int list_result = libusb_get_active_config_descriptor(platform_device_, &platform_config); if (list_result == 0) return new UsbConfigDescriptorImpl(platform_config); return NULL; } void UsbDeviceImpl::OnDisconnect() { DCHECK(thread_checker_.CalledOnValidThread()); HandlesVector handles; swap(handles, handles_); for (HandlesVector::iterator it = handles.begin(); it != handles.end(); ++it) (*it)->InternalClose(); } } // namespace usb_service