smdk-dltool-0.20-libusb-1.0-r1.patch 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. migrate to libusb-1 by me (Mike Frysinger)
  2. workaround kernel/libusb transfer sizes by Julius Werner
  3. --- a/Makefile
  4. +++ b/Makefile
  5. @@ -10,8 +10,8 @@
  6. CFLAGS ?= -O2 -g
  7. CFLAGS += -Wall
  8. PKG_CONFIG ?= pkg-config
  9. -CPPFLAGS += $(shell $(PKG_CONFIG) --cflags libusb)
  10. -LDLIBS = $(shell $(PKG_CONFIG) --libs libusb)
  11. +CPPFLAGS += $(shell $(PKG_CONFIG) --cflags libusb-1.0)
  12. +LDLIBS = $(shell $(PKG_CONFIG) --libs libusb-1.0)
  13. all: dltool
  14. --- a/dltool.c
  15. +++ b/dltool.c
  16. @@ -7,15 +7,25 @@
  17. #include <sys/types.h>
  18. #include <sys/stat.h>
  19. +#include <sys/param.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <stdio.h>
  23. #include <getopt.h>
  24. #include <fcntl.h>
  25. +#include <errno.h>
  26. +#include <unistd.h>
  27. -#include <usb.h>
  28. +#include <libusb.h>
  29. +
  30. +/* The kernel USB layer is restrictive in the max size in a single URB.
  31. + * When we exceed that, the kernel throws ENOMEM, but the libusb layer
  32. + * doesn't handle things gracefully. So manually split up into chunks
  33. + * ourselves so we can avoid that failure case.
  34. + */
  35. +#define CHUNKSIZE (1 << 18)
  36. unsigned int debug = 0;
  37. unsigned long dl_addr = 0x30000000L;
  38. @@ -23,12 +33,22 @@ unsigned long dl_size = 0L;
  39. unsigned char *dl_data = NULL;
  40. char *dl_file = "download.dat";
  41. -char *dl_udev = NULL;
  42. -char *dl_ubus = NULL;
  43. +libusb_context *ctx = NULL;
  44. +libusb_device_handle *devh = NULL;
  45. int ep_out = 0;
  46. #define DBG(x) if (debug) { printf x; }
  47. +#define err(fmt, args...) \
  48. + do { \
  49. + if (devh) \
  50. + libusb_close(devh); \
  51. + if (ctx) \
  52. + libusb_exit(ctx); \
  53. + fprintf(stderr, "dltool: " fmt "\n", ## args); \
  54. + exit(1); \
  55. + } while (0)
  56. +#define errp(fmt, args...) err(fmt ": %s", ## args, strerror(errno))
  57. void write_u32(unsigned char *dp, unsigned long val)
  58. {
  59. @@ -108,25 +128,30 @@ void calc_cksum(unsigned char *data, ssize_t len)
  60. cp[1] = cksum >> 8;
  61. }
  62. -int verify_device(struct usb_device *dev)
  63. +int verify_device(libusb_device *dev)
  64. {
  65. + struct libusb_device_descriptor desc;
  66. +
  67. + if (libusb_get_device_descriptor(dev, &desc))
  68. + return 0;
  69. +
  70. DBG(("dev %p: configurations %d\n",
  71. - dev, dev->descriptor.bNumConfigurations));
  72. + dev, desc.bNumConfigurations));
  73. - if (dev->descriptor.bNumConfigurations != 1)
  74. + if (desc.bNumConfigurations != 1)
  75. return 0;
  76. - DBG(("\t=> bLength %d\n", dev->descriptor.bLength));
  77. - DBG(("\t=> bType %d\n", dev->descriptor.bDescriptorType));
  78. - DBG(("\t=> bcdUSB %x\n", dev->descriptor.bcdUSB));
  79. - DBG(("\t=> idVendor %x\n", dev->descriptor.idVendor));
  80. - DBG(("\t=> idProduct %x\n", dev->descriptor.idProduct));
  81. + DBG(("\t=> bLength %d\n", desc.bLength));
  82. + DBG(("\t=> bType %d\n", desc.bDescriptorType));
  83. + DBG(("\t=> bcdUSB %x\n", desc.bcdUSB));
  84. + DBG(("\t=> idVendor %x\n", desc.idVendor));
  85. + DBG(("\t=> idProduct %x\n", desc.idProduct));
  86. - if (dev->descriptor.idVendor == 0x5345 && dev->descriptor.idProduct == 0x1234) {
  87. + if (desc.idVendor == 0x5345 && desc.idProduct == 0x1234) {
  88. ep_out = 3;
  89. return 1;
  90. }
  91. - else if(dev->descriptor.idVendor == 0x4e8 && dev->descriptor.idProduct == 0x1234){
  92. + else if(desc.idVendor == 0x4e8 && desc.idProduct == 0x1234){
  93. printf("S3C64XX Detected!\n");
  94. ep_out = 2;
  95. return 1;
  96. @@ -173,6 +198,12 @@ struct option long_opts[] = {
  97. .val = 'x',
  98. },
  99. {
  100. + .name = "help",
  101. + .has_arg = 0,
  102. + .flag = NULL,
  103. + .val = 'h',
  104. + },
  105. + {
  106. .name = NULL
  107. }
  108. };
  109. @@ -181,12 +212,14 @@ int flg_show = 0;
  110. int main(int argc, char **argv)
  111. {
  112. - struct usb_bus *bus, *busp;
  113. - struct usb_device *result = NULL;
  114. - struct usb_device *found = NULL;
  115. + ssize_t num_devs, i;
  116. + libusb_device **list;
  117. + libusb_device *found;
  118. + int dl_ubus = -1;
  119. + int dl_udev = -1;
  120. + uint8_t bus_num, dev_num;
  121. unsigned long fsize;
  122. - usb_dev_handle *devh;
  123. - int ret;
  124. + int ret, transferred;
  125. printf("SMDK42XX,S3C64XX USB Download Tool\n");
  126. printf("Version 0.20 (c) 2004,2005,2006"
  127. @@ -197,7 +230,7 @@ int main(int argc, char **argv)
  128. int index = 0;
  129. int c;
  130. - c = getopt_long(argc, argv, "a:b:d:f:s", long_opts, &index);
  131. + c = getopt_long(argc, argv, "a:b:d:f:shx", long_opts, &index);
  132. DBG(("option index %d\n",c ));
  133. @@ -218,117 +251,134 @@ int main(int argc, char **argv)
  134. break;
  135. case 'b':
  136. - dl_ubus = optarg;
  137. + dl_ubus = atoi(optarg);
  138. break;
  139. case 'd':
  140. - dl_udev = optarg;
  141. + dl_udev = atoi(optarg);
  142. break;
  143. case 'x':
  144. debug = 1;
  145. + break;
  146. +
  147. + case 'h':
  148. + puts(
  149. + "Usage: dltool [options]\n"
  150. + "\n"
  151. + "-a <download addr>\n"
  152. + "-b <bus #>\n"
  153. + "-d <dev #>\n"
  154. + "-f <file>\n"
  155. + "-s Show found devices\n"
  156. + "-x Enable debug\n"
  157. + );
  158. + return 0;
  159. }
  160. }
  161. - usb_init();
  162. - usb_find_busses();
  163. - usb_find_devices();
  164. -
  165. - bus = usb_get_busses();
  166. -
  167. - DBG(("usb_get_busses: %p\n", bus));
  168. -
  169. - for (busp = bus; busp != NULL; busp = busp->next) {
  170. - struct usb_device *dev;
  171. -
  172. - DBG(("bus %p: dirname %s\n", busp, busp->dirname));
  173. -
  174. - if (dl_ubus) {
  175. - if (strcmp(busp->dirname, dl_ubus) != 0)
  176. - continue;
  177. - }
  178. + ret = libusb_init(&ctx);
  179. + if (ret)
  180. + errp("could not initialize usb stack");
  181. - for (dev = busp->devices; dev != NULL; dev = dev->next) {
  182. - DBG(("dev %p filename %s\n", dev, dev->filename));
  183. + bus_num = dev_num = 0;
  184. + found = NULL;
  185. + num_devs = libusb_get_device_list(ctx, &list);
  186. + for (i = 0; i < num_devs; ++i) {
  187. + libusb_device *dev = list[i];
  188. + bus_num = libusb_get_bus_number(dev);
  189. + dev_num = libusb_get_device_address(dev);
  190. - if (!verify_device(dev))
  191. - continue;
  192. + DBG(("bus %u; dev %u (%p)\n", bus_num, dev_num, dev));
  193. - if (flg_show) {
  194. - printf("bus %s: device %s\n",
  195. - busp->dirname, dev->filename);
  196. - continue;
  197. - }
  198. + if (dl_ubus >= 0 && bus_num != dl_ubus)
  199. + continue;
  200. - found = dev;
  201. + if (!verify_device(dev))
  202. + continue;
  203. - if (dl_udev) {
  204. - if (strcmp(dev->filename, dl_udev) == 0) {
  205. - result = dev;
  206. - break;
  207. - }
  208. - }
  209. + if (flg_show) {
  210. + printf("bus %u: device %u\n", bus_num, dev_num);
  211. + continue;
  212. }
  213. - if (result != NULL)
  214. - break;
  215. + if (dl_udev >= 0 && dev_num != dl_udev)
  216. + continue;
  217. +
  218. + found = dev;
  219. + break;
  220. }
  221. if (flg_show)
  222. return 0;
  223. - DBG(("device %p, found %p\n", result, found));
  224. + DBG(("found %p\n", found));
  225. - if (result == NULL && found != NULL)
  226. - result = found;
  227. -
  228. - if (result == NULL) {
  229. - fprintf(stderr, "failed to find device\n");
  230. - return 1;
  231. - }
  232. + if (found == NULL)
  233. + err("failed to find device\n");
  234. - printf("=> found device: bus %s, dev %s\n",
  235. - result->bus->dirname, result->filename);
  236. + printf("=> found device: bus %u, dev %u\n",
  237. + bus_num, dev_num);
  238. dl_data = load_file(dl_file, &dl_size, &fsize);
  239. - if (dl_data == NULL) {
  240. - printf("failed to load %s\n", dl_file);
  241. - return 1;
  242. - }
  243. + if (dl_data == NULL)
  244. + errp("failed to load %s", dl_file);
  245. printf("=> loaded %ld bytes from %s\n", fsize, dl_file);
  246. - devh = usb_open(result);
  247. - if (devh == NULL) {
  248. - perror("usb_open");
  249. - return 1;
  250. - }
  251. + ret = libusb_open(found, &devh);
  252. + if (ret == 0) {
  253. + /*
  254. + * Seems to break some recovery modes :(
  255. + * http://crosbug.com/26083
  256. + * These fail:
  257. + * smdk-dltool -a 0x02021400 -f bl1.bin
  258. + * smdk-dltool -a 0x02023400 -f bl2.bin
  259. + */
  260. +#if 0
  261. + uint8_t configuration;
  262. + struct libusb_config_descriptor *config;
  263. + libusb_get_active_config_descriptor(found, &config);
  264. + configuration = config->bConfigurationValue;
  265. + libusb_free_config_descriptor(config);
  266. + libusb_set_configuration(devh, configuration);
  267. +#endif
  268. + } else
  269. + errp("libusb_open");
  270. DBG(("claim interface\n"));
  271. - if (usb_claim_interface(devh, 0) < 0) {
  272. - perror("usb_claim_interface");
  273. - usb_close(devh);
  274. - return 1;
  275. - }
  276. + ret = libusb_claim_interface(devh, 0);
  277. + if (ret)
  278. + errp("libusb_claim_interface");
  279. printf("=> Downloading %ld bytes to 0x%08lx\n", dl_size, dl_addr);
  280. write_header(dl_data, dl_addr, dl_size);
  281. calc_cksum(dl_data, dl_size);
  282. - //ret = usb_bulk_write(devh, 3, (void *)dl_data, dl_size, 5*1000*1000);
  283. - ret = usb_bulk_write(devh, ep_out, (void *)dl_data, dl_size, 5*1000*1000);
  284. - printf("=> usb_bulk_write() returned %d\n", ret);
  285. -
  286. - if (ret != dl_size) {
  287. - printf("failed to write %ld bytes\n", dl_size);
  288. + transferred = 0;
  289. + while (transferred < dl_size) {
  290. + int actual, expected = MIN(dl_size - transferred, CHUNKSIZE);
  291. + ret = libusb_bulk_transfer(devh, ep_out, dl_data + transferred,
  292. + expected, &actual, 5 * 1000 * 1000);
  293. + printf("=> usb_bulk_write(%d) returned %d, wrote %d\n",
  294. + expected, ret, actual);
  295. + transferred += actual;
  296. +
  297. + if (ret || (expected != actual)) {
  298. + printf("failed to write %ld bytes (wrote %d): %s\n",
  299. + dl_size, transferred, strerror(errno));
  300. + ret = 1;
  301. + break;
  302. + }
  303. }
  304. free(dl_data);
  305. - usb_release_interface(devh, 0);
  306. - usb_close(devh);
  307. + libusb_release_interface(devh, 0);
  308. + libusb_close(devh);
  309. + libusb_exit(ctx);
  310. - return 0;
  311. + return ret;
  312. }