source: mainline/uspace/lib/usbvirt/stdreq.c@ 7a7bfeb3

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

Virtual USB overhaul almost complete

The virtual HC, hub and keyboard are rewritten after changes to HCD API.
Comments will be added later.

  • Property mode set to 100644
File size: 5.5 KB
Line 
1/*
2 * Copyright (c) 2010 Vojtech Horky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libusbvirt usb
30 * @{
31 */
32/** @file
33 * @brief Preprocessing of standard device requests.
34 */
35#include <errno.h>
36#include <stdlib.h>
37#include <mem.h>
38#include <usb/devreq.h>
39
40#include "private.h"
41
42
43
44/*
45 * All sub handlers must return EFORWARD to inform the caller that
46 * they were not able to process the request (yes, it is abuse of
47 * this error code but such error code shall not collide with anything
48 * else in this context).
49 */
50
51static int handle_get_descriptor(uint8_t type, uint8_t index, uint16_t language,
52 uint16_t length)
53{
54 /*
55 * Standard device descriptor.
56 */
57 if ((type == USB_DESCTYPE_DEVICE) && (index == 0)) {
58 if (device->descriptors && device->descriptors->device) {
59 return device->control_transfer_reply(device, 0,
60 device->descriptors->device,
61 device->descriptors->device->length);
62 } else {
63 return EFORWARD;
64 }
65 }
66
67 /*
68 * Configuration descriptor together with interface, endpoint and
69 * class-specific descriptors.
70 */
71 if (type == USB_DESCTYPE_CONFIGURATION) {
72 if (!device->descriptors) {
73 return EFORWARD;
74 }
75 if (index >= device->descriptors->configuration_count) {
76 return EFORWARD;
77 }
78 /* Copy the data. */
79 usbvirt_device_configuration_t *config = &device->descriptors
80 ->configuration[index];
81 uint8_t *all_data = malloc(config->descriptor->total_length);
82 if (all_data == NULL) {
83 return ENOMEM;
84 }
85
86 uint8_t *ptr = all_data;
87 memcpy(ptr, config->descriptor, config->descriptor->length);
88 ptr += config->descriptor->length;
89 size_t i;
90 for (i = 0; i < config->extra_count; i++) {
91 usbvirt_device_configuration_extras_t *extra
92 = &config->extra[i];
93 memcpy(ptr, extra->data, extra->length);
94 ptr += extra->length;
95 }
96
97 int rc = device->control_transfer_reply(device, 0,
98 all_data, config->descriptor->total_length);
99
100 free(all_data);
101
102 return rc;
103 }
104
105 return EFORWARD;
106}
107
108static int handle_set_address(uint16_t new_address,
109 uint16_t zero1, uint16_t zero2)
110{
111 if ((zero1 != 0) || (zero2 != 0)) {
112 return EINVAL;
113 }
114
115 if (new_address > 127) {
116 return EINVAL;
117 }
118
119 dev_new_address = new_address;
120
121 return EOK;
122}
123
124static int handle_set_configuration(uint16_t configuration_value,
125 uint16_t zero1, uint16_t zero2)
126{
127 if ((zero1 != 0) || (zero2 != 0)) {
128 return EINVAL;
129 }
130
131 /*
132 * Configuration value is 1 byte information.
133 */
134 if (configuration_value > 255) {
135 return EINVAL;
136 }
137
138 /*
139 * Do nothing when in default state. According to specification,
140 * this is not specified.
141 */
142 if (device->state == USBVIRT_STATE_DEFAULT) {
143 return EOK;
144 }
145
146 if (configuration_value == 0) {
147 device->state = USBVIRT_STATE_ADDRESS;
148 } else {
149 /*
150 * TODO: browse provided configurations and verify that
151 * user selected existing configuration.
152 */
153 device->state = USBVIRT_STATE_CONFIGURED;
154 if (device->descriptors) {
155 device->descriptors->current_configuration
156 = configuration_value;
157 }
158 }
159
160 return EOK;
161}
162
163#define HANDLE_REQUEST(request, data, type, dev, user_callback, default_handler) \
164 do { \
165 if ((request)->request == (type)) { \
166 int _rc = EFORWARD; \
167 if (((dev)->ops) && ((dev)->ops->standard_request_ops) \
168 && ((dev)->ops->standard_request_ops->user_callback)) { \
169 _rc = (dev)->ops->standard_request_ops->\
170 user_callback(dev, request, data); \
171 } \
172 if (_rc == EFORWARD) { \
173 default_handler; \
174 } \
175 return _rc; \
176 } \
177 } while (false)
178
179
180int handle_std_request(usb_device_request_setup_packet_t *request, uint8_t *data)
181{
182 HANDLE_REQUEST(request, data, USB_DEVREQ_GET_DESCRIPTOR,
183 device, on_get_descriptor,
184 handle_get_descriptor(request->value_low, request->value_high,
185 request->index, request->length));
186
187 HANDLE_REQUEST(request, data, USB_DEVREQ_SET_ADDRESS,
188 device, on_set_address,
189 handle_set_address(request->value,
190 request->index, request->length));
191
192 HANDLE_REQUEST(request, data, USB_DEVREQ_SET_CONFIGURATION,
193 device, on_set_configuration,
194 handle_set_configuration(request->value,
195 request->index, request->length));
196
197 return ENOTSUP;
198}
199
200/**
201 * @}
202 */
Note: See TracBrowser for help on using the repository browser.