Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
3 changes: 2 additions & 1 deletion v5/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ set(TEST_SOURCES_LIST
tests/static_list.test.cpp
tests/steady_clock.test.cpp
tests/streams.test.cpp
tests/usb.test.cpp
# tests/usb.test.cpp
tests/usb2.test.cpp
tests/timeout.test.cpp
tests/bit_bang_i2c.test.cpp
tests/bit_bang_spi.test.cpp
Expand Down
2 changes: 1 addition & 1 deletion v5/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def build_requirements(self):
self.test_requires("boost-ext-ut/2.1.0")

def requirements(self):
self.requires("libhal/[^4.21.0]", transitive_headers=True)
self.requires("libhal/[^4.22.0]", transitive_headers=True)

def layout(self):
cmake_layout(self)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace constants {

constexpr byte device_descriptor_size = 18;
constexpr byte configuration_descriptor_size = 9;
constexpr byte inferface_descriptor_size = 9;
constexpr byte interface_descriptor_size = 9;
constexpr byte endpoint_descriptor_size = 7;
constexpr byte interface_association_descriptor_size = 0x08;

Expand Down Expand Up @@ -64,6 +64,14 @@ enum class class_code : hal::byte
vendor_specific = 0xFF // Vendor Specific
};

enum class transfer_type : hal::byte
{
control = 0x00,
isochronous = 0x01,
bulk = 0x02,
interrupt = 0x03,
};

// Default types
enum class descriptor_type : hal::byte
{
Expand Down
103 changes: 95 additions & 8 deletions v5/include/libhal-util/usb/descriptors.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
#include <libhal/units.hpp>
#include <libhal/usb.hpp>

#include "utils.hpp"
#include "constants.hpp"

// TODO(#95): Device qualifer descriptor (happens between device and config)
// TODO(#96): USB 3.x Superspeed descriptors (BOS Descriptor, Device Capability,
Expand All @@ -38,7 +38,6 @@ namespace hal::v5::usb {
class device
{
public:
template<size_t>
friend class enumerator;

struct device_arguments
Expand Down Expand Up @@ -192,7 +191,6 @@ concept usb_interface_concept = std::derived_from<T, interface>;
class configuration
{
public:
template<size_t>
friend class enumerator;

struct bitmap
Expand Down Expand Up @@ -249,11 +247,11 @@ class configuration
u8 idx = 0;

// Anything marked with 0 is to be populated at enumeration time
m_packed_arr[idx++] = 0; // 0 Total Length
m_packed_arr[idx++] = 0;
m_packed_arr[idx++] = 0; // 0 Total Length 1/2
m_packed_arr[idx++] = 0; // 1 Total Length 2/2
m_packed_arr[idx++] = m_interfaces.size(); // 2 number of interfaces
m_packed_arr[idx++] = 0; // 3 Config number
m_packed_arr[idx++] = 0; // 4 Configuration name string index
m_packed_arr[idx++] = 0; // 4 Configuration string index

m_packed_arr[idx++] = p_info.attributes.to_byte(); // 5
m_packed_arr[idx++] = p_info.max_power; // 6
Expand Down Expand Up @@ -315,18 +313,107 @@ class configuration
m_packed_arr[3] = p_value;
}

[[nodiscard]] constexpr u8 configuration_index() const
[[nodiscard]] constexpr u8 configuration_string_index() const
{
return m_packed_arr[4];
}
constexpr void set_configuration_index(u8 p_index)
constexpr void set_configuration_string_index(u8 p_index)
{
m_packed_arr[4] = p_index;
}

std::pmr::vector<strong_ptr<interface>> m_interfaces;
std::array<hal::byte, 7> m_packed_arr;
};

struct interface_descriptor_info
{
u8 interface_number;
u8 alternate_setting;
u8 num_endpoints;
class_code interface_class;
u8 interface_subclass;
u8 interface_protocol;
u8 interface_string_index;
};

constexpr auto generate_interface_descriptor(interface_descriptor_info p_info)
{
static constexpr u8 b_length = 0;
static constexpr u8 b_descriptor_type = 1;
static constexpr u8 b_interface_number = 2;
static constexpr u8 b_alternate_setting = 3;
static constexpr u8 b_num_endpoints = 4;
static constexpr u8 b_interface_class = 5;
static constexpr u8 b_interface_sub_class = 6;
static constexpr u8 b_interface_protocol = 7;
static constexpr u8 i_interface = 8;

std::array<byte, constants::interface_descriptor_size> descriptor{};

descriptor[b_length] = static_cast<byte>(descriptor.size());
descriptor[b_descriptor_type] = static_cast<byte>(descriptor_type::interface);
descriptor[b_interface_number] = p_info.interface_number;
descriptor[b_alternate_setting] = p_info.alternate_setting;
descriptor[b_num_endpoints] = p_info.num_endpoints;
descriptor[b_interface_class] = static_cast<byte>(p_info.interface_class);
descriptor[b_interface_sub_class] = p_info.interface_subclass;
descriptor[b_interface_protocol] = p_info.interface_protocol;
descriptor[i_interface] = p_info.interface_string_index;

return descriptor;
}

template<typename T>
concept usb_endpoint_type = std::is_base_of_v<hal::usb::endpoint, T>;

constexpr auto generate_endpoint_descriptor(usb_endpoint_type auto& p_endpoint,
u8 p_interval)
{
using Endpoint = std::remove_reference_t<decltype(p_endpoint)>;
using hal::usb::bulk_in_endpoint;
using hal::usb::bulk_out_endpoint;
using hal::usb::interrupt_in_endpoint;
using hal::usb::interrupt_out_endpoint;

constexpr transfer_type type = [] {
if constexpr (std::is_base_of_v<bulk_in_endpoint, Endpoint> or
std::is_base_of_v<bulk_out_endpoint, Endpoint>) {
return transfer_type::bulk;
} else if constexpr (std::is_base_of_v<interrupt_in_endpoint, Endpoint> or
std::is_base_of_v<interrupt_out_endpoint, Endpoint>) {
return transfer_type::interrupt;
} else {
return transfer_type::control;
}
}();

static constexpr u8 b_length = 0;
static constexpr u8 b_descriptor_type = 1;
static constexpr u8 b_endpoint_address = 2;
static constexpr u8 bm_attributes = 3;
static constexpr u8 w_max_packet_size_lo = 4;
static constexpr u8 w_max_packet_size_hi = 5;
static constexpr u8 b_interval = 6;

std::array<byte, constants::endpoint_descriptor_size> descriptor{};

auto const ep_info = p_endpoint.info();

descriptor[b_length] = static_cast<byte>(descriptor.size());
descriptor[b_descriptor_type] = static_cast<byte>(descriptor_type::endpoint);
descriptor[b_endpoint_address] = ep_info.number;
descriptor[bm_attributes] = static_cast<byte>(type);

auto const max_packet_size_bytes = setup_packet::to_le_u16(ep_info.size);
descriptor[w_max_packet_size_lo] = max_packet_size_bytes[0];
descriptor[w_max_packet_size_hi] = max_packet_size_bytes[1];

descriptor[b_interval] = p_interval;

return descriptor;
}

} // namespace hal::v5::usb

namespace hal::usb {
Expand Down
Loading