source: mainline/uspace/lib/usbvirt/src/stdreq.c@ a943106

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a943106 was 6cb58e6, checked in by Vojtech Horky <vojtechhorky@…>, 14 years ago

Virtual USB layer rewritten

Major changes include

  • IPC sends whole transfers (not transactions)
  • separate transfer queues for each device in host controller
  • possibility to return NAK from virtual device (handled by HC)
  • better implementation of callbacks for non-zero endpoints

Still missing

  • communication for some transfer types (bulk)
  • face-lift ;-)
  • documentation
  • Property mode set to 100644
File size: 4.2 KB
RevLine 
[6cb58e6]1#include "private.h"
[0f21c0c]2#include <usb/request.h>
[6cb58e6]3#include <assert.h>
4#include <errno.h>
[4971812]5
[6cb58e6]6void usbvirt_control_reply_helper(const usb_device_request_setup_packet_t *setup_packet,
7 uint8_t *data, size_t *act_size,
8 void *actual_data, size_t actual_data_size)
9{
10 size_t expected_size = setup_packet->length;
11 if (expected_size < actual_data_size) {
12 actual_data_size = expected_size;
13 }
14
15 memcpy(data, actual_data, actual_data_size);
16
17 if (act_size != NULL) {
18 *act_size = actual_data_size;
19 }
20}
[4971812]21
[ca07cd3]22/** GET_DESCRIPTOR handler. */
[6cb58e6]23static int req_get_descriptor(usbvirt_device_t *device,
24 const usb_device_request_setup_packet_t *setup_packet, uint8_t *data, size_t *act_size)
[4971812]25{
[56b962d]26 uint8_t type = setup_packet->value_high;
27 uint8_t index = setup_packet->value_low;
28
[6cb58e6]29 /*
[4971812]30 * Standard device descriptor.
31 */
32 if ((type == USB_DESCTYPE_DEVICE) && (index == 0)) {
[2c381250]33 if (device->descriptors && device->descriptors->device) {
[6cb58e6]34 usbvirt_control_reply_helper(setup_packet, data, act_size,
[2c381250]35 device->descriptors->device,
36 device->descriptors->device->length);
[6cb58e6]37 return EOK;
[4971812]38 } else {
39 return EFORWARD;
40 }
41 }
[6cb58e6]42
[2c381250]43 /*
44 * Configuration descriptor together with interface, endpoint and
45 * class-specific descriptors.
46 */
47 if (type == USB_DESCTYPE_CONFIGURATION) {
48 if (!device->descriptors) {
49 return EFORWARD;
50 }
51 if (index >= device->descriptors->configuration_count) {
52 return EFORWARD;
53 }
54 /* Copy the data. */
55 usbvirt_device_configuration_t *config = &device->descriptors
56 ->configuration[index];
57 uint8_t *all_data = malloc(config->descriptor->total_length);
58 if (all_data == NULL) {
59 return ENOMEM;
60 }
[6cb58e6]61
[2c381250]62 uint8_t *ptr = all_data;
63 memcpy(ptr, config->descriptor, config->descriptor->length);
64 ptr += config->descriptor->length;
65 size_t i;
66 for (i = 0; i < config->extra_count; i++) {
67 usbvirt_device_configuration_extras_t *extra
68 = &config->extra[i];
69 memcpy(ptr, extra->data, extra->length);
70 ptr += extra->length;
71 }
[6cb58e6]72
73 usbvirt_control_reply_helper(setup_packet, data, act_size,
[7a7bfeb3]74 all_data, config->descriptor->total_length);
[6cb58e6]75
[2c381250]76 free(all_data);
[6cb58e6]77
78 return EOK;
[2c381250]79 }
[6cb58e6]80
[4971812]81 return EFORWARD;
82}
83
[6cb58e6]84static int req_set_address(usbvirt_device_t *device,
85 const usb_device_request_setup_packet_t *setup_packet, uint8_t *data, size_t *act_size)
[4971812]86{
[56b962d]87 uint16_t new_address = setup_packet->value;
88 uint16_t zero1 = setup_packet->index;
89 uint16_t zero2 = setup_packet->length;
90
[4971812]91 if ((zero1 != 0) || (zero2 != 0)) {
92 return EINVAL;
93 }
[6cb58e6]94
[4971812]95 if (new_address > 127) {
96 return EINVAL;
97 }
[6cb58e6]98
99 device->address = new_address;
100
[4971812]101 return EOK;
102}
103
[6cb58e6]104static int req_set_configuration(usbvirt_device_t *device,
105 const usb_device_request_setup_packet_t *setup_packet, uint8_t *data, size_t *act_size)
[08af5a6]106{
[56b962d]107 uint16_t configuration_value = setup_packet->value;
108 uint16_t zero1 = setup_packet->index;
109 uint16_t zero2 = setup_packet->length;
110
[08af5a6]111 if ((zero1 != 0) || (zero2 != 0)) {
112 return EINVAL;
113 }
[6cb58e6]114
[08af5a6]115 /*
116 * Configuration value is 1 byte information.
117 */
118 if (configuration_value > 255) {
119 return EINVAL;
120 }
[6cb58e6]121
[08af5a6]122 /*
123 * Do nothing when in default state. According to specification,
124 * this is not specified.
125 */
126 if (device->state == USBVIRT_STATE_DEFAULT) {
127 return EOK;
128 }
[6cb58e6]129
130 usbvirt_device_state_t new_state;
[08af5a6]131 if (configuration_value == 0) {
[6cb58e6]132 new_state = USBVIRT_STATE_ADDRESS;
[08af5a6]133 } else {
[6cb58e6]134 // FIXME: check that this configuration exists
135 new_state = USBVIRT_STATE_CONFIGURED;
[08af5a6]136 }
137
[6cb58e6]138 if (device->ops && device->ops->state_changed) {
139 device->ops->state_changed(device, device->state, new_state);
140 }
141 device->state = new_state;
[56b962d]142
[6cb58e6]143 return EOK;
144}
[7feeb84]145
[6cb58e6]146usbvirt_control_request_handler_t library_handlers[] = {
[7feeb84]147 {
[6cb58e6]148 .req_direction = USB_DIRECTION_OUT,
149 .req_recipient = USB_REQUEST_RECIPIENT_DEVICE,
150 .req_type = USB_REQUEST_TYPE_STANDARD,
151 .request = USB_DEVREQ_SET_ADDRESS,
152 .name = "SetAddress",
153 .callback = req_set_address
[7feeb84]154 },
155 {
[6cb58e6]156 .req_direction = USB_DIRECTION_IN,
157 .req_recipient = USB_REQUEST_RECIPIENT_DEVICE,
158 .req_type = USB_REQUEST_TYPE_STANDARD,
159 .request = USB_DEVREQ_GET_DESCRIPTOR,
160 .name = "GetDescriptor",
161 .callback = req_get_descriptor
[7feeb84]162 },
163 {
[6cb58e6]164 .req_direction = USB_DIRECTION_OUT,
165 .req_recipient = USB_REQUEST_RECIPIENT_DEVICE,
166 .req_type = USB_REQUEST_TYPE_STANDARD,
[7feeb84]167 .request = USB_DEVREQ_SET_CONFIGURATION,
[6cb58e6]168 .name = "SetConfiguration",
169 .callback = req_set_configuration
[7feeb84]170 },
[6cb58e6]171
172 { .callback = NULL }
[7feeb84]173};
[4971812]174
Note: See TracBrowser for help on using the repository browser.