📄 illum.c
字号:
/* * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; * Look at the file LICENSE for details **/#define IN_CAS 1#include "readconf.h"#include "illum.h"char rcfname[RCLINELEN] = RCFNAME,line_str[RCLINELEN] = "/dev/ttyS0",speed_str[RCLINELEN] = "9600",passwd_str[RCLINELEN] = "",parity_str[RCLINELEN] = "none",dbase_str[RCLINELEN] = DEFAULTDB,line_str_[RCLINELEN] = "/dev/ttyb",dbase_bak[RCLINELEN] = "~/.casiodb.bak";int bytelen=8,tflag = 0,debugmode = 0, Port = 0,firstAck=0, /* if writting(5x80), we havent received the first Ack yet */firstheader = 1;byte ackbyte = IACK;const CONFIG casio_config[] = {/* kind tag refecence size delim flags */ {CF_INT, "bytelen", &bytelen, 0, NULL, 0, NULL}, {CF_INT, "debug", &debugmode, 0, NULL, 0, NULL}, {CF_STRING, "line", line_str, RCLINELEN, NULL, 0, NULL}, {CF_STRING, "speed", speed_str, RCLINELEN, NULL, 0, NULL}, {CF_STRING, "passwd", passwd_str, RCLINELEN, NULL, 0, NULL}, {CF_STRING, "parity", parity_str, RCLINELEN, NULL, 0, NULL}, {CF_STRING, "dbase", dbase_str, RCLINELEN, NULL, 0, NULL},};/* * global variables: */char *version = "2.2";char *hello = "\nCASIO interface program Solaris 2.x , Sunos4.x, and Linux v. %s\n\n";char *info = "\This program is a backup and restore utility for a CASIO digital diary.\n\\n\The syntax is:\n\\n\CASIO <-r|-w> [-l <commport>] [-o <file>] [-t]\n\\n\ -r|-w: The direction of the data transfer. -r is used for reading\n\ data from the CASIO to the PC. -w for the opposite direction.\n\\n\ commport: The PC's serial port that has to be used. Specify as COM1,\n\ COM2,COM3 or COM4 or simply as 1,2,3 or 4. For Solaris and \n\ specify TTYA or TTYB or simply as A or B.\n\\n\ baudrate: Either 2400, 4800 or 9600 must be specified. Note that not\n\ all communication speeds are supported by all CASIO's.\n\ fixed at 9600 for the Illuminator models\n\ can not be edited. \n\\n\ parity: none, odd, even. The Illuminator understands none only\n\ can not be edited. \n\\n\ bytelength: The number of bits transfered for one Byte, 7 or 8 are valid values. \n\ The value is fixed for the Illuminator to 8 bits \n\ can not be edited. \n\\n\ file: The name of the file where the backup data are to be written\n\ to or read from.\n\\n\The other communication parameters on the CASIO have to be set to 8N1 \n\\n\\n\The layout of the used file is not directly in a readable format since\n\all data records as needed for the CASIO are not really processed into\n\a convenient format. The file data are used for backup/restore purposes\n\only and should not be edited.\n\\n\CAUTION: Do not interface the CASIO directly to the PC's serial port, since\n\ this may cause permanent damage to the CASIO. Always use the\n\ circuit as described in circuit*.gif. It contains level converters\n\ for converting the +12/-12 Volts levels on the PC side to the\n\ +5/0 Volts levels that the CASIO uses.\n\\n\ Also keep in mind that the Secret Area of the CASIO has to be\n\ backuped/restored separately.\n\\n";int Port;unsigned int Record;int blkflg;byte DataBuffer[512], Direction = READ;byte nbytes;byte Stopped;/* * Default values for communication parameters -- illuminator */tcflag_t speed = B9600, bytel = CS8;static struct termios term;static struct termios save_stdin;static struct termios oldterm;int err;main (int argc, char *argv[]){int j; /* * Expand ~ in rc filename to home path */ if (strcpy(rcfname, tilde_expand_filename(rcfname, getuid())) == NULL) { perror("tilde_expand_filename()"); exit(-1); } /* * Read rc file in home dir */ if (read_config_file(argv[0], casio_config, NELEM(casio_config), rcfname) < 0) { perror(rcfname); exit(-1); } /* * Pars arguments */ while ((ch = getopt(argc, argv, "d:hl:o:rvwt")) != EOF) { switch(ch) { case 'd': debugmode = atoi(optarg); break; case 'l': strcpy(line_str, optarg); break; case 'o': strcpy(dbase_str, optarg); break; case 'r': Direction = READ; break; case 't': tflag++; break; case 'v': debugmode++; break; case 'w': Direction = WRITE; break; case 'h': default: fprintf (stderr, hello, version); fprintf (stderr, "%s", info); return (-1); } } dispose_config(argv[0], casio_config, NELEM(casio_config)); /* * Expand ~ in database filename to home path */ if (strcpy(dbase_str, tilde_expand_filename(dbase_str, getuid())) == NULL) { perror("tilde_expand_filename()"); exit(-1); } if (debugmode > 0) { printf ("Settings:\n"); printf ("=========\n\n"); printf ("line=%s\n", line_str); printf("speed=%s\n", speed_str); printf("parity=%s\n", parity_str); printf("bytelen=%d\n", bytelen); printf ("dbase=%s\n", dbase_str); printf ("debug=%d\n", debugmode); printf("direction=%s\n", Direction?"Read From Casio":"Write to Casio"); printf("database file =%s\n", dbase_str); } if (debugmode == 6) { printf("\n Debug Level 6 is used only for printing setup info; change to something else\n\n"); exit(0);} time (&now); tmstruct = localtime (&now); strftime (tbuff, 10, ".%y%d%m", tmstruct); if (debugmode > 0) { strcpy (deb, "debug"); strcat (deb, tbuff); dbg = fopen (deb, "w"); } if (tflag) { printf ("Opening data file\n"); strcpy (dat, "data"); strcat (dat, tbuff); data = fopen (dat, "w"); } if (debugmode > 1) fprintf (dbg, "\nopening port %s...\n", line_str); printf ("\nopening port %s ...\n", line_str); if ((Port = open (line_str, O_RDWR)) < 0) { fprintf (stderr, "Unknown COM port %s\n", line_str); terminate (); }#if !defined(Solaris2) if ((signal (SIGINT, sig_catch)) == SIG_ERR) /* catch signals */ fprintf (stderr, "signal(SIGINT) error %d", err);#endif /* !defined(Solaris2) */ if ((signal (SIGQUIT, sig_catch)) == SIG_ERR) fprintf (stderr, "signal(SIGINT) error "); if ((signal (SIGTERM, sig_catch)) == SIG_ERR) fprintf (stderr, "signal(SIGINT) error "); /* even more error checking! */ /* should be terminal device - exit if not */ if (isatty (Port) == 0) { fprintf (stderr, "\nNot terminal device...\n"); terminate (); } /* get port attributes, store in oldterm */ if (tcgetattr (Port, &oldterm) < 0) { fprintf (stderr, "\ntcgetattr error..."); terminate (); } /* copy old into new; restore the old sometime when done */ term = oldterm;/* 5x** only understands 9600 8N1 */ term.c_cflag &= ~PARENB; term.c_cflag &= ~CSIZE; term.c_cflag |= speed | CREAD | bytel | CLOCAL; cfsetispeed (&term, speed); cfsetospeed (&term, speed); /* set non-canonical mode */ term.c_lflag = 0; /* * Ignore bytes with parity errors and make terminal raw and dumb. */ term.c_iflag = 0; term.c_iflag |= IGNBRK; term.c_iflag |= IGNPAR; term.c_oflag &= ~OPOST; /* blocking read until 1 char arrives */ term.c_cc[VMIN] = 1; term.c_cc[VTIME] = 0; /* * Open the required file */ if (Direction == READ) { term.c_iflag |= IXOFF; term.c_cc[VSTART] = XON; term.c_cc[VSTOP] = XOFF; /* * Backup existing database file */ if ((casiofile = fopen (dbase_str, "rb")) != (FILE *) 0) { strcpy (dbase_bak, dbase_str); strcat (dbase_bak, ".bak"); if (debugmode > 1) fprintf (dbg, "Creating backup file %s...", dbase_bak); fclose (casiofile); if (rename (dbase_str, dbase_bak) != 0) { fprintf (stderr, "Cannot rename file %s to %s\n", dbase_str, dbase_bak); terminate (); } if (debugmode > 1) fprintf (dbg, " done\n"); } if ((casiofile = fopen (dbase_str, "wb")) == (FILE *) 0) { fprintf (stderr, "Cannot create output file %s\n", dbase_str); terminate (); } } else { if ((casiofile = fopen (dbase_str, "rb")) == (FILE *) 0) { fprintf (stderr, "Cannot open input file %s\n", dbase_str); terminate (); } } /* now clean the serial line and activate the settings for casio */ tcflush (Port, TCIOFLUSH); if (tcsetattr (Port, TCSAFLUSH, &term) < 0) { fprintf (stderr, "\n failed to set port attr ... exiting \n"); terminate (); } Stopped = 0; WriteStatus = 0; fprintf (stdout, hello, version); /* set the stdin to cbreak mode */ tty_cbreak (STDIN_FILENO); while (1) { if (Direction == READ) { fprintf (stderr, "\nRead data from CASIO to file %s\n", dbase_str); if (debugmode > 1) fprintf (dbg, "\nRead data to file %s\n", dbase_str); while (!Stopped) { if (debugmode > 1) fprintf (dbg, "\n++++++++++++++++++++++++++++++++++++++++++++\n"); ReadLine ();/* */ if (debugmode > 2) fprintf (dbg, "\nwriting data to casiofile: \n"); fwrite (&ourheader, sizeof (byte), 1, casiofile); fwrite (&ourdata.type, sizeof (byte), 1, casiofile); fwrite (&ourdata.length, sizeof (byte), 1, casiofile); fwrite (&ourdata.data, ourdata.length, 1, casiofile); fwrite (&ourdata.cksum, sizeof (byte), 1, casiofile);/* usleep(100); */ if ((j = write (Port, &ackbyte, 1)) != 1) { fprintf (stderr, "\n %d ERROR %d: couldnt write the ack(0xBD) to serial port \nterminating ..\n", j, errno); perror ("oops write"); fprintf (stderr, "\n%d %d %d %d %d %d %d\n", EBADF, EINVAL, EFAULT, EPIPE, EAGAIN, EINTR, ENOSPC); terminate (); } if (debugmode > 2) fprintf (dbg, "\nAcked record \n"); } if (debugmode > 2) fprintf (dbg, "\n =========> stopped =1? real=%d\n", Stopped); } else { fprintf (stderr, "\n\nWrite data from file %s to CASIO\n\n", dbase_str); fprintf (stderr, "Hit ESC to terminate at any time \n"); blkflg &= ~O_NONBLOCK; if (fcntl (Port, F_SETFL, blkflg) < 0) { fprintf (stderr, "\nexiting ..\n"); terminate (); } if (!Stopped) { fprintf (stderr, "Casio is ready to receive\n"); if (debugmode > 1) fprintf (dbg, "Casio is ready to receive\n"); } while (!Stopped) { WriteLine (casiofile); DisplayStatus (); }/* Stopped = 1;*/ break; } } terminate ();}/* * R e a d H e a d e r * * Read a record header from the CASIO * The illuminator version */voidReadHeader (void){ int retval, readval, len = 0; if (debugmode > 2) fprintf (dbg, "\nReadheader waiting for a char"); if (firstheader) {/* for the first header wait up to 10 minutes */ if (debugmode > 2) fprintf (dbg, "waiting for the first header\n"); readval = ReadByte (300, 0, 0); firstheader = 0; }/* make sure we grab the syncronization byte hex 8a */ while ((readval & 0xff) != 0x8A) { readval = ReadByte (30, 0, 1); if (debugmode > 3) fprintf (dbg, "\nread:>%2X< >%c< ", readval & 0xff, readval & 0xff); }/* grab the type byte */ readval = ReadByte (5, 0, 0); ourdata.type = (byte) readval & 0xff;}void ReadSchData (){ int readval, i = 0, len = 0;/* */ for (i = 0; i < 3; i++) { /* ReadBytea char and store in i */ readval = ReadByte (5, 0, 1); ourdata.data[len] = (byte) readval & 0xff; len++; } switch (ourdata.type) { case 0x0c: { for (i = 0; i < 5; i++) { /* ReadBytea char and store in i */ readval = ReadByte (5, 0, 1); ourdata.data[len] = (byte) readval & 0xff; len++; } break; } case 0x0d: { for (i = 0; i < 3; i++) { /* ReadBytea char and store in i */ readval = ReadByte (5, 0, 1); ourdata.data[len] = (byte) readval & 0xff; len++; } break; } case 0x0e: { for (i = 0; i < 9; i++) { /* ReadBytea char and store in i */ readval = ReadByte (5, 0, 1); ourdata.data[len] = (byte) readval & 0xff; len++; } break; } default: { printf ("\nUnknown schedule type"); break; } }/* now we are at par; ReadBytethe remainder of the data *//* keep reading until we see an FF */ do { /* ReadBytea char and store in i */ readval = ReadByte (5, 0, 1); ourdata.data[len] = (byte) readval & 0xff; len++; } while ((readval & 0xff) != 0xFF);/* grab the checksum */ ourdata.length = (byte) len - 1; readval = ReadByte (5, 0, 1); ourdata.cksum = (byte) readval & 0xff; printf ("\nchecksum: %2X %c ", readval & 0xff, readval & 0xff);}/********************/void ReadRemData (){ int readval = 0xff, i = 0, len = 0; for (i = 0; i < 12; i++) { readval = ReadByte (5, 0, 1); ourdata.data[len] = (byte) readval & 0xff; len++; } do { readval = ReadByte (5, 0, 1); ourdata.data[len] = (byte) readval & 0xff; len++; } while ((readval & 0xff) != 0xFF); while ((readval & 0xff) == 0xFF) { readval = ReadByte (5, 0, 1); ourdata.data[len] = (byte) readval & 0xff; printf ("\nreading FFs:>%2X< >%c< ", readval & 0xff, readval & 0xff); len++; }/* */ ourdata.length = (byte) len - 1; ourdata.cksum = (byte) readval & 0xff; printf ("\nchecksum: %2X %c ", readval & 0xff, readval & 0xff);}/********************/void ReadExpData (){ int readval = 0xff, i = 0, len = 0; for (i = 0; i < 12; i++) { readval = ReadByte (5, 0, 1); ourdata.data[len] = (byte) readval & 0xff; len++; } do { readval = ReadByte (5, 0, 1); ourdata.data[len] = (byte) readval & 0xff; len++; } while ((readval & 0xff) != 0xFF); while ((readval & 0xff) == 0xFF) { readval = ReadByte (5, 0, 1); ourdata.data[len] = (byte) readval & 0xff; printf ("\nreading FFs:>%2X< >%c< ", readval & 0xff, readval & 0xff); len++; }/* */ ourdata.length = (byte) len - 1; ourdata.cksum = (byte) readval & 0xff; printf ("\nchecksum: %2X %c ", readval & 0xff, readval & 0xff);}/********************In this scenario we dont know what the record type isso we just ReadByteevrything and timeout if there is nothingto be ReadByteafter 5 secs; this gives us leeway so thatif we can send an ack before the 30 secs timer expires;The assumption here is that the illuminator will nottimeout.*************************/void ReadUnknown (){ int readval, readval2, len = 0; do {/* fprintf (stderr, "\nReadheader waiting for a char from %d\n",5); */ /* ReadBytea char and store in i */ readval = ReadByte (5, 0, 1); ourdata.data[len] = (byte) readval & 0xff; len++; } while ((readval2 = waitforchar (5, 5, 0))); ourdata.cksum = (byte) readval & 0xff; len--; ourdata.length = (byte) len;}/*********************************************/void ReadGenData (){ int readval, len = 0;/* keep reading until we see an FF */ do { /* ReadBytea char and store in i */ readval = ReadByte (5, 0, 1); ourdata.data[len] = (byte) readval & 0xff; len++; } while ((readval & 0xff) != 0xFF);/* keep going until we hit a checksum */ while ((readval & 0xff) == 0xFF) {/* fprintf (stderr, "\nReadheader2 waiting for a char from %d\n",5); */ /* ReadBytea char and store in i */ readval = ReadByte (5, 0, 1); ourdata.data[len] = (byte) readval & 0xff;/* printf("\nreading FFs:>%2X< >%c< ",readval&0xff,readval&0xff); */ len++; }/* jamal -- until we fix it the last byte is a checkusm; offset it */ ourdata.length = (byte) len - 1;/* grab the checksum */ ourdata.cksum = (byte) readval & 0xff;/* printf("\nchecksum: %2X %c ",readval&0xff,readval&0xff);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -