source: mainline/uspace/lib/usb/src/hcdhubd.c@ 4d31d58

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

Interrupt transfers ready for local drivers

  • Property mode set to 100644
File size: 6.4 KB
RevLine 
[c7137738]1/*
2 * Copyright (c) 2010 Vojtech Horky
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 libusb usb
30 * @{
31 */
32/** @file
33 * @brief HC driver and hub driver (implementation).
34 */
[4b4c797]35#include <usb/hcdhubd.h>
[cb59f787]36#include <usbhc_iface.h>
[c7137738]37#include <driver.h>
38#include <bool.h>
39#include <errno.h>
40
[0ee648a]41#define USB_HUB_DEVICE_NAME "usbhub"
42
[c7137738]43/** List of handled host controllers. */
44static LIST_INITIALIZE(hc_list);
45
46/** Our HC driver. */
47static usb_hc_driver_t *hc_driver = NULL;
48
[cb59f787]49static usbhc_iface_t usb_interface = {
[7034be15]50 .interrupt_out = NULL,
51 .interrupt_in = NULL
52};
53
54static device_ops_t usb_device_ops = {
[cb59f787]55 .interfaces[USBHC_DEV_IFACE] = &usb_interface
[7034be15]56};
57
[c7137738]58/** Callback when new device is detected and must be handled by this driver.
59 *
60 * @param dev New device.
61 * @return Error code.
62 */
63static int add_device(device_t *dev)
64{
65 /*
66 * FIXME: use some magic to determine whether hub or another HC
67 * was connected.
68 */
[0ee648a]69 bool is_hc = str_cmp(dev->name, USB_HUB_DEVICE_NAME) != 0;
70 printf("%s: add_device(name=\"%s\")\n", hc_driver->name, dev->name);
[c7137738]71
72 if (is_hc) {
73 /*
74 * We are the HC itself.
75 */
76 usb_hc_device_t *hc_dev = malloc(sizeof(usb_hc_device_t));
77 list_initialize(&hc_dev->link);
[7034be15]78 hc_dev->transfer_ops = NULL;
[c7137738]79
80 hc_dev->generic = dev;
[e27595b]81 dev->ops = &usb_device_ops;
82 hc_dev->generic->driver_data = hc_dev;
83
[c7137738]84 int rc = hc_driver->add_hc(hc_dev);
85 if (rc != EOK) {
86 free(hc_dev);
87 return rc;
88 }
89
[7034be15]90 /*
91 * FIXME: The following line causes devman to hang.
92 * Will investigate later why.
93 */
94 // add_device_to_class(dev, "usbhc");
[c7137738]95
96 list_append(&hc_dev->link, &hc_list);
97
98 return EOK;
99 } else {
100 /*
101 * We are some (probably deeply nested) hub.
102 * Thus, assign our own operations and explore already
103 * connected devices.
104 */
105 return ENOTSUP;
106 }
107}
108
109/** Check changes on all known hubs.
110 */
111static void check_hub_changes(void)
112{
113 /*
114 * Iterate through all HCs.
115 */
116 link_t *link_hc;
117 for (link_hc = hc_list.next;
118 link_hc != &hc_list;
119 link_hc = link_hc->next) {
120 usb_hc_device_t *hc = list_get_instance(link_hc,
121 usb_hc_device_t, link);
122 /*
123 * Iterate through all their hubs.
124 */
125 link_t *link_hub;
126 for (link_hub = hc->hubs.next;
127 link_hub != &hc->hubs;
128 link_hub = link_hub->next) {
129 usb_hcd_hub_info_t *hub = list_get_instance(link_hub,
130 usb_hcd_hub_info_t, link);
131
132 /*
133 * Check status change pipe of this hub.
134 */
135 usb_target_t target = {
136 .address = hub->device->address,
137 .endpoint = 1
138 };
139
140 // FIXME: count properly
141 size_t byte_length = (hub->port_count / 8) + 1;
142
143 void *change_bitmap = malloc(byte_length);
144 size_t actual_size;
145 usb_handle_t handle;
146
147 /*
148 * Send the request.
149 * FIXME: check returned value for possible errors
150 */
[7034be15]151 usb_hc_async_interrupt_in(hc, target,
[c7137738]152 change_bitmap, byte_length, &actual_size,
153 &handle);
154
[7034be15]155 usb_hc_async_wait_for(handle);
[c7137738]156
157 /*
158 * TODO: handle the changes.
159 */
160 }
161 }
162}
163
164/** Operations for combined HC and HUB driver. */
165static driver_ops_t hc_driver_generic_ops = {
166 .add_device = add_device
167};
168
169/** Combined HC and HUB driver. */
170static driver_t hc_driver_generic = {
171 .driver_ops = &hc_driver_generic_ops
172};
173
174/** Main USB host controller driver routine.
175 *
176 * @see driver_main
177 *
178 * @param hc Host controller driver.
179 * @return Error code.
180 */
181int usb_hcd_main(usb_hc_driver_t *hc)
182{
183 hc_driver = hc;
184 hc_driver_generic.name = hc->name;
185
186 /*
187 * Launch here fibril that will periodically check all
188 * attached hubs for status change.
189 * WARN: This call will effectively do nothing.
190 */
191 check_hub_changes();
192
193 /*
194 * Run the device driver framework.
195 */
196 return driver_main(&hc_driver_generic);
197}
198
199/** Add a root hub for given host controller.
200 * This function shall be called only once for each host controller driven
201 * by this driver.
202 * It takes care of creating child device - hub - that will be driven by
203 * this task.
204 *
205 * @param dev Host controller device.
206 * @return Error code.
207 */
208int usb_hcd_add_root_hub(usb_hc_device_t *dev)
209{
[7034be15]210 int rc;
211
212 /*
213 * For testing/debugging purposes only.
214 * Try to send some data to default USB address.
215 */
216 usb_target_t target = {0, 0};
217 usb_handle_t handle = 0;
218 char *data = (char *) "Hello, World!";
219
220
221 (void)usb_hc_async_interrupt_out(dev, target, data, str_length(data), &handle);
222 (void)usb_hc_async_wait_for(handle);
223
[c7137738]224 /*
225 * Announce presence of child device.
226 */
227 device_t *hub = NULL;
228 match_id_t *match_id = NULL;
229
230 hub = create_device();
231 if (hub == NULL) {
232 rc = ENOMEM;
233 goto failure;
234 }
[0ee648a]235 hub->name = USB_HUB_DEVICE_NAME;
[c7137738]236
237 match_id = create_match_id();
238 if (match_id == NULL) {
239 rc = ENOMEM;
240 goto failure;
241 }
242
243 char *id;
244 rc = asprintf(&id, "usb&hc=%s&hub", dev->generic->name);
245 if (rc <= 0) {
246 rc = ENOMEM;
247 goto failure;
248 }
249
250 match_id->id = id;
[7034be15]251 match_id->score = 30;
[c7137738]252
253 add_match_id(&hub->match_ids, match_id);
254
255 rc = child_device_register(hub, dev->generic);
256 if (rc != EOK) {
257 goto failure;
258 }
259
[7034be15]260 printf("%s: registered root hub\n", dev->generic->name);
[c7137738]261 return EOK;
262
263failure:
264 if (hub != NULL) {
265 hub->name = NULL;
266 delete_device(hub);
267 }
268 delete_match_id(match_id);
269
270 return rc;
271}
272
273/**
274 * @}
275 */
Note: See TracBrowser for help on using the repository browser.