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

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

Bugfixes and workarounds

Fixed problem when VHC died due to uninitialized list.

Another workaround for devman. Probably another deadlock. Oh, well.

  • Property mode set to 100644
File size: 6.0 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
[dac43be]33 * @brief Common stuff for both HC driver and hub driver.
[c7137738]34 */
[4b4c797]35#include <usb/hcdhubd.h>
[8f62b0f]36#include <usb/devreq.h>
[cb59f787]37#include <usbhc_iface.h>
[da55d5b]38#include <usb/descriptor.h>
[c7137738]39#include <driver.h>
40#include <bool.h>
41#include <errno.h>
[ba7f671]42#include <str_error.h>
[03171de]43#include <usb/classes/hub.h>
[c7137738]44
[dac43be]45#include "hcdhubd_private.h"
[8f62b0f]46
[c7137738]47/** Callback when new device is detected and must be handled by this driver.
48 *
49 * @param dev New device.
[dac43be]50 * @return Error code.
[c7137738]51 */
[da55d5b]52static int add_device(device_t *dev) {
[0ee648a]53 bool is_hc = str_cmp(dev->name, USB_HUB_DEVICE_NAME) != 0;
54 printf("%s: add_device(name=\"%s\")\n", hc_driver->name, dev->name);
[c7137738]55
56 if (is_hc) {
57 /*
58 * We are the HC itself.
59 */
[dac43be]60 return usb_add_hc_device(dev);
[c7137738]61 } else {
62 /*
[dac43be]63 * We are some (maybe deeply nested) hub.
[c7137738]64 * Thus, assign our own operations and explore already
65 * connected devices.
66 */
[dac43be]67 return usb_add_hub_device(dev);
[c7137738]68 }
69}
70
71/** Operations for combined HC and HUB driver. */
72static driver_ops_t hc_driver_generic_ops = {
73 .add_device = add_device
74};
75
76/** Combined HC and HUB driver. */
77static driver_t hc_driver_generic = {
78 .driver_ops = &hc_driver_generic_ops
79};
80
81/** Main USB host controller driver routine.
82 *
83 * @see driver_main
84 *
85 * @param hc Host controller driver.
86 * @return Error code.
87 */
[da55d5b]88int usb_hcd_main(usb_hc_driver_t *hc) {
[c7137738]89 hc_driver = hc;
90 hc_driver_generic.name = hc->name;
91
92 /*
93 * Run the device driver framework.
94 */
95 return driver_main(&hc_driver_generic);
96}
97
98/** Add a root hub for given host controller.
99 * This function shall be called only once for each host controller driven
100 * by this driver.
101 * It takes care of creating child device - hub - that will be driven by
102 * this task.
103 *
104 * @param dev Host controller device.
105 * @return Error code.
106 */
107int usb_hcd_add_root_hub(usb_hc_device_t *dev)
108{
[e4dbfda]109 char *id;
110 int rc = asprintf(&id, "usb&hc=%s&hub", dev->generic->name);
111 if (rc <= 0) {
112 return rc;
113 }
114
[1f43c8f]115 rc = usb_hc_add_child_device(dev->generic, USB_HUB_DEVICE_NAME, id, true);
[e4dbfda]116 if (rc != EOK) {
117 free(id);
118 }
119
120 return rc;
121}
122
123/** Info about child device. */
124struct child_device_info {
125 device_t *parent;
126 const char *name;
127 const char *match_id;
128};
129
130/** Adds a child device fibril worker. */
131static int fibril_add_child_device(void *arg)
132{
133 struct child_device_info *child_info
134 = (struct child_device_info *) arg;
[7034be15]135 int rc;
136
[e4dbfda]137 device_t *child = create_device();
[c7137738]138 match_id_t *match_id = NULL;
139
[e4dbfda]140 if (child == NULL) {
[c7137738]141 rc = ENOMEM;
142 goto failure;
143 }
[e4dbfda]144 child->name = child_info->name;
[c7137738]145
146 match_id = create_match_id();
147 if (match_id == NULL) {
148 rc = ENOMEM;
149 goto failure;
150 }
[e4dbfda]151 match_id->id = child_info->match_id;
152 match_id->score = 10;
153 add_match_id(&child->match_ids, match_id);
[c7137738]154
[1f43c8f]155 printf("%s: adding child device `%s' with match \"%s\"\n",
156 hc_driver->name, child->name, match_id->id);
[e4dbfda]157 rc = child_device_register(child, child_info->parent);
[1f43c8f]158 printf("%s: child device `%s' registration: %s\n",
159 hc_driver->name, child->name, str_error(rc));
160
[e4dbfda]161 if (rc != EOK) {
[c7137738]162 goto failure;
163 }
164
[e4dbfda]165 goto leave;
[c7137738]166
[e4dbfda]167failure:
168 if (child != NULL) {
169 child->name = NULL;
170 delete_device(child);
171 }
[c7137738]172
[e4dbfda]173 if (match_id != NULL) {
174 match_id->id = NULL;
175 delete_match_id(match_id);
[c7137738]176 }
177
[e4dbfda]178leave:
179 free(arg);
[1f43c8f]180 return EOK;
[e4dbfda]181}
[c7137738]182
[e4dbfda]183/** Adds a child.
184 * Due to deadlock in devman when parent registers child that oughts to be
185 * driven by the same task, the child adding is done in separate fibril.
186 * Not optimal, but it works.
[1f43c8f]187 * Update: not under all circumstances the new fibril is successful either.
188 * Thus the last parameter to let the caller choose.
[e4dbfda]189 *
190 * @param parent Parent device.
191 * @param name Device name.
192 * @param match_id Match id.
[1f43c8f]193 * @param create_fibril Whether to run the addition in new fibril.
[e4dbfda]194 * @return Error code.
195 */
196int usb_hc_add_child_device(device_t *parent, const char *name,
[1f43c8f]197 const char *match_id, bool create_fibril)
[e4dbfda]198{
[1f43c8f]199 printf("%s: about to add child device `%s' (%s)\n", hc_driver->name,
200 name, match_id);
201
[e4dbfda]202 struct child_device_info *child_info
203 = malloc(sizeof(struct child_device_info));
204
205 child_info->parent = parent;
206 child_info->name = name;
207 child_info->match_id = match_id;
208
[1f43c8f]209 if (create_fibril) {
210 fid_t fibril = fibril_create(fibril_add_child_device, child_info);
211 if (!fibril) {
212 return ENOMEM;
213 }
214 fibril_add_ready(fibril);
215 } else {
216 fibril_add_child_device(child_info);
[c7137738]217 }
218
[e4dbfda]219 return EOK;
[c7137738]220}
221
[fe5e00d6]222/** Tell USB address of given device.
223 *
224 * @param handle Devman handle of the device.
225 * @return USB device address or error code.
226 */
227usb_address_t usb_get_address_by_handle(devman_handle_t handle)
228{
229 /* TODO: search list of attached devices. */
230 return ENOENT;
231}
232
[c7137738]233/**
234 * @}
235 */
Note: See TracBrowser for help on using the repository browser.