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

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

Add new tracking mechanism for complex transfers

  • Property mode set to 100644
File size: 9.7 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#include <mem.h>
36
37#include <usb/debug.h>
38
39#include "tracker.h"
40
41#define SETUP_PACKET_DATA_SIZE 8
42#define DEFAULT_ERROR_COUNT 3
43#define MAX(a,b) ((a > b) ? a : b)
44#define MIN(a,b) ((a < b) ? a : b)
45
46static void tracker_control_read_data(tracker_t *instance);
47static void tracker_control_write_data(tracker_t *instance);
48static void tracker_control_read_status(tracker_t *instance);
49static void tracker_control_write_status(tracker_t *instance);
50
51
52int tracker_init(tracker_t *instance, device_t *dev, usb_target_t target,
53 size_t max_packet_size, dev_speed_t speed, char *buffer, size_t size,
54 usbhc_iface_transfer_in_callback_t func_in,
55 usbhc_iface_transfer_out_callback_t func_out, void *arg)
56{
57 assert(instance);
58 assert(func_in == NULL || func_out == NULL);
59 assert(func_in != NULL || func_out != NULL);
60
61 instance->td = malloc32(sizeof(transfer_descriptor_t));
62 if (!instance->td) {
63 usb_log_error("Failed to allocate transfer descriptor.\n");
64 return ENOMEM;
65 }
66
67 instance->packet = max_packet_size ? malloc32(max_packet_size) : NULL;
68 if (max_packet_size && !instance->packet) {
69 usb_log_error("Failed to allocate device acessible buffer.\n");
70 free32(instance->td);
71 return ENOMEM;
72 }
73 instance->max_packet_size = max_packet_size;
74 instance->packet_size = 0;
75 instance->buffer_offset = 0;
76
77 link_initialize(&instance->link);
78 instance->target = target;
79
80 if (func_out)
81 instance->callback_out = func_out;
82 if (func_in)
83 instance->callback_in = func_in;
84 instance->buffer = buffer;
85 instance->buffer_size = size;
86 instance->dev = dev;
87 instance->arg = arg;
88 instance->toggle = 0;
89 return EOK;
90}
91/*----------------------------------------------------------------------------*/
92void tracker_control_write(tracker_t *instance)
93{
94 assert(instance);
95 assert(instance->buffer_offset == 0);
96 instance->packet_size = SETUP_PACKET_DATA_SIZE;
97 memcpy(instance->packet, instance->buffer, SETUP_PACKET_DATA_SIZE);
98 transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
99 SETUP_PACKET_DATA_SIZE, false, instance->target, USB_PID_SETUP,
100 instance->packet);
101 instance->buffer_offset += SETUP_PACKET_DATA_SIZE;
102 instance->next_step = tracker_control_write_data;
103 //TODO: add to scheduler
104}
105/*----------------------------------------------------------------------------*/
106void tracker_control_read(tracker_t *instance)
107{
108 assert(instance);
109 assert(instance->buffer_offset == 0);
110 instance->packet_size = SETUP_PACKET_DATA_SIZE;
111 memcpy(instance->packet, instance->buffer, SETUP_PACKET_DATA_SIZE);
112 transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
113 SETUP_PACKET_DATA_SIZE, false, instance->target, USB_PID_SETUP,
114 instance->packet);
115 instance->buffer_offset += SETUP_PACKET_DATA_SIZE;
116 instance->next_step = tracker_control_read_data;
117 //TODO: add to scheduler
118}
119/*----------------------------------------------------------------------------*/
120void tracker_control_read_data(tracker_t *instance)
121{
122 assert(instance);
123
124 /* check for errors */
125 int err = transfer_descriptor_status(instance->td);
126 if (err != EOK) {
127 tracker_call_in_and_dispose(instance);
128 return;
129 }
130
131 /* we are data in, we want data from our device */
132 memcpy(instance->buffer + instance->buffer_offset, instance->packet,
133 instance->packet_size);
134 instance->buffer_offset += instance->packet_size;
135
136 /* prepare next packet, no copy, we are receiving data */
137 instance->packet_size = MIN(instance->max_packet_size,
138 instance->buffer_size - instance->buffer_offset);
139 transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
140 instance->packet_size, false, instance->target, USB_PID_IN,
141 instance->packet);
142 // TODO: add to uhci scheduler
143
144 /* set next step */
145 if ((instance->buffer_offset + instance->packet_size)
146 < instance->buffer_size) {
147 /* that's all, end coomunication */
148 instance->next_step = tracker_control_read_status;
149 }
150}
151/*----------------------------------------------------------------------------*/
152void tracker_control_write_data(tracker_t *instance)
153{
154 assert(instance);
155
156 /* check for errors */
157 int err = transfer_descriptor_status(instance->td);
158 if (err != EOK) {
159 tracker_call_out_and_dispose(instance);
160 return;
161 }
162
163 /* we are data out, we down't want data from our device */
164 instance->buffer_offset += instance->packet_size;
165
166 /* prepare next packet, copy data to packet */
167 instance->packet_size = MIN(instance->max_packet_size,
168 instance->buffer_size - instance->buffer_offset);
169 memcpy(instance->packet, instance->buffer + instance->buffer_offset,
170 instance->packet_size);
171 transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
172 instance->packet_size, false, instance->target, USB_PID_OUT,
173 instance->packet);
174 // TODO: add to uhci scheduler
175
176 /* set next step */
177 if ((instance->buffer_offset + instance->packet_size)
178 < instance->buffer_size) {
179 /* that's all, end coomunication */
180 instance->next_step = tracker_control_write_status;
181 }
182}
183/*----------------------------------------------------------------------------*/
184void tracker_control_read_status(tracker_t *instance)
185{
186 assert(instance);
187
188 /* check for errors */
189 int err = transfer_descriptor_status(instance->td);
190 if (err != EOK) {
191 tracker_call_in_and_dispose(instance);
192 return;
193 }
194
195 /* we are data in, we want data from our device */
196 memcpy(instance->buffer + instance->buffer_offset, instance->packet,
197 instance->packet_size);
198 instance->buffer_offset += instance->packet_size;
199 assert(instance->buffer_offset = instance->buffer_size);
200
201 /* prepare next packet, no nothing, just an empty packet */
202 instance->packet_size = 0;
203 transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
204 0, false, instance->target, USB_PID_OUT, NULL);
205 // TODO: add to uhci scheduler
206
207 /* set next step, callback and cleanup */
208 instance->next_step = tracker_call_in_and_dispose;
209}
210/*----------------------------------------------------------------------------*/
211void tracker_control_write_status(tracker_t *instance)
212{
213 assert(instance);
214
215 /* check for errors */
216 int err = transfer_descriptor_status(instance->td);
217 if (err != EOK) {
218 tracker_call_out_and_dispose(instance);
219 return;
220 }
221
222 /* we are data in, we want data from our device */
223 memcpy(instance->buffer + instance->buffer_offset, instance->packet,
224 instance->packet_size);
225 instance->buffer_offset += instance->packet_size;
226 assert(instance->buffer_offset = instance->buffer_size);
227
228 /* prepare next packet, no nothing, just an empty packet */
229 instance->packet_size = 0;
230 transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
231 0, false, instance->target, USB_PID_OUT, NULL);
232 // TODO: add to uhci scheduler
233
234 /* set next step, callback and cleanup */
235 instance->next_step = tracker_call_out_and_dispose;
236}
237/*----------------------------------------------------------------------------*/
238void tracker_interrupt_in(tracker_t *instance)
239{
240}
241/*----------------------------------------------------------------------------*/
242void tracker_interrupt_out(tracker_t *instance)
243{
244}
245/*----------------------------------------------------------------------------*/
246void tracker_call_in(tracker_t *instance)
247{
248 assert(instance);
249 assert(instance->callback_in);
250
251 /* check for errors */
252 int err = transfer_descriptor_status(instance->td);
253 if (err == EOK && instance->packet_size) {
254 memcpy(instance->buffer + instance->buffer_offset, instance->packet,
255 instance->packet_size);
256 }
257 instance->callback_in(instance->dev,
258 err ? USB_OUTCOME_CRCERROR : USB_OUTCOME_OK, instance->buffer_offset,
259 instance->arg);
260}
261/*----------------------------------------------------------------------------*/
262void tracker_call_out(tracker_t *instance)
263{
264 assert(instance);
265 assert(instance->callback_out);
266
267 /* check for errors */
268 int err = transfer_descriptor_status(instance->td);
269 instance->callback_out(instance->dev,
270 err ? USB_OUTCOME_CRCERROR : USB_OUTCOME_OK, instance->arg);
271}
272/*----------------------------------------------------------------------------*/
273void tracker_call_in_and_dispose(tracker_t *instance)
274{
275 assert(instance);
276 tracker_call_in(instance);
277 free32(instance->td);
278 free32(instance->packet);
279 free(instance);
280}
281/*----------------------------------------------------------------------------*/
282void tracker_call_out_and_dispose(tracker_t *instance)
283{
284 assert(instance);
285 tracker_call_out(instance);
286 free32(instance->td);
287 free32(instance->packet);
288 free(instance);
289}
290/**
291 * @}
292 */
Note: See TracBrowser for help on using the repository browser.