snesuploader.c 9.0 KB

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