source: mainline/uspace/drv/uhci-hcd/tracker.c@ 8f198c9

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 8f198c9 was 53338bda, checked in by Jan Vesely <jano.vesely@…>, 15 years ago

remove transfers from the list

  • Property mode set to 100644
File size: 15.8 KB
Line 
1/*
2 * Copyright (c) 2011 Jan Vesely
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/** @addtogroup usb
29 * @{
30 */
31/** @file
32 * @brief UHCI driver
33 */
34#include <errno.h>
35
36#include <usb/debug.h>
37
38#include "tracker.h"
39#include "transfer_list.h"
40#include "uhci.h"
41#include "utils/malloc32.h"
42
43#define SETUP_PACKET_DATA_SIZE 8
44#define DEFAULT_ERROR_COUNT 3
45#define MAX(a,b) ((a > b) ? a : b)
46#define MIN(a,b) ((a < b) ? a : b)
47
48static int tracker_schedule(tracker_t *instance);
49
50static void tracker_control_read_data(tracker_t *instance);
51static void tracker_control_write_data(tracker_t *instance);
52static void tracker_control_read_status(tracker_t *instance);
53static void tracker_control_write_status(tracker_t *instance);
54
55static void tracker_call_in(tracker_t *instance);
56static void tracker_call_out(tracker_t *instance);
57static void tracker_call_in_and_dispose(tracker_t *instance);
58static void tracker_call_out_and_dispose(tracker_t *instance);
59
60
61tracker_t * tracker_get(device_t *dev, usb_target_t target,
62 usb_transfer_type_t transfer_type, size_t max_packet_size,
63 dev_speed_t speed, char *buffer, size_t size,
64 usbhc_iface_transfer_in_callback_t func_in,
65 usbhc_iface_transfer_out_callback_t func_out, void *arg)
66{
67 assert(func_in == NULL || func_out == NULL);
68 assert(func_in != NULL || func_out != NULL);
69
70 tracker_t *instance = malloc(sizeof(tracker_t));
71 if (!instance) {
72 usb_log_error("Failed to allocate tracker isntance.\n");
73 return NULL;
74 }
75
76 instance->td = malloc32(sizeof(transfer_descriptor_t));
77 if (!instance->td) {
78 usb_log_error("Failed to allocate transfer descriptor.\n");
79 free(instance);
80 return NULL;
81 }
82 bzero(instance->td, sizeof(transfer_descriptor_t));
83
84 instance->packet = max_packet_size ? malloc32(max_packet_size) : NULL;
85 if (max_packet_size && !instance->packet) {
86 usb_log_error("Failed to allocate device acessible buffer.\n");
87 free32(instance->td);
88 free(instance);
89 return NULL;
90 }
91 instance->max_packet_size = max_packet_size;
92 instance->packet_size = 0;
93 instance->buffer_offset = 0;
94
95 link_initialize(&instance->link);
96 instance->target = target;
97 instance->transfer_type = transfer_type;
98
99 if (func_out)
100 instance->callback_out = func_out;
101 if (func_in)
102 instance->callback_in = func_in;
103 instance->buffer = buffer;
104 instance->buffer_size = size;
105 instance->dev = dev;
106 instance->arg = arg;
107 instance->toggle = 0;
108 instance->speed = speed;
109
110 return instance;
111}
112/*----------------------------------------------------------------------------*/
113void tracker_control_write(
114 tracker_t *instance, char* setup_buffer, size_t setup_size)
115{
116 assert(instance);
117 assert(instance->buffer_offset == 0);
118 assert(setup_size == 8);
119
120 instance->packet_size = 0;
121 memcpy(instance->packet, setup_buffer, setup_size);
122
123 transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
124 setup_size, instance->toggle++, false, instance->target,
125 USB_PID_SETUP, instance->packet);
126
127 instance->next_step = tracker_control_write_data;
128
129 tracker_schedule(instance);
130}
131/*----------------------------------------------------------------------------*/
132void tracker_control_read(
133 tracker_t *instance, char* setup_buffer, size_t setup_size)
134{
135 assert(instance);
136 assert(instance->buffer_offset == 0);
137 assert(setup_size == 8);
138
139 memcpy(instance->packet, setup_buffer, setup_size);
140
141 transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
142 setup_size, instance->toggle++, false, instance->target,
143 USB_PID_SETUP, instance->packet);
144
145 instance->next_step = tracker_control_read_data;
146
147 tracker_schedule(instance);
148}
149/*----------------------------------------------------------------------------*/
150void tracker_control_read_data(tracker_t *instance)
151{
152 assert(instance);
153
154 /* check for errors */
155 int err = transfer_descriptor_status(instance->td);
156 if (err != EOK) {
157 tracker_call_in_and_dispose(instance);
158 return;
159 }
160
161 /* we are data in, we want data from our device */
162 if (instance->packet_size) {
163 memcpy(instance->buffer + instance->buffer_offset, instance->packet,
164 instance->packet_size);
165 }
166 instance->buffer_offset += instance->packet_size;
167
168 /* prepare next packet, no copy, we are receiving data */
169 instance->packet_size = MIN(instance->max_packet_size,
170 instance->buffer_size - instance->buffer_offset);
171
172 transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
173 instance->packet_size, instance->toggle++, false, instance->target,
174 USB_PID_IN, instance->packet);
175
176 tracker_schedule(instance);
177
178 /* set next step */
179 if ((instance->buffer_offset + instance->packet_size)
180 >= instance->buffer_size) {
181 /* that's all, end coomunication */
182 instance->next_step = tracker_control_read_status;
183 }
184}
185/*----------------------------------------------------------------------------*/
186void tracker_control_write_data(tracker_t *instance)
187{
188 assert(instance);
189
190 /* check for errors */
191 int err = transfer_descriptor_status(instance->td);
192 if (err != EOK) {
193 tracker_call_out_and_dispose(instance);
194 return;
195 }
196
197 /* we are data out, we don't want data from our device */
198 instance->buffer_offset += instance->packet_size;
199
200 /* prepare next packet, copy data to packet */
201 instance->packet_size = MIN(instance->max_packet_size,
202 instance->buffer_size - instance->buffer_offset);
203 memcpy(instance->packet, instance->buffer + instance->buffer_offset,
204 instance->packet_size);
205
206 transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
207 instance->packet_size, instance->toggle++, false, instance->target,
208 USB_PID_OUT, instance->packet);
209
210 tracker_schedule(instance);
211
212 /* set next step */
213 if ((instance->buffer_offset + instance->packet_size)
214 >= instance->buffer_size) {
215 /* that's all, end coomunication */
216 instance->next_step = tracker_control_write_status;
217 }
218}
219/*----------------------------------------------------------------------------*/
220void tracker_control_read_status(tracker_t *instance)
221{
222 assert(instance);
223
224 /* check for errors */
225 int err = transfer_descriptor_status(instance->td);
226 if (err != EOK) {
227 tracker_call_in_and_dispose(instance);
228 return;
229 }
230
231 /* we are data in, we want data from our device */
232 memcpy(instance->buffer + instance->buffer_offset, instance->packet,
233 instance->packet_size);
234 instance->buffer_offset += instance->packet_size;
235 assert(instance->buffer_offset = instance->buffer_size);
236
237 /* prepare next packet, no nothing, just an empty packet */
238 instance->packet_size = 0;
239 transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
240 instance->packet_size, 1, false, instance->target, USB_PID_OUT, NULL);
241
242 tracker_schedule(instance);
243
244 /* set next step, callback and cleanup */
245 instance->next_step = tracker_call_in_and_dispose;
246}
247/*----------------------------------------------------------------------------*/
248void tracker_control_write_status(tracker_t *instance)
249{
250 assert(instance);
251
252 /* check for errors */
253 int err = transfer_descriptor_status(instance->td);
254 if (err != EOK) {
255 tracker_call_out_and_dispose(instance);
256 return;
257 }
258
259 /* we are data in, we want data from our device */
260 assert(
261 instance->buffer_offset + instance->packet_size <= instance->buffer_size);
262 memcpy(instance->buffer + instance->buffer_offset, instance->packet,
263 instance->packet_size);
264 instance->buffer_offset += instance->packet_size;
265 assert(instance->buffer_offset = instance->buffer_size);
266
267 /* prepare next packet, no nothing, just an empty packet */
268 instance->packet_size = 0;
269 transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
270 instance->packet_size, 1, false, instance->target, USB_PID_IN, NULL);
271
272 tracker_schedule(instance);
273
274 /* set next step, callback and cleanup */
275 instance->next_step = tracker_call_out_and_dispose;
276}
277/*----------------------------------------------------------------------------*/
278void tracker_interrupt_in(tracker_t *instance)
279{
280 assert(instance);
281
282 /* check for errors */
283 int err = transfer_descriptor_status(instance->td);
284 if (err != EOK) {
285 tracker_call_in_and_dispose(instance);
286 return;
287 }
288
289 assert(instance->packet_size <= instance->max_packet_size);
290 if (instance->packet_size) {
291 /* we are data in, we want data from our device. if there is data */
292 memcpy(instance->buffer + instance->buffer_offset, instance->packet,
293 instance->packet_size);
294 instance->buffer_offset += instance->packet_size;
295 }
296
297 /* prepare next packet, no copy, we are receiving data */
298 instance->packet_size = MIN(instance->max_packet_size,
299 instance->buffer_size - instance->buffer_offset);
300 assert(instance->packet_size <= instance->max_packet_size);
301
302 transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
303 instance->packet_size, instance->toggle++, false, instance->target,
304 USB_PID_IN, instance->packet);
305
306 tracker_schedule(instance);
307
308 /* set next step */
309 if ((instance->buffer_offset + instance->packet_size)
310 >= instance->buffer_size) {
311 /* that's all, end coomunication */
312 instance->next_step = tracker_call_in_and_dispose;
313 } else {
314 instance->next_step = tracker_interrupt_in;
315 }
316}
317/*----------------------------------------------------------------------------*/
318void tracker_interrupt_out(tracker_t *instance)
319{
320 assert(instance);
321
322 /* check for errors */
323 int err = transfer_descriptor_status(instance->td);
324 if (err != EOK) {
325 tracker_call_out_and_dispose(instance);
326 return;
327 }
328
329 /* we are data out, we don't want data from our device */
330 instance->buffer_offset += instance->packet_size;
331
332 /* prepare next packet, copy data to packet */
333 instance->packet_size = MIN(instance->max_packet_size,
334 instance->buffer_size - instance->buffer_offset);
335 memcpy(instance->packet, instance->buffer + instance->buffer_offset,
336 instance->packet_size);
337
338 transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
339 instance->packet_size, instance->toggle++, false, instance->target,
340 USB_PID_OUT, instance->packet);
341
342 tracker_schedule(instance);
343
344 /* set next step */
345 if ((instance->buffer_offset + instance->packet_size)
346 >= instance->buffer_size) {
347 /* that's all, end coomunication */
348 instance->next_step = tracker_call_out_and_dispose;
349 } else {
350 instance->next_step = tracker_interrupt_out;
351 }
352}
353/*----------------------------------------------------------------------------*/
354void tracker_call_in(tracker_t *instance)
355{
356 assert(instance);
357 assert(instance->callback_in);
358
359 /* check for errors */
360 int err = transfer_descriptor_status(instance->td);
361 if (err == EOK && instance->packet_size) {
362 memcpy(instance->buffer + instance->buffer_offset, instance->packet,
363 instance->packet_size);
364 instance->buffer_offset += instance->packet_size;
365 }
366 usb_log_debug("Callback IN(%d): %d, %zu.\n", instance->transfer_type,
367 err, instance->buffer_offset);
368 instance->callback_in(instance->dev,
369 err ? USB_OUTCOME_CRCERROR : USB_OUTCOME_OK, instance->buffer_offset,
370 instance->arg);
371}
372/*----------------------------------------------------------------------------*/
373void tracker_call_out(tracker_t *instance)
374{
375 assert(instance);
376 assert(instance->callback_out);
377
378 /* check for errors */
379 int err = transfer_descriptor_status(instance->td);
380 usb_log_debug("Callback OUT(%d): %d, %zu.\n", instance->transfer_type,
381 err, instance->buffer_offset);
382 instance->callback_out(instance->dev,
383 err ? USB_OUTCOME_CRCERROR : USB_OUTCOME_OK, instance->arg);
384}
385/*----------------------------------------------------------------------------*/
386void tracker_call_in_and_dispose(tracker_t *instance)
387{
388 assert(instance);
389 tracker_call_in(instance);
390 transfer_list_remove_tracker(instance->scheduled_list, instance);
391 free32(instance->td);
392 free32(instance->packet);
393 free(instance);
394}
395/*----------------------------------------------------------------------------*/
396void tracker_call_out_and_dispose(tracker_t *instance)
397{
398 assert(instance);
399 tracker_call_out(instance);
400 assert(instance->scheduled_list);
401 transfer_list_remove_tracker(instance->scheduled_list, instance);
402 free32(instance->td);
403 free32(instance->packet);
404 free(instance);
405}
406/*----------------------------------------------------------------------------*/
407int tracker_schedule(tracker_t *instance)
408{
409 assert(instance);
410 uhci_t *hc = dev_to_uhci(instance->dev);
411 assert(hc);
412 return uhci_schedule(hc, instance);
413}
414/*----------------------------------------------------------------------------*/
415/* DEPRECATED FUNCTIONS NEEDED BY THE OLD API */
416void tracker_control_setup_old(tracker_t *instance)
417{
418 assert(instance);
419 assert(instance->buffer_offset == 0);
420
421 instance->packet_size = SETUP_PACKET_DATA_SIZE;
422 memcpy(instance->packet, instance->buffer, SETUP_PACKET_DATA_SIZE);
423
424 transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
425 SETUP_PACKET_DATA_SIZE, 0, false, instance->target, USB_PID_SETUP,
426 instance->packet);
427
428 instance->buffer_offset += SETUP_PACKET_DATA_SIZE;
429 instance->next_step = tracker_call_out_and_dispose;
430
431 tracker_schedule(instance);
432}
433
434void tracker_control_write_data_old(tracker_t *instance)
435{
436 assert(instance);
437 assert(instance->max_packet_size == instance->buffer_size);
438
439 memcpy(instance->packet, instance->buffer, instance->max_packet_size);
440 instance->packet_size = instance->max_packet_size;
441
442 transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
443 instance->packet_size, 1, false, instance->target, USB_PID_OUT,
444 instance->packet);
445 instance->next_step = tracker_call_out_and_dispose;
446
447 tracker_schedule(instance);
448}
449
450void tracker_control_read_data_old(tracker_t *instance)
451{
452 assert(instance);
453 assert(instance->max_packet_size == instance->buffer_size);
454
455 instance->packet_size = instance->max_packet_size;
456
457 transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
458 instance->packet_size, 1, false, instance->target, USB_PID_IN,
459 instance->packet);
460
461 instance->next_step = tracker_call_in_and_dispose;
462
463 tracker_schedule(instance);
464}
465
466void tracker_control_write_status_old(tracker_t *instance)
467{
468 assert(instance);
469 assert(instance->max_packet_size == 0);
470 assert(instance->buffer_size == 0);
471 assert(instance->packet == NULL);
472
473 instance->packet_size = instance->max_packet_size;
474 instance->next_step = tracker_call_in_and_dispose;
475
476 transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
477 instance->packet_size, 1, false, instance->target, USB_PID_IN,
478 instance->packet);
479
480 tracker_schedule(instance);
481}
482
483void tracker_control_read_status_old(tracker_t *instance)
484{
485 assert(instance);
486 assert(instance->max_packet_size == 0);
487 assert(instance->buffer_size == 0);
488 assert(instance->packet == NULL);
489
490 instance->packet_size = instance->max_packet_size;
491 instance->next_step = tracker_call_out_and_dispose;
492
493 transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
494 instance->packet_size, 1, false, instance->target, USB_PID_OUT,
495 instance->packet);
496
497 tracker_schedule(instance);
498}
499/**
500 * @}
501 */
Note: See TracBrowser for help on using the repository browser.