source: mainline/uspace/drv/vhc/connhost.c@ 1d7a74e

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

Virtual HC remembers transfer type as well

  • Property mode set to 100644
File size: 8.1 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 usb
30 * @{
31 */
32/** @file
33 * @brief Connection handling of calls from host (implementation).
34 */
35#include <assert.h>
36#include <errno.h>
37#include <usb/usb.h>
38#include <usb/hcd.h>
39
40#include "vhcd.h"
41#include "conn.h"
42#include "hc.h"
43
44typedef struct {
45 usb_direction_t direction;
46 usbhc_iface_transfer_out_callback_t out_callback;
47 usbhc_iface_transfer_in_callback_t in_callback;
48 device_t *dev;
49 void *arg;
50} transfer_info_t;
51
52static void universal_callback(void *buffer, size_t size,
53 usb_transaction_outcome_t outcome, void *arg)
54{
55 transfer_info_t *transfer = (transfer_info_t *) arg;
56
57 switch (transfer->direction) {
58 case USB_DIRECTION_IN:
59 transfer->in_callback(transfer->dev,
60 outcome, size,
61 transfer->arg);
62 break;
63 case USB_DIRECTION_OUT:
64 transfer->out_callback(transfer->dev,
65 outcome,
66 transfer->arg);
67 break;
68 default:
69 assert(false && "unreachable");
70 break;
71 }
72
73 free(transfer);
74}
75
76static transfer_info_t *create_transfer_info(device_t *dev,
77 usb_direction_t direction, void *arg)
78{
79 transfer_info_t *transfer = malloc(sizeof(transfer_info_t));
80
81 transfer->direction = direction;
82 transfer->in_callback = NULL;
83 transfer->out_callback = NULL;
84 transfer->arg = arg;
85 transfer->dev = dev;
86
87 return transfer;
88}
89
90static int enqueue_transfer_out(device_t *dev,
91 usb_target_t target, usb_transfer_type_t transfer_type,
92 void *buffer, size_t size,
93 usbhc_iface_transfer_out_callback_t callback, void *arg)
94{
95 dprintf(3, "transfer OUT [%d.%d (%s); %zu]",
96 target.address, target.endpoint,
97 usb_str_transfer_type(transfer_type),
98 size);
99
100 transfer_info_t *transfer
101 = create_transfer_info(dev, USB_DIRECTION_OUT, arg);
102 transfer->out_callback = callback;
103
104 hc_add_transaction_to_device(false, target, transfer_type, buffer, size,
105 universal_callback, transfer);
106
107 return EOK;
108}
109
110static int enqueue_transfer_setup(device_t *dev,
111 usb_target_t target, usb_transfer_type_t transfer_type,
112 void *buffer, size_t size,
113 usbhc_iface_transfer_out_callback_t callback, void *arg)
114{
115 dprintf(3, "transfer SETUP [%d.%d (%s); %zu]",
116 target.address, target.endpoint,
117 usb_str_transfer_type(transfer_type),
118 size);
119
120 transfer_info_t *transfer
121 = create_transfer_info(dev, USB_DIRECTION_OUT, arg);
122 transfer->out_callback = callback;
123
124 hc_add_transaction_to_device(true, target, transfer_type, buffer, size,
125 universal_callback, transfer);
126
127 return EOK;
128}
129
130static int enqueue_transfer_in(device_t *dev,
131 usb_target_t target, usb_transfer_type_t transfer_type,
132 void *buffer, size_t size,
133 usbhc_iface_transfer_in_callback_t callback, void *arg)
134{
135 dprintf(3, "transfer IN [%d.%d (%s); %zu]",
136 target.address, target.endpoint,
137 usb_str_transfer_type(transfer_type),
138 size);
139
140 transfer_info_t *transfer
141 = create_transfer_info(dev, USB_DIRECTION_IN, arg);
142 transfer->in_callback = callback;
143
144 hc_add_transaction_from_device(target, transfer_type, buffer, size,
145 universal_callback, transfer);
146
147 return EOK;
148}
149
150
151static int interrupt_out(device_t *dev, usb_target_t target,
152 void *data, size_t size,
153 usbhc_iface_transfer_out_callback_t callback, void *arg)
154{
155 return enqueue_transfer_out(dev, target, USB_TRANSFER_INTERRUPT,
156 data, size,
157 callback, arg);
158}
159
160static int interrupt_in(device_t *dev, usb_target_t target,
161 void *data, size_t size,
162 usbhc_iface_transfer_in_callback_t callback, void *arg)
163{
164 return enqueue_transfer_in(dev, target, USB_TRANSFER_INTERRUPT,
165 data, size,
166 callback, arg);
167}
168
169static int control_write_setup(device_t *dev, usb_target_t target,
170 void *data, size_t size,
171 usbhc_iface_transfer_out_callback_t callback, void *arg)
172{
173 return enqueue_transfer_setup(dev, target, USB_TRANSFER_CONTROL,
174 data, size,
175 callback, arg);
176}
177
178static int control_write_data(device_t *dev, usb_target_t target,
179 void *data, size_t size,
180 usbhc_iface_transfer_out_callback_t callback, void *arg)
181{
182 return enqueue_transfer_out(dev, target, USB_TRANSFER_CONTROL,
183 data, size,
184 callback, arg);
185}
186
187static int control_write_status(device_t *dev, usb_target_t target,
188 usbhc_iface_transfer_in_callback_t callback, void *arg)
189{
190 return enqueue_transfer_in(dev, target, USB_TRANSFER_CONTROL,
191 NULL, 0,
192 callback, arg);
193}
194
195static int control_read_setup(device_t *dev, usb_target_t target,
196 void *data, size_t size,
197 usbhc_iface_transfer_out_callback_t callback, void *arg)
198{
199 return enqueue_transfer_setup(dev, target, USB_TRANSFER_CONTROL,
200 data, size,
201 callback, arg);
202}
203
204static int control_read_data(device_t *dev, usb_target_t target,
205 void *data, size_t size,
206 usbhc_iface_transfer_in_callback_t callback, void *arg)
207{
208 return enqueue_transfer_in(dev, target, USB_TRANSFER_CONTROL,
209 data, size,
210 callback, arg);
211}
212
213static int control_read_status(device_t *dev, usb_target_t target,
214 usbhc_iface_transfer_out_callback_t callback, void *arg)
215{
216 return enqueue_transfer_out(dev, target, USB_TRANSFER_CONTROL,
217 NULL, 0,
218 callback, arg);
219}
220
221static usb_address_keeping_t addresses;
222
223
224static int reserve_default_address(device_t *dev)
225{
226 usb_address_keeping_reserve_default(&addresses);
227 return EOK;
228}
229
230static int release_default_address(device_t *dev)
231{
232 usb_address_keeping_release_default(&addresses);
233 return EOK;
234}
235
236static int request_address(device_t *dev, usb_address_t *address)
237{
238 usb_address_t addr = usb_address_keeping_request(&addresses);
239 if (addr < 0) {
240 return (int)addr;
241 }
242
243 *address = addr;
244 return EOK;
245}
246
247static int release_address(device_t *dev, usb_address_t address)
248{
249 return usb_address_keeping_release(&addresses, address);
250}
251
252static int bind_address(device_t *dev, usb_address_t address,
253 devman_handle_t handle)
254{
255 usb_address_keeping_devman_bind(&addresses, address, handle);
256 return EOK;
257}
258
259static int tell_address(device_t *dev, devman_handle_t handle,
260 usb_address_t *address)
261{
262 usb_address_t addr = usb_address_keeping_find(&addresses, handle);
263 if (addr < 0) {
264 return addr;
265 }
266
267 *address = addr;
268 return EOK;
269}
270
271void address_init(void)
272{
273 usb_address_keeping_init(&addresses, 50);
274}
275
276usbhc_iface_t vhc_iface = {
277 .tell_address = tell_address,
278
279 .reserve_default_address = reserve_default_address,
280 .release_default_address = release_default_address,
281 .request_address = request_address,
282 .bind_address = bind_address,
283 .release_address = release_address,
284
285 .interrupt_out = interrupt_out,
286 .interrupt_in = interrupt_in,
287
288 .control_write_setup = control_write_setup,
289 .control_write_data = control_write_data,
290 .control_write_status = control_write_status,
291
292 .control_read_setup = control_read_setup,
293 .control_read_data = control_read_data,
294 .control_read_status = control_read_status
295};
296
297/**
298 * @}
299 */
Note: See TracBrowser for help on using the repository browser.