minipro.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. #include <libusb.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #ifdef __APPLE__
  5. #include <stdio.h>
  6. #else
  7. #include <malloc.h>
  8. #endif
  9. #include "minipro.h"
  10. #include "byte_utils.h"
  11. #include "error.h"
  12. minipro_handle_t *minipro_open(device_t *device) {
  13. int ret;
  14. minipro_handle_t *handle = malloc(sizeof(minipro_handle_t));
  15. if(handle == NULL) {
  16. ERROR("Couldn't malloc");
  17. }
  18. ret = libusb_init(&(handle->ctx));
  19. if(ret < 0) {
  20. free(handle);
  21. ERROR2("Error initializing libusb: %s", libusb_strerror(ret));
  22. }
  23. handle->usb_handle = libusb_open_device_with_vid_pid(handle->ctx, 0x04d8, 0xe11c);
  24. if(handle->usb_handle == NULL) {
  25. free(handle);
  26. ERROR("Error opening device");
  27. }
  28. handle->device = device;
  29. return(handle);
  30. }
  31. void minipro_close(minipro_handle_t *handle) {
  32. libusb_close(handle->usb_handle);
  33. free(handle);
  34. }
  35. unsigned char msg[MAX_WRITE_BUFFER_SIZE];
  36. static void msg_init(unsigned char *out_buf, unsigned char cmd, device_t *device, int icsp) {
  37. out_buf[0] = cmd;
  38. out_buf[1] = device->protocol_id;
  39. out_buf[2] = device->variant;
  40. out_buf[3] = 0x00;
  41. out_buf[4] = device->data_memory_size >> 8 & 0xFF;
  42. format_int(&(out_buf[5]), device->opts1, 2, MP_LITTLE_ENDIAN);
  43. out_buf[8] = out_buf[6];
  44. format_int(&(out_buf[6]), device->opts2, 2, MP_LITTLE_ENDIAN);
  45. format_int(&(out_buf[9]), device->opts3, 2, MP_LITTLE_ENDIAN);
  46. out_buf[11] = icsp;
  47. format_int(&(out_buf[12]), device->code_memory_size, 2, MP_LITTLE_ENDIAN);
  48. }
  49. static unsigned int msg_transfer(minipro_handle_t *handle, unsigned char *buf, int length, int direction) {
  50. int bytes_transferred;
  51. int ret;
  52. ret = libusb_claim_interface(handle->usb_handle, 0);
  53. if(ret != 0) ERROR2("IO error: claim_interface: %s\n", libusb_strerror(ret));
  54. ret = libusb_bulk_transfer(handle->usb_handle, (1 | direction), buf, length, &bytes_transferred, 0);
  55. if(ret != 0) ERROR2("IO error: bulk_transfer: %s\n", libusb_strerror(ret));
  56. ret = libusb_release_interface(handle->usb_handle, 0);
  57. if(ret != 0) ERROR2("IO error: release_interface: %s\n", libusb_strerror(ret));
  58. if(bytes_transferred != length) ERROR2("IO error: expected %d bytes but %d bytes transferred\n", length, bytes_transferred);
  59. return bytes_transferred;
  60. }
  61. #ifndef TEST
  62. static unsigned int msg_send(minipro_handle_t *handle, unsigned char *buf, int length) {
  63. return msg_transfer(handle, buf, length, LIBUSB_ENDPOINT_OUT);
  64. }
  65. static unsigned int msg_recv(minipro_handle_t *handle, unsigned char *buf, int length) {
  66. return msg_transfer(handle, buf, length, LIBUSB_ENDPOINT_IN);
  67. }
  68. #endif
  69. void minipro_begin_transaction(minipro_handle_t *handle) {
  70. memset(msg, 0, sizeof(msg));
  71. msg_init(msg, MP_REQUEST_STATUS1_MSG1, handle->device, handle->icsp);
  72. msg_send(handle, msg, 48);
  73. }
  74. void minipro_end_transaction(minipro_handle_t *handle) {
  75. msg_init(msg, 0x04, handle->device, handle->icsp);
  76. msg[3] = 0x00;
  77. msg_send(handle, msg, 4);
  78. }
  79. void minipro_protect_off(minipro_handle_t *handle) {
  80. memset(msg, 0, sizeof(msg));
  81. msg_init(msg, MP_PROTECT_OFF, handle->device, handle->icsp);
  82. msg_send(handle, msg, 10);
  83. }
  84. void minipro_protect_on(minipro_handle_t *handle) {
  85. memset(msg, 0, sizeof(msg));
  86. msg_init(msg, MP_PROTECT_ON, handle->device, handle->icsp);
  87. msg_send(handle, msg, 10);
  88. }
  89. int minipro_get_status(minipro_handle_t *handle) {
  90. unsigned char buf[32];
  91. msg_init(msg, MP_REQUEST_STATUS1_MSG2, handle->device, handle->icsp);
  92. msg_send(handle, msg, 5);
  93. msg_recv(handle, buf, 32);
  94. if(buf[9] != 0) {
  95. ERROR("Overcurrency protection");
  96. }
  97. return(load_int(buf, 2, MP_LITTLE_ENDIAN));
  98. }
  99. void minipro_read_block(minipro_handle_t *handle, unsigned int type, unsigned int addr, unsigned char *buf, unsigned int len) {
  100. msg_init(msg, type, handle->device, handle->icsp);
  101. format_int(&(msg[2]), len, 2, MP_LITTLE_ENDIAN);
  102. format_int(&(msg[4]), addr, 3, MP_LITTLE_ENDIAN);
  103. msg_send(handle, msg, 18);
  104. msg_recv(handle, buf, len);
  105. }
  106. void minipro_write_block(minipro_handle_t *handle, unsigned int type, unsigned int addr, unsigned char *buf, unsigned int len) {
  107. msg_init(msg, type, handle->device, handle->icsp);
  108. format_int(&(msg[2]), len, 2, MP_LITTLE_ENDIAN);
  109. format_int(&(msg[4]), addr, 3, MP_LITTLE_ENDIAN);
  110. memcpy(&(msg[7]), buf, len);
  111. msg_send(handle, msg, 7 + len);
  112. }
  113. /* Model-specific ID, e.g. AVR Device ID (not longer than 4 bytes) */
  114. int minipro_get_chip_id(minipro_handle_t *handle) {
  115. msg_init(msg, MP_GET_CHIP_ID, handle->device, handle->icsp);
  116. msg_send(handle, msg, 8);
  117. msg_recv(handle, msg, 5 + handle->device->chip_id_bytes_count);
  118. return(load_int(&(msg[2]), handle->device->chip_id_bytes_count, MP_BIG_ENDIAN));
  119. }
  120. void minipro_read_fuses(minipro_handle_t *handle, unsigned int type, unsigned int length, unsigned char *buf) {
  121. msg_init(msg, type, handle->device, handle->icsp);
  122. msg[2]=(type==18 && length==4)?2:1; // note that PICs with 1 config word will show length==2
  123. msg[5]=0x10;
  124. msg_send(handle, msg, 18);
  125. msg_recv(handle, msg, 7 + length );
  126. memcpy(buf, &(msg[7]), length);
  127. }
  128. void minipro_write_fuses(minipro_handle_t *handle, unsigned int type, unsigned int length, unsigned char *buf) {
  129. // Perform actual writing
  130. switch(type & 0xf0) {
  131. case 0x10:
  132. msg_init(msg, type + 1, handle->device, handle->icsp);
  133. msg[2] = (length==4)?0x02:0x01; // 2 fuse PICs have len=8
  134. msg[4] = 0xc8;
  135. msg[5] = 0x0f;
  136. msg[6] = 0x00;
  137. memcpy(&(msg[7]), buf, length);
  138. msg_send(handle, msg, 64);
  139. break;
  140. case 0x40:
  141. msg_init(msg, type - 1, handle->device, handle->icsp);
  142. memcpy(&(msg[7]), buf, length);
  143. msg_send(handle, msg, 10);
  144. break;
  145. }
  146. // The device waits us to get the status now
  147. msg_init(msg, type, handle->device, handle->icsp);
  148. msg[2]=(type==18 && length==4)?2:1; // note that PICs with 1 config word will show length==2
  149. memcpy(&(msg[7]), buf, length);
  150. msg_send(handle, msg, 18);
  151. msg_recv(handle, msg, 7 + length);
  152. if(memcmp(buf, &(msg[7]), length)) {
  153. ERROR("Failed while writing config bytes");
  154. }
  155. }
  156. void minipro_get_system_info(minipro_handle_t *handle, minipro_system_info_t *out) {
  157. unsigned char buf[40];
  158. memset(msg, 0x0, 5);
  159. msg[0] = MP_GET_SYSTEM_INFO;
  160. msg_send(handle, msg, 5);
  161. msg_recv(handle, buf, 40);
  162. // Protocol version
  163. switch(out->protocol = buf[1]) {
  164. case 1:
  165. case 2:
  166. break;
  167. default:
  168. ERROR("Protocol version error");
  169. }
  170. // Model
  171. switch(out->protocol = buf[6]) {
  172. case MP_TL866A:
  173. out->model_str = "TL866A";
  174. break;
  175. case MP_TL866CS:
  176. out->model_str = "TL866CS";
  177. break;
  178. default:
  179. ERROR("Unknown device");
  180. }
  181. // Firmware
  182. out->firmware = load_int(&(buf[4]), 2, MP_LITTLE_ENDIAN);
  183. if(out->firmware < MP_FIRMWARE_VERSION) {
  184. fprintf(stderr, "Warning: firmware is too old\n");
  185. }
  186. sprintf(out->firmware_str, "%d.%d.%d", buf[39], buf[4], buf[5]);
  187. }
  188. void minipro_prepare_writing(minipro_handle_t *handle) {
  189. unsigned char buf[10];
  190. msg_init(msg, MP_PREPARE_WRITING, handle->device, handle->icsp);
  191. format_int(&(msg[2]), 0x03, 2, MP_LITTLE_ENDIAN);
  192. msg[2] = handle->device->write_unlock;
  193. msg_send(handle, msg, 15);
  194. msg_recv(handle, buf, 10);
  195. }