source: mainline/uspace/lib/usbhost/src/hcd.c@ d8cdf39e

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

libusbhost: Drop ddf_fun argument.

  • Property mode set to 100644
File size: 5.2 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
29/** @addtogroup libusbhost
30 * @{
31 */
32/** @file
33 *
34 */
35
36#include <errno.h>
37#include <str_error.h>
38#include <usb_iface.h>
39#include <usb/debug.h>
40#include <usb/request.h>
41
42#include <usb/host/hcd.h>
43
44/** Initialize hcd_t structure.
45 * Initializes device and endpoint managers. Sets data and hook pointer to NULL.
46 *
47 * @param hcd hcd_t structure to initialize, non-null.
48 * @param max_speed Maximum supported USB speed (full, high).
49 * @param bandwidth Available bandwidth, passed to endpoint manager.
50 * @param bw_count Bandwidth compute function, passed to endpoint manager.
51 */
52void hcd_init(hcd_t *hcd, usb_speed_t max_speed, size_t bandwidth,
53 bw_count_func_t bw_count)
54{
55 assert(hcd);
56 usb_device_manager_init(&hcd->dev_manager, max_speed);
57 usb_endpoint_manager_init(&hcd->ep_manager, bandwidth, bw_count);
58
59 hcd->private_data = NULL;
60 hcd->schedule = NULL;
61 hcd->ep_add_hook = NULL;
62 hcd->ep_remove_hook = NULL;
63}
64
65typedef struct {
66 void *original_data;
67 usbhc_iface_transfer_out_callback_t original_callback;
68 usb_target_t target;
69 hcd_t *hcd;
70} toggle_t;
71
72static void toggle_reset_callback(int retval, void *arg)
73{
74 assert(arg);
75 toggle_t *toggle = arg;
76 if (retval == EOK) {
77 usb_log_debug2("Reseting toggle on %d:%d.\n",
78 toggle->target.address, toggle->target.endpoint);
79 usb_endpoint_manager_reset_toggle(&toggle->hcd->ep_manager,
80 toggle->target, toggle->target.endpoint == 0);
81 }
82
83 toggle->original_callback(retval, toggle->original_data);
84}
85
86/** Prepare generic usb_transfer_batch and schedule it.
87 * @param hcd Host controller driver.
88 * @param fun DDF fun
89 * @param target address and endpoint number.
90 * @param setup_data Data to use in setup stage (Control communication type)
91 * @param in Callback for device to host communication.
92 * @param out Callback for host to device communication.
93 * @param arg Callback parameter.
94 * @param name Communication identifier (for nicer output).
95 * @return Error code.
96 */
97int hcd_send_batch(
98 hcd_t *hcd, usb_target_t target, usb_direction_t direction,
99 void *data, size_t size, uint64_t setup_data,
100 usbhc_iface_transfer_in_callback_t in,
101 usbhc_iface_transfer_out_callback_t out, void *arg, const char* name)
102{
103 assert(hcd);
104
105 endpoint_t *ep = usb_endpoint_manager_find_ep(&hcd->ep_manager,
106 target.address, target.endpoint, direction);
107 if (ep == NULL) {
108 usb_log_error("Endpoint(%d:%d) not registered for %s.\n",
109 target.address, target.endpoint, name);
110 return ENOENT;
111 }
112
113 usb_log_debug2("%s %d:%d %zu(%zu).\n",
114 name, target.address, target.endpoint, size, ep->max_packet_size);
115
116 const size_t bw = bandwidth_count_usb11(
117 ep->speed, ep->transfer_type, size, ep->max_packet_size);
118 /* Check if we have enough bandwidth reserved */
119 if (ep->bandwidth < bw) {
120 usb_log_error("Endpoint(%d:%d) %s needs %zu bw "
121 "but only %zu is reserved.\n",
122 ep->address, ep->endpoint, name, bw, ep->bandwidth);
123 return ENOSPC;
124 }
125 if (!hcd->schedule) {
126 usb_log_error("HCD does not implement scheduler.\n");
127 return ENOTSUP;
128 }
129
130 /* Check for commands that reset toggle bit */
131 if (ep->transfer_type == USB_TRANSFER_CONTROL) {
132 const int reset_toggle = usb_request_needs_toggle_reset(
133 (usb_device_request_setup_packet_t *) &setup_data);
134 if (reset_toggle >= 0) {
135 assert(out);
136 toggle_t *toggle = malloc(sizeof(toggle_t));
137 if (!toggle)
138 return ENOMEM;
139 toggle->target.address = target.address;
140 toggle->target.endpoint = reset_toggle;
141 toggle->original_callback = out;
142 toggle->original_data = arg;
143 toggle->hcd = hcd;
144
145 arg = toggle;
146 out = toggle_reset_callback;
147 }
148 }
149
150 usb_transfer_batch_t *batch = usb_transfer_batch_create(
151 ep, data, size, setup_data, in, out, arg);
152 if (!batch) {
153 return ENOMEM;
154 }
155
156 const int ret = hcd->schedule(hcd, batch);
157 if (ret != EOK)
158 usb_transfer_batch_destroy(batch);
159
160 return ret;
161}
162
163/**
164 * @}
165 */
Note: See TracBrowser for help on using the repository browser.