source: mainline/uspace/lib/usbvirt/transaction.c@ 23cb44b

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

Bugfixes in libusbvirt

  • Property mode set to 100644
File size: 6.9 KB
RevLine 
[7a7bfeb3]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 Transaction processing.
34 */
35#include <errno.h>
36#include <stdlib.h>
37#include <mem.h>
38
[ca07cd3]39#include "hub.h"
[7a7bfeb3]40#include "private.h"
41
[ca07cd3]42static usb_direction_t setup_transaction_direction(usbvirt_device_t *,
43 usb_endpoint_t, void *, size_t);
44static void process_control_transfer(usbvirt_device_t *,
45 usb_endpoint_t, usbvirt_control_transfer_t *);
[7a7bfeb3]46
[355f7c2]47/** Convert virtual USB transaction type to string.
48 */
49const char *usbvirt_str_transaction_type(usbvirt_transaction_type_t type)
50{
51 switch (type) {
52 case USBVIRT_TRANSACTION_SETUP:
53 return "setup";
54 case USBVIRT_TRANSACTION_IN:
55 return "in";
56 case USBVIRT_TRANSACTION_OUT:
57 return "out";
58 default:
59 return "unknown";
60 }
61}
62
[ca07cd3]63/** SETUP transaction handling.
64 * The setup transaction only prepares control transfer on given endpoint.
65 */
[7a7bfeb3]66int transaction_setup(usbvirt_device_t *device, usb_endpoint_t endpoint,
67 void *buffer, size_t size)
68{
69 usbvirt_control_transfer_t *transfer = &device->current_control_transfers[endpoint];
70
71 if (transfer->request != NULL) {
72 free(transfer->request);
73 }
74 if (transfer->data != NULL) {
75 free(transfer->data);
76 }
77
[ca07cd3]78 transfer->direction = setup_transaction_direction(device, endpoint,
[7a7bfeb3]79 buffer, size);
[23cb44b]80 transfer->request = malloc(size);
81 memcpy(transfer->request, buffer, size);
[7a7bfeb3]82 transfer->request_size = size;
83 transfer->data = NULL;
84 transfer->data_size = 0;
85
[ca07cd3]86 if (transfer->direction == USB_DIRECTION_IN) {
87 process_control_transfer(device, endpoint, transfer);
88 }
89
[7a7bfeb3]90 return EOK;
91}
92
[ca07cd3]93/** OUT transaction handling.
94 * The OUT transaction can trigger processing of a control transfer.
95 */
[7a7bfeb3]96int transaction_out(usbvirt_device_t *device, usb_endpoint_t endpoint,
97 void *buffer, size_t size)
98{
99 /*
100 * First check whether it is a transaction over control pipe.
101 */
102 usbvirt_control_transfer_t *transfer = &device->current_control_transfers[endpoint];
103 if (transfer->request != NULL) {
104 if (transfer->direction == USB_DIRECTION_OUT) {
105 /*
106 * For out transactions, append the data to the buffer.
107 */
108 uint8_t *new_buffer = (uint8_t *) malloc(transfer->data_size + size);
109 if (transfer->data) {
110 memcpy(new_buffer, transfer->data, transfer->data_size);
111 }
112 memcpy(new_buffer + transfer->data_size, buffer, size);
113
114 if (transfer->data) {
115 free(transfer->data);
116 }
117 transfer->data = new_buffer;
118 transfer->data_size += size;
119 } else {
120 /*
121 * For in transactions, this means end of the
122 * transaction.
123 */
124 free(transfer->request);
125 if (transfer->data) {
126 free(transfer->data);
127 }
128 transfer->request = NULL;
129 transfer->request_size = 0;
130 transfer->data = NULL;
131 transfer->data_size = 0;
132 }
133
134 return EOK;
135 }
136
137 /*
138 * Otherwise, announce that some data has come.
139 */
140 if (device->ops && device->ops->on_data) {
141 return device->ops->on_data(device, endpoint, buffer, size);
142 } else {
143 return ENOTSUP;
144 }
145}
146
[ca07cd3]147/** IN transaction handling.
148 * The IN transaction can trigger processing of a control transfer.
149 */
[7a7bfeb3]150int transaction_in(usbvirt_device_t *device, usb_endpoint_t endpoint,
151 void *buffer, size_t size, size_t *data_size)
152{
153 /*
154 * First check whether it is a transaction over control pipe.
155 */
156 usbvirt_control_transfer_t *transfer = &device->current_control_transfers[endpoint];
157 if (transfer->request != NULL) {
158 if (transfer->direction == USB_DIRECTION_OUT) {
159 /*
160 * This means end of input data.
161 */
[ca07cd3]162 process_control_transfer(device, endpoint, transfer);
[7a7bfeb3]163 } else {
164 /*
165 * For in transactions, this means sending next part
166 * of the buffer.
167 */
[ca07cd3]168 // FIXME: handle when the HC wants the data back
169 // in more chunks
170 size_t actual_size = 0;
171 if (transfer->data) {
172 actual_size = transfer->data_size;
173 }
174 if (actual_size > size) {
175 actual_size = size;
176 }
177 if (actual_size > 0) {
178 memcpy(buffer, transfer->data, actual_size);
179 if (data_size) {
180 *data_size = actual_size;
181 }
182 }
[7a7bfeb3]183 }
184
185 return EOK;
186 }
187
188 if (size == 0) {
189 return EINVAL;
190 }
191
192 int rc = 1;
193
194 if (device->ops && device->ops->on_data_request) {
195 rc = device->ops->on_data_request(device, endpoint, buffer, size, data_size);
196 }
197
198 return rc;
199}
200
[ca07cd3]201/** Determine direction of control transfer.
202 * First, try the user provided callback, otherwise guess, believing that
203 * it uses the same format as control pipe 0.
204 */
205static usb_direction_t setup_transaction_direction(usbvirt_device_t *device,
206 usb_endpoint_t endpoint,
[7a7bfeb3]207 void *data, size_t size)
208{
209 int direction = -1;
210 if (device->ops && device->ops->decide_control_transfer_direction) {
211 direction = device->ops->decide_control_transfer_direction(endpoint,
212 data, size);
213 }
214
215 /*
216 * If the user-supplied routine have not handled the direction
217 * (or simply was not provided) we will guess, hoping that it
218 * uses same format as standard request on control pipe zero.
219 */
220 if (direction < 0) {
221 if (size > 0) {
222 uint8_t *ptr = (uint8_t *) data;
223 if ((ptr[0] & 128) == 128) {
224 direction = USB_DIRECTION_IN;
225 } else {
226 direction = USB_DIRECTION_OUT;
227 }
228 } else {
229 /* This shall not happen anyway. */
230 direction = USB_DIRECTION_OUT;
231 }
232 }
233
234 return (usb_direction_t) direction;
235}
236
[ca07cd3]237/** Process control transfer.
238 */
239static void process_control_transfer(usbvirt_device_t *device,
240 usb_endpoint_t endpoint,
[7a7bfeb3]241 usbvirt_control_transfer_t *transfer)
242{
243 int rc = EFORWARD;
244
245 if (device->ops && device->ops->on_control_transfer) {
246 rc = device->ops->on_control_transfer(device, endpoint, transfer);
247 }
248
249 if (rc == EFORWARD) {
250 if (endpoint == 0) {
[ca07cd3]251 rc = control_pipe(device, transfer);
[7a7bfeb3]252 }
253 }
254}
255
256/**
257 * @}
258 */
Note: See TracBrowser for help on using the repository browser.