source: mainline/uspace/lib/usbhost/src/bus.c@ 2b61945

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 2b61945 was 20eaa82, checked in by Ondřej Hlavatý <aearsis@…>, 8 years ago

usbhost refactoring: introduced bus→enumerate_device

  • Property mode set to 100644
File size: 6.0 KB
Line 
1/*
2 * Copyright (c) 2017 Ondrej Hlavaty <aearsis@eideo.cz>
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 <usb/host/bus.h>
37#include <usb/host/endpoint.h>
38#include <ddf/driver.h>
39
40#include <mem.h>
41#include <errno.h>
42#include <stdio.h>
43
44/**
45 * Initializes the bus structure.
46 */
47void bus_init(bus_t *bus, size_t device_size)
48{
49 assert(bus);
50 assert(device_size >= sizeof(device_t));
51 memset(bus, 0, sizeof(bus_t));
52
53 fibril_mutex_initialize(&bus->guard);
54 bus->device_size = device_size;
55}
56
57int device_init(device_t *dev)
58{
59 memset(dev, 0, sizeof(*dev));
60
61 link_initialize(&dev->link);
62 list_initialize(&dev->devices);
63 fibril_mutex_initialize(&dev->guard);
64
65 return EOK;
66}
67
68int bus_add_ep(bus_t *bus, device_t *device, usb_endpoint_t endpoint,
69 usb_direction_t dir, usb_transfer_type_t type, size_t max_packet_size,
70 unsigned packets, size_t size)
71{
72 assert(bus);
73 assert(device);
74
75 /* Temporary reference */
76 endpoint_t *ep = bus_create_endpoint(bus);
77 if (!ep)
78 return ENOMEM;
79
80 ep->target = (usb_target_t) {
81 .address = device->address,
82 .endpoint = endpoint,
83 };
84
85 ep->device = device;
86 ep->direction = dir;
87 ep->transfer_type = type;
88 ep->max_packet_size = max_packet_size;
89 ep->packets = packets;
90
91 ep->bandwidth = bus_count_bw(ep, size);
92
93 const int err = bus_register_endpoint(bus, ep);
94
95 /* drop Temporary reference */
96 endpoint_del_ref(ep);
97
98 return err;
99}
100
101int bus_remove_ep(bus_t *bus, usb_target_t target, usb_direction_t dir)
102{
103 assert(bus);
104 endpoint_t *ep = bus_find_endpoint(bus, target, dir);
105 if (!ep)
106 return ENOENT;
107
108 return bus_release_endpoint(bus, ep);
109}
110
111int device_set_default_name(device_t *dev)
112{
113 assert(dev);
114 assert(dev->fun);
115
116 char buf[10] = { 0 }; /* usbxyz-ss */
117 snprintf(buf, sizeof(buf) - 1, "usb%u-%cs",
118 dev->address, usb_str_speed(dev->speed)[0]);
119
120 return ddf_fun_set_name(dev->fun, buf);
121}
122
123int bus_enumerate_device(bus_t *bus, hcd_t *hcd, device_t *dev)
124{
125 assert(bus);
126 assert(hcd);
127 assert(dev);
128
129 if (!bus->ops.enumerate_device)
130 return ENOTSUP;
131
132 fibril_mutex_lock(&bus->guard);
133 const int r = bus->ops.enumerate_device(bus, hcd, dev);
134 fibril_mutex_unlock(&bus->guard);
135 return r;
136}
137
138int bus_remove_device(bus_t *bus, hcd_t *hcd, device_t *dev)
139{
140 assert(bus);
141 assert(dev);
142
143 if (!bus->ops.remove_device)
144 return ENOTSUP;
145
146 fibril_mutex_lock(&bus->guard);
147 const int r = bus->ops.remove_device(bus, hcd, dev);
148 fibril_mutex_unlock(&bus->guard);
149 return r;
150}
151
152endpoint_t *bus_create_endpoint(bus_t *bus)
153{
154 assert(bus);
155
156 fibril_mutex_lock(&bus->guard);
157 endpoint_t *ep = bus->ops.create_endpoint(bus);
158 if (ep) {
159 /* Exporting reference */
160 endpoint_add_ref(ep);
161 }
162 fibril_mutex_unlock(&bus->guard);
163
164 return ep;
165}
166
167int bus_register_endpoint(bus_t *bus, endpoint_t *ep)
168{
169 assert(bus);
170 assert(ep);
171
172 /* Bus reference */
173 endpoint_add_ref(ep);
174
175 fibril_mutex_lock(&bus->guard);
176 const int r = bus->ops.register_endpoint(bus, ep);
177 fibril_mutex_unlock(&bus->guard);
178
179 return r;
180}
181
182int bus_release_endpoint(bus_t *bus, endpoint_t *ep)
183{
184 int err;
185
186 assert(bus);
187 assert(ep);
188
189 fibril_mutex_lock(&bus->guard);
190 if ((err = bus->ops.release_endpoint(bus, ep)))
191 return err;
192 fibril_mutex_unlock(&bus->guard);
193
194 /* Bus reference */
195 endpoint_del_ref(ep);
196
197 return EOK;
198}
199
200/** Searches for an endpoint. Returns a reference.
201 */
202endpoint_t *bus_find_endpoint(bus_t *bus, usb_target_t target, usb_direction_t dir)
203{
204 assert(bus);
205
206 fibril_mutex_lock(&bus->guard);
207 endpoint_t *ep = bus->ops.find_endpoint(bus, target, dir);
208 if (ep) {
209 /* Exporting reference */
210 endpoint_add_ref(ep);
211 }
212
213 fibril_mutex_unlock(&bus->guard);
214 return ep;
215}
216
217int bus_request_address(bus_t *bus, usb_address_t *hint, bool strict, usb_speed_t speed)
218{
219 assert(bus);
220
221 if (!bus->ops.request_address)
222 return ENOTSUP;
223
224 fibril_mutex_lock(&bus->guard);
225 const int r = bus->ops.request_address(bus, hint, strict, speed);
226 fibril_mutex_unlock(&bus->guard);
227 return r;
228}
229
230int bus_release_address(bus_t *bus, usb_address_t address)
231{
232 assert(bus);
233
234 if (!bus->ops.release_address)
235 return ENOTSUP;
236
237 fibril_mutex_lock(&bus->guard);
238 const int r = bus->ops.release_address(bus, address);
239 fibril_mutex_unlock(&bus->guard);
240 return r;
241}
242
243int bus_reset_toggle(bus_t *bus, usb_target_t target, bool all)
244{
245 assert(bus);
246
247 if (!bus->ops.reset_toggle)
248 return ENOTSUP;
249
250 fibril_mutex_lock(&bus->guard);
251 const int r = bus->ops.reset_toggle(bus, target, all);
252 fibril_mutex_unlock(&bus->guard);
253 return r;
254}
255
256size_t bus_count_bw(endpoint_t *ep, size_t size)
257{
258 assert(ep);
259
260 fibril_mutex_lock(&ep->guard);
261 const size_t bw = ep->bus->ops.count_bw(ep, size);
262 fibril_mutex_unlock(&ep->guard);
263 return bw;
264}
265
266/**
267 * @}
268 */
Note: See TracBrowser for help on using the repository browser.