g_dnl.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * g_dnl.c -- USB Downloader Gadget
  4. *
  5. * Copyright (C) 2012 Samsung Electronics
  6. * Lukasz Majewski <l.majewski@samsung.com>
  7. */
  8. #include <common.h>
  9. #include <log.h>
  10. #include <malloc.h>
  11. #include <mmc.h>
  12. #include <part.h>
  13. #include <usb.h>
  14. #include <g_dnl.h>
  15. #include <usb_mass_storage.h>
  16. #include <dfu.h>
  17. #include <thor.h>
  18. #include <env_callback.h>
  19. #include "gadget_chips.h"
  20. #include "composite.c"
  21. /*
  22. * One needs to define the following:
  23. * CONFIG_USB_GADGET_VENDOR_NUM
  24. * CONFIG_USB_GADGET_PRODUCT_NUM
  25. * CONFIG_USB_GADGET_MANUFACTURER
  26. * at e.g. ./configs/<board>_defconfig
  27. */
  28. #define STRING_MANUFACTURER 25
  29. #define STRING_PRODUCT 2
  30. /* Index of String Descriptor describing this configuration */
  31. #define STRING_USBDOWN 2
  32. /* Index of String serial */
  33. #define STRING_SERIAL 3
  34. #define MAX_STRING_SERIAL 256
  35. /* Number of supported configurations */
  36. #define CONFIGURATION_NUMBER 1
  37. #define DRIVER_VERSION "usb_dnl 2.0"
  38. static const char product[] = "USB download gadget";
  39. static char g_dnl_serial[MAX_STRING_SERIAL];
  40. static const char manufacturer[] = CONFIG_USB_GADGET_MANUFACTURER;
  41. void g_dnl_set_serialnumber(char *s)
  42. {
  43. memset(g_dnl_serial, 0, MAX_STRING_SERIAL);
  44. strncpy(g_dnl_serial, s, MAX_STRING_SERIAL - 1);
  45. }
  46. static struct usb_device_descriptor device_desc = {
  47. .bLength = sizeof device_desc,
  48. .bDescriptorType = USB_DT_DEVICE,
  49. .bcdUSB = __constant_cpu_to_le16(0x0200),
  50. .bDeviceClass = USB_CLASS_PER_INTERFACE,
  51. .bDeviceSubClass = 0, /*0x02:CDC-modem , 0x00:CDC-serial*/
  52. .idVendor = __constant_cpu_to_le16(CONFIG_USB_GADGET_VENDOR_NUM),
  53. .idProduct = __constant_cpu_to_le16(CONFIG_USB_GADGET_PRODUCT_NUM),
  54. /* .iProduct = DYNAMIC */
  55. /* .iSerialNumber = DYNAMIC */
  56. .bNumConfigurations = 1,
  57. };
  58. /*
  59. * static strings, in UTF-8
  60. * IDs for those strings are assigned dynamically at g_dnl_bind()
  61. */
  62. static struct usb_string g_dnl_string_defs[] = {
  63. {.s = manufacturer},
  64. {.s = product},
  65. {.s = g_dnl_serial},
  66. { } /* end of list */
  67. };
  68. static struct usb_gadget_strings g_dnl_string_tab = {
  69. .language = 0x0409, /* en-us */
  70. .strings = g_dnl_string_defs,
  71. };
  72. static struct usb_gadget_strings *g_dnl_composite_strings[] = {
  73. &g_dnl_string_tab,
  74. NULL,
  75. };
  76. void g_dnl_set_product(const char *s)
  77. {
  78. if (s)
  79. g_dnl_string_defs[1].s = s;
  80. else
  81. g_dnl_string_defs[1].s = product;
  82. }
  83. static int g_dnl_unbind(struct usb_composite_dev *cdev)
  84. {
  85. struct usb_gadget *gadget = cdev->gadget;
  86. debug("%s: calling usb_gadget_disconnect for "
  87. "controller '%s'\n", __func__, gadget->name);
  88. usb_gadget_disconnect(gadget);
  89. return 0;
  90. }
  91. static inline struct g_dnl_bind_callback *g_dnl_bind_callback_first(void)
  92. {
  93. return ll_entry_start(struct g_dnl_bind_callback,
  94. g_dnl_bind_callbacks);
  95. }
  96. static inline struct g_dnl_bind_callback *g_dnl_bind_callback_end(void)
  97. {
  98. return ll_entry_end(struct g_dnl_bind_callback,
  99. g_dnl_bind_callbacks);
  100. }
  101. static int g_dnl_do_config(struct usb_configuration *c)
  102. {
  103. const char *s = c->cdev->driver->name;
  104. struct g_dnl_bind_callback *callback = g_dnl_bind_callback_first();
  105. debug("%s: configuration: 0x%p composite dev: 0x%p\n",
  106. __func__, c, c->cdev);
  107. for (; callback != g_dnl_bind_callback_end(); callback++)
  108. if (!strcmp(s, callback->usb_function_name))
  109. return callback->fptr(c);
  110. return -ENODEV;
  111. }
  112. static int g_dnl_config_register(struct usb_composite_dev *cdev)
  113. {
  114. struct usb_configuration *config;
  115. const char *name = "usb_dnload";
  116. config = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*config));
  117. if (!config)
  118. return -ENOMEM;
  119. memset(config, 0, sizeof(*config));
  120. config->label = name;
  121. config->bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER;
  122. config->bConfigurationValue = CONFIGURATION_NUMBER;
  123. config->iConfiguration = STRING_USBDOWN;
  124. config->bind = g_dnl_do_config;
  125. return usb_add_config(cdev, config);
  126. }
  127. __weak
  128. int board_usb_init(int index, enum usb_init_type init)
  129. {
  130. return 0;
  131. }
  132. __weak
  133. int board_usb_cleanup(int index, enum usb_init_type init)
  134. {
  135. return 0;
  136. }
  137. __weak
  138. int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name)
  139. {
  140. return 0;
  141. }
  142. __weak int g_dnl_get_board_bcd_device_number(int gcnum)
  143. {
  144. return gcnum;
  145. }
  146. __weak int g_dnl_board_usb_cable_connected(void)
  147. {
  148. return -EOPNOTSUPP;
  149. }
  150. static bool g_dnl_detach_request;
  151. bool g_dnl_detach(void)
  152. {
  153. return g_dnl_detach_request;
  154. }
  155. void g_dnl_trigger_detach(void)
  156. {
  157. g_dnl_detach_request = true;
  158. }
  159. void g_dnl_clear_detach(void)
  160. {
  161. g_dnl_detach_request = false;
  162. }
  163. static int g_dnl_get_bcd_device_number(struct usb_composite_dev *cdev)
  164. {
  165. struct usb_gadget *gadget = cdev->gadget;
  166. int gcnum;
  167. gcnum = usb_gadget_controller_number(gadget);
  168. if (gcnum > 0)
  169. gcnum += 0x200;
  170. return g_dnl_get_board_bcd_device_number(gcnum);
  171. }
  172. /**
  173. * Update internal serial number variable when the "serial#" env var changes.
  174. *
  175. * Handle all cases, even when flags == H_PROGRAMMATIC or op == env_op_delete.
  176. */
  177. static int on_serialno(const char *name, const char *value, enum env_op op,
  178. int flags)
  179. {
  180. g_dnl_set_serialnumber((char *)value);
  181. return 0;
  182. }
  183. U_BOOT_ENV_CALLBACK(serialno, on_serialno);
  184. static int g_dnl_bind(struct usb_composite_dev *cdev)
  185. {
  186. struct usb_gadget *gadget = cdev->gadget;
  187. int id, ret;
  188. int gcnum;
  189. debug("%s: gadget: 0x%p cdev: 0x%p\n", __func__, gadget, cdev);
  190. id = usb_string_id(cdev);
  191. if (id < 0)
  192. return id;
  193. g_dnl_string_defs[0].id = id;
  194. device_desc.iManufacturer = id;
  195. id = usb_string_id(cdev);
  196. if (id < 0)
  197. return id;
  198. g_dnl_string_defs[1].id = id;
  199. device_desc.iProduct = id;
  200. g_dnl_bind_fixup(&device_desc, cdev->driver->name);
  201. if (strlen(g_dnl_serial)) {
  202. id = usb_string_id(cdev);
  203. if (id < 0)
  204. return id;
  205. g_dnl_string_defs[2].id = id;
  206. device_desc.iSerialNumber = id;
  207. }
  208. ret = g_dnl_config_register(cdev);
  209. if (ret)
  210. goto error;
  211. gcnum = g_dnl_get_bcd_device_number(cdev);
  212. if (gcnum >= 0)
  213. device_desc.bcdDevice = cpu_to_le16(gcnum);
  214. else {
  215. debug("%s: controller '%s' not recognized\n",
  216. __func__, gadget->name);
  217. device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
  218. }
  219. debug("%s: calling usb_gadget_connect for "
  220. "controller '%s'\n", __func__, gadget->name);
  221. usb_gadget_connect(gadget);
  222. return 0;
  223. error:
  224. g_dnl_unbind(cdev);
  225. return -ENOMEM;
  226. }
  227. static struct usb_composite_driver g_dnl_driver = {
  228. .name = NULL,
  229. .dev = &device_desc,
  230. .strings = g_dnl_composite_strings,
  231. .max_speed = USB_SPEED_SUPER,
  232. .bind = g_dnl_bind,
  233. .unbind = g_dnl_unbind,
  234. };
  235. /*
  236. * NOTICE:
  237. * Registering via USB function name won't be necessary after rewriting
  238. * g_dnl to support multiple USB functions.
  239. */
  240. int g_dnl_register(const char *name)
  241. {
  242. int ret;
  243. debug("%s: g_dnl_driver.name = %s\n", __func__, name);
  244. g_dnl_driver.name = name;
  245. ret = usb_composite_register(&g_dnl_driver);
  246. if (ret) {
  247. printf("%s: failed!, error: %d\n", __func__, ret);
  248. return ret;
  249. }
  250. return 0;
  251. }
  252. void g_dnl_unregister(void)
  253. {
  254. usb_composite_unregister(&g_dnl_driver);
  255. }