]> git.proxmox.com Git - grub2.git/blob - bus/usb/usb.c
2009-02-08 Marco Gerards <marco@gnu.org>
[grub2.git] / bus / usb / usb.c
1 /* usb.c - Generic USB interfaces. */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2008 Free Software Foundation, Inc.
5 *
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.
10 *
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.
15 *
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/>.
18 */
19
20 #include <grub/dl.h>
21 #include <grub/mm.h>
22 #include <grub/usb.h>
23 #include <grub/misc.h>
24
25 static grub_usb_controller_dev_t grub_usb_list;
26
27 void
28 grub_usb_controller_dev_register (grub_usb_controller_dev_t usb)
29 {
30 auto int iterate_hook (grub_usb_controller_t dev);
31
32 /* Iterate over all controllers found by the driver. */
33 int iterate_hook (grub_usb_controller_t dev)
34 {
35 dev->dev = usb;
36
37 /* Enable the ports of the USB Root Hub. */
38 grub_usb_root_hub (dev);
39
40 return 0;
41 }
42
43 usb->next = grub_usb_list;
44 grub_usb_list = usb;
45
46 if (usb->iterate)
47 usb->iterate (iterate_hook);
48 }
49
50 void
51 grub_usb_controller_dev_unregister (grub_usb_controller_dev_t usb)
52 {
53 grub_usb_controller_dev_t *p, q;
54
55 for (p = &grub_usb_list, q = *p; q; p = &(q->next), q = q->next)
56 if (q == usb)
57 {
58 *p = q->next;
59 break;
60 }
61 }
62
63 #if 0
64 int
65 grub_usb_controller_iterate (int (*hook) (grub_usb_controller_t dev))
66 {
67 grub_usb_controller_dev_t p;
68
69 auto int iterate_hook (grub_usb_controller_t dev);
70
71 int iterate_hook (grub_usb_controller_t dev)
72 {
73 dev->dev = p;
74 if (hook (dev))
75 return 1;
76 return 0;
77 }
78
79 /* Iterate over all controller drivers. */
80 for (p = grub_usb_list; p; p = p->next)
81 {
82 /* Iterate over the busses of the controllers. XXX: Actually, a
83 hub driver should do this. */
84 if (p->iterate (iterate_hook))
85 return 1;
86 }
87
88 return 0;
89 }
90 #endif
91
92 \f
93 grub_usb_err_t
94 grub_usb_clear_halt (grub_usb_device_t dev, int endpoint)
95 {
96 dev->toggle[endpoint] = 0;
97 return grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
98 | GRUB_USB_REQTYPE_STANDARD
99 | GRUB_USB_REQTYPE_TARGET_ENDP),
100 GRUB_USB_REQ_CLEAR_FEATURE,
101 GRUB_USB_FEATURE_ENDP_HALT,
102 endpoint, 0, 0);
103 }
104
105 grub_usb_err_t
106 grub_usb_set_configuration (grub_usb_device_t dev, int configuration)
107 {
108 int i;
109
110 for (i = 0; i < 16; i++)
111 dev->toggle[i] = 0;
112
113 return grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
114 | GRUB_USB_REQTYPE_STANDARD
115 | GRUB_USB_REQTYPE_TARGET_DEV),
116 GRUB_USB_REQ_SET_CONFIGURATION, configuration,
117 0, 0, NULL);
118 }
119
120 grub_usb_err_t
121 grub_usb_get_descriptor (grub_usb_device_t dev,
122 grub_uint8_t type, grub_uint8_t index,
123 grub_size_t size, char *data)
124 {
125 return grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN
126 | GRUB_USB_REQTYPE_STANDARD
127 | GRUB_USB_REQTYPE_TARGET_DEV),
128 GRUB_USB_REQ_GET_DESCRIPTOR,
129 (type << 8) | index,
130 0, size, data);
131 }
132
133 struct grub_usb_desc_endp *
134 grub_usb_get_endpdescriptor (grub_usb_device_t usbdev, int addr)
135 {
136 int i;
137
138 for (i = 0; i < usbdev->config[0].descconf->numif; i++)
139 {
140 struct grub_usb_desc_if *interf;
141 int j;
142
143 interf = usbdev->config[0].interf[i].descif;
144
145 for (j = 0; j < interf->endpointcnt; j++)
146 {
147 struct grub_usb_desc_endp *endp;
148 endp = &usbdev->config[0].interf[i].descendp[j];
149
150 if (endp->endp_addr == addr)
151 return endp;
152 }
153 }
154
155 return NULL;
156 }
157
158 grub_usb_err_t
159 grub_usb_get_string (grub_usb_device_t dev, grub_uint8_t index, int langid,
160 char **string)
161 {
162 struct grub_usb_desc_str descstr;
163 struct grub_usb_desc_str *descstrp;
164 grub_usb_err_t err;
165
166 /* Only get the length. */
167 err = grub_usb_control_msg (dev, 1 << 7,
168 0x06, (3 << 8) | index,
169 langid, 1, (char *) &descstr);
170 if (err)
171 return err;
172
173 descstrp = grub_malloc (descstr.length);
174 if (! descstrp)
175 return GRUB_USB_ERR_INTERNAL;
176 err = grub_usb_control_msg (dev, 1 << 7,
177 0x06, (3 << 8) | index,
178 langid, descstr.length, (char *) descstrp);
179
180 *string = grub_malloc (descstr.length / 2);
181 if (! *string)
182 {
183 grub_free (descstrp);
184 return GRUB_USB_ERR_INTERNAL;
185 }
186
187 grub_utf16_to_utf8 ((grub_uint8_t *) *string, descstrp->str, descstrp->length / 2 - 1);
188 (*string)[descstr.length / 2 - 1] = '\0';
189 grub_free (descstrp);
190
191 return GRUB_USB_ERR_NONE;
192 }
193
194 grub_usb_err_t
195 grub_usb_device_initialize (grub_usb_device_t dev)
196 {
197 struct grub_usb_desc_device *descdev;
198 struct grub_usb_desc_config config;
199 grub_usb_err_t err;
200 int i;
201
202 err = grub_usb_get_descriptor (dev, GRUB_USB_DESCRIPTOR_DEVICE,
203 0, sizeof (struct grub_usb_desc_device),
204 (char *) &dev->descdev);
205 if (err)
206 return err;
207 descdev = &dev->descdev;
208
209 for (i = 0; i < 8; i++)
210 dev->config[i].descconf = NULL;
211
212 for (i = 0; i < descdev->configcnt; i++)
213 {
214 int pos;
215 int currif;
216 char *data;
217
218 /* First just read the first 4 bytes of the configuration
219 descriptor, after that it is known how many bytes really have
220 to be read. */
221 err = grub_usb_get_descriptor (dev, GRUB_USB_DESCRIPTOR_CONFIG, i, 4,
222 (char *) &config);
223
224 data = grub_malloc (config.totallen);
225 if (! data)
226 {
227 err = GRUB_USB_ERR_INTERNAL;
228 goto fail;
229 }
230
231 dev->config[i].descconf = (struct grub_usb_desc_config *) data;
232 err = grub_usb_get_descriptor (dev, GRUB_USB_DESCRIPTOR_CONFIG, i,
233 config.totallen, data);
234 if (err)
235 goto fail;
236
237 /* Skip the configuration descriptor. */
238 pos = sizeof (struct grub_usb_desc_config);
239
240 /* Read all interfaces. */
241 for (currif = 0; currif < dev->config[i].descconf->numif; currif++)
242 {
243 dev->config[i].interf[currif].descif
244 = (struct grub_usb_desc_if *) &data[pos];
245 pos += sizeof (struct grub_usb_desc_if);
246
247 /* Point to the first endpoint. */
248 dev->config[i].interf[currif].descendp
249 = (struct grub_usb_desc_endp *) &data[pos];
250 pos += (sizeof (struct grub_usb_desc_endp)
251 * dev->config[i].interf[currif].descif->endpointcnt);
252 }
253 }
254
255 return GRUB_USB_ERR_NONE;
256
257 fail:
258
259 for (i = 0; i < 8; i++)
260 grub_free (dev->config[i].descconf);
261
262 return err;
263 }