-
Notifications
You must be signed in to change notification settings - Fork 202
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
1,677 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,366 @@ | ||
/* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation; either version 2 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Library General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program; if not, write to the Free Software | ||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
* | ||
* LibUsbAdaptor.cpp | ||
* The wrapper around libusb calls. | ||
* Copyright (C) 2014 Simon Newton | ||
*/ | ||
|
||
#include "plugins/usbdmx/LibUsbAdaptor.h" | ||
|
||
#include <libusb.h> | ||
#include <ola/Logging.h> | ||
#include <string> | ||
|
||
#include "plugins/usbdmx/LibUsbThread.h" | ||
|
||
namespace ola { | ||
namespace plugin { | ||
namespace usbdmx { | ||
|
||
using std::string; | ||
|
||
namespace { | ||
|
||
/** | ||
* @brief A wrapper around libusb_get_string_descriptor_ascii. | ||
*/ | ||
bool GetStringDescriptorAscii(libusb_device_handle *usb_handle, | ||
uint8_t desc_index, | ||
string *data) { | ||
enum { buffer_size = 32 }; // static arrays FTW! | ||
unsigned char buffer[buffer_size]; | ||
int r = libusb_get_string_descriptor_ascii( | ||
usb_handle, | ||
desc_index, | ||
buffer, | ||
buffer_size); | ||
|
||
if (r <= 0) { | ||
OLA_INFO << "libusb_get_string_descriptor_ascii failed: " | ||
<< libusb_error_name(r); | ||
return false; | ||
} | ||
data->assign(reinterpret_cast<char*>(buffer)); | ||
return true; | ||
} | ||
|
||
/** | ||
* @brief A wrapper around libusb_open. | ||
*/ | ||
bool Open(libusb_device *usb_device, | ||
libusb_device_handle **usb_handle) { | ||
int r = libusb_open(usb_device, usb_handle); | ||
if (r) { | ||
OLA_WARN << "Failed to open libusb device: " << usb_device << ": " | ||
<< libusb_error_name(r);; | ||
return false; | ||
} | ||
return true; | ||
} | ||
|
||
bool OpenHandleAndClaimInterface(libusb_device *usb_device, | ||
int interface, | ||
libusb_device_handle **usb_handle) { | ||
if (!Open(usb_device, usb_handle)) { | ||
return false; | ||
} | ||
|
||
int r = libusb_claim_interface(*usb_handle, 0); | ||
if (r) { | ||
OLA_WARN << "Failed to claim interface " << interface | ||
<< " on device: " << usb_device << ": " | ||
<< libusb_error_name(r); | ||
libusb_close(*usb_handle); | ||
return false; | ||
} | ||
return true; | ||
} | ||
} // namespace | ||
|
||
// LibUsbAdaptor | ||
// ---------------------------------------------------------------------------- | ||
|
||
bool LibUsbAdaptor::GetDeviceInfo( | ||
struct libusb_device *usb_device, | ||
const struct libusb_device_descriptor &device_descriptor, | ||
DeviceInformation *device_info) { | ||
// Since the calls on the handle are syncronous, we don't bother adding the | ||
// handle to the thread. | ||
libusb_device_handle *usb_handle; | ||
if (!Open(usb_device, &usb_handle)) { | ||
return false; | ||
} | ||
|
||
if (!GetStringDescriptorAscii(usb_handle, device_descriptor.iManufacturer, | ||
&device_info->manufacturer)) { | ||
OLA_INFO << "Failed to get manufacturer name"; | ||
} | ||
|
||
if (!GetStringDescriptorAscii(usb_handle, device_descriptor.iProduct, | ||
&device_info->product)) { | ||
OLA_INFO << "Failed to get product name"; | ||
} | ||
|
||
if (!GetStringDescriptorAscii(usb_handle, device_descriptor.iSerialNumber, | ||
&device_info->serial)) { | ||
OLA_WARN << "Failed to read serial number, the device probably doesn't " | ||
<< "have one"; | ||
} | ||
|
||
libusb_close(usb_handle); | ||
return true; | ||
} | ||
|
||
bool LibUsbAdaptor::CheckManufacturer(const string &expected, | ||
const string &actual) { | ||
if (expected != actual) { | ||
OLA_WARN << "Manufacturer mismatch: " << expected << " != " << actual; | ||
return false; | ||
} | ||
return true; | ||
} | ||
|
||
bool LibUsbAdaptor::CheckProduct(const string &expected, const string &actual) { | ||
if (expected != actual) { | ||
OLA_WARN << "Product mismatch: " << expected << " != " << actual; | ||
return false; | ||
} | ||
return true; | ||
} | ||
|
||
// BaseLibUsbAdaptor | ||
// ---------------------------------------------------------------------------- | ||
libusb_device* BaseLibUsbAdaptor::RefDevice(libusb_device *dev) { | ||
return libusb_ref_device(dev); | ||
} | ||
|
||
void BaseLibUsbAdaptor::UnrefDevice(libusb_device *dev) { | ||
libusb_unref_device(dev); | ||
} | ||
|
||
int BaseLibUsbAdaptor::SetConfiguration(libusb_device_handle *dev, | ||
int configuration) { | ||
return libusb_set_configuration(dev, configuration); | ||
} | ||
|
||
int BaseLibUsbAdaptor::ClaimInterface(libusb_device_handle *dev, | ||
int interface_number) { | ||
return libusb_claim_interface(dev, interface_number); | ||
} | ||
|
||
int BaseLibUsbAdaptor::DetachKernelDriver(libusb_device_handle *dev, | ||
int interface_number) { | ||
if (libusb_kernel_driver_active(dev, interface_number)) { | ||
return libusb_detach_kernel_driver(dev, interface_number); | ||
} else { | ||
return 0; | ||
} | ||
} | ||
|
||
int BaseLibUsbAdaptor::GetActiveConfigDescriptor( | ||
libusb_device *dev, | ||
struct libusb_config_descriptor **config) { | ||
return libusb_get_active_config_descriptor(dev, config); | ||
} | ||
|
||
int BaseLibUsbAdaptor::GetConfigDescriptor( | ||
libusb_device *dev, | ||
uint8_t config_index, | ||
struct libusb_config_descriptor **config) { | ||
return libusb_get_config_descriptor(dev, config_index, config); | ||
} | ||
|
||
void BaseLibUsbAdaptor::FreeConfigDescriptor( | ||
struct libusb_config_descriptor *config) { | ||
libusb_free_config_descriptor(config); | ||
} | ||
|
||
struct libusb_transfer* BaseLibUsbAdaptor::AllocTransfer(int iso_packets) { | ||
return libusb_alloc_transfer(iso_packets); | ||
} | ||
|
||
void BaseLibUsbAdaptor::FreeTransfer(struct libusb_transfer *transfer) { | ||
return libusb_free_transfer(transfer); | ||
} | ||
|
||
int BaseLibUsbAdaptor::SubmitTransfer(struct libusb_transfer *transfer) { | ||
return libusb_submit_transfer(transfer); | ||
} | ||
|
||
int BaseLibUsbAdaptor::CancelTransfer(struct libusb_transfer *transfer) { | ||
return libusb_cancel_transfer(transfer); | ||
} | ||
|
||
void BaseLibUsbAdaptor::FillControlSetup(unsigned char *buffer, | ||
uint8_t bmRequestType, | ||
uint8_t bRequest, | ||
uint16_t wValue, | ||
uint16_t wIndex, | ||
uint16_t wLength) { | ||
return libusb_fill_control_setup(buffer, bmRequestType, bRequest, wValue, | ||
wIndex, wLength); | ||
} | ||
|
||
void BaseLibUsbAdaptor::FillControlTransfer( | ||
struct libusb_transfer *transfer, | ||
libusb_device_handle *dev_handle, | ||
unsigned char *buffer, | ||
libusb_transfer_cb_fn callback, | ||
void *user_data, | ||
unsigned int timeout) { | ||
return libusb_fill_control_transfer(transfer, dev_handle, buffer, callback, | ||
user_data, timeout); | ||
} | ||
|
||
void BaseLibUsbAdaptor::FillBulkTransfer(struct libusb_transfer *transfer, | ||
libusb_device_handle *dev_handle, | ||
unsigned char endpoint, | ||
unsigned char *buffer, | ||
int length, | ||
libusb_transfer_cb_fn callback, | ||
void *user_data, | ||
unsigned int timeout) { | ||
libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, | ||
length, callback, user_data, timeout); | ||
} | ||
|
||
void BaseLibUsbAdaptor::FillInterruptTransfer(struct libusb_transfer *transfer, | ||
libusb_device_handle *dev_handle, | ||
unsigned char endpoint, | ||
unsigned char *buffer, | ||
int length, | ||
libusb_transfer_cb_fn callback, | ||
void *user_data, | ||
unsigned int timeout) { | ||
libusb_fill_interrupt_transfer(transfer, dev_handle, endpoint, buffer, | ||
length, callback, user_data, timeout); | ||
} | ||
|
||
int BaseLibUsbAdaptor::ControlTransfer( | ||
libusb_device_handle *dev_handle, | ||
uint8_t bmRequestType, | ||
uint8_t bRequest, | ||
uint16_t wValue, | ||
uint16_t wIndex, | ||
unsigned char *data, | ||
uint16_t wLength, | ||
unsigned int timeout) { | ||
return libusb_control_transfer(dev_handle, bmRequestType, bRequest, wValue, | ||
wIndex, data, wLength, timeout); | ||
} | ||
|
||
int BaseLibUsbAdaptor::BulkTransfer(struct libusb_device_handle *dev_handle, | ||
unsigned char endpoint, | ||
unsigned char *data, | ||
int length, | ||
int *transferred, | ||
unsigned int timeout) { | ||
return libusb_bulk_transfer(dev_handle, endpoint, data, length, transferred, | ||
timeout); | ||
} | ||
|
||
int BaseLibUsbAdaptor::InterruptTransfer(libusb_device_handle *dev_handle, | ||
unsigned char endpoint, | ||
unsigned char *data, | ||
int length, | ||
int *actual_length, | ||
unsigned int timeout) { | ||
return libusb_interrupt_transfer(dev_handle, endpoint, data, length, | ||
actual_length, timeout); | ||
} | ||
|
||
|
||
// SyncronousLibUsbAdaptor | ||
// ----------------------------------------------------------------------------- | ||
bool SyncronousLibUsbAdaptor::OpenDevice(libusb_device *usb_device, | ||
libusb_device_handle **usb_handle) { | ||
return Open(usb_device, usb_handle); | ||
} | ||
|
||
bool SyncronousLibUsbAdaptor::OpenDeviceAndClaimInterface( | ||
libusb_device *usb_device, | ||
int interface, | ||
libusb_device_handle **usb_handle) { | ||
return OpenHandleAndClaimInterface(usb_device, interface, usb_handle); | ||
} | ||
|
||
void SyncronousLibUsbAdaptor::Close(libusb_device_handle *usb_handle) { | ||
libusb_close(usb_handle); | ||
} | ||
|
||
// AsyncronousLibUsbAdaptor | ||
// ----------------------------------------------------------------------------- | ||
bool AsyncronousLibUsbAdaptor::OpenDevice(libusb_device *usb_device, | ||
libusb_device_handle **usb_handle) { | ||
bool ok = Open(usb_device, usb_handle); | ||
if (ok) { | ||
m_thread->OpenHandle(); | ||
} | ||
return ok; | ||
} | ||
|
||
bool AsyncronousLibUsbAdaptor::OpenDeviceAndClaimInterface( | ||
libusb_device *usb_device, | ||
int interface, | ||
libusb_device_handle **usb_handle) { | ||
bool ok = OpenHandleAndClaimInterface(usb_device, interface, usb_handle); | ||
if (ok) { | ||
m_thread->OpenHandle(); | ||
} | ||
return ok; | ||
} | ||
|
||
void AsyncronousLibUsbAdaptor::Close(libusb_device_handle *handle) { | ||
m_thread->CloseHandle(handle); | ||
} | ||
|
||
int AsyncronousLibUsbAdaptor::ControlTransfer( | ||
OLA_UNUSED libusb_device_handle *dev_handle, | ||
OLA_UNUSED uint8_t bmRequestType, | ||
OLA_UNUSED uint8_t bRequest, | ||
OLA_UNUSED uint16_t wValue, | ||
OLA_UNUSED uint16_t wIndex, | ||
OLA_UNUSED unsigned char *data, | ||
OLA_UNUSED uint16_t wLength, | ||
OLA_UNUSED unsigned int timeout) { | ||
OLA_WARN << "libusb_control_transfer in an AsyncronousLibUsbAdaptor"; | ||
return LIBUSB_ERROR_NOT_SUPPORTED; | ||
} | ||
|
||
int AsyncronousLibUsbAdaptor::BulkTransfer( | ||
OLA_UNUSED struct libusb_device_handle *dev_handle, | ||
OLA_UNUSED unsigned char endpoint, | ||
OLA_UNUSED unsigned char *data, | ||
OLA_UNUSED int length, | ||
OLA_UNUSED int *transferred, | ||
OLA_UNUSED unsigned int timeout) { | ||
OLA_WARN << "libusb_bulk_transfer in an AsyncronousLibUsbAdaptor"; | ||
return LIBUSB_ERROR_NOT_SUPPORTED; | ||
} | ||
|
||
int AsyncronousLibUsbAdaptor::InterruptTransfer( | ||
OLA_UNUSED libusb_device_handle *dev_handle, | ||
OLA_UNUSED unsigned char endpoint, | ||
OLA_UNUSED unsigned char *data, | ||
OLA_UNUSED int length, | ||
OLA_UNUSED int *actual_length, | ||
OLA_UNUSED unsigned int timeout) { | ||
OLA_WARN << "libusb_interrupt_transfer in an AsyncronousLibUsbAdaptor"; | ||
return LIBUSB_ERROR_NOT_SUPPORTED; | ||
} | ||
} // namespace usbdmx | ||
} // namespace plugin | ||
} // namespace ola |
Oops, something went wrong.