serial_cmd.c

Go to the documentation of this file.
00001 
00012 #include "edtinc.h"
00013 #include "pciload.h" /* for strip_newline function */
00014 
00015 #define SERBUFSIZE 512
00016 
00017 /* prototypes */
00018 void    print_ascii_string(char *buf);
00019 long    PdvDispatch(int argc, char *argv[], char *edt_devname);
00020 long
00021 PdvSerialWriteRead(int argc, char *argv[], int unit, int hexin,
00022            int do_wait, int do_printflush, int inter, int timeout, int verbose,
00023            int baud, int readonly, int channel);
00024 long    isascii_str(u_char *buf, int n);
00025 long    ack_nak_str(u_char *buf, int n);
00026 
00027 int print_inter_help()
00028 {
00029     puts("");
00030     puts("EDT serial_cmd, interactive mode help");
00031     puts("");
00032     puts("Enter any command that is valid for the camera. For example, to get camera");
00033     puts("status from a Kodak MEGAPLUS camera, type in STS? then press ENTER.");
00034     puts("");
00035     puts("If you don't get responses from query commands, make sure the camera is");
00036     puts("configured for RS-422 control. Kodak MEGAPLUS cameras may be factory");
00037     puts("configured for either RS-232 or RS-422 control, and must be switched");
00038     puts("to RS-422 to work with the EDT interface.");
00039     puts("");
00040     puts("See your camera users guide for control options and valid commands.");
00041     puts("Run \"serial_cmd -h\" for command line options.");
00042     puts("");
00043     return 0;
00044 }
00045 
00046 int pnum=0;
00047 void
00048 printify(u_char *buf, u_char *dest, int n, int show_nonprint)
00049 {
00050     int     has_lf = FALSE;
00051     int     i, j;
00052 
00053     for (i = 0; i < n; i++)
00054     {
00055         if (buf[i] == 10)
00056             has_lf = TRUE;
00057     }
00058 
00059     for (i = 0, j = 0; i < n; i++)
00060     {
00061 
00062         if (buf[i] == 13)
00063         {
00064             if (!has_lf)
00065             dest[j++] = '\n';
00066         }
00067         else if (buf[i] == 10 || (buf[i] >= ' ' && buf[i] < 127))
00068             dest[j++] = buf[i];
00069         else if (show_nonprint)
00070         {
00071             switch (buf[i])
00072             {
00073             case 0x06:
00074             strcpy((char *) dest + j, "<ACK>");
00075             break;
00076             case 0x15:
00077             strcpy((char *) dest + j, "<NAK>");
00078             break;
00079             case 0x02:
00080             strcpy((char *) dest + j, "<STX>");
00081             break;
00082             case 0x03:
00083             strcpy((char *) dest + j, "<ETX>");
00084             break;
00085             default:
00086             sprintf((char *) dest + j, "<%02x>", buf[i]);
00087             }
00088 
00089             j = strlen((char *) dest);
00090 
00091         }
00092 
00093         dest[j] = 0;
00094     }
00095 }
00096 
00097 int     basler_framing = 0;
00098 int     duncan_framing = 0;
00099 
00100 void
00101 usage(char *err)
00102 {
00103     printf("%s", err);
00104     printf("Usage: \n");
00105     printf(
00106        "    -?, /?, -h      - Help message\n"
00107        "    --help          - Help message\n"
00108        "    -u N            - Unit number (default 0)\n"
00109        "    -f N            - FOI (fiber optic remote) unit #\n"
00110        "    -c N            - channel #\n"
00111        "    -b baud         - Set baud rate\n"
00112        "    -v              - Verbose\n"
00113        "    -w              - Wait before read\n"
00114        "    -r              - Read only\n"
00115        "    -p              - Print what's in the buffer on start\n"
00116        "    -t              - Serial timeout override value\n"
00117        "    -B              - Basler framing mode -- cmd should be hex cmd (bytes separated by\n"
00118        "    -D              - Duncan framing mode -- cmd should be hex cmd (bytes separated by\n"
00119        "                      spaces, with NO framing info (serial_cmd will add STX and Checksum)\n"
00120        "    -x              - Hex mode -- cmd should be hex bytes separared by spaces\n"
00121        "   \"cmd\"            - ASCII (default) or hex command(s) to send\n"
00122     );
00123 }
00124 
00125 
00126 
00127 /*
00128  * Main module. NO_MAIN is typically only defined when compiling for vxworks; if you
00129  * want to use this code outside of a main module in any other OS, just copy the code
00130  * and modify it to work as a standalone subroutine, including adding parameters in
00131  * place of the command line arguments
00132  */
00133 #ifdef NO_MAIN
00134 #include "opt_util.h"
00135 char *argument ;
00136 int option ;
00137 int
00138 serial_cmd(char *command_line)
00139 #else
00140 int
00141 main(int argc, char **argv)
00142 #endif
00143 {
00144     long    status;        /* return status from command */
00145     int     unit = 0;
00146     int     hexin = 0;
00147     int     inter = 0;
00148     int     verbose = 0;
00149     int     do_wait = 0;
00150     int     do_printflush = 0;
00151     int     timeout = 0;
00152     int     channel = 0;
00153     int     readonly = 0;
00154     int     baud = 0;
00155 #ifdef NO_MAIN
00156     char **argv  = 0 ;
00157     int argc = 0 ;
00158     opt_create_argv("serial_cmd",command_line,&argc,&argv);
00159 #endif
00160 
00161     --argc;
00162     ++argv;
00163     while ((argc > 0) && ((argv[0][0] == '-') || (argv[0][0] == '/')))
00164     {
00165         switch (argv[0][1])
00166         {
00167             case 'u':        /* device unit number */
00168                 ++argv;
00169                 --argc;
00170                 if (argc < 1) 
00171                 {
00172                     usage("Error: option 'u' requires a numeric argument\n");
00173                     exit(1);
00174                 }
00175                 if ((argv[0][0] >= '0') && (argv[0][0] <= '9'))
00176                 {
00177                     unit = atoi(argv[0]);
00178                 }
00179                 else 
00180                 {
00181                     usage("Error: option 'u' requires a numeric argument\n");
00182                     exit(1);
00183                 }
00184                 break;
00185 
00186             case 'x':  
00187                 hexin = 1; /* command input is in hex */
00188                 break;
00189 
00190             case 'w':
00191                 do_wait = 1;  /* asks user before proceeding with read */
00192                 break;
00193 
00194             case 'p':
00195                 do_printflush = 1;  /* just print the flush buffer and exit */
00196                 break;
00197 
00198             case 't':
00199                 ++argv;
00200                 --argc;
00201                 if (argc < 1) {
00202                 usage("Error: option 't' requires argument\n");
00203                 exit(1);
00204                 }
00205                 if ((argv[0][0] >= '0') && (argv[0][0] <= '9'))
00206                 timeout = atoi(argv[0]);
00207                 break;
00208 
00209             case 'b':
00210                 ++argv;
00211                 --argc;
00212                 if (argc < 1) {
00213                 usage("Error: option 'b' requires argument\n");
00214                 exit(1);
00215                 }
00216                 baud = atoi(argv[0]);
00217                 break;
00218 
00219             case 'v':
00220                 verbose = 1;
00221                 break;
00222 
00223             case '-':
00224                 if (strcmp(argv[0], "--help") == 0) {
00225                 usage("");
00226                 exit(0);
00227                 } else {
00228                 fprintf(stderr, "unknown option: %s\n", argv[0]);
00229                 usage("");
00230                 exit(1);
00231                 }
00232                 break;
00233 
00234             case 'h':
00235             case '?':
00236                 usage("");
00237                 exit(0);
00238                 break;
00239 
00240             case 'r':
00241                 readonly = 1;
00242                 break;
00243 
00244             case 'c':
00245                 ++argv;
00246                 --argc;
00247                 if (argc < 1)
00248                 {
00249                 usage("Error - channel # expected\n");
00250                 exit(-1);
00251                 }
00252                 channel = atoi(argv[0]);
00253                 break;
00254 
00255             case 'B':
00256                 basler_framing = 1;
00257                 break;
00258 
00259             case 'D':
00260                 duncan_framing = 1;
00261                 break;
00262 
00263             default:
00264                 usage("unknown flag\n");
00265                 exit(1);
00266                 break;
00267         }
00268         argc--;
00269         argv++;
00270     }
00271 
00272     if ((argc < 1) && !readonly && !do_printflush)
00273     inter = 1;
00274 
00275     if (readonly && (timeout == 0))
00276     timeout = 60000;
00277 
00278     status = PdvSerialWriteRead(argc, argv, unit, hexin, do_wait, do_printflush, inter,
00279             timeout, verbose,  baud, readonly, channel);
00280 #ifndef NO_MAIN
00281     exit(status);
00282 #endif
00283     return (0);
00284 }
00285 
00286 
00287 long
00288 PdvSerialWriteRead(int argc, char *argv[], int unit, int hexin,
00289           int do_wait, int do_printflush,  int inter, int timeout, int verbose, 
00290            int baud, int readonly, int channel)
00291 {
00292     int     i;
00293     int     ret;
00294     int     nbytes;
00295     int     length=0;
00296     u_char  hbuf[SERBUFSIZE];
00297     char    tmpbuf[SERBUFSIZE+1];
00298     char    getbuf[SERBUFSIZE+1];
00299     char    *ibuf_p;
00300     u_char  lastbyte, waitc;
00301     char    buf[SERBUFSIZE+1];
00302     char    bs[32][3];
00303     EdtDev *ed;
00304 
00305     /* open a handle to the device     */
00306     ed = pdv_open_channel(EDT_INTERFACE, unit, channel);
00307     if (ed == NULL)
00308     {
00309         pdv_perror(EDT_INTERFACE);
00310         return -1;
00311     }
00312 
00313     pdv_serial_read_enable(ed);
00314 
00315     if (timeout < 1)
00316     timeout = ed->dd_p->serial_timeout;
00317 
00318     if (verbose)
00319     printf("serial timeout %d\n", timeout);
00320 
00321     if (inter)
00322     {
00323         ibuf_p = getbuf;
00324         printf("\nEnter command (Ctrl-C to quit)\n\n");
00325     }
00326     else
00327     ibuf_p = argv[0];
00328 
00329     if (baud)
00330     {
00331         pdv_set_baud(ed, baud);
00332     }
00333 
00334     if ((pdv_serial_read(ed, buf, SERBUFSIZE) > 0) && do_printflush)
00335     {
00336         printf("%s\n", buf);
00337         exit (0);
00338     }
00339 
00340     do
00341     {
00342         if (inter)
00343         {
00344             printf("> ");
00345             if (strlen(fgets(ibuf_p,SERBUFSIZE,stdin)) > SERBUFSIZE-1)
00346             {
00347                 printf("Max command string length (%d) exceeded\n", SERBUFSIZE-1);
00348                 continue;
00349             }
00350         }
00351 
00352         if (!readonly)
00353         {
00354             if (hexin)
00355             {
00356                 u_int val;
00357                 i = 0;
00358 
00359                 strip_newline(ibuf_p);
00360 
00361                 while (*ibuf_p)
00362                 {
00363                     while ((*ibuf_p == ' ') || (*ibuf_p == '\t'))
00364                     ++ibuf_p;
00365 
00366                     if (*ibuf_p == '\0')
00367                     break;
00368 
00369                     if (sscanf(ibuf_p, "%x", &val) != 1)
00370                     {
00371                     printf("error reading input byte %d\n",i);
00372                     i = 0;
00373                     break;
00374                     }
00375 
00376                     if (val > 0xff)
00377                     {
00378                     printf("Hex string format error -- expect hex bytes separated by spaces, e.g. '00 a0 ff ...' \n");
00379                     i = 0;
00380                     break;
00381                     }
00382                     else hbuf[i++] = val;
00383 
00384                     while ((*ibuf_p != ' ') && (*ibuf_p != '\t') && (*ibuf_p != '\0'))
00385                         ++ibuf_p;
00386                 }
00387 
00388                 /*
00389                  * using pdv_serial_binary_command instead of
00390                  * pdv_serial_write because it prepends a 'c' if FOI
00391                  */
00392                 if (i)
00393                     pdv_serial_binary_command(ed, (char *) hbuf, i);
00394             }
00395             else if (duncan_framing)
00396                 {
00397                     nbytes = sscanf(ibuf_p, "%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s",
00398                          bs[0], bs[1], bs[2], bs[3], bs[4], bs[5], bs[6], bs[7],
00399                             bs[8], bs[9], bs[10], bs[11], bs[12], bs[13], bs[14], bs[15]);
00400 
00401                     for (i = 0; i < nbytes; i++)
00402                     {
00403                         if (strlen(bs[i]) > 2)
00404                         {
00405                         printf("duncan command format error\n");
00406                         break;
00407                         }
00408                         hbuf[i] = (u_char) (strtoul(bs[i], NULL, 16) & 0xff);
00409                     }
00410 
00411                     pdv_send_duncan_frame(ed, hbuf, nbytes);
00412                     /* edt_msleep(10000); */
00413                 }
00414             else if (basler_framing)
00415             {
00416                 nbytes = sscanf(ibuf_p, "%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s",
00417                      bs[0], bs[1], bs[2], bs[3], bs[4], bs[5], bs[6], bs[7],
00418                         bs[8], bs[9], bs[10], bs[11], bs[12], bs[13], bs[14], bs[15]);
00419 
00420                 for (i = 0; i < nbytes; i++)
00421                 {
00422                     if (strlen(bs[i]) > 2)
00423                     {
00424                         printf("basler command format error\n");
00425                         break;
00426                     }
00427                     hbuf[i] = (u_char) (strtoul(bs[i], NULL, 16) & 0xff);
00428                 }
00429 
00430                 pdv_send_basler_frame(ed, hbuf, nbytes);
00431                 /* edt_msleep(10000); */
00432             }
00433             else
00434             {
00435                 sprintf(tmpbuf, "%s\r", ibuf_p);
00436                 if (verbose)
00437                     printf("writing <%s>\n", ibuf_p);
00438                 pdv_serial_command(ed, tmpbuf);
00439             }
00440         }
00441 
00442         /*
00443          * serial_timeout comes from the config file (or -t override flag in
00444          * this app), or if not present defaults to 500 unless readonly
00445          * defaults to 60000
00446          */
00447         if (duncan_framing)
00448         {
00449             ret = pdv_read_duncan_frame(ed, (u_char *)buf);
00450             printf("resp <");
00451             for (i = 0; i < ret; i++)
00452                 printf("%02x%s", (u_char)buf[i], (i == ret-1)? ">\n" : " ");
00453         }
00454         else
00455         {
00456 
00457             pdv_serial_wait(ed, timeout, 64);
00458 
00459             if (do_wait)
00460             {
00461                 printf("return to read response: ");
00462                 getchar();
00463             }
00464 
00465             /*
00466              * read and print the response. Could be large or small so loop
00467              * no more characters (OR waitchar seen, if any). Format output
00468              * for 1) ASCII, 2) HEX, or 3) Pulnix STX/ETX format, as
00469              * appropriate
00470              */
00471             do
00472             {
00473                 ret = pdv_serial_read(ed, buf, SERBUFSIZE);
00474                 if (verbose)
00475                     printf("read returned %d\n", ret);
00476 
00477                 if (*buf)
00478                     lastbyte = (u_char)buf[strlen(buf)-1];
00479 
00480                 if (ret != 0)
00481                 {
00482                     buf[ret + 1] = 0;
00483                     if (hexin || basler_framing || duncan_framing)
00484                     {
00485                         int     i;
00486 
00487                         if (ret)
00488                         {
00489                             printf("resp <");
00490                             for (i = 0; i < ret; i++)
00491                             printf("%s%02x", i ? " " : "", (u_char) buf[i]);
00492                             printf(">\n");
00493                         }
00494                     }
00495                     else        /* simple ASCII */
00496                     print_ascii_string(buf);
00497                     length += ret;
00498                 }
00499 
00500                 if (ed->devid == PDVFOI_ID)
00501                     ret = pdv_serial_wait(ed, 500, 0);
00502                 else if (pdv_get_waitchar(ed, &waitc) && (lastbyte == waitc))
00503                     ret = 0; /* jump out if waitchar is enabled/received */
00504                 else ret = pdv_serial_wait(ed, 500, 64);
00505             } while (ret > 0);
00506         }
00507 
00508         printf("\n");
00509 
00510     } while (inter);
00511 
00512     pdv_close(ed);
00513 
00514     return (1);
00515 }
00516 
00517 /*
00518  * print ascii string. Replace \r or Ctrl-M with \n for consistency and
00519  * pretty printing
00520  */
00521 void
00522 print_ascii_string(char *buf)
00523 {
00524 #if 0
00525     int     i = 0;
00526     char   *p = buf;
00527 #endif
00528     char    tmpbuf[SERBUFSIZE];
00529 
00530     printify((u_char *) buf, (u_char *) tmpbuf, strlen(buf), 1);
00531 
00532 #if 0
00533     while (*p)
00534     {
00535         if ((*p == '\r' || *p == '\n')
00536             && (p != buf) && (*(p - 1) != '\n') && (*(p + 1) != '\n'))
00537             tmpbuf[i++] = '\n';
00538         else
00539             tmpbuf[i++] = *p;
00540         ++p;
00541     }
00542     if (tmpbuf[i - 1] != '\n')
00543         tmpbuf[i++] = '\n';
00544     tmpbuf[i] = '\0';
00545 
00546 #endif
00547     fputs(tmpbuf, stdout);
00548     fflush(stdout);
00549 }
00550 
00551 long
00552 isascii_str(u_char * buf, int n)
00553 {
00554     int     i;
00555 
00556     for (i = 0; i < n; i++)
00557     if ((buf[i] < ' ' || buf[i] > '~')
00558         && (buf[i] != '\t')
00559         && (buf[i] != '\n')
00560         && (buf[i] != '\r'))
00561         return 0;
00562     return 1;
00563 }
00564 
00565 long
00566 ack_nak_str(u_char *buf, int n)
00567 {
00568     int     i;
00569 
00570     /* check for all ASCII between the 1st and last chars, or ACK or NAK */
00571     for (i = 0; i < n; i++)
00572     if ((buf[i] < ' ' || buf[i] > '~')
00573         && (buf[i] != 0x15)    /* NAK */
00574         && (buf[i] != 0x6)    /* ACK */
00575         && (buf[i] != '\n')    /* LF */
00576         && (buf[i] != '\r'))/* CR */
00577         return 0;
00578     return 1;
00579 }

Generated on 19 Jun 2015 by  doxygen 1.4.7