Indentation fix, cleanup.
[AROS.git] / arch / all-pc / boot / grub2-aros / grub-core / bus / usb / usb.c
blob8da5e4c7491b55df25c01e420700f7d76b583051
1 /* usb.c - Generic USB interfaces. */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2008 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
20 #include <grub/dl.h>
21 #include <grub/mm.h>
22 #include <grub/usb.h>
23 #include <grub/misc.h>
24 #include <grub/list.h>
25 #include <grub/term.h>
27 GRUB_MOD_LICENSE ("GPLv3+");
29 static struct grub_usb_attach_desc *attach_hooks;
31 #if 0
32 /* Context for grub_usb_controller_iterate. */
33 struct grub_usb_controller_iterate_ctx
35 grub_usb_controller_iterate_hook_t hook;
36 void *hook_data;
37 grub_usb_controller_dev_t p;
40 /* Helper for grub_usb_controller_iterate. */
41 static int
42 grub_usb_controller_iterate_iter (grub_usb_controller_t dev, void *data)
44 struct grub_usb_controller_iterate_ctx *ctx = data;
46 dev->dev = ctx->p;
47 if (ctx->hook (dev, ctx->hook_data))
48 return 1;
49 return 0;
52 int
53 grub_usb_controller_iterate (grub_usb_controller_iterate_hook_t hook,
54 void *hook_data)
56 struct grub_usb_controller_iterate_ctx ctx = {
57 .hook = hook,
58 .hook_data = hook_data
61 /* Iterate over all controller drivers. */
62 for (ctx.p = grub_usb_list; ctx.p; ctx.p = ctx.p->next)
64 /* Iterate over the busses of the controllers. XXX: Actually, a
65 hub driver should do this. */
66 if (ctx.p->iterate (grub_usb_controller_iterate_iter, &ctx))
67 return 1;
70 return 0;
72 #endif
75 grub_usb_err_t
76 grub_usb_clear_halt (grub_usb_device_t dev, int endpoint)
78 dev->toggle[endpoint] = 0;
79 return grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
80 | GRUB_USB_REQTYPE_STANDARD
81 | GRUB_USB_REQTYPE_TARGET_ENDP),
82 GRUB_USB_REQ_CLEAR_FEATURE,
83 GRUB_USB_FEATURE_ENDP_HALT,
84 endpoint, 0, 0);
87 grub_usb_err_t
88 grub_usb_set_configuration (grub_usb_device_t dev, int configuration)
90 grub_memset (dev->toggle, 0, sizeof (dev->toggle));
92 return grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
93 | GRUB_USB_REQTYPE_STANDARD
94 | GRUB_USB_REQTYPE_TARGET_DEV),
95 GRUB_USB_REQ_SET_CONFIGURATION, configuration,
96 0, 0, NULL);
99 grub_usb_err_t
100 grub_usb_get_descriptor (grub_usb_device_t dev,
101 grub_uint8_t type, grub_uint8_t index,
102 grub_size_t size, char *data)
104 return grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN
105 | GRUB_USB_REQTYPE_STANDARD
106 | GRUB_USB_REQTYPE_TARGET_DEV),
107 GRUB_USB_REQ_GET_DESCRIPTOR,
108 (type << 8) | index,
109 0, size, data);
112 grub_usb_err_t
113 grub_usb_device_initialize (grub_usb_device_t dev)
115 struct grub_usb_desc_device *descdev;
116 struct grub_usb_desc_config config;
117 grub_usb_err_t err;
118 int i;
120 /* First we have to read first 8 bytes only and determine
121 * max. size of packet */
122 dev->descdev.maxsize0 = 0; /* invalidating, for safety only, can be removed if it is sure it is zero here */
123 err = grub_usb_get_descriptor (dev, GRUB_USB_DESCRIPTOR_DEVICE,
124 0, 8, (char *) &dev->descdev);
125 if (err)
126 return err;
128 /* Now we have valid value in dev->descdev.maxsize0,
129 * so we can read whole device descriptor */
130 err = grub_usb_get_descriptor (dev, GRUB_USB_DESCRIPTOR_DEVICE,
131 0, sizeof (struct grub_usb_desc_device),
132 (char *) &dev->descdev);
133 if (err)
134 return err;
135 descdev = &dev->descdev;
137 for (i = 0; i < 8; i++)
138 dev->config[i].descconf = NULL;
140 if (descdev->configcnt == 0)
142 err = GRUB_USB_ERR_BADDEVICE;
143 goto fail;
146 for (i = 0; i < descdev->configcnt; i++)
148 int pos;
149 int currif;
150 char *data;
151 struct grub_usb_desc *desc;
153 /* First just read the first 4 bytes of the configuration
154 descriptor, after that it is known how many bytes really have
155 to be read. */
156 err = grub_usb_get_descriptor (dev, GRUB_USB_DESCRIPTOR_CONFIG, i, 4,
157 (char *) &config);
159 data = grub_malloc (config.totallen);
160 if (! data)
162 err = GRUB_USB_ERR_INTERNAL;
163 goto fail;
166 dev->config[i].descconf = (struct grub_usb_desc_config *) data;
167 err = grub_usb_get_descriptor (dev, GRUB_USB_DESCRIPTOR_CONFIG, i,
168 config.totallen, data);
169 if (err)
170 goto fail;
172 /* Skip the configuration descriptor. */
173 pos = dev->config[i].descconf->length;
175 /* Read all interfaces. */
176 for (currif = 0; currif < dev->config[i].descconf->numif; currif++)
178 while (pos < config.totallen)
180 desc = (struct grub_usb_desc *)&data[pos];
181 if (desc->type == GRUB_USB_DESCRIPTOR_INTERFACE)
182 break;
183 if (!desc->length)
185 err = GRUB_USB_ERR_BADDEVICE;
186 goto fail;
188 pos += desc->length;
191 dev->config[i].interf[currif].descif
192 = (struct grub_usb_desc_if *) &data[pos];
193 pos += dev->config[i].interf[currif].descif->length;
195 while (pos < config.totallen)
197 desc = (struct grub_usb_desc *)&data[pos];
198 if (desc->type == GRUB_USB_DESCRIPTOR_ENDPOINT)
199 break;
200 if (!desc->length)
202 err = GRUB_USB_ERR_BADDEVICE;
203 goto fail;
205 pos += desc->length;
208 /* Point to the first endpoint. */
209 dev->config[i].interf[currif].descendp
210 = (struct grub_usb_desc_endp *) &data[pos];
211 pos += (sizeof (struct grub_usb_desc_endp)
212 * dev->config[i].interf[currif].descif->endpointcnt);
216 return GRUB_USB_ERR_NONE;
218 fail:
220 for (i = 0; i < 8; i++)
221 grub_free (dev->config[i].descconf);
223 return err;
226 void grub_usb_device_attach (grub_usb_device_t dev)
228 int i;
230 /* XXX: Just check configuration 0 for now. */
231 for (i = 0; i < dev->config[0].descconf->numif; i++)
233 struct grub_usb_desc_if *interf;
234 struct grub_usb_attach_desc *desc;
236 interf = dev->config[0].interf[i].descif;
238 grub_dprintf ("usb", "iterate: interf=%d, class=%d, subclass=%d, protocol=%d\n",
239 i, interf->class, interf->subclass, interf->protocol);
241 if (dev->config[0].interf[i].attached)
242 continue;
244 for (desc = attach_hooks; desc; desc = desc->next)
245 if (interf->class == desc->class)
247 grub_boot_time ("Probing USB device driver class %x", desc->class);
248 if (desc->hook (dev, 0, i))
249 dev->config[0].interf[i].attached = 1;
250 grub_boot_time ("Probed USB device driver class %x", desc->class);
253 if (dev->config[0].interf[i].attached)
254 continue;
256 switch (interf->class)
258 case GRUB_USB_CLASS_MASS_STORAGE:
259 grub_dl_load ("usbms");
260 grub_print_error ();
261 break;
262 case GRUB_USB_CLASS_HID:
263 grub_dl_load ("usb_keyboard");
264 grub_print_error ();
265 break;
266 case 0xff:
267 /* FIXME: don't load useless modules. */
268 grub_dl_load ("usbserial_ftdi");
269 grub_print_error ();
270 grub_dl_load ("usbserial_pl2303");
271 grub_print_error ();
272 grub_dl_load ("usbserial_usbdebug");
273 grub_print_error ();
274 break;
279 /* Helper for grub_usb_register_attach_hook_class. */
280 static int
281 grub_usb_register_attach_hook_class_iter (grub_usb_device_t usbdev, void *data)
283 struct grub_usb_attach_desc *desc = data;
284 struct grub_usb_desc_device *descdev = &usbdev->descdev;
285 int i;
287 if (descdev->class != 0 || descdev->subclass || descdev->protocol != 0
288 || descdev->configcnt == 0)
289 return 0;
291 /* XXX: Just check configuration 0 for now. */
292 for (i = 0; i < usbdev->config[0].descconf->numif; i++)
294 struct grub_usb_desc_if *interf;
296 interf = usbdev->config[0].interf[i].descif;
298 grub_dprintf ("usb", "iterate: interf=%d, class=%d, subclass=%d, protocol=%d\n",
299 i, interf->class, interf->subclass, interf->protocol);
301 if (usbdev->config[0].interf[i].attached)
302 continue;
304 if (interf->class != desc->class)
305 continue;
306 if (desc->hook (usbdev, 0, i))
307 usbdev->config[0].interf[i].attached = 1;
310 return 0;
313 void
314 grub_usb_register_attach_hook_class (struct grub_usb_attach_desc *desc)
316 desc->next = attach_hooks;
317 attach_hooks = desc;
319 grub_usb_iterate (grub_usb_register_attach_hook_class_iter, desc);
322 void
323 grub_usb_unregister_attach_hook_class (struct grub_usb_attach_desc *desc)
325 grub_list_remove (GRUB_AS_LIST (desc));
329 GRUB_MOD_INIT(usb)
331 grub_term_poll_usb = grub_usb_poll_devices;
334 GRUB_MOD_FINI(usb)
336 grub_term_poll_usb = NULL;