source: mainline/uspace/lib/usbvirt/transaction.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 Transaction processing.
34 */
35#include <errno.h>
36#include <stdlib.h>
37#include <stdio.h>
38#include <mem.h>
39
40#include "private.h"
41
42static usb_direction_t setup_transaction_direction(usb_endpoint_t, void *, size_t);
43static void process_control_transfer(usb_endpoint_t, usbvirt_control_transfer_t *);
44
45int transaction_setup(usbvirt_device_t *device, usb_endpoint_t endpoint,
46 void *buffer, size_t size)
47{
48 usbvirt_control_transfer_t *transfer = &device->current_control_transfers[endpoint];
49
50 if (transfer->request != NULL) {
51 free(transfer->request);
52 }
53 if (transfer->data != NULL) {
54 free(transfer->data);
55 }
56
57 transfer->direction = setup_transaction_direction(endpoint,
58 buffer, size);
59 transfer->request = buffer;
60 transfer->request_size = size;
61 transfer->data = NULL;
62 transfer->data_size = 0;
63
64 return EOK;
65}
66
67int transaction_out(usbvirt_device_t *device, usb_endpoint_t endpoint,
68 void *buffer, size_t size)
69{
70 /*
71 * First check whether it is a transaction over control pipe.
72 */
73 usbvirt_control_transfer_t *transfer = &device->current_control_transfers[endpoint];
74 if (transfer->request != NULL) {
75 if (transfer->direction == USB_DIRECTION_OUT) {
76 /*
77 * For out transactions, append the data to the buffer.
78 */
79 uint8_t *new_buffer = (uint8_t *) malloc(transfer->data_size + size);
80 if (transfer->data) {
81 memcpy(new_buffer, transfer->data, transfer->data_size);
82 }
83 memcpy(new_buffer + transfer->data_size, buffer, size);
84
85 if (transfer->data) {
86 free(transfer->data);
87 }
88 transfer->data = new_buffer;
89 transfer->data_size += size;
90 } else {
91 /*
92 * For in transactions, this means end of the
93 * transaction.
94 */
95 free(transfer->request);
96 if (transfer->data) {
97 free(transfer->data);
98 }
99 transfer->request = NULL;
100 transfer->request_size = 0;
101 transfer->data = NULL;
102 transfer->data_size = 0;
103 }
104
105 return EOK;
106 }
107
108 /*
109 * Otherwise, announce that some data has come.
110 */
111 if (device->ops && device->ops->on_data) {
112 return device->ops->on_data(device, endpoint, buffer, size);
113 } else {
114 return ENOTSUP;
115 }
116}
117
118int transaction_in(usbvirt_device_t *device, usb_endpoint_t endpoint,
119 void *buffer, size_t size, size_t *data_size)
120{
121 /*
122 * First check whether it is a transaction over control pipe.
123 */
124 usbvirt_control_transfer_t *transfer = &device->current_control_transfers[endpoint];
125 if (transfer->request != NULL) {
126 if (transfer->direction == USB_DIRECTION_OUT) {
127 /*
128 * This means end of input data.
129 */
130 process_control_transfer(endpoint, transfer);
131 } else {
132 /*
133 * For in transactions, this means sending next part
134 * of the buffer.
135 */
136 // TODO: implement
137 }
138
139 return EOK;
140 }
141
142 if (size == 0) {
143 return EINVAL;
144 }
145
146 int rc = 1;
147
148 if (device->ops && device->ops->on_data_request) {
149 rc = device->ops->on_data_request(device, endpoint, buffer, size, data_size);
150 }
151
152 return rc;
153}
154
155
156static usb_direction_t setup_transaction_direction(usb_endpoint_t endpoint,
157 void *data, size_t size)
158{
159 int direction = -1;
160 if (device->ops && device->ops->decide_control_transfer_direction) {
161 direction = device->ops->decide_control_transfer_direction(endpoint,
162 data, size);
163 }
164
165 /*
166 * If the user-supplied routine have not handled the direction
167 * (or simply was not provided) we will guess, hoping that it
168 * uses same format as standard request on control pipe zero.
169 */
170 if (direction < 0) {
171 if (size > 0) {
172 uint8_t *ptr = (uint8_t *) data;
173 if ((ptr[0] & 128) == 128) {
174 direction = USB_DIRECTION_IN;
175 } else {
176 direction = USB_DIRECTION_OUT;
177 }
178 } else {
179 /* This shall not happen anyway. */
180 direction = USB_DIRECTION_OUT;
181 }
182 }
183
184 return (usb_direction_t) direction;
185}
186
187static void process_control_transfer(usb_endpoint_t endpoint,
188 usbvirt_control_transfer_t *transfer)
189{
190 int rc = EFORWARD;
191
192 if (device->ops && device->ops->on_control_transfer) {
193 rc = device->ops->on_control_transfer(device, endpoint, transfer);
194 }
195
196 if (rc == EFORWARD) {
197 if (endpoint == 0) {
198 rc = control_pipe(transfer);
199 }
200 }
201}
202
203/**
204 * @}
205 */
Note: See TracBrowser for help on using the repository browser.