snesuploader.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. /*
  2. * =====================================================================================
  3. *
  4. * ________ .__ __ ________ ____ ________
  5. * \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
  6. * / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
  7. * / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
  8. * \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
  9. * \__> \/ \/ \/ \/ \/
  10. *
  11. * www.optixx.org
  12. *
  13. *
  14. * Version: 1.0
  15. * Created: 07/21/2009 03:32:16 PM
  16. * Author: david@optixx.org
  17. * Based on: custom-class, a basic USB example
  18. * Author: Christian Starkjohann
  19. * =====================================================================================
  20. */
  21. #define BANK_SIZE_SHIFT 15
  22. #define BANK_SIZE (1<<BANK_SIZE_SHIFT)
  23. #define READ_BUFFER_SIZE (1<<BANK_SIZE_SHIFT)
  24. #define SEND_BUFFER_SIZE 128
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <stdint.h>
  28. #include <string.h>
  29. #include <sys/stat.h>
  30. #include <usb.h> /* this is libusb */
  31. #include "opendevice.h" /* common code moved to separate module */
  32. #include "../requests.h" /* custom request numbers */
  33. #include "../usbconfig.h" /* device's VID/PID and names */
  34. void dump_packet(uint32_t addr, uint32_t len, uint8_t * packet)
  35. {
  36. uint16_t i,
  37. j;
  38. uint16_t sum = 0;
  39. uint8_t clear = 0;
  40. for (i = 0; i < len; i += 16) {
  41. sum = 0;
  42. for (j = 0; j < 16; j++) {
  43. sum += packet[i + j];
  44. }
  45. if (!sum) {
  46. clear = 1;
  47. continue;
  48. }
  49. if (clear) {
  50. printf("*\n");
  51. clear = 0;
  52. }
  53. printf("%08x:", addr + i);
  54. for (j = 0; j < 16; j++) {
  55. printf(" %02x", packet[i + j]);
  56. }
  57. printf(" |");
  58. for (j = 0; j < 16; j++) {
  59. if (packet[i + j] >= 33 && packet[i + j] <= 126)
  60. printf("%c", packet[i + j]);
  61. else
  62. printf(".");
  63. }
  64. printf("|\n");
  65. }
  66. }
  67. uint16_t crc_xmodem_update(uint16_t crc, uint8_t data)
  68. {
  69. int i;
  70. crc = crc ^ ((uint16_t) data << 8);
  71. for (i = 0; i < 8; i++) {
  72. if (crc & 0x8000)
  73. crc = (crc << 1) ^ 0x1021;
  74. else
  75. crc <<= 1;
  76. }
  77. return crc;
  78. }
  79. uint16_t do_crc(uint8_t * data, uint16_t size)
  80. {
  81. uint16_t crc = 0;
  82. uint16_t i;
  83. for (i = 0; i < size; i++) {
  84. crc = crc_xmodem_update(crc, data[i]);
  85. }
  86. return crc;
  87. }
  88. uint16_t do_crc_update(uint16_t crc, uint8_t * data, uint16_t size)
  89. {
  90. uint16_t i;
  91. for (i = 0; i < size; i++)
  92. crc = crc_xmodem_update(crc, data[i]);
  93. return crc;
  94. }
  95. static void usage(char *name)
  96. {
  97. fprintf(stderr, "usage:\n");
  98. fprintf(stderr, " %s upload filename.. upload\n", name);
  99. }
  100. int main(int argc, char **argv)
  101. {
  102. usb_dev_handle *handle = NULL;
  103. const unsigned char rawVid[2] = { USB_CFG_VENDOR_ID }, rawPid[2] = {
  104. USB_CFG_DEVICE_ID};
  105. char vendor[] = { USB_CFG_VENDOR_NAME, 0 }, product[] = {
  106. USB_CFG_DEVICE_NAME, 0};
  107. int cnt, vid, pid;
  108. uint8_t *read_buffer;
  109. uint8_t *crc_buffer;
  110. uint8_t *ptr;
  111. uint32_t addr = 0;
  112. uint16_t addr_lo = 0;
  113. uint16_t addr_hi = 0;
  114. uint32_t step = 0;
  115. uint16_t crc = 0;
  116. uint8_t bank = 0;
  117. uint8_t bank_cnt = 0;
  118. uint32_t file_size = 0;
  119. uint32_t file_offset = 0;
  120. FILE *fp;
  121. usb_init();
  122. if (argc < 2) { /* we need at least one argument */
  123. usage(argv[0]);
  124. exit(1);
  125. }
  126. /*
  127. * compute VID/PID from usbconfig.h so that there is a central source
  128. * of information
  129. */
  130. vid = rawVid[1] * 256 + rawVid[0];
  131. pid = rawPid[1] * 256 + rawPid[0];
  132. /*
  133. * The following function is in opendevice.c:
  134. */
  135. if (usbOpenDevice(&handle, vid, vendor, pid, product, NULL, NULL, NULL) !=
  136. 0) {
  137. fprintf(stderr,
  138. "Could not find USB device \"%s\" with vid=0x%x pid=0x%x\n",
  139. product, vid, pid);
  140. exit(1);
  141. }
  142. printf("Open USB device \"%s\" with vid=0x%x pid=0x%x\n", product, vid,
  143. pid);
  144. if (strcasecmp(argv[1], "upload") == 0) {
  145. if (argc < 3) { /* we need at least one argument */
  146. usage(argv[0]);
  147. exit(1);
  148. }
  149. fp = fopen(argv[2], "r");
  150. if (fp == NULL) {
  151. fprintf(stderr, "Cannot open file %s ", argv[2]);
  152. exit(1);
  153. }
  154. fseek (fp, 0, SEEK_END);
  155. file_size = ftell (fp);
  156. file_offset = 512;
  157. if (strstr(argv[2],".smc") || strstr(argv[2],".swc")){
  158. printf("Skip 512 Byte header\n");
  159. file_size -= 512;
  160. fseek (fp, 512, SEEK_SET);
  161. } else {
  162. fseek (fp, 0, SEEK_SET);
  163. }
  164. bank_cnt = file_size / BANK_SIZE;
  165. printf("Transfer '%s' %i Bytes, %i Banks\n",argv[2],file_size,bank_cnt);
  166. read_buffer = (unsigned char *) malloc(READ_BUFFER_SIZE);
  167. crc_buffer = (unsigned char *) malloc(0x1000);
  168. memset(crc_buffer, 0, 0x1000);
  169. addr = 0x000000;
  170. cnt = usb_control_msg(handle,
  171. USB_TYPE_VENDOR | USB_RECIP_DEVICE |
  172. USB_ENDPOINT_OUT, USB_MODE_AVR, 0, 0, NULL,
  173. 0, 5000);
  174. cnt = usb_control_msg(handle,
  175. USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT,
  176. USB_BULK_UPLOAD_INIT, BANK_SIZE_SHIFT , bank_cnt, NULL, 0, 5000);
  177. if (cnt < 0) {
  178. fprintf(stderr, "USB error: %s\n", usb_strerror());
  179. usb_close(handle);
  180. exit(-1);
  181. }
  182. ptr = crc_buffer;
  183. while ((cnt = fread(read_buffer, READ_BUFFER_SIZE, 1, fp)) > 0) {
  184. ptr = crc_buffer;
  185. for (step = 0; step < READ_BUFFER_SIZE; step += SEND_BUFFER_SIZE) {
  186. addr_lo = addr & 0xffff;
  187. addr_hi = (addr >> 16) & 0x00ff;
  188. if (addr == 0x000000){
  189. cnt = usb_control_msg(handle,
  190. USB_TYPE_VENDOR | USB_RECIP_DEVICE |
  191. USB_ENDPOINT_OUT, USB_BULK_UPLOAD_ADDR, addr_hi,
  192. addr_lo, (char *) read_buffer + step,
  193. SEND_BUFFER_SIZE, 5000);
  194. } else {
  195. cnt = usb_control_msg(handle,
  196. USB_TYPE_VENDOR | USB_RECIP_DEVICE |
  197. USB_ENDPOINT_OUT, USB_BULK_UPLOAD_NEXT, addr_hi,
  198. addr_lo, (char *) read_buffer + step,
  199. SEND_BUFFER_SIZE, 5000);
  200. }
  201. if (cnt < 0) {
  202. fprintf(stderr, "USB error: %s\n", usb_strerror());
  203. usb_close(handle);
  204. exit(-1);
  205. }
  206. memcpy(ptr, read_buffer + step, SEND_BUFFER_SIZE);
  207. addr += SEND_BUFFER_SIZE;
  208. ptr += SEND_BUFFER_SIZE;
  209. if ( addr % BANK_SIZE == 0){
  210. crc = do_crc(crc_buffer, 0x1000);
  211. printf ("bank=0x%02x addr=0x%08x addr=0x%08x crc=0x%04x\n", bank, addr - 0x1000, addr, crc);
  212. ptr = crc_buffer;
  213. if ( addr % BANK_SIZE == 0) {
  214. bank++;
  215. }
  216. }
  217. }
  218. }
  219. bank = 0;
  220. cnt = usb_control_msg(handle,
  221. USB_TYPE_VENDOR | USB_RECIP_DEVICE |
  222. USB_ENDPOINT_OUT, USB_BULK_UPLOAD_END, 0, 0, NULL,
  223. 0, 5000);
  224. fseek(fp, file_offset, SEEK_SET);
  225. while ((cnt = fread(read_buffer, READ_BUFFER_SIZE, 1, fp)) > 0) {
  226. printf ("bank=0x%02x crc=0x%04x\n", bank++,
  227. do_crc(read_buffer, READ_BUFFER_SIZE));
  228. }
  229. fclose(fp);
  230. cnt = usb_control_msg(handle,
  231. USB_TYPE_VENDOR | USB_RECIP_DEVICE |
  232. USB_ENDPOINT_OUT, USB_MODE_SNES, 0, 0, NULL,
  233. 0, 5000);
  234. if (cnt < 1) {
  235. if (cnt < 0) {
  236. fprintf(stderr, "USB error: %s\n", usb_strerror());
  237. } else {
  238. fprintf(stderr, "only %d bytes received.\n", cnt);
  239. }
  240. }
  241. } else if (strcasecmp(argv[1], "crc") == 0) {
  242. /*
  243. * if(argc < 2){ usage(argv[0]); exit(1); }
  244. */
  245. addr = 0x000000;
  246. addr_lo = addr & 0xffff;
  247. addr_hi = (addr >> 16) & 0xff;
  248. printf("Request CRC for Addr: 0x%06x\n", addr);
  249. cnt = usb_control_msg(handle,
  250. USB_TYPE_VENDOR | USB_RECIP_DEVICE |
  251. USB_ENDPOINT_OUT, USB_CRC_ADDR, addr_hi, addr_lo,
  252. NULL, (1 << 15) / 4, 5000);
  253. if (cnt < 1) {
  254. if (cnt < 0) {
  255. fprintf(stderr, "USB error: %s\n", usb_strerror());
  256. } else {
  257. fprintf(stderr, "only %d bytes received.\n", cnt);
  258. }
  259. }
  260. } else {
  261. usage(argv[0]);
  262. exit(1);
  263. }
  264. usb_close(handle);
  265. return 0;
  266. }