Home | History | Annotate | Download | only in usb
      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