Moved wMaxPacketSize retrieval to Usb::UsbDevice class.

And some other bits of tidying
This commit is contained in:
Nav
2023-12-02 19:31:20 +00:00
parent eab1688b1a
commit 084eef1a30
7 changed files with 93 additions and 48 deletions

View File

@@ -40,7 +40,9 @@ namespace DebugToolDrivers::Microchip
auto cmsisHidInterface = Usb::HidInterface(
this->cmsisHidInterfaceNumber,
this->getCmsisHidReportSize(),
this->getEndpointMaxPacketSize(
this->getFirstEndpointAddress(this->cmsisHidInterfaceNumber, LIBUSB_ENDPOINT_IN)
),
this->vendorId,
this->productId
);
@@ -157,33 +159,4 @@ namespace DebugToolDrivers::Microchip
this->sessionStarted = false;
}
std::uint16_t EdbgDevice::getCmsisHidReportSize() {
const auto activeConfigDescriptor = this->getConfigDescriptor();
for (auto interfaceIndex = 0; interfaceIndex < activeConfigDescriptor->bNumInterfaces; ++interfaceIndex) {
const auto* interfaceDescriptor = (activeConfigDescriptor->interface + interfaceIndex)->altsetting;
if (interfaceDescriptor->bInterfaceNumber != this->cmsisHidInterfaceNumber) {
continue;
}
for (auto endpointIndex = 0; endpointIndex < activeConfigDescriptor->bNumInterfaces; ++endpointIndex) {
const auto* endpointDescriptor = (interfaceDescriptor->endpoint + endpointIndex);
if ((endpointDescriptor->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) != LIBUSB_ENDPOINT_IN) {
// Not an IN endpoint
continue;
}
return endpointDescriptor->wMaxPacketSize;
}
}
throw DeviceInitializationFailure(
"Failed to obtain CMSIS-DAP HID report size via endpoint descriptor - could not find IN endpoint for "
"selected configuration value (" + std::to_string(activeConfigDescriptor->bConfigurationValue)
+ ") and interface number (" + std::to_string(this->cmsisHidInterfaceNumber) + ")"
);
}
}

View File

@@ -155,17 +155,6 @@ namespace DebugToolDrivers::Microchip
bool sessionStarted = false;
/**
* Because EDBG devices require fixed-length reports to be transmitted to/from their HID interface, we must
* know the HID report size (as it differs across EDBG devices).
*
* This member function will obtain the report size from the endpoint descriptor of the IN endpoint, from the
* HID interface.
*
* @return
*/
std::uint16_t getCmsisHidReportSize();
virtual void configureAvr8Interface() {
return;
}

View File

@@ -4,6 +4,8 @@
#include <array>
#include "src/Logger/Logger.hpp"
#include "src/Services/StringService.hpp"
#include "src/TargetController/Exceptions/DeviceInitializationFailure.hpp"
#include "src/TargetController/Exceptions/DeviceCommunicationFailure.hpp"
#include "src/TargetController/Exceptions/DeviceNotFound.hpp"
@@ -100,6 +102,53 @@ namespace Usb
}
}
std::uint8_t UsbDevice::getFirstEndpointAddress(
std::uint8_t interfaceNumber,
::libusb_endpoint_direction direction
) {
const auto activeConfigDescriptor = this->getConfigDescriptor();
for (auto interfaceIndex = 0; interfaceIndex < activeConfigDescriptor->bNumInterfaces; ++interfaceIndex) {
const auto* interfaceDescriptor = (activeConfigDescriptor->interface + interfaceIndex)->altsetting;
if (interfaceDescriptor->bInterfaceNumber != interfaceNumber) {
continue;
}
for (auto endpointIndex = 0; endpointIndex < interfaceDescriptor->bNumEndpoints; ++endpointIndex) {
const auto* endpointDescriptor = (interfaceDescriptor->endpoint + endpointIndex);
if ((endpointDescriptor->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) != direction) {
return endpointDescriptor->bEndpointAddress;
}
}
}
throw DeviceInitializationFailure("Failed to obtain address of USB endpoint");
}
std::uint16_t UsbDevice::getEndpointMaxPacketSize(std::uint8_t endpointAddress) {
const auto activeConfigDescriptor = this->getConfigDescriptor();
for (auto interfaceIndex = 0; interfaceIndex < activeConfigDescriptor->bNumInterfaces; ++interfaceIndex) {
const auto* interfaceDescriptor = (activeConfigDescriptor->interface + interfaceIndex)->altsetting;
for (auto endpointIndex = 0; endpointIndex < interfaceDescriptor->bNumEndpoints; ++endpointIndex) {
const auto* endpointDescriptor = (interfaceDescriptor->endpoint + endpointIndex);
if (endpointDescriptor->bEndpointAddress == endpointAddress) {
return endpointDescriptor->wMaxPacketSize;
}
}
}
throw DeviceInitializationFailure(
"Failed to obtain maximum packet size of USB endpoint (address: 0x"
+ Services::StringService::toHex(endpointAddress) + "). Endpoint not found. Selected configuration "
"value (" + std::to_string(activeConfigDescriptor->bConfigurationValue) + ")"
);
}
std::vector<LibusbDevice> UsbDevice::findMatchingDevices(std::uint16_t vendorId, std::uint16_t productId) {
::libusb_device** devices = nullptr;
::libusb_device* device;

View File

@@ -38,6 +38,22 @@ namespace Usb
*/
std::string getSerialNumber() const;
/**
* Obtains the address of the first endpoint within a given interface and of a particular direction.
*
* @param endpointAddress
* @return
*/
std::uint8_t getFirstEndpointAddress(std::uint8_t interfaceNumber, ::libusb_endpoint_direction direction);
/**
* Obtains the maximum packet size of an endpoint.
*
* @param endpointAddress
* @return
*/
std::uint16_t getEndpointMaxPacketSize(std::uint8_t endpointAddress);
/**
* Selects a specific configuration on the device, using the configuration index.
*

View File

@@ -21,8 +21,10 @@ namespace DebugToolDrivers::Wch::Protocols::WchLink
using Targets::RiscV::DebugModule::DmiOperation;
WchLinkInterface::WchLinkInterface(Usb::UsbInterface& usbInterface)
WchLinkInterface::WchLinkInterface(Usb::UsbInterface& usbInterface, Usb::UsbDevice& usbDevice)
: usbInterface(usbInterface)
, commandEndpointMaxPacketSize(usbDevice.getEndpointMaxPacketSize(WchLinkInterface::USB_COMMAND_ENDPOINT_OUT))
, dataEndpointMaxPacketSize(usbDevice.getEndpointMaxPacketSize(WchLinkInterface::USB_DATA_ENDPOINT_OUT))
{}
DeviceInfo WchLinkInterface::getDeviceInfo() {

View File

@@ -3,9 +3,11 @@
#include <memory>
#include <optional>
#include <vector>
#include <utility>
#include "src/DebugToolDrivers/TargetInterfaces/RiscV/RiscVDebugInterface.hpp"
#include "src/DebugToolDrivers/USB/UsbInterface.hpp"
#include "src/DebugToolDrivers/USB/UsbDevice.hpp"
#include "src/DebugToolDrivers/WCH/WchGeneric.hpp"
#include "Commands/Command.hpp"
@@ -23,7 +25,7 @@ namespace DebugToolDrivers::Wch::Protocols::WchLink
class WchLinkInterface: public TargetInterfaces::RiscV::RiscVDebugInterface
{
public:
explicit WchLinkInterface(Usb::UsbInterface& usbInterface);
WchLinkInterface(Usb::UsbInterface& usbInterface, Usb::UsbDevice& usbDevice);
DeviceInfo getDeviceInfo();
@@ -43,11 +45,16 @@ namespace DebugToolDrivers::Wch::Protocols::WchLink
) override;
private:
static constexpr std::uint8_t USB_ENDPOINT_IN = 0x81;
static constexpr std::uint8_t USB_ENDPOINT_OUT = 0x01;
static constexpr std::uint8_t USB_COMMAND_ENDPOINT_IN = 0x81;
static constexpr std::uint8_t USB_COMMAND_ENDPOINT_OUT = 0x01;
static constexpr std::uint8_t USB_DATA_ENDPOINT_IN = 0x82;
static constexpr std::uint8_t USB_DATA_ENDPOINT_OUT = 0x02;
Usb::UsbInterface& usbInterface;
std::uint16_t commandEndpointMaxPacketSize = 0;
std::uint16_t dataEndpointMaxPacketSize = 0;
/**
* The 'target activation' command returns a payload of 5 bytes.
*
@@ -67,9 +74,17 @@ namespace DebugToolDrivers::Wch::Protocols::WchLink
template <class CommandType>
auto sendCommandAndWaitForResponse(const CommandType& command) {
this->usbInterface.writeBulk(WchLinkInterface::USB_ENDPOINT_OUT, command.getRawCommand());
auto rawCommand = command.getRawCommand();
const auto rawResponse = this->usbInterface.readBulk(WchLinkInterface::USB_ENDPOINT_IN);
if (rawCommand.size() > this->commandEndpointMaxPacketSize) {
throw Exceptions::DeviceCommunicationFailure(
"Raw command size exceeds maximum packet size for command endpoint"
);
}
this->usbInterface.writeBulk(WchLinkInterface::USB_COMMAND_ENDPOINT_OUT, std::move(rawCommand));
const auto rawResponse = this->usbInterface.readBulk(WchLinkInterface::USB_COMMAND_ENDPOINT_IN);
if (rawResponse.size() < 3) {
throw Exceptions::DeviceCommunicationFailure("Invalid response size from device");

View File

@@ -32,7 +32,8 @@ namespace DebugToolDrivers::Wch
this->wchLinkUsbInterface->init();
this->wchLinkInterface = std::make_unique<Protocols::WchLink::WchLinkInterface>(
*(this->wchLinkUsbInterface.get())
*(this->wchLinkUsbInterface.get()),
*this
);
if (this->getDeviceInfo().variant != this->variant) {