source: mainline/uspace/lib/usbvirt/stdreq.c@ 47e3a8e

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

Virtual USB device tracks its address

Now, each virtual device tracks its address and its state.

The virtual HC dispatches all transactions to all devices, thus
more precisely simulating situation on USB. The usbvirt framework
then decides whether it can accept the data or not, based on
their destination address.

  • Property mode set to 100644
File size: 4.7 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->send_data(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->send_data(device, 0, all_data,
98 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 /*
120 * TODO: handle when this request is invalid (e.g.
121 * setting address when in configured state).
122 */
123 if (new_address == 0) {
124 device->state = USBVIRT_STATE_DEFAULT;
125 } else {
126 device->state = USBVIRT_STATE_ADDRESS;
127 }
128
129 device->address = new_address;
130
131 return EOK;
132}
133
134#define HANDLE_REQUEST(request, data, type, dev, user_callback, default_handler) \
135 do { \
136 if ((request)->request == (type)) { \
137 int _rc = EFORWARD; \
138 if (((dev)->ops) && ((dev)->ops->standard_request_ops) \
139 && ((dev)->ops->standard_request_ops->user_callback)) { \
140 _rc = (dev)->ops->standard_request_ops->\
141 user_callback(dev, request, data); \
142 } \
143 if (_rc == EFORWARD) { \
144 default_handler; \
145 } \
146 return _rc; \
147 } \
148 } while (false)
149
150
151int handle_std_request(usb_device_request_setup_packet_t *request, uint8_t *data)
152{
153 HANDLE_REQUEST(request, data, USB_DEVREQ_GET_DESCRIPTOR,
154 device, on_get_descriptor,
155 handle_get_descriptor(request->value_low, request->value_high,
156 request->index, request->length));
157
158 HANDLE_REQUEST(request, data, USB_DEVREQ_SET_ADDRESS,
159 device, on_set_address,
160 handle_set_address(request->value,
161 request->index, request->length));
162
163 return ENOTSUP;
164}
165
166/**
167 * @}
168 */
Note: See TracBrowser for help on using the repository browser.