HelenOS sources
This source file includes following definitions.
- usbvirt_control_reply_helper
- req_nop
- req_get_descriptor
- req_set_address
- req_set_configuration
- req_get_dev_status
- req_get_iface_ep_status
#include "private.h"
#include <usb/dev/request.h>
#include <assert.h>
#include <errno.h>
void usbvirt_control_reply_helper(const usb_device_request_setup_packet_t *setup_packet,
    uint8_t *data, size_t *act_size,
    const void *actual_data, size_t actual_data_size)
{
        size_t expected_size = setup_packet->length;
        if (expected_size < actual_data_size) {
                actual_data_size = expected_size;
        }
        memcpy(data, actual_data, actual_data_size);
        if (act_size != NULL) {
                *act_size = actual_data_size;
        }
}
errno_t req_nop(usbvirt_device_t *device,
    const usb_device_request_setup_packet_t *setup_packet,
    uint8_t *data, size_t *act_size)
{
        return EOK;
}
static errno_t req_get_descriptor(usbvirt_device_t *device,
    const usb_device_request_setup_packet_t *setup_packet, uint8_t *data, size_t *act_size)
{
        uint8_t type = setup_packet->value_high;
        uint8_t index = setup_packet->value_low;
        
        if ((type == USB_DESCTYPE_DEVICE) && (index == 0)) {
                if (device->descriptors && device->descriptors->device) {
                        usbvirt_control_reply_helper(setup_packet, data, act_size,
                            device->descriptors->device,
                            device->descriptors->device->length);
                        return EOK;
                } else {
                        return EFORWARD;
                }
        }
        
        if (type == USB_DESCTYPE_CONFIGURATION) {
                if (!device->descriptors) {
                        return EFORWARD;
                }
                if (index >= device->descriptors->configuration_count) {
                        return EFORWARD;
                }
                
                const usbvirt_device_configuration_t *config =
                    &device->descriptors->configuration[index];
                uint8_t *all_data = malloc(config->descriptor->total_length);
                if (all_data == NULL) {
                        return ENOMEM;
                }
                uint8_t *ptr = all_data;
                memcpy(ptr, config->descriptor, config->descriptor->length);
                ptr += config->descriptor->length;
                size_t i;
                for (i = 0; i < config->extra_count; i++) {
                        const usbvirt_device_configuration_extras_t *extra =
                            &config->extra[i];
                        memcpy(ptr, extra->data, extra->length);
                        ptr += extra->length;
                }
                usbvirt_control_reply_helper(setup_packet, data, act_size,
                    all_data, config->descriptor->total_length);
                free(all_data);
                return EOK;
        }
        return EFORWARD;
}
static errno_t req_set_address(usbvirt_device_t *device,
    const usb_device_request_setup_packet_t *setup_packet, uint8_t *data, size_t *act_size)
{
        uint16_t new_address = setup_packet->value;
        uint16_t zero1 = setup_packet->index;
        uint16_t zero2 = setup_packet->length;
        if ((zero1 != 0) || (zero2 != 0)) {
                return EINVAL;
        }
        if (new_address > 127) {
                return EINVAL;
        }
        device->address = new_address;
        return EOK;
}
static errno_t req_set_configuration(usbvirt_device_t *device,
    const usb_device_request_setup_packet_t *setup_packet, uint8_t *data, size_t *act_size)
{
        uint16_t configuration_value = setup_packet->value;
        uint16_t zero1 = setup_packet->index;
        uint16_t zero2 = setup_packet->length;
        if ((zero1 != 0) || (zero2 != 0)) {
                return EINVAL;
        }
        
        if (configuration_value > 255) {
                return EINVAL;
        }
        
        if (device->state == USBVIRT_STATE_DEFAULT) {
                return EOK;
        }
        usbvirt_device_state_t new_state;
        if (configuration_value == 0) {
                new_state = USBVIRT_STATE_ADDRESS;
        } else {
                
                new_state = USBVIRT_STATE_CONFIGURED;
        }
        if (device->ops && device->ops->state_changed) {
                device->ops->state_changed(device, device->state, new_state);
        }
        device->state = new_state;
        return EOK;
}
static errno_t req_get_dev_status(usbvirt_device_t *device,
    const usb_device_request_setup_packet_t *setup_packet, uint8_t *data, size_t *act_size)
{
        if (setup_packet->length != 2)
                return ESTALL;
        data[0] = (device->self_powered ? 1 : 0) | (device->remote_wakeup ? 2 : 0);
        data[1] = 0;
        *act_size = 2;
        return EOK;
}
static errno_t req_get_iface_ep_status(usbvirt_device_t *device,
    const usb_device_request_setup_packet_t *setup_packet, uint8_t *data, size_t *act_size)
{
        if (setup_packet->length != 2)
                return ESTALL;
        data[0] = 0;
        data[1] = 0;
        *act_size = 2;
        return EOK;
}
usbvirt_control_request_handler_t library_handlers[] = {
        {
                STD_REQ_OUT(USB_REQUEST_RECIPIENT_DEVICE, USB_DEVREQ_SET_ADDRESS),
                .name = "SetAddress",
                .callback = req_set_address
        },
        {
                STD_REQ_IN(USB_REQUEST_RECIPIENT_DEVICE, USB_DEVREQ_GET_DESCRIPTOR),
                .name = "GetStdDescriptor",
                .callback = req_get_descriptor
        },
        {
                STD_REQ_OUT(USB_REQUEST_RECIPIENT_DEVICE, USB_DEVREQ_SET_CONFIGURATION),
                .name = "SetConfiguration",
                .callback = req_set_configuration
        },
        {
                STD_REQ_IN(USB_REQUEST_RECIPIENT_DEVICE, USB_DEVREQ_GET_STATUS),
                .name = "GetDeviceStatus",
                .callback = req_get_dev_status,
        },
        {
                STD_REQ_IN(USB_REQUEST_RECIPIENT_INTERFACE, USB_DEVREQ_GET_STATUS),
                .name = "GetInterfaceStatus",
                .callback = req_get_iface_ep_status,
        },
        {
                
                STD_REQ_IN(USB_REQUEST_RECIPIENT_ENDPOINT, USB_DEVREQ_GET_STATUS),
                .name = "GetEndpointStatus",
                .callback = req_get_iface_ep_status,
        },
        { .callback = NULL }
};
HelenOS homepage, sources at GitHub