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
15using content::BrowserThread;
16
17UsbDevice::UsbDevice(
18    scoped_refptr<UsbContext> context,
19    PlatformUsbDevice platform_device,
20    uint16 vendor_id,
21    uint16 product_id)
22    : platform_device_(platform_device),
23      vendor_id_(vendor_id),
24      product_id_(product_id),
25      context_(context) {
26  CHECK(platform_device) << "platform_device cannot be NULL";
27  libusb_ref_device(platform_device);
28}
29
30UsbDevice::UsbDevice()
31    : platform_device_(NULL),
32      vendor_id_(0),
33      product_id_(0),
34      context_(NULL) {
35}
36
37UsbDevice::~UsbDevice() {
38  DCHECK(thread_checker_.CalledOnValidThread());
39  for (HandlesVector::iterator it = handles_.begin();
40      it != handles_.end();
41      ++it) {
42    (*it)->InternalClose();
43  }
44  STLClearObject(&handles_);
45  libusb_unref_device(platform_device_);
46}
47
48scoped_refptr<UsbDeviceHandle> UsbDevice::Open() {
49  DCHECK(thread_checker_.CalledOnValidThread());
50  PlatformUsbDeviceHandle handle;
51  int rv = libusb_open(platform_device_, &handle);
52  if (LIBUSB_SUCCESS == rv) {
53    scoped_refptr<UsbDeviceHandle> device_handle =
54        new UsbDeviceHandle(context_, this, handle);
55    handles_.push_back(device_handle);
56    return device_handle;
57  }
58  return NULL;
59}
60
61bool UsbDevice::Close(scoped_refptr<UsbDeviceHandle> handle) {
62  DCHECK(thread_checker_.CalledOnValidThread());
63
64  for (HandlesVector::iterator it = handles_.begin();
65      it != handles_.end();
66      ++it) {
67    if (*it == handle) {
68      (*it)->InternalClose();
69      handles_.erase(it);
70      return true;
71    }
72  }
73  return false;
74}
75
76bool UsbDevice::ListInterfaces(UsbConfigDescriptor* config) {
77  DCHECK(thread_checker_.CalledOnValidThread());
78
79  PlatformUsbConfigDescriptor platform_config;
80  const int list_result =
81      libusb_get_active_config_descriptor(platform_device_, &platform_config);
82  if (list_result == 0)
83    config->Reset(platform_config);
84
85  return list_result == 0;
86}
87
88void UsbDevice::OnDisconnect() {
89  DCHECK(thread_checker_.CalledOnValidThread());
90  HandlesVector handles;
91  swap(handles, handles_);
92  for (std::vector<scoped_refptr<UsbDeviceHandle> >::iterator it =
93      handles.begin();
94      it != handles.end();
95      ++it) {
96    (*it)->InternalClose();
97  }
98}
99