| // Copyright (c) 2013 The Chromium OS 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 "mist/usb_device.h" |
| |
| #include <libusb.h> |
| |
| #include <base/logging.h> |
| |
| #include "mist/usb_config_descriptor.h" |
| #include "mist/usb_device_descriptor.h" |
| |
| using std::string; |
| using std::unique_ptr; |
| |
| namespace mist { |
| |
| UsbDevice::UsbDevice(libusb_device* device) |
| : device_(device), |
| device_handle_(nullptr) { |
| CHECK(device_); |
| libusb_ref_device(device_); |
| } |
| |
| UsbDevice::UsbDevice(libusb_device_handle* device_handle) |
| : device_(nullptr), |
| device_handle_(device_handle) { |
| CHECK(device_handle_); |
| device_ = libusb_get_device(device_handle_); |
| CHECK(device_); |
| libusb_ref_device(device_); |
| } |
| |
| UsbDevice::~UsbDevice() { |
| Close(); |
| libusb_unref_device(device_); |
| device_ = nullptr; |
| } |
| |
| bool UsbDevice::IsOpen() const { |
| return device_handle_ != nullptr; |
| } |
| |
| bool UsbDevice::VerifyOpen() { |
| if (IsOpen()) |
| return true; |
| |
| error_.set_type(UsbError::kErrorDeviceNotOpen); |
| return false; |
| } |
| |
| bool UsbDevice::Open() { |
| if (IsOpen()) { |
| error_.Clear(); |
| return true; |
| } |
| |
| int result = libusb_open(device_, &device_handle_); |
| return error_.SetFromLibUsbError(static_cast<libusb_error>(result)); |
| } |
| |
| void UsbDevice::Close() { |
| if (!IsOpen()) |
| return; |
| |
| libusb_close(device_handle_); |
| device_handle_ = nullptr; |
| } |
| |
| bool UsbDevice::Reset() { |
| if (!VerifyOpen()) |
| return false; |
| |
| int result = libusb_reset_device(device_handle_); |
| return error_.SetFromLibUsbError(static_cast<libusb_error>(result)); |
| } |
| |
| uint8_t UsbDevice::GetBusNumber() const { |
| return libusb_get_bus_number(device_); |
| } |
| |
| uint8_t UsbDevice::GetDeviceAddress() const { |
| return libusb_get_device_address(device_); |
| } |
| |
| UsbSpeed UsbDevice::GetDeviceSpeed() const { |
| int speed = libusb_get_device_speed(device_); |
| switch (speed) { |
| case kUsbSpeedLow: |
| case kUsbSpeedFull: |
| case kUsbSpeedHigh: |
| case kUsbSpeedSuper: |
| return static_cast<UsbSpeed>(speed); |
| default: |
| return kUsbSpeedUnknown; |
| } |
| } |
| |
| bool UsbDevice::GetConfiguration(int* configuration) { |
| if (!VerifyOpen()) |
| return false; |
| |
| int result = libusb_get_configuration(device_handle_, configuration); |
| return error_.SetFromLibUsbError(static_cast<libusb_error>(result)); |
| } |
| |
| bool UsbDevice::SetConfiguration(int configuration) { |
| if (!VerifyOpen()) |
| return false; |
| |
| int result = libusb_set_configuration(device_handle_, configuration); |
| return error_.SetFromLibUsbError(static_cast<libusb_error>(result)); |
| } |
| |
| bool UsbDevice::ClaimInterface(int interface_number) { |
| if (!VerifyOpen()) |
| return false; |
| |
| int result = libusb_claim_interface(device_handle_, interface_number); |
| return error_.SetFromLibUsbError(static_cast<libusb_error>(result)); |
| } |
| |
| bool UsbDevice::ReleaseInterface(int interface_number) { |
| if (!VerifyOpen()) |
| return false; |
| |
| int result = libusb_release_interface(device_handle_, interface_number); |
| return error_.SetFromLibUsbError(static_cast<libusb_error>(result)); |
| } |
| |
| bool UsbDevice::SetInterfaceAlternateSetting(int interface_number, |
| int alternate_setting) { |
| if (!VerifyOpen()) |
| return false; |
| |
| int result = libusb_set_interface_alt_setting( |
| device_handle_, interface_number, alternate_setting); |
| return error_.SetFromLibUsbError(static_cast<libusb_error>(result)); |
| } |
| |
| bool UsbDevice::IsKernelDriverActive(int interface_number) { |
| if (!VerifyOpen()) |
| return false; |
| |
| int result = libusb_kernel_driver_active(device_handle_, interface_number); |
| if (result == 1) { |
| error_.Clear(); |
| return true; |
| } |
| |
| return error_.SetFromLibUsbError(static_cast<libusb_error>(result)); |
| } |
| |
| bool UsbDevice::AttachKernelDriver(int interface_number) { |
| if (!VerifyOpen()) |
| return false; |
| |
| int result = libusb_attach_kernel_driver(device_handle_, interface_number); |
| return error_.SetFromLibUsbError(static_cast<libusb_error>(result)); |
| } |
| |
| bool UsbDevice::DetachKernelDriver(int interface_number) { |
| if (!VerifyOpen()) |
| return false; |
| |
| int result = libusb_detach_kernel_driver(device_handle_, interface_number); |
| return error_.SetFromLibUsbError(static_cast<libusb_error>(result)); |
| } |
| |
| bool UsbDevice::ClearHalt(uint8_t endpoint) { |
| if (!VerifyOpen()) |
| return false; |
| |
| int result = libusb_clear_halt(device_handle_, endpoint); |
| return error_.SetFromLibUsbError(static_cast<libusb_error>(result)); |
| } |
| |
| UsbConfigDescriptor* UsbDevice::GetActiveConfigDescriptor() { |
| libusb_config_descriptor* config_descriptor = nullptr; |
| |
| int result = libusb_get_active_config_descriptor(device_, &config_descriptor); |
| if (error_.SetFromLibUsbError(static_cast<libusb_error>(result))) |
| return new UsbConfigDescriptor(AsWeakPtr(), config_descriptor, true); |
| |
| return nullptr; |
| } |
| |
| UsbConfigDescriptor* UsbDevice::GetConfigDescriptor(uint8_t index) { |
| libusb_config_descriptor* config_descriptor = nullptr; |
| |
| int result = libusb_get_config_descriptor(device_, index, &config_descriptor); |
| if (error_.SetFromLibUsbError(static_cast<libusb_error>(result))) |
| return new UsbConfigDescriptor(AsWeakPtr(), config_descriptor, true); |
| |
| return nullptr; |
| } |
| |
| UsbConfigDescriptor* UsbDevice::GetConfigDescriptorByValue( |
| uint8_t configuration_value) { |
| libusb_config_descriptor* config_descriptor = nullptr; |
| |
| int result = libusb_get_config_descriptor_by_value( |
| device_, configuration_value, &config_descriptor); |
| if (error_.SetFromLibUsbError(static_cast<libusb_error>(result))) |
| return new UsbConfigDescriptor(AsWeakPtr(), config_descriptor, true); |
| |
| return nullptr; |
| } |
| |
| UsbDeviceDescriptor* UsbDevice::GetDeviceDescriptor() { |
| if (!device_descriptor_) |
| device_descriptor_.reset(new libusb_device_descriptor()); |
| |
| int result = libusb_get_device_descriptor(device_, device_descriptor_.get()); |
| if (error_.SetFromLibUsbError(static_cast<libusb_error>(result))) |
| return new UsbDeviceDescriptor(AsWeakPtr(), device_descriptor_.get()); |
| |
| return nullptr; |
| } |
| |
| string UsbDevice::GetStringDescriptorAscii(uint8_t index) { |
| if (!VerifyOpen()) |
| return string(); |
| |
| // libusb_get_string_descriptor_ascii uses an internal buffer that can only |
| // hold up to 128 ASCII characters. |
| int length = 128; |
| unique_ptr<uint8_t[]> data(new uint8_t[length]); |
| int result = libusb_get_string_descriptor_ascii( |
| device_handle_, index, data.get(), length); |
| if (result < 0) { |
| error_.SetFromLibUsbError(static_cast<libusb_error>(result)); |
| return string(); |
| } |
| |
| error_.Clear(); |
| return string(reinterpret_cast<const char*>(data.get()), result); |
| } |
| |
| } // namespace mist |