📄 gpsflash.c
字号:
/* $Id: gpsflash.c 4471 2007-12-08 08:02:57Z ckuethe $ *//* * This is the GPS-type-independent part of the gpsflash program. * *//* * Copyright (c) 2005-2007 Chris Kuethe <chris.kuethe@gmail.com> * Copyright (c) 2005-2007 Eric S. Raymond <esr@thyrsus.com> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */#include <sys/types.h>#include <stdarg.h>#include <string.h>#include "gpsd_config.h"#include "gpsd.h"#include "gpsflash.h"/* block size when writing to the serial port. related to FIFO size */#define WRBLK 128static char *progname;static int verbosity = 0;static bool srec_check(const char *data);void gpsd_report(int errlevel, const char *fmt, ... )/* assemble command in printf(3) style, use stderr or syslog */{ if (errlevel <= verbosity) { char buf[BUFSIZ]; va_list ap; (void)strlcpy(buf, progname, BUFSIZ); (void)strlcat(buf, ": ", BUFSIZ); va_start(ap, fmt) ; (void)vsnprintf(buf + strlen(buf), sizeof(buf)-strlen(buf), fmt, ap); va_end(ap); (void)fputs(buf, stdout); }}static voidusage(void){ fprintf(stderr, "Usage: %s [-v d] [-n] [-l <loader_file>] -f <firmware_file> {<tty>}\n", progname);}intserialSpeed(int pfd, struct termios *term, int speed){ int rv; int r = 0; switch(speed){#ifdef B115200 case 115200: speed = B115200; break;#endif#ifdef B57600 case 57600: speed = B57600; break;#endif case 38400: speed = B38400; break;#ifdef B28800 case 28800: speed = B28800; break;#endif case 19200: speed = B19200; break;#ifdef B14400 case 14400: speed = B14400; break;#endif case 9600: speed = B9600; break; case 4800: speed = B9600; break; default: errno = EINVAL; return -1; } /* set UART speed */ (int)tcgetattr(pfd, term); /*@ ignore @*/ cfsetispeed(term, speed); cfsetospeed(term, speed); /*@ end @*/ while (((rv = tcsetattr(pfd, TCSAFLUSH, term)) == -1) && \ (errno == EINTR) && (r < 3)) { /* retry up to 3 times on EINTR */ (void)usleep(1000); r++; } if(rv == -1) return -1; else return 0;}intserialConfig(int pfd, struct termios *term, int speed){ int rv; int r = 0; /* get the current terminal settings */ (void)tcgetattr(pfd, term); /* set the port into "raw" mode. */ /*@i@*/cfmakeraw(term); term->c_lflag &=~ (ICANON); /* Enable serial I/O, ignore modem lines */ term->c_cflag |= (CLOCAL | CREAD); /* No output postprocessing */ term->c_oflag &=~ (OPOST); /* 8 data bits */ term->c_cflag |= CS8; term->c_iflag &=~ (ISTRIP); /* No parity */ term->c_iflag &=~ (INPCK); term->c_cflag &=~ (PARENB | PARODD); /* 1 Stop bit */ term->c_cflag &=~ (CSIZE | CSTOPB); /* No flow control */ term->c_iflag &=~ (IXON | IXOFF);#if defined(CCTS_OFLOW) && defined(CRTS_IFLOW) && defined(MDMBUF) term->c_oflag &=~ (CCTS_OFLOW | CRTS_IFLOW | MDMBUF);#endif#if defined(CRTSCTS) term->c_oflag &=~ (CRTSCTS);#endif /* we'd like to read back at least 2 characters in .2sec */ /*@i@*/term->c_cc[VMIN] = 2; /*@i@*/term->c_cc[VTIME] = 2; /* apply all the funky control settings */ while (((rv = tcsetattr(pfd, TCSAFLUSH, term)) == -1) && \ (errno == EINTR) && (r < 3)) { /* retry up to 3 times on EINTR */ (void)usleep(1000); r++; } if(rv == -1) return -1; /* and if that all worked, try change the UART speed */ return serialSpeed(pfd, term, speed);}intbinary_send(int pfd, char *data UNUSED , size_t ls){ unsigned char *msg; size_t nbr, nbs, nbx; ssize_t r; static int count; double start = timestamp(); /*@ -compdef @*/ if((msg = malloc(ls+10)) == NULL){ return -1; /* oops. bail out */ } fprintf(stderr, "gpsflash: transferring binary... \010"); count = 0; nbr = ls+10; nbs = WRBLK ; nbx = 0; while(nbr){ if(nbr > WRBLK ) nbs = WRBLK ; else nbs = nbr;r0: if((r = write(pfd, msg+nbx, nbs)) == -1){ if (errno == EAGAIN){ /* retry */ (void)tcdrain(pfd); /* wait a moment */ errno = 0; /* clear errno */ nbr -= r; /* number bytes remaining */ nbx += r; /* number bytes sent */ goto r0; } else { (void)free(msg); return -1; /* oops. bail out */ } } nbr -= r; nbx += r; (void)fputc("-/|\\"[count % 4], stderr); (void)fputc('\010', stderr); (void)fflush(stdout); } /*@ +compdef @*/ (void)fprintf(stderr, "...done (%2.2f sec).\n", timestamp()-start); (void)free(msg); return 0;}intsrecord_send(int pfd, char *data, size_t len){ int r, i; size_t tl; char sendbuf[85], recvbuf[8]; static int count; double start = timestamp(); /* srecord loading is interactive. send line, get reply */ /* when sending S-records, check for SA/S5 or SE */ fprintf(stderr, "gpsflash: transferring S-records... \010"); count = 0; memset(recvbuf, 0, 8); i = 0; while(strlen(data)){ /* grab a line of firmware, ignore line endings */ if ((r = (int)strlen(data))){ memset(sendbuf,0,85); if((r = sscanf(data, "%80s", sendbuf)) == EOF) return 0; tl = strlen(sendbuf); if ((tl < 1) || (tl > 80)) return -1; data += tl; len -= tl; while((data[0] != 'S') && (data[0] != '\0')) data++; sendbuf[tl] = '\r'; sendbuf[tl+1] = '\n'; tl += 2; if ((++i % 1000) == 0) printf ("%6d\n", i); (void)tcflush(pfd, TCIFLUSH); if((r = (int)write(pfd, sendbuf, tl+2)) != (int)tl+2) return -1; /* oops. bail out */ (void)tcdrain(pfd); if((r = (int)read(pfd, recvbuf, 7)) == -1) return -1; /* oops. bail out */ if (!((recvbuf[0] == 'S') && ((recvbuf[1] == 'A') || (recvbuf[1] == '5')))) return -1; /* oops. bail out */ } (void)fputc("-/|\\"[count % 4], stderr); (void)fputc('\010', stderr); (void)fflush(stdout); } (void)fprintf(stderr, "...done (%2.2f sec).\n", timestamp()-start); return 0;}bool expect(int pfd, const char *str, size_t len, time_t timeout)/* keep reading till we see a specified expect string or time out */{ size_t got = 0; char ch; double start = timestamp(); gpsd_report(LOG_PROG, "expect(%s, %d)\n", gpsd_hexdump((char *)str, len), timeout); for (;;) { if (read(pfd, &ch, 1) != 1) return false; /* I/O failed */ gpsd_report(LOG_RAW, "I see %d: %02x\n", got, (unsigned)(ch & 0xff)); if (timestamp() - start > (double)timeout) return false; /* we're timed out */ else if (got == len) return true; /* we're done */ else if (ch == str[got]) got++; /* match continues */ else got = 0; /* match fails, retry */ }}#if defined(SIRF_ENABLE) && defined(BINARY_ENABLE)/* add new types by adding pointers to their driver blocks to this list *//*@ -nullassign @*/static struct flashloader_t *types[] = {&sirf_type, NULL};/*@ +nullassign @*/#else/* add new types by adding pointers to their driver blocks to this list *//*@ -nullassign @*/static struct flashloader_t *types[] = {NULL, NULL};/*@ +nullassign @*/#endifintmain(int argc, char **argv){ int ch; int lfd, ffd, pfd; size_t ls, fs; bool fflag = false, lflag = false, nflag = false; struct stat sb; struct flashloader_t *gpstype, **gp; char *fname = NULL; char *lname = NULL; char *port = NULL; char *warning; struct termios term; sigset_t sigset; char *firmware = NULL; char *loader = NULL; char *version = NULL; progname = argv[0];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -