1 /* usb.c - Generic USB interfaces. */
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/>.
23 #include <grub/misc.h>
25 static grub_usb_controller_dev_t grub_usb_list
;
28 grub_usb_controller_dev_register (grub_usb_controller_dev_t usb
)
30 auto int iterate_hook (grub_usb_controller_t dev
);
32 /* Iterate over all controllers found by the driver. */
33 int iterate_hook (grub_usb_controller_t dev
)
37 /* Enable the ports of the USB Root Hub. */
38 grub_usb_root_hub (dev
);
43 usb
->next
= grub_usb_list
;
47 usb
->iterate (iterate_hook
);
51 grub_usb_controller_dev_unregister (grub_usb_controller_dev_t usb
)
53 grub_usb_controller_dev_t
*p
, q
;
55 for (p
= &grub_usb_list
, q
= *p
; q
; p
= &(q
->next
), q
= q
->next
)
65 grub_usb_controller_iterate (int (*hook
) (grub_usb_controller_t dev
))
67 grub_usb_controller_dev_t p
;
69 auto int iterate_hook (grub_usb_controller_t dev
);
71 int iterate_hook (grub_usb_controller_t dev
)
79 /* Iterate over all controller drivers. */
80 for (p
= grub_usb_list
; p
; p
= p
->next
)
82 /* Iterate over the busses of the controllers. XXX: Actually, a
83 hub driver should do this. */
84 if (p
->iterate (iterate_hook
))
94 grub_usb_clear_halt (grub_usb_device_t dev
, int endpoint
)
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
,
106 grub_usb_set_configuration (grub_usb_device_t dev
, int configuration
)
110 for (i
= 0; i
< 16; i
++)
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
,
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
)
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
,
133 struct grub_usb_desc_endp
*
134 grub_usb_get_endpdescriptor (grub_usb_device_t usbdev
, int addr
)
138 for (i
= 0; i
< usbdev
->config
[0].descconf
->numif
; i
++)
140 struct grub_usb_desc_if
*interf
;
143 interf
= usbdev
->config
[0].interf
[i
].descif
;
145 for (j
= 0; j
< interf
->endpointcnt
; j
++)
147 struct grub_usb_desc_endp
*endp
;
148 endp
= &usbdev
->config
[0].interf
[i
].descendp
[j
];
150 if (endp
->endp_addr
== addr
)
159 grub_usb_get_string (grub_usb_device_t dev
, grub_uint8_t index
, int langid
,
162 struct grub_usb_desc_str descstr
;
163 struct grub_usb_desc_str
*descstrp
;
166 /* Only get the length. */
167 err
= grub_usb_control_msg (dev
, 1 << 7,
168 0x06, (3 << 8) | index
,
169 langid
, 1, (char *) &descstr
);
173 descstrp
= grub_malloc (descstr
.length
);
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
);
180 *string
= grub_malloc (descstr
.length
/ 2);
183 grub_free (descstrp
);
184 return GRUB_USB_ERR_INTERNAL
;
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
);
191 return GRUB_USB_ERR_NONE
;
195 grub_usb_device_initialize (grub_usb_device_t dev
)
197 struct grub_usb_desc_device
*descdev
;
198 struct grub_usb_desc_config config
;
202 err
= grub_usb_get_descriptor (dev
, GRUB_USB_DESCRIPTOR_DEVICE
,
203 0, sizeof (struct grub_usb_desc_device
),
204 (char *) &dev
->descdev
);
207 descdev
= &dev
->descdev
;
209 for (i
= 0; i
< 8; i
++)
210 dev
->config
[i
].descconf
= NULL
;
212 for (i
= 0; i
< descdev
->configcnt
; i
++)
218 /* First just read the first 4 bytes of the configuration
219 descriptor, after that it is known how many bytes really have
221 err
= grub_usb_get_descriptor (dev
, GRUB_USB_DESCRIPTOR_CONFIG
, i
, 4,
224 data
= grub_malloc (config
.totallen
);
227 err
= GRUB_USB_ERR_INTERNAL
;
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
);
237 /* Skip the configuration descriptor. */
238 pos
= sizeof (struct grub_usb_desc_config
);
240 /* Read all interfaces. */
241 for (currif
= 0; currif
< dev
->config
[i
].descconf
->numif
; currif
++)
243 dev
->config
[i
].interf
[currif
].descif
244 = (struct grub_usb_desc_if
*) &data
[pos
];
245 pos
+= sizeof (struct grub_usb_desc_if
);
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
);
255 return GRUB_USB_ERR_NONE
;
259 for (i
= 0; i
< 8; i
++)
260 grub_free (dev
->config
[i
].descconf
);