HelenOS sources
This source file includes following definitions.
- usb_interface_count_alternates
- usb_alternate_interfaces_init
- usb_alternate_interfaces_deinit
#include <usb/dev/alternate_ifaces.h>
#include <usb/dev/dp.h>
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <stddef.h>
size_t usb_interface_count_alternates(const uint8_t *config_descr,
size_t config_descr_size, uint8_t interface_no)
{
assert(config_descr != NULL);
assert(config_descr_size > 0);
const usb_dp_parser_t dp_parser = {
.nesting = usb_dp_standard_descriptor_nesting
};
const usb_dp_parser_data_t dp_data = {
.data = config_descr,
.size = config_descr_size,
.arg = NULL
};
size_t alternate_count = 0;
const void *iface_ptr =
usb_dp_get_nested_descriptor(&dp_parser, &dp_data, config_descr);
while (iface_ptr != NULL) {
const usb_standard_interface_descriptor_t *iface = iface_ptr;
if (iface->descriptor_type == USB_DESCTYPE_INTERFACE &&
iface->interface_number == interface_no) {
++alternate_count;
}
iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data,
config_descr, iface_ptr);
}
return alternate_count;
}
errno_t usb_alternate_interfaces_init(usb_alternate_interfaces_t *alternates,
const uint8_t *config_descr, size_t config_descr_size, int interface_number)
{
assert(alternates != NULL);
assert(config_descr != NULL);
assert(config_descr_size > 0);
alternates->alternatives = NULL;
alternates->alternative_count = 0;
alternates->current = 0;
if (interface_number < 0) {
return EOK;
}
const size_t alt_count = usb_interface_count_alternates(config_descr,
config_descr_size, interface_number);
if (alt_count == 0) {
return ENOENT;
}
usb_alternate_interface_descriptors_t *alts = calloc(alt_count,
sizeof(usb_alternate_interface_descriptors_t));
if (alts == NULL) {
return ENOMEM;
}
const usb_dp_parser_t dp_parser = {
.nesting = usb_dp_standard_descriptor_nesting
};
const usb_dp_parser_data_t dp_data = {
.data = config_descr,
.size = config_descr_size,
.arg = NULL
};
const void *iface_ptr =
usb_dp_get_nested_descriptor(&dp_parser, &dp_data, dp_data.data);
usb_alternate_interface_descriptors_t *iterator = alts;
for (; iface_ptr != NULL && iterator < &alts[alt_count]; ++iterator) {
const usb_standard_interface_descriptor_t *iface = iface_ptr;
if ((iface->descriptor_type != USB_DESCTYPE_INTERFACE) ||
(iface->interface_number != interface_number)) {
iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser,
&dp_data, dp_data.data, iface_ptr);
continue;
}
iterator->interface = iface;
iterator->nested_descriptors = iface_ptr + sizeof(*iface);
iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data,
dp_data.data, iface_ptr);
const uint8_t *next = (iface_ptr == NULL) ?
dp_data.data + dp_data.size : iface_ptr;
iterator->nested_descriptors_size =
next - iterator->nested_descriptors;
}
alternates->alternatives = alts;
alternates->alternative_count = alt_count;
return EOK;
}
void usb_alternate_interfaces_deinit(usb_alternate_interfaces_t *instance)
{
if (!instance)
return;
free(instance->alternatives);
instance->alternatives = NULL;
}
HelenOS homepage, sources at GitHub