Removed using namespace directive for class member function definitions in source files

This commit is contained in:
Nav
2022-02-05 15:32:08 +00:00
parent 9bbc534973
commit 53a3c815d7
116 changed files with 13113 additions and 12664 deletions

View File

@@ -5,127 +5,133 @@
#include "src/TargetController/Exceptions/DeviceInitializationFailure.hpp"
#include "src/TargetController/Exceptions/DeviceCommunicationFailure.hpp"
using namespace Bloom::Usb;
using namespace Bloom::Exceptions;
namespace Bloom::Usb
{
using namespace Bloom::Exceptions;
void HidInterface::init() {
if (this->libUsbDevice == nullptr) {
throw DeviceInitializationFailure("Cannot initialise interface without libusb device pointer.");
}
hid_init();
hid_device* hidDevice = nullptr;
std::string hidInterfacePath = this->getDevicePathByInterfaceNumber(this->getNumber());
Logger::debug("HID device path: " + hidInterfacePath);
if ((hidDevice = hid_open_path(hidInterfacePath.c_str())) == nullptr) {
throw DeviceInitializationFailure("Failed to open HID device via hidapi.");
}
if (hidDevice->input_ep_max_packet_size < 1) {
throw DeviceInitializationFailure(
"Invalid max packet size for USB endpoint, on interface " + std::to_string(this->getNumber())
);
}
this->setHidDevice(hidDevice);
this->setInputReportSize(static_cast<std::size_t>(hidDevice->input_ep_max_packet_size));
this->libUsbDeviceHandle = hidDevice->device_handle;
this->initialised = true;
}
void HidInterface::close() {
auto* hidDevice = this->getHidDevice();
if (hidDevice != nullptr) {
this->libUsbDeviceHandle = nullptr;
hid_close(hidDevice);
// hid_close() releases the interface
this->claimed = false;
}
hid_exit();
Interface::close();
}
std::vector<unsigned char> HidInterface::read(unsigned int timeout) {
std::vector<unsigned char> output;
auto readSize = this->getInputReportSize();
// Attempt to read the first HID report packet, and whatever is left after that.
output.resize(readSize);
auto transferredByteCount = this->read(output.data(), readSize, timeout);
auto totalByteCount = transferredByteCount;
while (transferredByteCount >= readSize) {
output.resize(totalByteCount + readSize);
transferredByteCount = this->read(output.data() + totalByteCount, readSize, 1);
totalByteCount += transferredByteCount;
}
output.resize(totalByteCount);
return output;
}
void HidInterface::write(std::vector<unsigned char> buffer) {
if (buffer.size() > this->getInputReportSize()) {
throw DeviceCommunicationFailure(
"Cannot send data via HID interface - data exceeds maximum packet size."
);
}
if (buffer.size() < this->getInputReportSize()) {
/*
* Every report we send via the USB HID interface should be of a fixed size.
* In the event of a report being too small, we just fill the buffer vector with 0.
*/
buffer.resize(this->getInputReportSize(), 0);
}
int transferred = 0;
auto length = buffer.size();
if ((transferred = hid_write(this->getHidDevice(), buffer.data(), length)) != length) {
Logger::debug("Attempted to write " + std::to_string(length)
+ " bytes to HID interface. Bytes written: " + std::to_string(transferred));
throw DeviceCommunicationFailure("Failed to write data to HID interface.");
}
}
std::size_t HidInterface::read(unsigned char* buffer, std::size_t maxLength, unsigned int timeout) {
int transferred;
if ((transferred = hid_read_timeout(
this->hidDevice,
buffer,
maxLength,
timeout == 0 ? -1 : static_cast<int>(timeout))
) == -1
) {
throw DeviceCommunicationFailure("Failed to read from HID device.");
}
return static_cast<std::size_t>(transferred);
}
std::string HidInterface::getDevicePathByInterfaceNumber(const std::uint16_t& interfaceNumber) {
hid_device_info* hidDeviceInfoList = hid_enumerate(this->getVendorId(), this->getProductId());
while (hidDeviceInfoList != nullptr) {
if (hidDeviceInfoList->interface_number == interfaceNumber) {
break;
void HidInterface::init() {
if (this->libUsbDevice == nullptr) {
throw DeviceInitializationFailure("Cannot initialise interface without libusb device pointer.");
}
hidDeviceInfoList = hidDeviceInfoList->next;
hid_init();
hid_device* hidDevice = nullptr;
std::string hidInterfacePath = this->getDevicePathByInterfaceNumber(this->getNumber());
Logger::debug("HID device path: " + hidInterfacePath);
if ((hidDevice = hid_open_path(hidInterfacePath.c_str())) == nullptr) {
throw DeviceInitializationFailure("Failed to open HID device via hidapi.");
}
if (hidDevice->input_ep_max_packet_size < 1) {
throw DeviceInitializationFailure(
"Invalid max packet size for USB endpoint, on interface "
+ std::to_string(this->getNumber())
);
}
this->setHidDevice(hidDevice);
this->setInputReportSize(static_cast<std::size_t>(hidDevice->input_ep_max_packet_size));
this->libUsbDeviceHandle = hidDevice->device_handle;
this->initialised = true;
}
if (hidDeviceInfoList == nullptr) {
throw DeviceInitializationFailure("Failed to match interface number with HID interface.");
void HidInterface::close() {
auto* hidDevice = this->getHidDevice();
if (hidDevice != nullptr) {
this->libUsbDeviceHandle = nullptr;
hid_close(hidDevice);
// hid_close() releases the interface
this->claimed = false;
}
hid_exit();
Interface::close();
}
auto path = std::string(hidDeviceInfoList->path);
hid_free_enumeration(hidDeviceInfoList);
return path;
std::vector<unsigned char> HidInterface::read(unsigned int timeout) {
std::vector<unsigned char> output;
auto readSize = this->getInputReportSize();
// Attempt to read the first HID report packet, and whatever is left after that.
output.resize(readSize);
auto transferredByteCount = this->read(output.data(), readSize, timeout);
auto totalByteCount = transferredByteCount;
while (transferredByteCount >= readSize) {
output.resize(totalByteCount + readSize);
transferredByteCount = this->read(output.data() + totalByteCount, readSize, 1);
totalByteCount += transferredByteCount;
}
output.resize(totalByteCount);
return output;
}
void HidInterface::write(std::vector<unsigned char> buffer) {
if (buffer.size() > this->getInputReportSize()) {
throw DeviceCommunicationFailure(
"Cannot send data via HID interface - data exceeds maximum packet size."
);
}
if (buffer.size() < this->getInputReportSize()) {
/*
* Every report we send via the USB HID interface should be of a fixed size.
* In the event of a report being too small, we just fill the buffer vector with 0.
*/
buffer.resize(this->getInputReportSize(), 0);
}
int transferred = 0;
auto length = buffer.size();
if ((transferred = hid_write(this->getHidDevice(), buffer.data(), length)) != length) {
Logger::debug("Attempted to write " + std::to_string(length)
+ " bytes to HID interface. Bytes written: " + std::to_string(transferred));
throw DeviceCommunicationFailure("Failed to write data to HID interface.");
}
}
std::size_t HidInterface::read(unsigned char* buffer, std::size_t maxLength, unsigned int timeout) {
int transferred;
if ((transferred = hid_read_timeout(
this->hidDevice,
buffer,
maxLength,
timeout == 0 ? -1 : static_cast<int>(timeout))
) == -1
) {
throw DeviceCommunicationFailure("Failed to read from HID device.");
}
return static_cast<std::size_t>(transferred);
}
std::string HidInterface::getDevicePathByInterfaceNumber(const std::uint16_t& interfaceNumber) {
hid_device_info* hidDeviceInfoList = hid_enumerate(
this->getVendorId(),
this->getProductId()
);
while (hidDeviceInfoList != nullptr) {
if (hidDeviceInfoList->interface_number == interfaceNumber) {
break;
}
hidDeviceInfoList = hidDeviceInfoList->next;
}
if (hidDeviceInfoList == nullptr) {
throw DeviceInitializationFailure("Failed to match interface number with HID interface.");
}
auto path = std::string(hidDeviceInfoList->path);
hid_free_enumeration(hidDeviceInfoList);
return path;
}
}

View File

@@ -1,121 +1,123 @@
#include "Interface.hpp"
#include <libusb-1.0/libusb.h>
#include <chrono>
#include "src/TargetController/Exceptions/DeviceFailure.hpp"
#include "src/TargetController/Exceptions/DeviceCommunicationFailure.hpp"
#include "src/TargetController/Exceptions/DeviceInitializationFailure.hpp"
using namespace Bloom::Usb;
using namespace Bloom::Exceptions;
namespace Bloom::Usb
{
using namespace Bloom::Exceptions;
void Interface::init() {
if (this->libUsbDevice == nullptr) {
throw DeviceInitializationFailure("Cannot initialise interface without libusb device pointer.");
}
if (this->libUsbDeviceHandle == nullptr) {
throw DeviceInitializationFailure("Cannot initialise interface without libusb device handle.");
}
this->initialised = true;
}
void Interface::close() {
if (this->libUsbDeviceHandle != nullptr) {
this->release();
}
this->initialised = false;
}
void Interface::claim() {
int interfaceNumber = this->getNumber();
this->detachKernelDriver();
if (libusb_claim_interface(this->libUsbDeviceHandle, interfaceNumber) != 0) {
throw DeviceInitializationFailure(
"Failed to claim interface {" + std::to_string(interfaceNumber) + "} on USB device\n"
);
}
this->claimed = true;
}
void Interface::detachKernelDriver() {
int interfaceNumber = this->getNumber();
int libUsbStatusCode;
if ((libUsbStatusCode = libusb_kernel_driver_active(this->libUsbDeviceHandle, interfaceNumber)) != 0) {
if (libUsbStatusCode == 1) {
// A kernel driver is active on this interface. Attempt to detach it
if (libusb_detach_kernel_driver(this->libUsbDeviceHandle, interfaceNumber) != 0) {
throw DeviceInitializationFailure("Failed to detach kernel driver from interface " +
std::to_string(interfaceNumber) + "\n");
}
} else {
throw DeviceInitializationFailure("Failed to check for active kernel driver on USB interface.");
void Interface::init() {
if (this->libUsbDevice == nullptr) {
throw DeviceInitializationFailure("Cannot initialise interface without libusb device pointer.");
}
}
}
void Interface::release() {
if (this->isClaimed()) {
if (libusb_release_interface(this->libUsbDeviceHandle, this->getNumber()) != 0) {
throw DeviceFailure(
"Failed to release interface {" + std::to_string(this->getNumber()) + "} on USB device\n"
if (this->libUsbDeviceHandle == nullptr) {
throw DeviceInitializationFailure("Cannot initialise interface without libusb device handle.");
}
this->initialised = true;
}
void Interface::close() {
if (this->libUsbDeviceHandle != nullptr) {
this->release();
}
this->initialised = false;
}
void Interface::claim() {
int interfaceNumber = this->getNumber();
this->detachKernelDriver();
if (libusb_claim_interface(this->libUsbDeviceHandle, interfaceNumber) != 0) {
throw DeviceInitializationFailure(
"Failed to claim interface {" + std::to_string(interfaceNumber) + "} on USB device\n"
);
}
this->claimed = false;
this->claimed = true;
}
}
int Interface::read(unsigned char* buffer, unsigned char endPoint, size_t length, size_t timeout) {
int totalTransferred = 0;
int transferred = 0;
int libUsbStatusCode = 0;
void Interface::detachKernelDriver() {
int interfaceNumber = this->getNumber();
int libUsbStatusCode;
if ((libUsbStatusCode = libusb_kernel_driver_active(this->libUsbDeviceHandle, interfaceNumber)) != 0) {
if (libUsbStatusCode == 1) {
// A kernel driver is active on this interface. Attempt to detach it
if (libusb_detach_kernel_driver(this->libUsbDeviceHandle, interfaceNumber) != 0) {
throw DeviceInitializationFailure("Failed to detach kernel driver from interface " +
std::to_string(interfaceNumber) + "\n");
}
} else {
throw DeviceInitializationFailure("Failed to check for active kernel driver on USB interface.");
}
}
}
void Interface::release() {
if (this->isClaimed()) {
if (libusb_release_interface(this->libUsbDeviceHandle, this->getNumber()) != 0) {
throw DeviceFailure(
"Failed to release interface {" + std::to_string(this->getNumber())
+ "} on USB device\n"
);
}
this->claimed = false;
}
}
int Interface::read(unsigned char* buffer, unsigned char endPoint, size_t length, size_t timeout) {
int totalTransferred = 0;
int transferred = 0;
int libUsbStatusCode = 0;
while (length > totalTransferred) {
libUsbStatusCode = libusb_interrupt_transfer(
this->libUsbDeviceHandle,
endPoint,
buffer,
static_cast<int>(length),
&transferred,
static_cast<unsigned int>(timeout)
);
if (libUsbStatusCode != 0 && libUsbStatusCode != -7) {
throw DeviceCommunicationFailure(
"Failed to read from USB device. Error code returned: " + std::to_string(libUsbStatusCode)
);
}
totalTransferred += transferred;
}
return transferred;
}
void Interface::write(unsigned char* buffer, unsigned char endPoint, int length) {
int transferred = 0;
int libUsbStatusCode = 0;
while (length > totalTransferred) {
libUsbStatusCode = libusb_interrupt_transfer(
this->libUsbDeviceHandle,
endPoint,
buffer,
static_cast<int>(length),
length,
&transferred,
static_cast<unsigned int>(timeout)
0
);
if (libUsbStatusCode != 0 && libUsbStatusCode != -7) {
if (libUsbStatusCode != 0) {
throw DeviceCommunicationFailure(
"Failed to read from USB device. Error code returned: " + std::to_string(libUsbStatusCode)
);
}
totalTransferred += transferred;
}
return transferred;
}
void Interface::write(unsigned char* buffer, unsigned char endPoint, int length) {
int transferred = 0;
int libUsbStatusCode = 0;
libUsbStatusCode = libusb_interrupt_transfer(
this->libUsbDeviceHandle,
endPoint,
buffer,
length,
&transferred,
0
);
if (libUsbStatusCode != 0) {
throw DeviceCommunicationFailure(
"Failed to read from USB device. Error code returned: " + std::to_string(libUsbStatusCode)
);
}
}

View File

@@ -3,102 +3,107 @@
#include "src/Logger/Logger.hpp"
#include "src/TargetController/Exceptions/DeviceInitializationFailure.hpp"
using Bloom::Usb::UsbDevice;
using namespace Bloom::Exceptions;
namespace Bloom::Usb
{
using namespace Bloom::Exceptions;
void UsbDevice::init() {
libusb_init(&this->libUsbContext);
// libusb_set_option(this->libUsbContext, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_NONE);
auto devices = this->findMatchingDevices();
void UsbDevice::init() {
libusb_init(&this->libUsbContext);
// libusb_set_option(this->libUsbContext, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_NONE);
auto devices = this->findMatchingDevices();
if (devices.empty()) {
throw DeviceInitializationFailure("Failed to find USB device with matching vendor & product ID.");
} else if (devices.size() > 1) {
// TODO: implement support for multiple devices (maybe via serial number?)
throw DeviceInitializationFailure(
"Numerous devices of matching vendor & product ID found.\n"
"Please ensure that only one debug tool is connected and then try again."
);
}
// For now, just use the first device found.
auto device = devices.front();
this->setLibUsbDevice(device);
int libUsbStatusCode;
// Obtain a device handle from libusb
if ((libUsbStatusCode = libusb_open(libUsbDevice, &this->libUsbDeviceHandle)) < 0) {
throw DeviceInitializationFailure(
"Failed to open USB device - error code " + std::to_string(libUsbStatusCode) + " returned."
);
}
}
void UsbDevice::setConfiguration(int configIndex) {
libusb_config_descriptor* configDescriptor = {};
int libUsbStatusCode;
if ((libUsbStatusCode = libusb_get_config_descriptor(this->libUsbDevice, 0, &configDescriptor))) {
throw DeviceInitializationFailure(
"Failed to obtain USB configuration descriptor - error code " + std::to_string(libUsbStatusCode)
+ " returned."
);
}
if ((libUsbStatusCode = libusb_set_configuration(this->libUsbDeviceHandle, configDescriptor->bConfigurationValue))) {
throw DeviceInitializationFailure(
"Failed to set USB configuration - error code " + std::to_string(libUsbStatusCode) + " returned."
);
}
libusb_free_config_descriptor(configDescriptor);
}
std::vector<libusb_device*> UsbDevice::findMatchingDevices(
std::optional<std::uint16_t> vendorId, std::optional<std::uint16_t> productId
) {
auto libUsbContext = this->libUsbContext;
libusb_device** devices = nullptr;
libusb_device* device;
std::vector<libusb_device*> matchedDevices;
ssize_t i = 0, libUsbStatusCode;
auto vendorIdToMatch = vendorId.value_or(this->vendorId);
auto productIdToMatch = productId.value_or(this->productId);
if ((libUsbStatusCode = libusb_get_device_list(libUsbContext, &devices)) < 0) {
throw DeviceInitializationFailure(
"Failed to retrieve USB devices - return code: '" + std::to_string(libUsbStatusCode) + "'"
);
}
while ((device = devices[i++]) != nullptr) {
struct libusb_device_descriptor desc = {};
if ((libUsbStatusCode = libusb_get_device_descriptor(device, &desc)) < 0) {
Logger::warning("Failed to retrieve USB device descriptor - return code: '"
+ std::to_string(libUsbStatusCode) + "'");
continue;
if (devices.empty()) {
throw DeviceInitializationFailure("Failed to find USB device with matching vendor & product ID.");
}
if (desc.idVendor == vendorIdToMatch && desc.idProduct == productIdToMatch) {
matchedDevices.push_back(device);
if (devices.size() > 1) {
// TODO: implement support for multiple devices (maybe via serial number?)
throw DeviceInitializationFailure(
"Numerous devices of matching vendor & product ID found.\n"
"Please ensure that only one debug tool is connected and then try again."
);
}
// For now, just use the first device found.
auto* device = devices.front();
this->setLibUsbDevice(device);
const int libUsbStatusCode = libusb_open(libUsbDevice, &this->libUsbDeviceHandle);
// Obtain a device handle from libusb
if (libUsbStatusCode < 0) {
throw DeviceInitializationFailure(
"Failed to open USB device - error code " + std::to_string(libUsbStatusCode) + " returned."
);
}
}
libusb_free_device_list(devices, 1);
return matchedDevices;
}
void UsbDevice::setConfiguration(int configIndex) {
libusb_config_descriptor* configDescriptor = {};
int libUsbStatusCode = libusb_get_config_descriptor(this->libUsbDevice, 0, &configDescriptor);
void UsbDevice::close() {
if (this->libUsbDeviceHandle != nullptr) {
libusb_close(this->libUsbDeviceHandle);
this->libUsbDeviceHandle = nullptr;
if (libUsbStatusCode < 0) {
throw DeviceInitializationFailure(
"Failed to obtain USB configuration descriptor - error code " + std::to_string(libUsbStatusCode)
+ " returned."
);
}
libUsbStatusCode = libusb_set_configuration(this->libUsbDeviceHandle, configDescriptor->bConfigurationValue);
if (libUsbStatusCode < 0) {
throw DeviceInitializationFailure(
"Failed to set USB configuration - error code " + std::to_string(libUsbStatusCode) + " returned."
);
}
libusb_free_config_descriptor(configDescriptor);
}
if (this->libUsbContext != nullptr) {
libusb_exit(this->libUsbContext);
std::vector<libusb_device*> UsbDevice::findMatchingDevices(
std::optional<std::uint16_t> vendorId, std::optional<std::uint16_t> productId
) {
auto* libUsbContext = this->libUsbContext;
libusb_device** devices = nullptr;
libusb_device* device;
std::vector<libusb_device*> matchedDevices;
auto vendorIdToMatch = vendorId.value_or(this->vendorId);
auto productIdToMatch = productId.value_or(this->productId);
ssize_t libUsbStatusCode = libusb_get_device_list(libUsbContext, &devices);
if (libUsbStatusCode < 0) {
throw DeviceInitializationFailure(
"Failed to retrieve USB devices - return code: '" + std::to_string(libUsbStatusCode) + "'"
);
}
ssize_t i = 0;
while ((device = devices[i++]) != nullptr) {
struct libusb_device_descriptor desc = {};
if ((libUsbStatusCode = libusb_get_device_descriptor(device, &desc)) < 0) {
Logger::warning("Failed to retrieve USB device descriptor - return code: '"
+ std::to_string(libUsbStatusCode) + "'");
continue;
}
if (desc.idVendor == vendorIdToMatch && desc.idProduct == productIdToMatch) {
matchedDevices.push_back(device);
}
}
libusb_free_device_list(devices, 1);
return matchedDevices;
}
void UsbDevice::close() {
if (this->libUsbDeviceHandle != nullptr) {
libusb_close(this->libUsbDeviceHandle);
this->libUsbDeviceHandle = nullptr;
}
if (this->libUsbContext != nullptr) {
libusb_exit(this->libUsbContext);
}
}
}