00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 #include <sys/types.h>
00069 #include <sys/stat.h>
00070 #include <fcntl.h>
00071 #include <stdlib.h>
00072 #include <unistd.h>
00073 #include <termios.h>
00074 #include <stdio.h>
00075 #include <string.h>
00076 #include <sys/time.h>
00077 #include <ctype.h>
00078 #include <string.h>
00079 #include <assert.h>
00080
00081 #if defined(_WIN32)
00082 #include <windows.h>
00083 #endif
00084
00085 #include "rcx_comm.h"
00086 #include "srec.h"
00087
00088
00089
00090 #if defined(LINUX) || defined(linux)
00091 #define DEFAULTTTY "/dev/ttyS0"
00092 #elif defined (_WIN32)
00093 #define DEFAULTTTY "com1"
00094 #elif defined (sun)
00095 #define DEFAULTTTY "/dev/ttya"
00096 #else
00097 #define DEFAULTTTY "/dev/ttyd2"
00098 #endif
00099
00100
00101
00102 char *progname;
00103 int tty_usb = 0;
00104 extern int __comm_debug;
00105
00106 #include "fastdl.h"
00107
00108
00109
00110 #define BUFFERSIZE 4096
00111 #define RETRIES 10
00112 #define WAKEUP_TIMEOUT 4000
00113
00114 #define UPLOAD_TIMEOUT 50
00115
00116 #define IMAGE_START 0x8000
00117 #define IMAGE_MAXLEN 0x7000
00118 #define TRANSFER_SIZE 200
00119
00120
00121
00122
00123
00124
00125
00126 #if 0
00127 #define FORCE_ZERO_STRIPPING
00128 #endif
00129
00130
00131
00132 int srec_load (char *name, unsigned char *image, int maxlen, unsigned short *start)
00133 {
00134 FILE *file;
00135 char buf[256];
00136 srec_t srec;
00137 int line = 0;
00138 int length = 0;
00139 int strip = 0;
00140
00141
00142 *start = IMAGE_START;
00143
00144
00145 if ((file = fopen(name, "r")) == NULL) {
00146 fprintf(stderr, "%s: ERROR- failed to open %s\n", progname, name);
00147 exit(1);
00148 }
00149
00150
00151 memset(image, 0, maxlen);
00152
00153
00154 while (fgets(buf, sizeof(buf), file)) {
00155 int error, i;
00156 line++;
00157
00158 for (i = 0; buf[i]; i++)
00159 if (!isspace(buf[i]))
00160 break;
00161 if (!buf[i])
00162 continue;
00163
00164 if ((error = srec_decode(&srec, buf)) < 0) {
00165 if (error != SREC_INVALID_CKSUM) {
00166 fprintf(stderr, "%s: %s on line %d\n",
00167 name, srec_strerror(error), line);
00168 exit(1);
00169 }
00170 }
00171
00172 if (srec.type == 0) {
00173 if (srec.count == 16)
00174 if (!strncmp(srec.data, "?LIB_VERSION_L00", 16))
00175 strip = 1;
00176 }
00177
00178 else if (srec.type == 1) {
00179 if (srec.addr < IMAGE_START ||
00180 srec.addr + srec.count > IMAGE_START + maxlen) {
00181 fprintf(stderr, "%s: address out of bounds on line %d\n",
00182 name, line);
00183 exit(1);
00184 }
00185 if (srec.addr + srec.count - IMAGE_START > length)
00186 length = srec.addr + srec.count - IMAGE_START;
00187 memcpy(&image[srec.addr - IMAGE_START], &srec.data, srec.count);
00188 }
00189
00190 else if (srec.type == 9) {
00191 if (srec.addr < IMAGE_START ||
00192 srec.addr > IMAGE_START + maxlen) {
00193 fprintf(stderr, "%s: address out of bounds on line %d\n",
00194 name, line);
00195 exit(1);
00196 }
00197 *start = srec.addr;
00198 }
00199 }
00200
00201
00202 #ifdef FORCE_ZERO_STRIPPING
00203 strip = 1;
00204 #endif
00205
00206 if (strip) {
00207 int pos;
00208 for (pos = IMAGE_MAXLEN - 1; pos >= 0 && image[pos] == 0; pos--);
00209 length = pos + 1;
00210 }
00211
00212
00213 if (length == 0) {
00214 fprintf(stderr, "%s: image contains no data\n", name);
00215 exit(1);
00216 }
00217
00218 return length;
00219 }
00220
00221 void image_dl(FILEDESCR fd, unsigned char *image, int len, unsigned short start,
00222 int use_comp, char *filename)
00223 {
00224 unsigned short cksum = 0;
00225 unsigned char send[BUFFERSIZE];
00226 unsigned char recv[BUFFERSIZE];
00227 int addr, index, size, i;
00228
00229
00230 int cksumlen = (start + len < 0xcc00) ? len : 0xcc00 - start;
00231 assert(len > 0);
00232 for (i = 0; i < cksumlen; i++)
00233 cksum += image[i];
00234
00235
00236 send[0] = 0x65;
00237 send[1] = 1;
00238 send[2] = 3;
00239 send[3] = 5;
00240 send[4] = 7;
00241 send[5] = 11;
00242
00243 if (rcx_sendrecv(fd, send, 6, recv, 1, 50, RETRIES, use_comp) != 1) {
00244 fprintf(stderr, "%s: delete firmware failed\n", progname);
00245 exit(1);
00246 }
00247
00248
00249 send[0] = 0x75;
00250 send[1] = (start >> 0) & 0xff;
00251 send[2] = (start >> 8) & 0xff;
00252 send[3] = (cksum >> 0) & 0xff;
00253 send[4] = (cksum >> 8) & 0xff;
00254 send[5] = 0;
00255
00256 if (rcx_sendrecv(fd, send, 6, recv, 2, 50, RETRIES, use_comp) != 2) {
00257 fprintf(stderr, "%s: start firmware download failed\n", progname);
00258 exit(1);
00259 }
00260
00261
00262 fprintf(stderr, "\rTransferring \"%s\" to RCX...\n", filename);
00263 addr = 0;
00264 index = 1;
00265 for (addr = 0, index = 1; addr < len; addr += size, index++) {
00266 fprintf(stderr,"\r%3d%% \r",(100*addr)/len);
00267 size = len - addr;
00268 send[0] = 0x45;
00269 if (index & 1)
00270 send[0] |= 0x08;
00271 if (size > TRANSFER_SIZE)
00272 size = TRANSFER_SIZE;
00273 else if (0)
00274
00275 index = 0;
00276 send[1] = (index >> 0) & 0xff;
00277 send[2] = (index >> 8) & 0xff;
00278 send[3] = (size >> 0) & 0xff;
00279 send[4] = (size >> 8) & 0xff;
00280 memcpy(&send[5], &image[addr], size);
00281 for (i = 0, cksum = 0; i < size; i++)
00282 cksum += send[5 + i];
00283 send[size + 5] = cksum & 0xff;
00284
00285 if (rcx_sendrecv(fd, send, size + 6, recv, 2, UPLOAD_TIMEOUT, RETRIES,
00286 use_comp) != 2 || recv[1] != 0) {
00287 fprintf(stderr, "%s: transfer data failed\n", progname);
00288 exit(1);
00289 }
00290 }
00291 fputs("100% \n",stderr);
00292
00293
00294 send[0] = 0xa5;
00295 send[1] = 76;
00296 send[2] = 69;
00297 send[3] = 71;
00298 send[4] = 79;
00299 send[5] = 174;
00300
00301
00302 if (rcx_sendrecv(fd, send, 6, recv, 26, 150, RETRIES, use_comp) != 26) {
00303 fprintf(stderr, "%s: unlock firmware failed\n", progname);
00304 exit(1);
00305 }
00306 }
00307
00308 int main (int argc, char **argv)
00309 {
00310 unsigned char image[IMAGE_MAXLEN];
00311 unsigned short image_start;
00312 unsigned int image_len;
00313 char *tty = NULL;
00314 int use_fast = 1;
00315 int usage = 0;
00316 FILEDESCR fd;
00317 int status;
00318
00319 progname = argv[0];
00320
00321
00322
00323 argv++; argc--;
00324 while (argc && argv[0][0] == '-') {
00325 if (argv[0][1] == '-') {
00326 if (!strcmp(argv[0], "--")) {
00327 argv++; argc--;
00328 break;
00329 }
00330 else if (!strcmp(argv[0], "--debug")) {
00331 __comm_debug = 1;
00332 }
00333 else if (!strcmp(argv[0], "--fast")) {
00334 use_fast = 1;
00335 }
00336 else if (!strcmp(argv[0], "--slow")) {
00337 use_fast = 0;
00338 }
00339 else if (!strncmp(argv[0], "--tty", 5)) {
00340 if (argv[0][5] == '=') {
00341 tty = &argv[0][6];
00342 }
00343 else if (argc > 1) {
00344 argv++; argc--;
00345 tty = argv[0];
00346 }
00347 else
00348 tty = "";
00349 if (!tty[0]) {
00350 fprintf(stderr, "%s: invalid tty: %s\n", progname, tty);
00351 exit(1);
00352 }
00353 }
00354 else if (!strcmp(argv[0], "--help")) {
00355 usage = 1;
00356 }
00357 else {
00358 fprintf(stderr, "%s: unrecognized option %s\n",
00359 progname, argv[0]);
00360 exit(1);
00361 }
00362 }
00363 else {
00364 char *p = &argv[0][1];
00365 if (!*p)
00366 break;
00367 while (*p) {
00368 switch (*p) {
00369 case 'f': use_fast = 1; break;
00370 case 's': use_fast = 0; break;
00371 case 'h': usage = 1; break;
00372 default:
00373 fprintf(stderr, "%s: unrecognized option -- %c\n",
00374 progname, *p);
00375 exit(1);
00376 }
00377 p++;
00378 }
00379 }
00380 argv++;
00381 argc--;
00382 }
00383
00384 if (usage || argc != 1) {
00385 char *usage_string =
00386 " --debug show debug output, mostly raw bytes\n"
00387 " -f, --fast use fast 4x downloading (default)\n"
00388 " -s, --slow use slow 1x downloading\n"
00389 " --tty=TTY assume tower connected to TTY\n"
00390 #if defined(_WIN32)
00391 " --tty=usb assume tower connected to USB\n"
00392 #else
00393 " (if device name contains \"usb\", use USB mode)\n"
00394 #endif
00395 " -h, --help display this help and exit\n"
00396 ;
00397
00398 fprintf(stderr, "usage: %s [options] filename\n", progname);
00399 fprintf(stderr, usage_string);
00400 exit(1);
00401 }
00402
00403
00404
00405 image_len = srec_load(argv[0], image, IMAGE_MAXLEN, &image_start);
00406
00407
00408
00409 if (!tty)
00410 tty = getenv("RCXTTY");
00411 if (!tty)
00412 tty = DEFAULTTTY;
00413
00414 #if defined(_WIN32)
00415
00416 if(stricmp(tty,"usb")==0) {
00417 tty_usb = 1;
00418 if(__comm_debug)
00419 fprintf(stderr, "Hary Mahesan - USB IR Tower Mode.\n");
00420 tty = "\\\\.\\legotower1";
00421 }
00422 #elif defined(LINUX) || defined(linux)
00423
00424
00425
00426
00427
00428 if (strstr(tty,"usb") !=0) {
00429 tty_usb=1;
00430 if (__comm_debug)
00431 fprintf(stderr, "P.C. Chan & Tyler Akins - USB IR Tower Mode for Linux.\n");
00432 }
00433 #endif
00434
00435 if (use_fast && (tty_usb==0)) {
00436
00437
00438 fd = rcx_init(tty, 0);
00439
00440 if ((status = rcx_wakeup_tower(fd, WAKEUP_TIMEOUT)) < 0) {
00441 fprintf(stderr, "%s: %s\n", progname, rcx_strerror(status));
00442 exit(1);
00443 }
00444
00445
00446 rcx_close(fd);
00447 fd = rcx_init(tty, 1);
00448
00449
00450 if (!rcx_is_alive(fd, 0)) {
00451
00452
00453 rcx_close(fd);
00454 fd = rcx_init(tty, 0);
00455
00456 if (!rcx_is_alive(fd, 1)) {
00457 fprintf(stderr, "%s: no response from rcx\n", progname);
00458 exit(1);
00459 }
00460
00461 image_dl(fd, fastdl_image, fastdl_len, fastdl_start, 1, "Fast Download Image");
00462
00463
00464 rcx_close(fd);
00465 fd = rcx_init(tty, 1);
00466 }
00467
00468
00469
00470 image_dl(fd, image, image_len, image_start, 0, argv[0]);
00471 rcx_close(fd);
00472 } else {
00473
00474
00475 fd = rcx_init(tty, 0);
00476
00477
00478 if(tty_usb==0) {
00479 if ((status = rcx_wakeup_tower(fd, WAKEUP_TIMEOUT)) < 0) {
00480 fprintf(stderr, "%s: %s\n", progname, rcx_strerror(status));
00481 exit(1);
00482 }
00483
00484 if (!rcx_is_alive(fd, 1)) {
00485
00486
00487 rcx_close(fd);
00488 fd = rcx_init(tty, 1);
00489
00490 if (rcx_is_alive(fd, 0)) {
00491 fprintf(stderr, "%s: rcx is in fast mode\n", progname);
00492 fprintf(stderr, "%s: turn rcx off then back on to "
00493 "use slow mode\n", progname);
00494 exit(1);
00495 }
00496
00497 fprintf(stderr, "%s: no response from rcx\n", progname);
00498 exit(1);
00499 }
00500 }
00501
00502
00503 image_dl(fd, image, image_len, image_start, 1, argv[0]);
00504
00505 rcx_close(fd);
00506 }
00507
00508 return 0;
00509 }