usb.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  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. #include <grub/dl.h>
  20. #include <grub/mm.h>
  21. #include <grub/usb.h>
  22. #include <grub/misc.h>
  23. #include <grub/list.h>
  24. #include <grub/term.h>
  25. GRUB_MOD_LICENSE ("GPLv3+");
  26. static struct grub_usb_attach_desc *attach_hooks;
  27. #if 0
  28. /* Context for grub_usb_controller_iterate. */
  29. struct grub_usb_controller_iterate_ctx
  30. {
  31. grub_usb_controller_iterate_hook_t hook;
  32. void *hook_data;
  33. grub_usb_controller_dev_t p;
  34. };
  35. /* Helper for grub_usb_controller_iterate. */
  36. static int
  37. grub_usb_controller_iterate_iter (grub_usb_controller_t dev, void *data)
  38. {
  39. struct grub_usb_controller_iterate_ctx *ctx = data;
  40. dev->dev = ctx->p;
  41. if (ctx->hook (dev, ctx->hook_data))
  42. return 1;
  43. return 0;
  44. }
  45. int
  46. grub_usb_controller_iterate (grub_usb_controller_iterate_hook_t hook,
  47. void *hook_data)
  48. {
  49. struct grub_usb_controller_iterate_ctx ctx = {
  50. .hook = hook,
  51. .hook_data = hook_data
  52. };
  53. /* Iterate over all controller drivers. */
  54. for (ctx.p = grub_usb_list; ctx.p; ctx.p = ctx.p->next)
  55. {
  56. /* Iterate over the busses of the controllers. XXX: Actually, a
  57. hub driver should do this. */
  58. if (ctx.p->iterate (grub_usb_controller_iterate_iter, &ctx))
  59. return 1;
  60. }
  61. return 0;
  62. }
  63. #endif
  64. grub_usb_err_t
  65. grub_usb_clear_halt (grub_usb_device_t dev, int endpoint)
  66. {
  67. if (endpoint >= GRUB_USB_MAX_TOGGLE)
  68. return GRUB_USB_ERR_BADDEVICE;
  69. dev->toggle[endpoint] = 0;
  70. return grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
  71. | GRUB_USB_REQTYPE_STANDARD
  72. | GRUB_USB_REQTYPE_TARGET_ENDP),
  73. GRUB_USB_REQ_CLEAR_FEATURE,
  74. GRUB_USB_FEATURE_ENDP_HALT,
  75. endpoint, 0, 0);
  76. }
  77. grub_usb_err_t
  78. grub_usb_set_configuration (grub_usb_device_t dev, int configuration)
  79. {
  80. grub_memset (dev->toggle, 0, sizeof (dev->toggle));
  81. return grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
  82. | GRUB_USB_REQTYPE_STANDARD
  83. | GRUB_USB_REQTYPE_TARGET_DEV),
  84. GRUB_USB_REQ_SET_CONFIGURATION, configuration,
  85. 0, 0, NULL);
  86. }
  87. grub_usb_err_t
  88. grub_usb_get_descriptor (grub_usb_device_t dev,
  89. grub_uint8_t type, grub_uint8_t index,
  90. grub_size_t size, char *data)
  91. {
  92. return grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN
  93. | GRUB_USB_REQTYPE_STANDARD
  94. | GRUB_USB_REQTYPE_TARGET_DEV),
  95. GRUB_USB_REQ_GET_DESCRIPTOR,
  96. (type << 8) | index,
  97. 0, size, data);
  98. }
  99. grub_usb_err_t
  100. grub_usb_device_initialize (grub_usb_device_t dev)
  101. {
  102. struct grub_usb_desc_device *descdev;
  103. struct grub_usb_desc_config config;
  104. grub_usb_err_t err;
  105. int i;
  106. /* First we have to read first 8 bytes only and determine
  107. * max. size of packet */
  108. dev->descdev.maxsize0 = 0; /* invalidating, for safety only, can be removed if it is sure it is zero here */
  109. err = grub_usb_get_descriptor (dev, GRUB_USB_DESCRIPTOR_DEVICE,
  110. 0, 8, (char *) &dev->descdev);
  111. if (err)
  112. return err;
  113. /* Now we have valid value in dev->descdev.maxsize0,
  114. * so we can read whole device descriptor */
  115. err = grub_usb_get_descriptor (dev, GRUB_USB_DESCRIPTOR_DEVICE,
  116. 0, sizeof (struct grub_usb_desc_device),
  117. (char *) &dev->descdev);
  118. if (err)
  119. return err;
  120. descdev = &dev->descdev;
  121. for (i = 0; i < GRUB_USB_MAX_CONF; i++)
  122. dev->config[i].descconf = NULL;
  123. if (descdev->configcnt == 0 || descdev->configcnt > GRUB_USB_MAX_CONF)
  124. {
  125. err = GRUB_USB_ERR_BADDEVICE;
  126. goto fail;
  127. }
  128. for (i = 0; i < descdev->configcnt; i++)
  129. {
  130. int pos;
  131. int currif;
  132. char *data;
  133. struct grub_usb_desc *desc;
  134. /* First just read the first 4 bytes of the configuration
  135. descriptor, after that it is known how many bytes really have
  136. to be read. */
  137. err = grub_usb_get_descriptor (dev, GRUB_USB_DESCRIPTOR_CONFIG, i, 4,
  138. (char *) &config);
  139. data = grub_malloc (config.totallen);
  140. if (! data)
  141. {
  142. err = GRUB_USB_ERR_INTERNAL;
  143. goto fail;
  144. }
  145. dev->config[i].descconf = (struct grub_usb_desc_config *) data;
  146. err = grub_usb_get_descriptor (dev, GRUB_USB_DESCRIPTOR_CONFIG, i,
  147. config.totallen, data);
  148. if (err)
  149. goto fail;
  150. /* Skip the configuration descriptor. */
  151. pos = dev->config[i].descconf->length;
  152. if (dev->config[i].descconf->numif > GRUB_USB_MAX_IF)
  153. {
  154. err = GRUB_USB_ERR_BADDEVICE;
  155. goto fail;
  156. }
  157. /* Read all interfaces. */
  158. for (currif = 0; currif < dev->config[i].descconf->numif; currif++)
  159. {
  160. while (pos < config.totallen)
  161. {
  162. desc = (struct grub_usb_desc *)&data[pos];
  163. if (desc->type == GRUB_USB_DESCRIPTOR_INTERFACE)
  164. break;
  165. if (!desc->length)
  166. {
  167. err = GRUB_USB_ERR_BADDEVICE;
  168. goto fail;
  169. }
  170. pos += desc->length;
  171. }
  172. dev->config[i].interf[currif].descif
  173. = (struct grub_usb_desc_if *) &data[pos];
  174. pos += dev->config[i].interf[currif].descif->length;
  175. while (pos < config.totallen)
  176. {
  177. desc = (struct grub_usb_desc *)&data[pos];
  178. if (desc->type == GRUB_USB_DESCRIPTOR_ENDPOINT)
  179. break;
  180. if (!desc->length)
  181. {
  182. err = GRUB_USB_ERR_BADDEVICE;
  183. goto fail;
  184. }
  185. pos += desc->length;
  186. }
  187. /* Point to the first endpoint. */
  188. dev->config[i].interf[currif].descendp
  189. = (struct grub_usb_desc_endp *) &data[pos];
  190. pos += (sizeof (struct grub_usb_desc_endp)
  191. * dev->config[i].interf[currif].descif->endpointcnt);
  192. }
  193. }
  194. return GRUB_USB_ERR_NONE;
  195. fail:
  196. for (i = 0; i < GRUB_USB_MAX_CONF; i++)
  197. grub_free (dev->config[i].descconf);
  198. return err;
  199. }
  200. void grub_usb_device_attach (grub_usb_device_t dev)
  201. {
  202. int i;
  203. /* XXX: Just check configuration 0 for now. */
  204. for (i = 0; i < dev->config[0].descconf->numif; i++)
  205. {
  206. struct grub_usb_desc_if *interf;
  207. struct grub_usb_attach_desc *desc;
  208. interf = dev->config[0].interf[i].descif;
  209. grub_dprintf ("usb", "iterate: interf=%d, class=%d, subclass=%d, protocol=%d\n",
  210. i, interf->class, interf->subclass, interf->protocol);
  211. if (dev->config[0].interf[i].attached)
  212. continue;
  213. for (desc = attach_hooks; desc; desc = desc->next)
  214. if (interf->class == desc->class)
  215. {
  216. grub_boot_time ("Probing USB device driver class %x", desc->class);
  217. if (desc->hook (dev, 0, i))
  218. dev->config[0].interf[i].attached = 1;
  219. grub_boot_time ("Probed USB device driver class %x", desc->class);
  220. }
  221. if (dev->config[0].interf[i].attached)
  222. continue;
  223. switch (interf->class)
  224. {
  225. case GRUB_USB_CLASS_MASS_STORAGE:
  226. grub_dl_load ("usbms");
  227. grub_print_error ();
  228. break;
  229. case GRUB_USB_CLASS_HID:
  230. grub_dl_load ("usb_keyboard");
  231. grub_print_error ();
  232. break;
  233. case 0xff:
  234. /* FIXME: don't load useless modules. */
  235. grub_dl_load ("usbserial_ftdi");
  236. grub_print_error ();
  237. grub_dl_load ("usbserial_pl2303");
  238. grub_print_error ();
  239. grub_dl_load ("usbserial_usbdebug");
  240. grub_print_error ();
  241. break;
  242. }
  243. }
  244. }
  245. /* Helper for grub_usb_register_attach_hook_class. */
  246. static int
  247. grub_usb_register_attach_hook_class_iter (grub_usb_device_t usbdev, void *data)
  248. {
  249. struct grub_usb_attach_desc *desc = data;
  250. struct grub_usb_desc_device *descdev = &usbdev->descdev;
  251. int i;
  252. if (descdev->class != 0 || descdev->subclass || descdev->protocol != 0
  253. || descdev->configcnt == 0)
  254. return 0;
  255. /* XXX: Just check configuration 0 for now. */
  256. for (i = 0; i < usbdev->config[0].descconf->numif; i++)
  257. {
  258. struct grub_usb_desc_if *interf;
  259. interf = usbdev->config[0].interf[i].descif;
  260. grub_dprintf ("usb", "iterate: interf=%d, class=%d, subclass=%d, protocol=%d\n",
  261. i, interf->class, interf->subclass, interf->protocol);
  262. if (usbdev->config[0].interf[i].attached)
  263. continue;
  264. if (interf->class != desc->class)
  265. continue;
  266. if (desc->hook (usbdev, 0, i))
  267. usbdev->config[0].interf[i].attached = 1;
  268. }
  269. return 0;
  270. }
  271. void
  272. grub_usb_register_attach_hook_class (struct grub_usb_attach_desc *desc)
  273. {
  274. desc->next = attach_hooks;
  275. attach_hooks = desc;
  276. grub_usb_iterate (grub_usb_register_attach_hook_class_iter, desc);
  277. }
  278. void
  279. grub_usb_unregister_attach_hook_class (struct grub_usb_attach_desc *desc)
  280. {
  281. grub_list_remove (GRUB_AS_LIST (desc));
  282. }
  283. GRUB_MOD_INIT(usb)
  284. {
  285. grub_term_poll_usb = grub_usb_poll_devices;
  286. }
  287. GRUB_MOD_FINI(usb)
  288. {
  289. grub_term_poll_usb = NULL;
  290. }