source: mainline/uspace/drv/uhci_hcd/iface.c@ c4fb5ecd

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

Less logging in USB host controller drivers

Many of the debug messages were degraded to debug2 level or
completely removed. Also added formatting string for unified
dump of USB transfer batches.

Warnings in EHCI stub use debug level now.

  • Property mode set to 100644
File size: 13.3 KB
Line 
1/*
2 * Copyright (c) 2011 Vojtech Horky, 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 drvusbuhcihc
29 * @{
30 */
31/** @file
32 * @brief UHCI driver hc interface implementation
33 */
34#include <ddf/driver.h>
35#include <errno.h>
36
37#include <usb/debug.h>
38#include <usb/host/endpoint.h>
39
40#include "iface.h"
41#include "batch.h"
42#include "hc.h"
43
44static inline int setup_batch(
45 ddf_fun_t *fun, usb_target_t target, usb_direction_t direction,
46 void *data, size_t size, void * setup_data, size_t setup_size,
47 usbhc_iface_transfer_in_callback_t in,
48 usbhc_iface_transfer_out_callback_t out, void *arg, const char* name,
49 hc_t **hc, usb_transfer_batch_t **batch)
50{
51 assert(hc);
52 assert(batch);
53 assert(fun);
54 *hc = fun_to_hc(fun);
55 assert(*hc);
56
57 size_t res_bw;
58 endpoint_t *ep = usb_endpoint_manager_get_ep(&(*hc)->ep_manager,
59 target.address, target.endpoint, direction, &res_bw);
60 if (ep == NULL) {
61 usb_log_error("Endpoint(%d:%d) not registered for %s.\n",
62 target.address, target.endpoint, name);
63 return ENOENT;
64 }
65
66 usb_log_debug2("%s %d:%d %zu(%zu).\n",
67 name, target.address, target.endpoint, size, ep->max_packet_size);
68
69 const size_t bw = bandwidth_count_usb11(
70 ep->speed, ep->transfer_type, size, ep->max_packet_size);
71 if (res_bw < bw) {
72 usb_log_error("Endpoint(%d:%d) %s needs %zu bw "
73 "but only %zu is reserved.\n",
74 target.address, target.endpoint, name, bw, res_bw);
75 return ENOSPC;
76 }
77
78 *batch = batch_get(
79 fun, ep, data, size, setup_data, setup_size, in, out, arg);
80 if (!*batch)
81 return ENOMEM;
82 return EOK;
83}
84/*----------------------------------------------------------------------------*/
85/** Request address interface function
86 *
87 * @param[in] fun DDF function that was called.
88 * @param[in] speed Speed to associate with the new default address.
89 * @param[out] address Place to write a new address.
90 * @return Error code.
91 */
92static int request_address(
93 ddf_fun_t *fun, usb_speed_t speed, usb_address_t *address)
94{
95 assert(fun);
96 hc_t *hc = fun_to_hc(fun);
97 assert(hc);
98 assert(address);
99
100 usb_log_debug("Address request with speed %d.\n", speed);
101 *address = device_keeper_get_free_address(&hc->manager, speed);
102 usb_log_debug("Address request with result: %d.\n", *address);
103 if (*address <= 0)
104 return *address;
105 return EOK;
106}
107/*----------------------------------------------------------------------------*/
108/** Bind address interface function
109 *
110 * @param[in] fun DDF function that was called.
111 * @param[in] address Address of the device
112 * @param[in] handle Devman handle of the device driver.
113 * @return Error code.
114 */
115static int bind_address(
116 ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
117{
118 assert(fun);
119 hc_t *hc = fun_to_hc(fun);
120 assert(hc);
121 usb_log_debug("Address bind %d-%" PRIun ".\n", address, handle);
122 usb_device_keeper_bind(&hc->manager, address, handle);
123 return EOK;
124}
125/*----------------------------------------------------------------------------*/
126/** Find device handle by address interface function.
127 *
128 * @param[in] fun DDF function that was called.
129 * @param[in] address Address in question.
130 * @param[out] handle Where to store device handle if found.
131 * @return Error code.
132 */
133static int find_by_address(ddf_fun_t *fun, usb_address_t address,
134 devman_handle_t *handle)
135{
136 assert(fun);
137 hc_t *hc = fun_to_hc(fun);
138 assert(hc);
139 const bool found =
140 usb_device_keeper_find_by_address(&hc->manager, address, handle);
141 return found ? EOK : ENOENT;
142}
143/*----------------------------------------------------------------------------*/
144/** Release address interface function
145 *
146 * @param[in] fun DDF function that was called.
147 * @param[in] address USB address to be released.
148 * @return Error code.
149 */
150static int release_address(ddf_fun_t *fun, usb_address_t address)
151{
152 assert(fun);
153 hc_t *hc = fun_to_hc(fun);
154 assert(hc);
155 usb_log_debug("Address release %d.\n", address);
156 usb_device_keeper_release(&hc->manager, address);
157 return EOK;
158}
159/*----------------------------------------------------------------------------*/
160static int register_endpoint(
161 ddf_fun_t *fun, usb_address_t address, usb_speed_t ep_speed,
162 usb_endpoint_t endpoint,
163 usb_transfer_type_t transfer_type, usb_direction_t direction,
164 size_t max_packet_size, unsigned int interval)
165{
166 assert(fun);
167 hc_t *hc = fun_to_hc(fun);
168 assert(hc);
169 const size_t size = max_packet_size;
170 usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, address);
171 if (speed >= USB_SPEED_MAX) {
172 speed = ep_speed;
173 }
174 usb_log_debug("Register endpoint %d:%d %s-%s %s %zuB %ums.\n",
175 address, endpoint, usb_str_transfer_type(transfer_type),
176 usb_str_direction(direction), usb_str_speed(speed),
177 max_packet_size, interval);
178
179 return usb_endpoint_manager_add_ep(&hc->ep_manager, address, endpoint,
180 direction, transfer_type, speed, max_packet_size, size);
181}
182/*----------------------------------------------------------------------------*/
183static int unregister_endpoint(
184 ddf_fun_t *fun, usb_address_t address,
185 usb_endpoint_t endpoint, usb_direction_t direction)
186{
187 assert(fun);
188 hc_t *hc = fun_to_hc(fun);
189 assert(hc);
190 usb_log_debug("Unregister endpoint %d:%d %s.\n",
191 address, endpoint, usb_str_direction(direction));
192 return usb_endpoint_manager_unregister_ep(&hc->ep_manager, address,
193 endpoint, direction);
194}
195/*----------------------------------------------------------------------------*/
196/** Interrupt out transaction interface function
197 *
198 * @param[in] fun DDF function that was called.
199 * @param[in] target USB device to write to.
200 * @param[in] data Source of data.
201 * @param[in] size Size of data source.
202 * @param[in] callback Function to call on transaction completion
203 * @param[in] arg Additional for callback function.
204 * @return Error code.
205 */
206static int interrupt_out(
207 ddf_fun_t *fun, usb_target_t target, void *data,
208 size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
209{
210 usb_transfer_batch_t *batch = NULL;
211 hc_t *hc = NULL;
212 int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
213 NULL, 0, NULL, callback, arg, "Interrupt OUT", &hc, &batch);
214 if (ret != EOK)
215 return ret;
216 assert(batch);
217 assert(hc);
218 batch_interrupt_out(batch);
219 ret = hc_schedule(hc, batch);
220 if (ret != EOK) {
221 usb_transfer_batch_dispose(batch);
222 }
223 return ret;
224}
225/*----------------------------------------------------------------------------*/
226/** Interrupt in transaction interface function
227 *
228 * @param[in] fun DDF function that was called.
229 * @param[in] target USB device to write to.
230 * @param[out] data Data destination.
231 * @param[in] size Size of data source.
232 * @param[in] callback Function to call on transaction completion
233 * @param[in] arg Additional for callback function.
234 * @return Error code.
235 */
236static int interrupt_in(
237 ddf_fun_t *fun, usb_target_t target, void *data,
238 size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
239{
240 usb_transfer_batch_t *batch = NULL;
241 hc_t *hc = NULL;
242 int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
243 NULL, 0, callback, NULL, arg, "Interrupt IN", &hc, &batch);
244 if (ret != EOK)
245 return ret;
246 assert(batch);
247 assert(hc);
248 batch_interrupt_in(batch);
249 ret = hc_schedule(hc, batch);
250 if (ret != EOK) {
251 usb_transfer_batch_dispose(batch);
252 }
253 return ret;
254}
255/*----------------------------------------------------------------------------*/
256/** Bulk out transaction interface function
257 *
258 * @param[in] fun DDF function that was called.
259 * @param[in] target USB device to write to.
260 * @param[in] data Source of data.
261 * @param[in] size Size of data source.
262 * @param[in] callback Function to call on transaction completion
263 * @param[in] arg Additional for callback function.
264 * @return Error code.
265 */
266static int bulk_out(
267 ddf_fun_t *fun, usb_target_t target, void *data,
268 size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
269{
270 usb_transfer_batch_t *batch = NULL;
271 hc_t *hc = NULL;
272 int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
273 NULL, 0, NULL, callback, arg, "Bulk OUT", &hc, &batch);
274 if (ret != EOK)
275 return ret;
276 assert(batch);
277 assert(hc);
278 batch_bulk_out(batch);
279 ret = hc_schedule(hc, batch);
280 if (ret != EOK) {
281 usb_transfer_batch_dispose(batch);
282 }
283 return ret;
284}
285/*----------------------------------------------------------------------------*/
286/** Bulk in transaction interface function
287 *
288 * @param[in] fun DDF function that was called.
289 * @param[in] target USB device to write to.
290 * @param[out] data Data destination.
291 * @param[in] size Size of data source.
292 * @param[in] callback Function to call on transaction completion
293 * @param[in] arg Additional for callback function.
294 * @return Error code.
295 */
296static int bulk_in(
297 ddf_fun_t *fun, usb_target_t target, void *data,
298 size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
299{
300 usb_transfer_batch_t *batch = NULL;
301 hc_t *hc = NULL;
302 int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
303 NULL, 0, callback, NULL, arg, "Bulk IN", &hc, &batch);
304 if (ret != EOK)
305 return ret;
306 assert(batch);
307 assert(hc);
308 batch_bulk_in(batch);
309 ret = hc_schedule(hc, batch);
310 if (ret != EOK) {
311 usb_transfer_batch_dispose(batch);
312 }
313 return ret;
314}
315/*----------------------------------------------------------------------------*/
316/** Control write transaction interface function
317 *
318 * @param[in] fun DDF function that was called.
319 * @param[in] target USB device to write to.
320 * @param[in] setup_data Data to send with SETUP transfer.
321 * @param[in] setup_size Size of data to send with SETUP transfer (always 8B).
322 * @param[in] data Source of data.
323 * @param[in] size Size of data source.
324 * @param[in] callback Function to call on transaction completion.
325 * @param[in] arg Additional for callback function.
326 * @return Error code.
327 */
328static int control_write(
329 ddf_fun_t *fun, usb_target_t target,
330 void *setup_data, size_t setup_size, void *data, size_t size,
331 usbhc_iface_transfer_out_callback_t callback, void *arg)
332{
333 usb_transfer_batch_t *batch = NULL;
334 hc_t *hc = NULL;
335 int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
336 setup_data, setup_size, NULL, callback, arg, "Control WRITE",
337 &hc, &batch);
338 if (ret != EOK)
339 return ret;
340 assert(batch);
341 assert(hc);
342 usb_endpoint_manager_reset_if_need(&hc->ep_manager, target, setup_data);
343 batch_control_write(batch);
344 ret = hc_schedule(hc, batch);
345 if (ret != EOK) {
346 usb_transfer_batch_dispose(batch);
347 }
348 return ret;
349}
350/*----------------------------------------------------------------------------*/
351/** Control read transaction interface function
352 *
353 * @param[in] fun DDF function that was called.
354 * @param[in] target USB device to write to.
355 * @param[in] setup_data Data to send with SETUP packet.
356 * @param[in] setup_size Size of data to send with SETUP packet (should be 8B).
357 * @param[out] data Source of data.
358 * @param[in] size Size of data source.
359 * @param[in] callback Function to call on transaction completion.
360 * @param[in] arg Additional for callback function.
361 * @return Error code.
362 */
363static int control_read(
364 ddf_fun_t *fun, usb_target_t target,
365 void *setup_data, size_t setup_size, void *data, size_t size,
366 usbhc_iface_transfer_in_callback_t callback, void *arg)
367{
368 usb_transfer_batch_t *batch = NULL;
369 hc_t *hc = NULL;
370 int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
371 setup_data, setup_size, callback, NULL, arg, "Control READ",
372 &hc, &batch);
373 if (ret != EOK)
374 return ret;
375 assert(batch);
376 assert(hc);
377 batch_control_read(batch);
378 ret = hc_schedule(hc, batch);
379 if (ret != EOK) {
380 usb_transfer_batch_dispose(batch);
381 }
382 return ret;
383}
384/*----------------------------------------------------------------------------*/
385usbhc_iface_t hc_iface = {
386 .request_address = request_address,
387 .bind_address = bind_address,
388 .find_by_address = find_by_address,
389 .release_address = release_address,
390
391 .register_endpoint = register_endpoint,
392 .unregister_endpoint = unregister_endpoint,
393
394 .interrupt_out = interrupt_out,
395 .interrupt_in = interrupt_in,
396
397 .bulk_out = bulk_out,
398 .bulk_in = bulk_in,
399
400 .control_write = control_write,
401 .control_read = control_read,
402};
403/**
404 * @}
405 */
Note: See TracBrowser for help on using the repository browser.