source: mainline/uspace/drv/vhc/connhost.c@ 30a4301

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

USB HC interface has max packet size

Currently, it is only a hack to extend the interface as the values
are hard coded inside the remote part of the interface.

Sending of real values will be added once the old drivers API is
completely removed (no sense in changing the same thing twice).

  • Property mode set to 100644
File size: 12.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 drvusbvhc
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/addrkeep.h>
39
40#include "vhcd.h"
41#include "conn.h"
42#include "hc.h"
43
44
45typedef struct {
46 usb_direction_t direction;
47 usbhc_iface_transfer_out_callback_t out_callback;
48 usbhc_iface_transfer_in_callback_t in_callback;
49 device_t *dev;
50 size_t reported_size;
51 void *arg;
52} transfer_info_t;
53
54typedef struct {
55 usb_direction_t direction;
56 usb_target_t target;
57 usbhc_iface_transfer_out_callback_t out_callback;
58 usbhc_iface_transfer_in_callback_t in_callback;
59 device_t *dev;
60 void *arg;
61 void *data_buffer;
62 size_t data_buffer_size;
63} control_transfer_info_t;
64
65static void universal_callback(void *buffer, size_t size,
66 int outcome, void *arg)
67{
68 transfer_info_t *transfer = (transfer_info_t *) arg;
69
70 if (transfer->reported_size != (size_t) -1) {
71 size = transfer->reported_size;
72 }
73
74 switch (transfer->direction) {
75 case USB_DIRECTION_IN:
76 transfer->in_callback(transfer->dev,
77 outcome, size,
78 transfer->arg);
79 break;
80 case USB_DIRECTION_OUT:
81 transfer->out_callback(transfer->dev,
82 outcome,
83 transfer->arg);
84 break;
85 default:
86 assert(false && "unreachable");
87 break;
88 }
89
90 free(transfer);
91}
92
93static transfer_info_t *create_transfer_info(device_t *dev,
94 usb_direction_t direction, void *arg)
95{
96 transfer_info_t *transfer = malloc(sizeof(transfer_info_t));
97
98 transfer->direction = direction;
99 transfer->in_callback = NULL;
100 transfer->out_callback = NULL;
101 transfer->arg = arg;
102 transfer->dev = dev;
103 transfer->reported_size = (size_t) -1;
104
105 return transfer;
106}
107
108static void control_abort_prematurely(control_transfer_info_t *transfer,
109 size_t size, int outcome)
110{
111 switch (transfer->direction) {
112 case USB_DIRECTION_IN:
113 transfer->in_callback(transfer->dev,
114 outcome, size,
115 transfer->arg);
116 break;
117 case USB_DIRECTION_OUT:
118 transfer->out_callback(transfer->dev,
119 outcome,
120 transfer->arg);
121 break;
122 default:
123 assert(false && "unreachable");
124 break;
125 }
126}
127
128static void control_callback_two(void *buffer, size_t size,
129 int outcome, void *arg)
130{
131 control_transfer_info_t *ctrl_transfer = (control_transfer_info_t *) arg;
132
133 if (outcome != EOK) {
134 control_abort_prematurely(ctrl_transfer, outcome, size);
135 free(ctrl_transfer);
136 return;
137 }
138
139 transfer_info_t *transfer = create_transfer_info(ctrl_transfer->dev,
140 ctrl_transfer->direction, ctrl_transfer->arg);
141 transfer->out_callback = ctrl_transfer->out_callback;
142 transfer->in_callback = ctrl_transfer->in_callback;
143 transfer->reported_size = size;
144
145 switch (ctrl_transfer->direction) {
146 case USB_DIRECTION_IN:
147 hc_add_transaction_to_device(false, ctrl_transfer->target,
148 USB_TRANSFER_CONTROL,
149 NULL, 0,
150 universal_callback, transfer);
151 break;
152 case USB_DIRECTION_OUT:
153 hc_add_transaction_from_device(ctrl_transfer->target,
154 USB_TRANSFER_CONTROL,
155 NULL, 0,
156 universal_callback, transfer);
157 break;
158 default:
159 assert(false && "unreachable");
160 break;
161 }
162
163 free(ctrl_transfer);
164}
165
166static void control_callback_one(void *buffer, size_t size,
167 int outcome, void *arg)
168{
169 control_transfer_info_t *transfer = (control_transfer_info_t *) arg;
170
171 if (outcome != EOK) {
172 control_abort_prematurely(transfer, outcome, size);
173 free(transfer);
174 return;
175 }
176
177 switch (transfer->direction) {
178 case USB_DIRECTION_IN:
179 hc_add_transaction_from_device(transfer->target,
180 USB_TRANSFER_CONTROL,
181 transfer->data_buffer, transfer->data_buffer_size,
182 control_callback_two, transfer);
183 break;
184 case USB_DIRECTION_OUT:
185 hc_add_transaction_to_device(false, transfer->target,
186 USB_TRANSFER_CONTROL,
187 transfer->data_buffer, transfer->data_buffer_size,
188 control_callback_two, transfer);
189 break;
190 default:
191 assert(false && "unreachable");
192 break;
193 }
194}
195
196static control_transfer_info_t *create_control_transfer_info(device_t *dev,
197 usb_direction_t direction, usb_target_t target,
198 void *data_buffer, size_t data_buffer_size,
199 void *arg)
200{
201 control_transfer_info_t *transfer
202 = malloc(sizeof(control_transfer_info_t));
203
204 transfer->direction = direction;
205 transfer->target = target;
206 transfer->in_callback = NULL;
207 transfer->out_callback = NULL;
208 transfer->arg = arg;
209 transfer->dev = dev;
210 transfer->data_buffer = data_buffer;
211 transfer->data_buffer_size = data_buffer_size;
212
213 return transfer;
214}
215
216static int enqueue_transfer_out(device_t *dev,
217 usb_target_t target, usb_transfer_type_t transfer_type,
218 void *buffer, size_t size,
219 usbhc_iface_transfer_out_callback_t callback, void *arg)
220{
221 usb_log_debug2("Transfer OUT [%d.%d (%s); %zu].\n",
222 target.address, target.endpoint,
223 usb_str_transfer_type(transfer_type),
224 size);
225
226 transfer_info_t *transfer
227 = create_transfer_info(dev, USB_DIRECTION_OUT, arg);
228 transfer->out_callback = callback;
229
230 hc_add_transaction_to_device(false, target, transfer_type, buffer, size,
231 universal_callback, transfer);
232
233 return EOK;
234}
235
236static int enqueue_transfer_setup(device_t *dev,
237 usb_target_t target, usb_transfer_type_t transfer_type,
238 void *buffer, size_t size,
239 usbhc_iface_transfer_out_callback_t callback, void *arg)
240{
241 usb_log_debug2("Transfer SETUP [%d.%d (%s); %zu].\n",
242 target.address, target.endpoint,
243 usb_str_transfer_type(transfer_type),
244 size);
245
246 transfer_info_t *transfer
247 = create_transfer_info(dev, USB_DIRECTION_OUT, arg);
248 transfer->out_callback = callback;
249
250 hc_add_transaction_to_device(true, target, transfer_type, buffer, size,
251 universal_callback, transfer);
252
253 return EOK;
254}
255
256static int enqueue_transfer_in(device_t *dev,
257 usb_target_t target, usb_transfer_type_t transfer_type,
258 void *buffer, size_t size,
259 usbhc_iface_transfer_in_callback_t callback, void *arg)
260{
261 usb_log_debug2("Transfer IN [%d.%d (%s); %zu].\n",
262 target.address, target.endpoint,
263 usb_str_transfer_type(transfer_type),
264 size);
265
266 transfer_info_t *transfer
267 = create_transfer_info(dev, USB_DIRECTION_IN, arg);
268 transfer->in_callback = callback;
269
270 hc_add_transaction_from_device(target, transfer_type, buffer, size,
271 universal_callback, transfer);
272
273 return EOK;
274}
275
276
277static int interrupt_out(device_t *dev, usb_target_t target,
278 size_t max_packet_size,
279 void *data, size_t size,
280 usbhc_iface_transfer_out_callback_t callback, void *arg)
281{
282 return enqueue_transfer_out(dev, target, USB_TRANSFER_INTERRUPT,
283 data, size,
284 callback, arg);
285}
286
287static int interrupt_in(device_t *dev, usb_target_t target,
288 size_t max_packet_size,
289 void *data, size_t size,
290 usbhc_iface_transfer_in_callback_t callback, void *arg)
291{
292 return enqueue_transfer_in(dev, target, USB_TRANSFER_INTERRUPT,
293 data, size,
294 callback, arg);
295}
296
297static int control_write_setup(device_t *dev, usb_target_t target,
298 size_t max_packet_size,
299 void *data, size_t size,
300 usbhc_iface_transfer_out_callback_t callback, void *arg)
301{
302 return enqueue_transfer_setup(dev, target, USB_TRANSFER_CONTROL,
303 data, size,
304 callback, arg);
305}
306
307static int control_write_data(device_t *dev, usb_target_t target,
308 size_t max_packet_size,
309 void *data, size_t size,
310 usbhc_iface_transfer_out_callback_t callback, void *arg)
311{
312 return enqueue_transfer_out(dev, target, USB_TRANSFER_CONTROL,
313 data, size,
314 callback, arg);
315}
316
317static int control_write_status(device_t *dev, usb_target_t target,
318 usbhc_iface_transfer_in_callback_t callback, void *arg)
319{
320 return enqueue_transfer_in(dev, target, USB_TRANSFER_CONTROL,
321 NULL, 0,
322 callback, arg);
323}
324
325static int control_write(device_t *dev, usb_target_t target,
326 size_t max_packet_size,
327 void *setup_packet, size_t setup_packet_size,
328 void *data, size_t data_size,
329 usbhc_iface_transfer_out_callback_t callback, void *arg)
330{
331 control_transfer_info_t *transfer
332 = create_control_transfer_info(dev, USB_DIRECTION_OUT, target,
333 data, data_size, arg);
334 transfer->out_callback = callback;
335
336 hc_add_transaction_to_device(true, target, USB_TRANSFER_CONTROL,
337 setup_packet, setup_packet_size,
338 control_callback_one, transfer);
339
340 return EOK;
341}
342
343static int control_read_setup(device_t *dev, usb_target_t target,
344 size_t max_packet_size,
345 void *data, size_t size,
346 usbhc_iface_transfer_out_callback_t callback, void *arg)
347{
348 return enqueue_transfer_setup(dev, target, USB_TRANSFER_CONTROL,
349 data, size,
350 callback, arg);
351}
352
353static int control_read_data(device_t *dev, usb_target_t target,
354 size_t max_packet_size,
355 void *data, size_t size,
356 usbhc_iface_transfer_in_callback_t callback, void *arg)
357{
358 return enqueue_transfer_in(dev, target, USB_TRANSFER_CONTROL,
359 data, size,
360 callback, arg);
361}
362
363static int control_read_status(device_t *dev, usb_target_t target,
364 usbhc_iface_transfer_out_callback_t callback, void *arg)
365{
366 return enqueue_transfer_out(dev, target, USB_TRANSFER_CONTROL,
367 NULL, 0,
368 callback, arg);
369}
370
371static int control_read(device_t *dev, usb_target_t target,
372 size_t max_packet_size,
373 void *setup_packet, size_t setup_packet_size,
374 void *data, size_t data_size,
375 usbhc_iface_transfer_in_callback_t callback, void *arg)
376{
377 control_transfer_info_t *transfer
378 = create_control_transfer_info(dev, USB_DIRECTION_IN, target,
379 data, data_size, arg);
380 transfer->in_callback = callback;
381
382 hc_add_transaction_to_device(true, target, USB_TRANSFER_CONTROL,
383 setup_packet, setup_packet_size,
384 control_callback_one, transfer);
385
386 return EOK;
387}
388
389static usb_address_keeping_t addresses;
390
391
392static int reserve_default_address(device_t *dev)
393{
394 usb_address_keeping_reserve_default(&addresses);
395 return EOK;
396}
397
398static int release_default_address(device_t *dev)
399{
400 usb_address_keeping_release_default(&addresses);
401 return EOK;
402}
403
404static int request_address(device_t *dev, usb_address_t *address)
405{
406 usb_address_t addr = usb_address_keeping_request(&addresses);
407 if (addr < 0) {
408 return (int)addr;
409 }
410
411 *address = addr;
412 return EOK;
413}
414
415static int release_address(device_t *dev, usb_address_t address)
416{
417 return usb_address_keeping_release(&addresses, address);
418}
419
420static int bind_address(device_t *dev, usb_address_t address,
421 devman_handle_t handle)
422{
423 usb_address_keeping_devman_bind(&addresses, address, handle);
424 return EOK;
425}
426
427static int tell_address(device_t *dev, devman_handle_t handle,
428 usb_address_t *address)
429{
430 usb_address_t addr = usb_address_keeping_find(&addresses, handle);
431 if (addr < 0) {
432 return addr;
433 }
434
435 *address = addr;
436 return EOK;
437}
438
439void address_init(void)
440{
441 usb_address_keeping_init(&addresses, 50);
442}
443
444usbhc_iface_t vhc_iface = {
445 .tell_address = tell_address,
446
447 .reserve_default_address = reserve_default_address,
448 .release_default_address = release_default_address,
449 .request_address = request_address,
450 .bind_address = bind_address,
451 .release_address = release_address,
452
453 .interrupt_out = interrupt_out,
454 .interrupt_in = interrupt_in,
455
456 .control_write_setup = control_write_setup,
457 .control_write_data = control_write_data,
458 .control_write_status = control_write_status,
459
460 .control_write = control_write,
461
462 .control_read_setup = control_read_setup,
463 .control_read_data = control_read_data,
464 .control_read_status = control_read_status,
465
466 .control_read = control_read
467};
468
469/**
470 * @}
471 */
Note: See TracBrowser for help on using the repository browser.