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

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

Adds new API hc stubs

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