source: mainline/uspace/drv/vhc/connhost.c@ f9c03b5

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

Merge mainline changes (DDF refactoring)

This merge includes DDF refactoring that brought multifunctional devices
(i.e. ddf_dev_t and ddf_fun_t). Please, see ticket #295 at HelenOS
upstream Trac.

The conflicts themselves were easy to solve (merely several renamings).

Changes to USB subsystem:

  • drivers uses ddf_dev_t and ddf_fun_t
  • different signatures of many library functions
  • several hacks around communication with parent device (now the communication is clearer and somehow what we have now is hack about other hacks)
    • will repair and clean later
  • maybe added some extra debugging messages (the diff has about 240K, and I admit I have no energy to double check that)

WARNING:

  • the diff is VERY long, recommended is viewing partial diffs of the merge (i.e. merges in mainline branch that lead to the parent one)
  • merging with your branches might involve huge renamings, sorry, no other way is possible

BUGS:

  • hub driver will not work (no function created)

GOOD NEWS:

  • QEMU keyboard seems to work with QEMU 0.13 and 0.14
  • we are up-to-date with mainline again
  • Property mode set to 100644
File size: 11.0 KB
RevLine 
[b371844]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
[bd8c753d]29/** @addtogroup drvusbvhc
[b371844]30 * @{
31 */
32/** @file
33 * @brief Connection handling of calls from host (implementation).
34 */
35#include <assert.h>
36#include <errno.h>
[4b4c797]37#include <usb/usb.h>
[8555112]38#include <usb/addrkeep.h>
[357a302]39#include <usb/ddfiface.h>
[b371844]40
41#include "vhcd.h"
42#include "conn.h"
43#include "hc.h"
44
[284c629]45
[c4ba29c7]46typedef struct {
47 usb_direction_t direction;
[4317827]48 usbhc_iface_transfer_out_callback_t out_callback;
49 usbhc_iface_transfer_in_callback_t in_callback;
[eb1a2f4]50 ddf_fun_t *fun;
[284c629]51 size_t reported_size;
[c4ba29c7]52 void *arg;
53} transfer_info_t;
54
[284c629]55typedef struct {
56 usb_direction_t direction;
57 usb_target_t target;
58 usbhc_iface_transfer_out_callback_t out_callback;
59 usbhc_iface_transfer_in_callback_t in_callback;
[eb1a2f4]60 ddf_fun_t *fun;
[284c629]61 void *arg;
62 void *data_buffer;
63 size_t data_buffer_size;
64} control_transfer_info_t;
65
[c4ba29c7]66static void universal_callback(void *buffer, size_t size,
[daec5e04]67 int outcome, void *arg)
[c4ba29c7]68{
69 transfer_info_t *transfer = (transfer_info_t *) arg;
70
[284c629]71 if (transfer->reported_size != (size_t) -1) {
72 size = transfer->reported_size;
73 }
74
[c4ba29c7]75 switch (transfer->direction) {
76 case USB_DIRECTION_IN:
[eb1a2f4]77 transfer->in_callback(transfer->fun,
[eac610e]78 outcome, size,
[c4ba29c7]79 transfer->arg);
80 break;
81 case USB_DIRECTION_OUT:
[eb1a2f4]82 transfer->out_callback(transfer->fun,
[c4ba29c7]83 outcome,
84 transfer->arg);
85 break;
86 default:
87 assert(false && "unreachable");
88 break;
89 }
90
91 free(transfer);
92}
93
[eb1a2f4]94static transfer_info_t *create_transfer_info(ddf_fun_t *fun,
[c4ba29c7]95 usb_direction_t direction, void *arg)
96{
97 transfer_info_t *transfer = malloc(sizeof(transfer_info_t));
98
99 transfer->direction = direction;
100 transfer->in_callback = NULL;
101 transfer->out_callback = NULL;
102 transfer->arg = arg;
[eb1a2f4]103 transfer->fun = fun;
[284c629]104 transfer->reported_size = (size_t) -1;
105
106 return transfer;
107}
108
109static void control_abort_prematurely(control_transfer_info_t *transfer,
[daec5e04]110 size_t size, int outcome)
[284c629]111{
112 switch (transfer->direction) {
113 case USB_DIRECTION_IN:
[eb1a2f4]114 transfer->in_callback(transfer->fun,
[284c629]115 outcome, size,
116 transfer->arg);
117 break;
118 case USB_DIRECTION_OUT:
[eb1a2f4]119 transfer->out_callback(transfer->fun,
[284c629]120 outcome,
121 transfer->arg);
122 break;
123 default:
124 assert(false && "unreachable");
125 break;
126 }
127}
128
129static void control_callback_two(void *buffer, size_t size,
[daec5e04]130 int outcome, void *arg)
[284c629]131{
132 control_transfer_info_t *ctrl_transfer = (control_transfer_info_t *) arg;
133
[daec5e04]134 if (outcome != EOK) {
[284c629]135 control_abort_prematurely(ctrl_transfer, outcome, size);
136 free(ctrl_transfer);
137 return;
138 }
139
[eb1a2f4]140 transfer_info_t *transfer = create_transfer_info(ctrl_transfer->fun,
[284c629]141 ctrl_transfer->direction, ctrl_transfer->arg);
142 transfer->out_callback = ctrl_transfer->out_callback;
143 transfer->in_callback = ctrl_transfer->in_callback;
144 transfer->reported_size = size;
145
146 switch (ctrl_transfer->direction) {
147 case USB_DIRECTION_IN:
148 hc_add_transaction_to_device(false, ctrl_transfer->target,
149 USB_TRANSFER_CONTROL,
150 NULL, 0,
151 universal_callback, transfer);
152 break;
153 case USB_DIRECTION_OUT:
154 hc_add_transaction_from_device(ctrl_transfer->target,
155 USB_TRANSFER_CONTROL,
156 NULL, 0,
157 universal_callback, transfer);
158 break;
159 default:
160 assert(false && "unreachable");
161 break;
162 }
163
164 free(ctrl_transfer);
165}
166
167static void control_callback_one(void *buffer, size_t size,
[daec5e04]168 int outcome, void *arg)
[284c629]169{
170 control_transfer_info_t *transfer = (control_transfer_info_t *) arg;
171
[daec5e04]172 if (outcome != EOK) {
[284c629]173 control_abort_prematurely(transfer, outcome, size);
174 free(transfer);
175 return;
176 }
177
178 switch (transfer->direction) {
179 case USB_DIRECTION_IN:
180 hc_add_transaction_from_device(transfer->target,
181 USB_TRANSFER_CONTROL,
182 transfer->data_buffer, transfer->data_buffer_size,
183 control_callback_two, transfer);
184 break;
185 case USB_DIRECTION_OUT:
186 hc_add_transaction_to_device(false, transfer->target,
187 USB_TRANSFER_CONTROL,
188 transfer->data_buffer, transfer->data_buffer_size,
189 control_callback_two, transfer);
190 break;
191 default:
192 assert(false && "unreachable");
193 break;
194 }
195}
196
[eb1a2f4]197static control_transfer_info_t *create_control_transfer_info(ddf_fun_t *fun,
[284c629]198 usb_direction_t direction, usb_target_t target,
199 void *data_buffer, size_t data_buffer_size,
200 void *arg)
201{
202 control_transfer_info_t *transfer
203 = malloc(sizeof(control_transfer_info_t));
204
205 transfer->direction = direction;
206 transfer->target = target;
207 transfer->in_callback = NULL;
208 transfer->out_callback = NULL;
209 transfer->arg = arg;
[eb1a2f4]210 transfer->fun = fun;
[284c629]211 transfer->data_buffer = data_buffer;
212 transfer->data_buffer_size = data_buffer_size;
[c4ba29c7]213
214 return transfer;
215}
216
[eb1a2f4]217static int enqueue_transfer_out(ddf_fun_t *fun,
[4317827]218 usb_target_t target, usb_transfer_type_t transfer_type,
[63b4f90]219 void *buffer, size_t size,
[4317827]220 usbhc_iface_transfer_out_callback_t callback, void *arg)
[63b4f90]221{
[0b31409]222 usb_log_debug2("Transfer OUT [%d.%d (%s); %zu].\n",
[4317827]223 target.address, target.endpoint,
224 usb_str_transfer_type(transfer_type),
[63b4f90]225 size);
[c4ba29c7]226
227 transfer_info_t *transfer
[eb1a2f4]228 = create_transfer_info(fun, USB_DIRECTION_OUT, arg);
[c4ba29c7]229 transfer->out_callback = callback;
230
[76daaf9f]231 hc_add_transaction_to_device(false, target, transfer_type, buffer, size,
[c4ba29c7]232 universal_callback, transfer);
233
234 return EOK;
[63b4f90]235}
236
[eb1a2f4]237static int enqueue_transfer_in(ddf_fun_t *fun,
[4317827]238 usb_target_t target, usb_transfer_type_t transfer_type,
[63b4f90]239 void *buffer, size_t size,
[4317827]240 usbhc_iface_transfer_in_callback_t callback, void *arg)
[63b4f90]241{
[0b31409]242 usb_log_debug2("Transfer IN [%d.%d (%s); %zu].\n",
[4317827]243 target.address, target.endpoint,
244 usb_str_transfer_type(transfer_type),
[63b4f90]245 size);
[c4ba29c7]246
247 transfer_info_t *transfer
[eb1a2f4]248 = create_transfer_info(fun, USB_DIRECTION_IN, arg);
[c4ba29c7]249 transfer->in_callback = callback;
250
[76daaf9f]251 hc_add_transaction_from_device(target, transfer_type, buffer, size,
[c4ba29c7]252 universal_callback, transfer);
253
254 return EOK;
[63b4f90]255}
256
257
[eb1a2f4]258static int interrupt_out(ddf_fun_t *fun, usb_target_t target,
[ec59693]259 size_t max_packet_size,
[4317827]260 void *data, size_t size,
261 usbhc_iface_transfer_out_callback_t callback, void *arg)
262{
[eb1a2f4]263 return enqueue_transfer_out(fun, target, USB_TRANSFER_INTERRUPT,
[4317827]264 data, size,
265 callback, arg);
266}
267
[eb1a2f4]268static int interrupt_in(ddf_fun_t *fun, usb_target_t target,
[ec59693]269 size_t max_packet_size,
[4317827]270 void *data, size_t size,
271 usbhc_iface_transfer_in_callback_t callback, void *arg)
272{
[eb1a2f4]273 return enqueue_transfer_in(fun, target, USB_TRANSFER_INTERRUPT,
[4317827]274 data, size,
275 callback, arg);
276}
277
[eb1a2f4]278static int control_write(ddf_fun_t *fun, usb_target_t target,
[ec59693]279 size_t max_packet_size,
[284c629]280 void *setup_packet, size_t setup_packet_size,
281 void *data, size_t data_size,
282 usbhc_iface_transfer_out_callback_t callback, void *arg)
283{
284 control_transfer_info_t *transfer
[eb1a2f4]285 = create_control_transfer_info(fun, USB_DIRECTION_OUT, target,
[284c629]286 data, data_size, arg);
287 transfer->out_callback = callback;
288
289 hc_add_transaction_to_device(true, target, USB_TRANSFER_CONTROL,
290 setup_packet, setup_packet_size,
291 control_callback_one, transfer);
292
293 return EOK;
294}
295
[eb1a2f4]296static int control_read(ddf_fun_t *fun, usb_target_t target,
[ec59693]297 size_t max_packet_size,
[284c629]298 void *setup_packet, size_t setup_packet_size,
299 void *data, size_t data_size,
300 usbhc_iface_transfer_in_callback_t callback, void *arg)
301{
302 control_transfer_info_t *transfer
[eb1a2f4]303 = create_control_transfer_info(fun, USB_DIRECTION_IN, target,
[284c629]304 data, data_size, arg);
305 transfer->in_callback = callback;
306
307 hc_add_transaction_to_device(true, target, USB_TRANSFER_CONTROL,
308 setup_packet, setup_packet_size,
309 control_callback_one, transfer);
310
311 return EOK;
312}
313
[be9cbec]314static usb_address_keeping_t addresses;
315
[eb1a2f4]316static int tell_address(ddf_fun_t *fun, devman_handle_t handle,
[357a302]317 usb_address_t *address)
318{
[eb1a2f4]319 usb_log_debug("tell_address(fun \"%s\", handle %zu)\n",
320 fun->name, (size_t) fun->handle);
[357a302]321 usb_address_t addr = usb_address_keeping_find(&addresses, handle);
322 if (addr < 0) {
323 return addr;
324 }
325
326 *address = addr;
327 return EOK;
328}
[be9cbec]329
[eb1a2f4]330static int reserve_default_address(ddf_fun_t *fun, usb_speed_t ignored)
[be9cbec]331{
332 usb_address_keeping_reserve_default(&addresses);
333 return EOK;
334}
335
[eb1a2f4]336static int release_default_address(ddf_fun_t *fun)
[be9cbec]337{
338 usb_address_keeping_release_default(&addresses);
339 return EOK;
340}
341
[eb1a2f4]342static int request_address(ddf_fun_t *fun, usb_speed_t ignored,
[fa48ebe]343 usb_address_t *address)
[be9cbec]344{
345 usb_address_t addr = usb_address_keeping_request(&addresses);
346 if (addr < 0) {
347 return (int)addr;
348 }
349
350 *address = addr;
351 return EOK;
352}
353
[eb1a2f4]354static int release_address(ddf_fun_t *fun, usb_address_t address)
[be9cbec]355{
356 return usb_address_keeping_release(&addresses, address);
357}
358
[eb1a2f4]359static int bind_address(ddf_fun_t *fun, usb_address_t address,
[be9cbec]360 devman_handle_t handle)
361{
362 usb_address_keeping_devman_bind(&addresses, address, handle);
363 return EOK;
364}
365
[eb1a2f4]366static int usb_iface_get_hc_handle_rh_impl(ddf_fun_t *root_hub_fun,
367 devman_handle_t *handle)
368{
369 ddf_fun_t *hc_fun = root_hub_fun->driver_data;
370 assert(hc_fun != NULL);
371
372 *handle = hc_fun->handle;
373
374 usb_log_debug("usb_iface_get_hc_handle_rh_impl returns %zu\n", *handle);
375
376 return EOK;
377}
378
379static int tell_address_rh(ddf_fun_t *root_hub_fun, devman_handle_t handle,
380 usb_address_t *address)
381{
382 ddf_fun_t *hc_fun = root_hub_fun->driver_data;
383 assert(hc_fun != NULL);
384
385 return tell_address(hc_fun, root_hub_fun->handle, address);
386}
387
[be9cbec]388void address_init(void)
389{
390 usb_address_keeping_init(&addresses, 50);
391}
[4317827]392
393usbhc_iface_t vhc_iface = {
[ad104e0]394 .reserve_default_address = reserve_default_address,
395 .release_default_address = release_default_address,
396 .request_address = request_address,
[ce687bbe]397 .bind_address = bind_address,
[ad104e0]398 .release_address = release_address,
399
[4317827]400 .interrupt_out = interrupt_out,
401 .interrupt_in = interrupt_in,
[ad104e0]402
[284c629]403 .control_write = control_write,
404 .control_read = control_read
[63b4f90]405};
406
[357a302]407usb_iface_t vhc_usb_iface = {
408 .get_hc_handle = usb_iface_get_hc_handle_hc_impl,
409 .get_address = tell_address
410};
411
[eb1a2f4]412usb_iface_t rh_usb_iface = {
413 .get_hc_handle = usb_iface_get_hc_handle_rh_impl,
414 .get_address = tell_address_rh
415};
416
[357a302]417
[b371844]418/**
419 * @}
420 */
Note: See TracBrowser for help on using the repository browser.