Working on serial utility functions, working on command line arguments
authorNathael Pajani <nathael.pajani@ed3l.fr>
Thu, 12 Apr 2012 11:43:36 +0000 (13:43 +0200)
committerNathael Pajani <nathael.pajani@ed3l.fr>
Thu, 12 Apr 2012 11:43:36 +0000 (13:43 +0200)
isp_main.c

index 5a02f2f..b18c24e 100644 (file)
@@ -5,16 +5,16 @@
  *********************************************************************/
 
 
-#include <stdlib.h>
+#include <stdlib.h> /* malloc, free */
 #include <stdio.h>
 #include <stdint.h>
 
-#include <unistd.h> /* for open, getopt, close */
+#include <unistd.h> /* open, getopt, close, usleep */
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 
-#include <string.h>
+#include <string.h> /* strncmp */
 #include <errno.h>
 #include <getopt.h>
 
@@ -38,30 +38,30 @@ void help(char *prog_name)
 {
        fprintf(stderr, "-----------------------------------------------------------------------\n");
        fprintf(stderr, "Usage: %s [options] device command [command arguments]\n" \
-               "Default baudrate is B115200\n" \
-               "<device> is the (host) serial line used to programm the device\n" \
-               "<command> is one of:\n" \
-               "  synchronize \n" \
-               "  unlock \n" \
-               "  set-baud-rate \n" \
-               "  echo \n" \
-               "  write-to-ram \n" \
-               "  read-memory \n" \
-               "  prepare-for-write \n" \
-               "  copy-ram-to-flash \n" \
-               "  go \n" \
-               "  erase \n" \
-               "  blank-check \n" \
-               "  read-part-id \n" \
-               "  read-boot-version \n" \
-               "  compare \n" \
-               "  read-uid \n" \
-               "Available options:\n" \
-               "  -s | --synchronize : Perform synchronization before sending command\n" \
-               "  -b | --baudrate=N : Use this baudrate (does not issue the set-baud-rate command)\n" \
-               "  -t | --trace : turn on trace output of serial communication\n" \
-               "  -h | --help : display this help\n" \
-               "  -v | --version : display version information\n", prog_name);
+               "  Default baudrate is B115200\n" \
+               "  <device> is the (host) serial line used to programm the device\n" \
+               "  <command> is one of:\n" \
+               "  \t synchronize \n" \
+               "  \t unlock \n" \
+               "  \t set-baud-rate \n" \
+               "  \t echo \n" \
+               "  \t write-to-ram \n" \
+               "  \t read-memory \n" \
+               "  \t prepare-for-write \n" \
+               "  \t copy-ram-to-flash \n" \
+               "  \t go \n" \
+               "  \t erase \n" \
+               "  \t blank-check \n" \
+               "  \t read-part-id \n" \
+               "  \t read-boot-version \n" \
+               "  \t compare \n" \
+               "  \t read-uid \n" \
+               "  Available options:\n" \
+               "  \t -s | --synchronize : Perform synchronization before sending command\n" \
+               "  \t -b | --baudrate=N : Use this baudrate (does not issue the set-baud-rate command)\n" \
+               "  \t -t | --trace : turn on trace output of serial communication\n" \
+               "  \t -h | --help : display this help\n" \
+               "  \t -v | --version : display version information\n", prog_name);
        fprintf(stderr, "-----------------------------------------------------------------------\n");
 }
 
@@ -72,30 +72,35 @@ void help(char *prog_name)
 
 #define SERIAL_BAUD  B115200
 
-char * serial_device = NULL;
 int serial_fd = -1;
 int trace_on = 0;
 
-int serial_open(int baudrate)
+
+/* Open the serial device and set it up.
+ * Returns 0 on success, negativ value on error.
+ * Actal setup is done according to LPC11xx user's manual.
+ * Only baudrate can be changed using command line option.
+ */
+int serial_open(int baudrate, char* serial_device)
 {
        struct termios tio;
 
        if (serial_device == NULL) {
                printf("No serial device given on command line\n");
-               exit(-1);
+               return -2;
        }
 
        /* Open serial port */
        serial_fd = open(serial_device, O_RDWR | O_NONBLOCK);
        if (serial_fd < 0) {
                perror("Unable to open serial_device");
-               printf("Tried to open %s.\n", serial_device);
+               printf("Tried to open \"%s\".\n", serial_device);
                return -1;
        }
        /* Setup serial port */
        memset(&tio, 0, sizeof(tio));
-       tio.c_iflag = IXON | IXOFF; /* See section 21.4.4 of LPC11xx user's manual (UM10398) */
-       tio.c_cflag = CS8 | CREAD | CLOCAL;    /* 8n1, see termios.h for more information */
+       tio.c_iflag = IXON | IXOFF;  /* See section 21.4.4 of LPC11xx user's manual (UM10398) */
+       tio.c_cflag = CS8 | CREAD | CLOCAL;  /* 8n1, see termios.h for more information */
        tio.c_cc[VMIN] = 1;
        tio.c_cc[VTIME] = 5;
        cfsetospeed(&tio, baudrate);
@@ -105,17 +110,18 @@ int serial_open(int baudrate)
        return 0;
 }
 
+/* Simple write() wrapper, with trace if enabled */
 int serial_write(const char* buf, unsigned int buf_size)
 {
        int nb = 0;
 
        if (trace_on) {
-               printf("Sending %d :\n", buf_size);
+               printf("Sending %d octet(s) :\n", buf_size);
                isp_dump((unsigned char*)buf, buf_size);
        }
        nb = write(serial_fd, buf, buf_size);
        if (nb <= 0) {
-               perror("Serial read error");
+               perror("Serial write error");
                return -1;
        }
        return nb;
@@ -125,28 +131,48 @@ int isp_ret_code(char* buf)
 {
        if (trace_on) {
                /* FIXME : Find how return code are sent (binary or ASCII) */
-               printf("Received code : '0x%02x'\n", *buf);
+               printf("Received code: '0x%02x'\n", *buf);
        }
        return 0;
 }
 
-int serial_read(char* buf, unsigned int buf_size)
+/* Try to read at least "min_read" characters from the serial line.
+ * Returns -1 on error, 0 on end of file, or read count otherwise.
+ */
+int serial_read(char* buf, unsigned int buf_size, unsigned int min_read)
 {
        int nb = 0;
-
-       nb = read(serial_fd, buf, buf_size);
-       if (nb < 0) {
-               perror("Serial read error");
-               return -1;
-       } else if (nb == 0) {
-               printf("End of file !!!!\n");
-               return -1;
+       unsigned int count = 0;
+       
+       if (min_read > buf_size) {
+               printf("serial_read: buffer too small for min read value.\n");
+               return -3;
        }
+
+       do {
+               nb = read(serial_fd, &buf[count], (buf_size - count));
+               if (nb < 0) {
+                       if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
+                               usleep( 5000 );
+                               continue;
+                       }
+                       perror("Serial read error");
+                       return -1;
+               } else if (nb == 0) {
+                       printf("serial_read: end of file !!!!\n");
+                       return 0;
+               }
+               if (trace_on == 2) {
+                       isp_dump((unsigned char*)(&buf[count]), nb);
+               }       
+               count += nb;
+       } while (count < min_read);
+
        if (trace_on) {
-               printf("Received : %d octets\n", nb);
-               isp_dump((unsigned char*)buf, nb);
+               printf("Received %d octet(s) :\n", count);
+               isp_dump((unsigned char*)buf, count);
        }
-       return nb;
+       return count;
 }
 
 /* Connect or reconnect to the target */
@@ -159,7 +185,7 @@ int connect()
        serial_write(SYNCHRO_START, 1);
 
        /* Wait for answer */
-       serial_read(buf, SERIAL_BUFSIZE);
+       serial_read(buf, SERIAL_BUFSIZE, strlen(SYNCHRO));
 
        /* Check answer, and acknoledge if OK */
        if (strncmp(SYNCHRO, buf, strlen(SYNCHRO)) == 0) {
@@ -169,7 +195,7 @@ int connect()
                return 0;
        }
        /* Empty read buffer (echo on ?) */
-       serial_read(buf, SERIAL_BUFSIZE);
+       serial_read(buf, SERIAL_BUFSIZE, 1);
        /* and turn off echo */
        serial_write("A 0\r\n", 1);
 
@@ -181,20 +207,29 @@ int main(int argc, char** argv)
 {
        int baudrate = SERIAL_BAUD;
        int synchronize = 0;
+       char* serial_device = NULL;
+
+       /* For "command" handling */
+       char* command = NULL;
+       char** cmd_args = NULL;
+       int nb_cmd_args = 0;
+
 
        /* parameter parsing */
        while(1) {
-               int option_index = 0, c=0;
+               int option_index = 0;
+               int c = 0;
 
                struct option long_options[] = {
-                       {"help", no_argument, 0, 'h'},
-                       {"baudrate", required_argument, 0, 'b'},
                        {"synchronize", no_argument, 0, 's'},
+                       {"baudrate", required_argument, 0, 'b'},
+                       {"trace", no_argument, 0, 't'},
+                       {"help", no_argument, 0, 'h'},
                        {"version", no_argument, 0, 'v'},
                        {0, 0, 0, 0}
                };
 
-               c = getopt_long_only(argc, argv, "hb:sv", long_options, &option_index);
+               c = getopt_long(argc, argv, "sb:thv", long_options, &option_index);
 
                /* no more options to parse */
                if (c == -1) break;
@@ -230,14 +265,40 @@ int main(int argc, char** argv)
                }
        }
 
-       /* FIXME : get serial device and command (and arguments) */
-       /* serial_device = strdup(optarg); */
+       /* Parse remaining command line arguments (not options). */
+
+       /* First one should be serial device */
+       if (optind < argc) {
+               serial_device = argv[optind++];
+               if (trace_on) {
+                       printf("Serial device : %s\n", serial_device);
+               }
+       }
+       /* Next one should be "command" */
+       if (optind < argc) {
+               command = argv[optind++];
+               if (trace_on) {
+                       printf("Command : %s\n", command);
+               }
+       }
+       /* And then remaining ones (if any) are command arguments */
+       if (optind < argc) {
+               nb_cmd_args = argc - optind;
+               cmd_args = malloc(nb_cmd_args * sizeof(char *));
+               while (optind < argc) {
+                       printf ("%s\n", argv[optind++]);
+               }
+       }
+
        if (serial_device == NULL) {
+               printf("No serial device given, exiting\n");
+               help(argv[0]);
                return 0;
        }
-
-
-       serial_open(baudrate);
+       if (serial_open(baudrate, serial_device) != 0) {
+               printf("Serial open failed, unable to initiate serial communication with target.\n");
+               return -1;
+       }
 
        /* FIXME : do not sync if command is sync */
        if (synchronize) {
@@ -247,6 +308,9 @@ int main(int argc, char** argv)
        /* FIXME : call command handler */
 
 
+       if (cmd_args != NULL) {
+               free(cmd_args);
+       }
        close(serial_fd);
        return 0;
 }