[Voyageurs] Get Configuration from USB device.

This commit is contained in:
Drew Galbraith 2024-02-24 08:25:22 -08:00
parent 39b6d32d86
commit af69415d4d
3 changed files with 87 additions and 2 deletions

View File

@ -21,7 +21,7 @@ class ReadControlCommand {
uint64_t value = RequestConstants<Output>::Value() << 16;
// TODO: May need to be non-0 for string descriptors.
uint64_t index = (uint64_t)0 << 32;
uint64_t length = sizeof(Output) << 48;
uint64_t length = (uint64_t)0x1000 << 48;
return {
.parameter = request_type | request | value | index | length,
.status = 8,
@ -34,7 +34,7 @@ class ReadControlCommand {
XhciTrb DataTrb() {
return {
.parameter = output_phys_,
.status = sizeof(Output),
.status = 0x1000,
.type_and_cycle = 1 | (1 << 5) | (3 << 10),
.control = 1,
};

View File

@ -34,3 +34,44 @@ class RequestConstants<DeviceDescriptor> {
static uint8_t Request() { return 0x6; };
static uint16_t Value() { return 0x100; };
};
struct ConfigurationDescriptor {
uint8_t length;
uint8_t type;
uint16_t total_length;
uint8_t num_interfaces;
uint8_t configuration_value;
uint8_t configuration_string_index;
uint8_t attributes;
uint8_t max_power;
} __attribute__((packed));
template <>
class RequestConstants<ConfigurationDescriptor> {
public:
static uint8_t RequestType() { return 0x80; }
static uint8_t Request() { return 0x6; }
// TODO: Consider getting other description indexes.
static uint16_t Value() { return 0x200; }
};
struct InterfaceDescriptor {
uint8_t length;
uint8_t type;
uint8_t interface_number;
uint8_t alternate_setting;
uint8_t num_endpoints;
uint8_t interface_class;
uint8_t interface_subclass;
uint8_t interface_protocol;
uint8_t interfact_string_index;
} __attribute__((packed));
struct EndpointDescriptor {
uint8_t length;
uint8_t type;
uint8_t endpoint_address;
uint8_t attributes;
uint16_t max_packet_size;
uint8_t interval;
} __attribute__((packed));

View File

@ -31,6 +31,45 @@ void configure_device(void* void_device_slot) {
dbgln("Descriptor Type {x}, ({x})", descriptor->type, descriptor->usb_spec);
dbgln("Device Class/Sub/Protocol: {x}/{x}/{x}", descriptor->device_class,
descriptor->device_subclass, descriptor->device_protocol);
dbgln("Num Configurations: {}", descriptor->num_configurations);
ReadControlCommand<ConfigurationDescriptor> config_command;
device_slot->ExecuteReadControlCommand(config_command);
ConfigurationDescriptor* config_descriptor = config_command.AwaitResult();
dbgln("Configuration Value: {x}", config_descriptor->configuration_value);
dbgln("Num Interfaces: {x}", config_descriptor->num_interfaces);
dbgln("Size: {x}, Total Length: {x}", config_descriptor->length,
config_descriptor->total_length);
uint64_t next_vaddr =
reinterpret_cast<uint64_t>(config_descriptor) + config_descriptor->length;
for (auto i = config_descriptor->num_interfaces; i > 0; i--) {
InterfaceDescriptor* interface =
reinterpret_cast<InterfaceDescriptor*>(next_vaddr);
dbgln("Interface: {x}", interface->interface_number);
dbgln("Interface Class/Sub/Protocol: {x}/{x}/{x}",
interface->interface_class, interface->interface_subclass,
interface->interface_protocol);
dbgln("Num Endpoints: {x}", interface->num_endpoints);
next_vaddr += interface->length;
for (auto j = interface->num_endpoints; j > 0; j--) {
EndpointDescriptor* endpoint =
reinterpret_cast<EndpointDescriptor*>(next_vaddr);
if (endpoint->type != 5) {
dbgln("Descriptor type {x}, skipping", endpoint->type);
j++;
next_vaddr += endpoint->length;
continue;
}
dbgln("Endpoint Addr: {x}", endpoint->endpoint_address);
dbgln("Endpoint Attr: {x}", endpoint->attributes);
next_vaddr += endpoint->length;
}
}
}
glcr::ErrorOr<glcr::UniquePtr<XhciDriver>> XhciDriver::InitiateDriver(
@ -300,6 +339,11 @@ void XhciDriver::HandleCommandCompletion(
}
void XhciDriver::HandleTransferCompletion(const XhciTrb& transfer_event_trb) {
uint8_t status = transfer_event_trb.status >> 24;
if (status != 1 && status != 0xD) {
dbgln("Unexpected Status {x}", status);
return;
}
uint8_t slot_id = transfer_event_trb.control >> 8;
uint8_t endpoint_id = transfer_event_trb.control & 0x1F;
uint64_t trb_phys = transfer_event_trb.parameter;