1 // Copyright 2013 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 "chrome/browser/usb/usb_device.h" 6 7 #include <algorithm> 8 9 #include "base/stl_util.h" 10 #include "chrome/browser/usb/usb_context.h" 11 #include "chrome/browser/usb/usb_device_handle.h" 12 #include "content/public/browser/browser_thread.h" 13 #include "third_party/libusb/src/libusb/libusb.h" 14 15 #if defined(OS_CHROMEOS) 16 #include "base/sys_info.h" 17 #include "chromeos/dbus/dbus_thread_manager.h" 18 #include "chromeos/dbus/permission_broker_client.h" 19 #endif // defined(OS_CHROMEOS) 20 21 using content::BrowserThread; 22 23 namespace { 24 25 #if defined(OS_CHROMEOS) 26 void OnRequestUsbAccessReplied( 27 const base::Callback<void(bool success)>& callback, 28 bool success) { 29 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 30 base::Bind(callback, success)); 31 } 32 #endif // defined(OS_CHROMEOS) 33 34 } // namespace 35 36 UsbDevice::UsbDevice( 37 scoped_refptr<UsbContext> context, 38 PlatformUsbDevice platform_device, 39 uint16 vendor_id, 40 uint16 product_id, 41 uint32 unique_id) 42 : platform_device_(platform_device), 43 vendor_id_(vendor_id), 44 product_id_(product_id), 45 unique_id_(unique_id), 46 context_(context) { 47 CHECK(platform_device) << "platform_device cannot be NULL"; 48 libusb_ref_device(platform_device); 49 } 50 51 UsbDevice::UsbDevice() 52 : platform_device_(NULL), 53 vendor_id_(0), 54 product_id_(0), 55 unique_id_(0), 56 context_(NULL) { 57 } 58 59 UsbDevice::~UsbDevice() { 60 DCHECK(thread_checker_.CalledOnValidThread()); 61 for (HandlesVector::iterator it = handles_.begin(); 62 it != handles_.end(); 63 ++it) { 64 (*it)->InternalClose(); 65 } 66 STLClearObject(&handles_); 67 libusb_unref_device(platform_device_); 68 } 69 70 #if defined(OS_CHROMEOS) 71 72 void UsbDevice::RequestUsbAcess( 73 int interface_id, 74 const base::Callback<void(bool success)>& callback) { 75 DCHECK(thread_checker_.CalledOnValidThread()); 76 77 // ChromeOS builds on non-ChromeOS machines (dev) should not attempt to 78 // use permission broker. 79 if (base::SysInfo::IsRunningOnChromeOS()) { 80 chromeos::PermissionBrokerClient* client = 81 chromeos::DBusThreadManager::Get()->GetPermissionBrokerClient(); 82 DCHECK(client) << "Could not get permission broker client."; 83 if (!client) { 84 callback.Run(false); 85 return; 86 } 87 88 BrowserThread::PostTask( 89 BrowserThread::UI, FROM_HERE, 90 base::Bind(&chromeos::PermissionBrokerClient::RequestUsbAccess, 91 base::Unretained(client), 92 this->vendor_id_, 93 this->product_id_, 94 interface_id, 95 base::Bind(&OnRequestUsbAccessReplied, callback))); 96 } 97 } 98 99 #endif 100 101 scoped_refptr<UsbDeviceHandle> UsbDevice::Open() { 102 DCHECK(thread_checker_.CalledOnValidThread()); 103 PlatformUsbDeviceHandle handle; 104 int rv = libusb_open(platform_device_, &handle); 105 if (LIBUSB_SUCCESS == rv) { 106 scoped_refptr<UsbConfigDescriptor> interfaces = ListInterfaces(); 107 if (!interfaces) 108 return NULL; 109 scoped_refptr<UsbDeviceHandle> device_handle = 110 new UsbDeviceHandle(context_, this, handle, interfaces); 111 handles_.push_back(device_handle); 112 return device_handle; 113 } 114 return NULL; 115 } 116 117 bool UsbDevice::Close(scoped_refptr<UsbDeviceHandle> handle) { 118 DCHECK(thread_checker_.CalledOnValidThread()); 119 120 for (HandlesVector::iterator it = handles_.begin(); 121 it != handles_.end(); 122 ++it) { 123 if (*it == handle) { 124 (*it)->InternalClose(); 125 handles_.erase(it); 126 return true; 127 } 128 } 129 return false; 130 } 131 132 scoped_refptr<UsbConfigDescriptor> UsbDevice::ListInterfaces() { 133 DCHECK(thread_checker_.CalledOnValidThread()); 134 135 PlatformUsbConfigDescriptor platform_config; 136 const int list_result = 137 libusb_get_active_config_descriptor(platform_device_, &platform_config); 138 if (list_result == 0) 139 return new UsbConfigDescriptor(platform_config); 140 141 return NULL; 142 } 143 144 void UsbDevice::OnDisconnect() { 145 DCHECK(thread_checker_.CalledOnValidThread()); 146 HandlesVector handles; 147 swap(handles, handles_); 148 for (std::vector<scoped_refptr<UsbDeviceHandle> >::iterator it = 149 handles.begin(); 150 it != handles.end(); 151 ++it) { 152 (*it)->InternalClose(); 153 } 154 } 155