diff options
Diffstat (limited to 'CDAL/LibusbDevice.cpp')
-rwxr-xr-x | CDAL/LibusbDevice.cpp | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/CDAL/LibusbDevice.cpp b/CDAL/LibusbDevice.cpp new file mode 100755 index 0000000..337df46 --- /dev/null +++ b/CDAL/LibusbDevice.cpp @@ -0,0 +1,149 @@ +/* + * LibusbDevice.cpp + * + * Copyright (C) ST-Ericsson SA 2011 + * Authors: Srimanta Panda <srimanta.panda@stericsson.com>, + * Ola Borgelin <ola.borgelin@stericsson.com>, + * Karin Hedlund <karin.hedlund@stericsson.com>, + * Markus Andersson <markus.m.andersson@stericsson.com> for ST-Ericsson. + * License terms: 3-clause BSD license + * + */ + +#include "LibusbDevice.h" +#include "Debug.h" +#include "CommException.h" +#include <libusb.h> + +using namespace std; + +#define MIN(A, B) ((A) < (B) ? (A) : (B)) + +LibusbDevice::LibusbDevice(libusb_device* device): device_(device) +{ + int status = libusb_open(device_, &handle_); + + if (status != LIBUSB_SUCCESS) { + throw CommException("failed to open usb device", COMM_DEVICE_LIBUSB_FAILED_TO_OPEN_PORT); + } + + status = libusb_claim_interface(handle_, 0); + + if (status != LIBUSB_SUCCESS) { + libusb_close(handle_); + throw CommException("failed to claim device interface", COMM_DEVICE_LIBUSB_FAILED_TO_CLAIM_INTERFACE); + } + + libusb_config_descriptor* config; + libusb_get_active_config_descriptor(device, &config); + Debug::info("LibusbDevice: found %d endpoints", config->interface->altsetting->bNumEndpoints); + + for (int i = 0; i != config->interface->altsetting->bNumEndpoints; ++i) { + if (config->interface->altsetting->endpoint[i].bEndpointAddress & LIBUSB_ENDPOINT_IN) { + inEndpoint_ = config->interface->altsetting->endpoint[i].bEndpointAddress; + Debug::info("LibusbDevice: in endpoint set to 0x%02x", inEndpoint_); + } else { + outEndpoint_ = config->interface->altsetting->endpoint[i].bEndpointAddress; + Debug::info("LibusbDevice: out endpoint set to 0x%02x", outEndpoint_); + } + } + + libusb_free_config_descriptor(config); + + libusb_get_device_descriptor(device, &descriptor_); + + readBufferLength_ = 0; + readBufferHead_ = readBuffer_; +} + +LibusbDevice::~LibusbDevice() +{ + libusb_release_interface(handle_, 0); + libusb_close(handle_); +} + +int LibusbDevice::read(void *buffer, size_t size) +{ + Debug::info("LibusbDevice read: called with size %d", size); + unsigned char* dest = static_cast<unsigned char*>(buffer); + + while (true) { + if (readBufferLength_) { + size_t toCopy = MIN(readBufferLength_, size); + memcpy(dest, readBufferHead_, toCopy); + dest += toCopy; + size -= toCopy; + readBufferLength_ -= toCopy; + + if (readBufferLength_ != 0) { + readBufferHead_ += toCopy; + } else { + readBufferHead_ = readBuffer_; + } + } + + if (size == 0) { + break; + } + + int transfered; + int error = libusb_bulk_transfer(handle_, inEndpoint_, readBuffer_, READ_BUFFER_SIZE, &transfered, 100000); + + if (isReadCanceled_) { + Debug::info("LibusbDevice read: canceled..."); + Debug::hexdump("read canceled", dest, transfered); + isReadCanceled_ = false; + return COMM_DEVICE_CANCEL; + } + + if (error) { + if (error == LIBUSB_ERROR_TIMEOUT) { + continue; + } else { + Debug::info("LibusbDevice read: error %d occured", error); + return error; + } + } + + readBufferLength_ = transfered; + } + + Debug::info("LibusbDevice read: complete"); + return 0; +} + +int LibusbDevice::write(void *buffer, size_t size) +{ + Debug::info("LibusbDevice write: called with size %d", size); + unsigned char* src = static_cast<unsigned char*>(buffer); + + while (size) { + int transfered; + //Call with timeout to enable possible cancel + int error = libusb_bulk_transfer(handle_, outEndpoint_, src, size, &transfered, 0); + + if (error) { + if (error == LIBUSB_ERROR_TIMEOUT) { + continue; + } else { + return error; + } + } + + size -= transfered; + src += transfered; + } + + Debug::info("LibusbDevice write: complete"); + return 0; +} + +int LibusbDevice::getVendorId() +{ + return descriptor_.idVendor; +} + +libusb_device* LibusbDevice::getPort() +{ + return device_; +} |