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

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

Adds tracker support for the old control connection API

  • Property mode set to 100644
File size: 12.0 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#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/* DEPRECATED FUNCTIONS NEEDED BY THE OLD API */
291void tracker_control_setup_old(tracker_t *instance)
292{
293 assert(instance);
294 assert(instance->buffer_offset == 0);
295 instance->packet_size = SETUP_PACKET_DATA_SIZE;
296 memcpy(instance->packet, instance->buffer, SETUP_PACKET_DATA_SIZE);
297 transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
298 SETUP_PACKET_DATA_SIZE, false, instance->target, USB_PID_SETUP,
299 instance->packet);
300 instance->buffer_offset += SETUP_PACKET_DATA_SIZE;
301 instance->next_step = tracker_call_out_and_dispose;
302 //TODO: add to scheduler
303}
304
305void tracker_control_write_data_old(tracker_t *instance)
306{
307 assert(instance);
308 assert(instance->max_packet_size == instance->buffer_size);
309 memcpy(instance->packet, instance->buffer, instance->max_packet_size);
310 instance->packet_size = instance->max_packet_size;
311 transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
312 instance->packet_size, false, instance->target, USB_PID_OUT,
313 instance->packet);
314 instance->next_step = tracker_call_out_and_dispose;
315}
316
317void tracker_control_read_data_old(tracker_t *instance)
318{
319 assert(instance);
320 assert(instance->max_packet_size == instance->buffer_size);
321 instance->packet_size = instance->max_packet_size;
322 transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
323 instance->packet_size, false, instance->target, USB_PID_IN,
324 instance->packet);
325 instance->next_step = tracker_call_in_and_dispose;
326}
327
328void tracker_control_write_status_old(tracker_t *instance)
329{
330 assert(instance);
331 assert(instance->max_packet_size == 0);
332 assert(instance->buffer_size == 0);
333 assert(instance->packet == NULL);
334
335 instance->packet_size = instance->max_packet_size;
336 transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
337 instance->packet_size, false, instance->target, USB_PID_IN,
338 instance->packet);
339 instance->next_step = tracker_call_in_and_dispose;
340}
341
342void tracker_control_read_status_old(tracker_t *instance)
343{
344 assert(instance);
345 assert(instance->max_packet_size == 0);
346 assert(instance->buffer_size == 0);
347 assert(instance->packet == NULL);
348
349 instance->packet_size = instance->max_packet_size;
350 transfer_descriptor_init(instance->td, DEFAULT_ERROR_COUNT,
351 instance->packet_size, false, instance->target, USB_PID_OUT,
352 instance->packet);
353 instance->next_step = tracker_call_out_and_dispose;
354}
355/**
356 * @}
357 */
Note: See TracBrowser for help on using the repository browser.