source: mainline/uspace/drv/bus/usb/xhci/bus.c@ cb69854

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since cb69854 was cb69854, checked in by Petr Manek <petr.manek@…>, 8 years ago

Returning some basic speed, so that we can get xhci up and running.

  • Property mode set to 100644
File size: 6.2 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/** @addtogroup libusbhost
29 * @{
30 */
31/** @file
32 * HC Endpoint management.
33 */
34
35#include <adt/hash_table.h>
36#include <adt/hash.h>
37#include <usb/host/endpoint.h>
38#include <usb/debug.h>
39
40#include <assert.h>
41#include <errno.h>
42#include <macros.h>
43#include <stdbool.h>
44
45#include "bus.h"
46#include "endpoint.h"
47
48/** Element of the hash table. */
49typedef struct {
50 ht_link_t link;
51
52 /** Endpoint */
53 xhci_endpoint_t *endpoint;
54} hashed_endpoint_t;
55
56/** Ops receive generic bus_t pointer. */
57static inline xhci_bus_t *bus_to_xhci_bus(bus_t *bus_base)
58{
59 assert(bus_base);
60 return (xhci_bus_t *) bus_base;
61}
62
63static endpoint_t *create_endpoint(bus_t *base)
64{
65 xhci_bus_t *bus = bus_to_xhci_bus(base);
66
67 xhci_endpoint_t *ep = malloc(sizeof(xhci_endpoint_t));
68 if (!ep)
69 return NULL;
70
71 if (xhci_endpoint_init(ep, bus)) {
72 free(ep);
73 return NULL;
74 }
75
76 return &ep->base;
77}
78
79static void destroy_endpoint(endpoint_t *ep)
80{
81 xhci_endpoint_t *xhci_ep = xhci_endpoint_get(ep);
82
83 xhci_endpoint_fini(xhci_ep);
84 free(xhci_ep);
85}
86
87static int endpoint_find_by_target(xhci_bus_t *bus, usb_target_t target, hashed_endpoint_t **ep)
88{
89 ht_link_t *link = hash_table_find(&bus->endpoints, &target.packed);
90 if (link == NULL)
91 return ENOENT;
92
93 *ep = hash_table_get_inst(link, hashed_endpoint_t, link);
94 return EOK;
95}
96
97static int register_endpoint(bus_t *bus_base, endpoint_t *ep)
98{
99 xhci_bus_t *bus = bus_to_xhci_bus(bus_base);
100 assert(bus);
101
102 hashed_endpoint_t *hashed_ep =
103 (hashed_endpoint_t *) malloc(sizeof(hashed_endpoint_t));
104 if (!hashed_ep)
105 return ENOMEM;
106
107 hashed_ep->endpoint = xhci_endpoint_get(ep);
108 hash_table_insert(&bus->endpoints, &hashed_ep->link);
109
110 return EOK;
111}
112
113static int release_endpoint(bus_t *bus_base, endpoint_t *ep)
114{
115 xhci_bus_t *bus = bus_to_xhci_bus(bus_base);
116 assert(bus);
117
118 hashed_endpoint_t *hashed_ep;
119 int res = endpoint_find_by_target(bus, ep->target, &hashed_ep);
120 if (res != EOK)
121 return res;
122
123 hash_table_remove(&bus->endpoints, &ep->target.packed);
124 free(hashed_ep);
125
126 return EOK;
127}
128
129static endpoint_t* find_endpoint(bus_t *bus_base, usb_target_t target, usb_direction_t direction)
130{
131 xhci_bus_t *bus = bus_to_xhci_bus(bus_base);
132 assert(bus);
133
134 hashed_endpoint_t *hashed_ep;
135 int res = endpoint_find_by_target(bus, target, &hashed_ep);
136 if (res != EOK)
137 return NULL;
138
139 return &hashed_ep->endpoint->base;
140}
141
142static int request_address(bus_t *bus_base, usb_address_t *addr, bool strict, usb_speed_t speed)
143{
144 // TODO: Implement me!
145 return ENOTSUP;
146}
147
148static int get_speed(bus_t *bus_base, usb_address_t address, usb_speed_t *speed)
149{
150 xhci_bus_t *bus = bus_to_xhci_bus(bus_base);
151 assert(bus);
152
153 // TODO: Use `xhci_get_port_speed` once we find the port corresponding to `address`.
154 *speed = USB_SPEED_SUPER;
155 return EOK;
156}
157
158static int release_address(bus_t *bus_base, usb_address_t address)
159{
160 // TODO: Implement me!
161 return ENOTSUP;
162}
163
164static int reset_toggle(bus_t *bus_base, usb_target_t target, bool all)
165{
166 // TODO: Implement me!
167 return ENOTSUP;
168}
169
170static size_t count_bw(endpoint_t *ep, size_t size)
171{
172 // TODO: Implement me!
173 return 0;
174}
175
176/* Endpoint ops, optional (have generic fallback) */
177static bool endpoint_get_toggle(endpoint_t *ep)
178{
179 // TODO: Implement me!
180 return ENOTSUP;
181}
182
183static void endpoint_set_toggle(endpoint_t *ep, bool toggle)
184{
185 // TODO: Implement me!
186}
187
188static const bus_ops_t xhci_bus_ops = {
189 .create_endpoint = create_endpoint,
190 .destroy_endpoint = destroy_endpoint,
191
192 .register_endpoint = register_endpoint,
193 .release_endpoint = release_endpoint,
194 .find_endpoint = find_endpoint,
195
196 .request_address = request_address,
197 .get_speed = get_speed,
198 .release_address = release_address,
199 .reset_toggle = reset_toggle,
200
201 .count_bw = count_bw,
202
203 .endpoint_get_toggle = endpoint_get_toggle,
204 .endpoint_set_toggle = endpoint_set_toggle,
205};
206
207static size_t endpoint_ht_hash(const ht_link_t *item)
208{
209 hashed_endpoint_t *ep = hash_table_get_inst(item, hashed_endpoint_t, link);
210 return (size_t) hash_mix32(ep->endpoint->base.target.packed);
211}
212
213static size_t endpoint_ht_key_hash(void *key)
214{
215 return (size_t) hash_mix32(*(uint32_t *)key);
216}
217
218static bool endpoint_ht_key_equal(void *key, const ht_link_t *item)
219{
220 hashed_endpoint_t *ep = hash_table_get_inst(item, hashed_endpoint_t, link);
221 return ep->endpoint->base.target.packed == *(uint32_t *) key;
222}
223
224/** Operations for the endpoint hash table. */
225static hash_table_ops_t endpoint_ht_ops = {
226 .hash = endpoint_ht_hash,
227 .key_hash = endpoint_ht_key_hash,
228 .key_equal = endpoint_ht_key_equal,
229 .equal = NULL,
230 .remove_callback = NULL
231};
232
233int xhci_bus_init(xhci_bus_t *bus)
234{
235 assert(bus);
236
237 bus_init(&bus->base);
238
239 if (!hash_table_create(&bus->endpoints, 0, 0, &endpoint_ht_ops)) {
240 // FIXME: Dealloc base!
241 return ENOMEM;
242 }
243
244 bus->base.ops = xhci_bus_ops;
245 return EOK;
246}
247
248void xhci_bus_fini(xhci_bus_t *bus)
249{
250 hash_table_destroy(&bus->endpoints);
251}
252/**
253 * @}
254 */
Note: See TracBrowser for help on using the repository browser.