IRQ handler rewrite by Gabor Juhos, uses C no longer assembly
[openwrt/staging/chunkeey.git] / target / linux / etrax-2.6 / image / e100boot / src / sendserial / sendserial.c
1 #include <termios.h>
2 #include <unistd.h>
3 #include <stdio.h>
4 #include <sys/stat.h>
5 #include <stdlib.h>
6 #include <sys/time.h>
7 #include <sys/types.h>
8 #include <signal.h>
9 #include <fcntl.h>
10 #include <string.h>
11 #include <ctype.h>
12
13 #define TRUE 1
14 #define FALSE 0
15
16 #define db1 0
17 #define db2 0
18 #define db3 0
19 #define db4 0
20
21 #define XON ('\11')
22 #define XOFF ('\13')
23
24 #define START_STR_SIZE 100
25 #define SERIAL_BUF_SIZE 1
26
27 int GetNumberOption (int *argNr, int argCount, char *argVect[], int *ret, char *option);
28 int GetStringOption (int *argNr, int argCount, char *argVect[], char *ret, char *option);
29 int WaitForRead (int s, int usecs);
30 int WaitForWrite (int s, int usecs);
31 int SetupSerial ();
32 int SetInputMode (FILE *fd, int value, int onoff);
33 int SetControlMode (FILE *fd, int value, int onoff);
34 int SetLocalMode (FILE *fd, int value, int onoff);
35 void ParseArgs (int argc, char *argv[]);
36
37 FILE *modemFd;
38 char dev[100] = "/dev/ttyS0";
39 char filename[100] = "";
40 char serial_buf[SERIAL_BUF_SIZE];
41 int baudRates[] = {0, 50, 75, 110, 134, 150, 200, 300, 600,
42 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200};
43 int check = FALSE;
44 int dotime = FALSE;
45 int got_start = TRUE;
46 int loop = FALSE;
47 int crtcts = FALSE;
48 int do_print = TRUE;
49 int received;
50 int set_baudrate = 9600;
51 int xonxoff = FALSE;
52 struct timeval start;
53 struct timeval stop;
54
55
56 int
57 main(int argc, char *argv[])
58 {
59 FILE *fd;
60 char *buf;
61 int ret;
62 struct stat st;
63
64 ParseArgs(argc, argv);
65 SetupSerial();
66
67 if (strcmp(filename, "") != 0) {
68
69 /* Read file. */
70 if ((fd = fopen(filename, "r")) == NULL) {
71 perror("Can't open file\n");
72 exit(0);
73 }
74
75 if (fstat(fileno(fd), &st) != 0) {
76 perror("stat failed\n");
77 exit(0);
78 }
79
80 buf = malloc(st.st_size);
81 if (fread(buf, 1, st.st_size, fd) != st.st_size) {
82 printf("fread failed\n");
83 }
84
85 fclose(fd);
86
87 printf("# sendserial transmitting %d bytes at baudrate %d.\n", (int)st.st_size, set_baudrate);
88 printf("# transmitting...\n");
89 /* Write file. */
90 {
91 int tr_len = 0;
92 int rec_len = 0;
93 char rec_buf[1000];
94 int connected = 0;
95
96 // while (tr_len != st.st_size) {
97 while (1) {
98 if (WaitForRead(fileno(modemFd), 0)) {
99 if((rec_len = fread(rec_buf, 1, 1, modemFd)) > 0) {
100 if (!connected++) {
101 printf("# connected!\n");
102 }
103 fwrite(rec_buf, rec_len, 1, stdout);
104 }
105 }
106 if (tr_len < st.st_size) {
107 while (!(WaitForWrite(fileno(modemFd), 1000000))) { }
108 fwrite(&buf[tr_len], 1, 1, modemFd);
109 tr_len++;
110 }
111 else if (tr_len++ == st.st_size) {
112 printf("# ...transmission done.\n");
113 }
114 }
115 }
116
117 exit(0);
118
119 do {
120 ret = fwrite(buf, 1, st.st_size, modemFd);
121 printf("Wrote %d bytes of %d.\n", ret, (int)st.st_size);
122 } while(loop);
123 }
124
125 {
126 int rec_len = 0;
127 char rec_buf[1000];
128
129 while (loop) {
130 if (WaitForRead(fileno(modemFd), 1000000)) {
131 if((rec_len = fread(rec_buf, 1, 1, modemFd)) > 0) {
132 fwrite(rec_buf, rec_len, 1, stdout);
133 }
134 }
135 }
136 }
137
138 return 1;
139 }
140
141 /****************************************************************************
142 *#
143 *# FUNCTION NAME: ParseArgs
144 *#
145 *# PARAMETERS: argc,argv
146 *#
147 *# DESCRIPTION:
148 *#
149 *#---------------------------------------------------------------------------
150 *# HISTORY
151 *#
152 *# DATE NAME CHANGES
153 *# ---- ---- -------
154 *# 960930 ronny Initial version
155 *#
156 *#***************************************************************************/
157
158 void
159 ParseArgs (int argc, char *argv[])
160 {
161 int argi;
162
163 for (argi=1; argi < argc; argi++) {
164
165 if (strncmp(argv[argi], "--xonxoff", 9) == 0) {
166 printf("xonxoff\n");
167 xonxoff = TRUE;
168 }
169
170 else if (strncmp(argv[argi], "--crtcts", 8) == 0) {
171 printf("crtcts\n");
172 crtcts = TRUE;
173 }
174
175 else if (strncmp(argv[argi], "--loop", 6) == 0) {
176 printf("loop\n");
177 loop = TRUE;
178 }
179
180 else if (strncmp(argv[argi], "--time", 6) == 0) {
181 dotime = TRUE;
182 got_start = FALSE;
183 }
184
185 else if (strncmp(argv[argi], "--check", 6) == 0) {
186 check = TRUE;
187 }
188
189 else if (strncmp(argv[argi], "--noprint", 9) == 0) {
190 do_print = FALSE;
191 }
192
193 else if (strncmp(argv[argi], "--device", 8) == 0) {
194 if (GetStringOption (&argi, argc, argv, dev, "--device") == 0) {
195 printf("--device name\n");
196 exit(0);
197 }
198 }
199
200 else if (strncmp(argv[argi], "--file", 6) == 0) {
201 if (GetStringOption (&argi, argc, argv, filename, "--file") == 0) {
202 printf("--file name\n");
203 exit(0);
204 }
205 }
206
207 else if (strncmp(argv[argi], "--baudrate", 10) == 0) {
208 if (GetNumberOption (&argi, argc, argv, &set_baudrate, "--baudrate") == 0) {
209 printf("--baudrate baudrate\n");
210 exit(0);
211 }
212 }
213 else {
214 printf("'%s' unknown command\n", argv[argi]);
215 printf("\nsendserial --file fname [--device dname] [--baudrate baudrate] [--xonxoff] [--crtcts]\n\n");
216 printf("%dbps on %s default. No handshake.\n", set_baudrate, dev);
217 exit(1);
218 }
219 }
220 }
221
222 /****************************************************************************
223 *#
224 *# FUNCTION NAME: GetNumberOption
225 *#
226 *# PARAMETERS:
227 *#
228 *# DESCRIPTION:
229 *#
230 *#---------------------------------------------------------------------------
231 *# HISTORY
232 *#
233 *# DATE NAME CHANGES
234 *# ---- ---- -------
235 *# 960930 ronny Initial version
236 *#
237 *#***************************************************************************/
238
239 int
240 GetNumberOption(int *argNr, int argCount, char *argVect[], int *ret, char *option)
241 {
242 int startChar = strlen(option);
243
244 if (strlen(argVect[*argNr]) <= (unsigned int) startChar) {
245 (*argNr)++;
246 startChar = 0;
247 }
248
249 if (*argNr > argCount) {
250 printf("ERROR! The option '%s' needs a number argument.\n", option);
251 return (0);
252 }
253
254 *ret = atoi(&argVect[*argNr][startChar]);
255 return (1);
256
257 }
258
259 /****************************************************************************
260 *#
261 *# FUNCTION NAME: GetStringOption
262 *#
263 *# PARAMETERS: int *argNr : Returns next argc here.
264 *# int argCount : Index of last argument.
265 *# char *argVect[] : argv.
266 *# char *ret : Copy string here.
267 *# char *option : Name of the option.
268 *#
269 *# DESCRIPTION: Extracts a string option from argv, and updates argnr.
270 *# Returns TRUE/FALSE and string in *ret.
271 *#
272 *#---------------------------------------------------------------------------
273 *# HISTORY
274 *#
275 *# DATE NAME CHANGES
276 *# ---- ---- -------
277 *# 960930 ronny Initial version
278 *# 961203 ronny Handles filenames with spaces within 'file name'.
279 *#
280 *#***************************************************************************/
281
282 int
283 GetStringOption(int *argNr, int argCount, char *argVect[], char *ret, char *option)
284 {
285 int startChar = strlen(option);
286 char tmp[256];
287
288 strcpy(ret, "");
289
290 /* Are there any more chars after option? If not skip to next argv. */
291 if (strlen(argVect[*argNr]) <= (unsigned int)startChar) {
292 (*argNr)++;
293 startChar = 0;
294 }
295
296 /* Any args left? */
297 if (*argNr >= argCount) {
298 printf("ERROR! The option '%s' needs a string argument.\n", option);
299 return (FALSE);
300 }
301
302 strcpy(ret, &argVect[*argNr][startChar]);
303
304 if (ret[0] == '\'' || ret[0] == '\"') {
305 if (db3) printf("Inside string\n");
306 strcpy(tmp, &ret[1]);
307 do {
308 if (tmp[strlen(tmp) - 1 ] == '\'' || tmp[strlen(tmp) - 1] == '\"') {
309 tmp[strlen(tmp) - 1] = '\0';
310 break;
311 }
312
313 (*argNr)++;
314
315 if (*argNr >= argCount) {
316 printf("ERROR! Mismatched ' or \" in options.\n");
317 return (FALSE);
318 }
319
320 strcat(tmp, &argVect[*argNr][0]);
321 if (db3) printf("tmp %s\n", tmp);
322 } while (1);
323
324 strcpy(ret, tmp);
325 }
326 if (db4) printf("<<< GetStringOption %s\n", ret);
327 return (TRUE);
328
329 }
330
331 /****************************************************************************
332 *#
333 *# FUNCTION NAME: SetupSerial
334 *#
335 *# PARAMETERS:
336 *#
337 *# DESCRIPTION:
338 *#
339 *#---------------------------------------------------------------------------
340 *# HISTORY
341 *#
342 *# DATE NAME CHANGES
343 *# ---- ---- -------
344 *# 970325 ronny Initial version
345 *#
346 *#***************************************************************************/
347
348 int
349 SetupSerial()
350 {
351
352 struct termios ti;
353 int baudrate;
354
355 if ((modemFd = fopen(dev, "r+")) == NULL) {
356 perror("Can't open modem\n");
357 return(FALSE);
358 }
359
360 /* Important. Remember this!!!!!!! */
361 /* setvbuf(modemFd, NULL, _IONBF, 0); */
362
363 setvbuf(modemFd, NULL, _IONBF, 0);
364 setvbuf(stdout, NULL, _IONBF, 0);
365
366 if (fcntl(fileno(modemFd), F_SETFL, O_NONBLOCK) == -1) {
367 perror("fcntl: ");
368 exit(0);
369 }
370
371 tcflush(fileno(modemFd), TCIOFLUSH);
372
373 if (tcgetattr (fileno(modemFd), &ti)) {
374 perror("tcgetattr");
375 return(FALSE);
376 }
377
378 if (db4) printf("VTIME:%d\n", ti.c_cc[VTIME]);
379 if (db4) printf("VMIN:%d\n", ti.c_cc[VMIN]);
380
381 ti.c_cc[VMIN] = 1;
382 ti.c_cc[VTIME] = 0;
383 ti.c_cc[VSTART] = XON;
384 ti.c_cc[VSTOP] = XOFF;
385
386 if (tcsetattr (fileno(modemFd), TCSANOW, &ti)) {
387 perror("tcsetattr");
388 return(FALSE);
389 }
390
391 //if (db3) printf("outspeed: %d, inspeed: %d\n", baudRates[cfgetospeed(&ti)], baudRates[cfgetispeed(&ti)]);
392 {
393 int new_baudrate = 0;
394
395 if (set_baudrate <= 50) {
396 baudrate = B50;
397 new_baudrate = 50;
398 }
399 else if (set_baudrate <= 75) {
400 baudrate = B75;
401 new_baudrate = 75;
402 }
403 else if (set_baudrate <= 110) {
404 baudrate = B110;
405 new_baudrate = 110;
406 }
407 else if (set_baudrate <= 134) {
408 baudrate = B134;
409 new_baudrate = 134;
410 }
411 else if (set_baudrate <= 150) {
412 baudrate = B150;
413 new_baudrate = 150;
414 }
415 else if (set_baudrate <= 200) {
416 baudrate = B200;
417 new_baudrate = 200;
418 }
419 else if (set_baudrate <= 300) {
420 baudrate = B300;
421 new_baudrate = 300;
422 }
423 else if (set_baudrate <= 600) {
424 baudrate = B600;
425 new_baudrate = 600;
426 }
427 else if (set_baudrate <= 1200) {
428 baudrate = B1200;
429 new_baudrate = 1200;
430 }
431 else if (set_baudrate <= 1800) {
432 baudrate = B1800;
433 new_baudrate = 1800;
434 }
435 else if (set_baudrate <= 2400) {
436 baudrate = B2400;
437 new_baudrate = 2400;
438 }
439 else if (set_baudrate <= 4800) {
440 baudrate = B4800;
441 new_baudrate = 4800;
442 }
443 else if (set_baudrate <= 9600) {
444 baudrate = B9600;
445 new_baudrate = 9600;
446 }
447 else if (set_baudrate <= 19200) {
448 baudrate = B19200;
449 new_baudrate = 19200;
450 }
451 else if (set_baudrate <= 38400)
452 baudrate = B38400;
453 #if defined (B57600) /* POSIX only defines >= 38400 */
454 else if (set_baudrate <= 57600) {
455 baudrate = B57600;
456 new_baudrate = 57600;
457 }
458 #endif
459 #if defined (B115200)
460 else if (set_baudrate <= 115200) {
461 baudrate = B115200;
462 new_baudrate = 115200;
463 }
464 #endif
465 #if defined (B230400)
466 else if (set_baudrate <= 230400) {
467 baudrate = B230400;
468 new_baudrate = 230400;
469 }
470 #endif
471 else {
472 baudrate = B38400;
473 }
474
475 cfsetispeed(&ti, B9600);
476 cfsetospeed(&ti, baudrate);
477 tcsetattr(fileno(modemFd), TCSANOW, &ti);
478
479 // printf("* baudrate set to %d\n", new_baudrate);
480 set_baudrate = new_baudrate;
481
482 if (db3) printf("outspeed: %d, inspeed: %d\n", baudRates[cfgetospeed(&ti)], baudRates[cfgetispeed(&ti)]);
483 }
484
485 cfmakeraw(&ti);
486
487 SetInputMode(modemFd, IXON, FALSE);
488 SetInputMode(modemFd, IXOFF, xonxoff); /* input */
489 SetInputMode(modemFd, IXANY, FALSE);
490 SetInputMode(modemFd, ICRNL, FALSE);
491 SetInputMode(modemFd, IGNPAR, TRUE);
492 SetInputMode(modemFd, IGNBRK, TRUE);
493 SetInputMode(modemFd, IGNPAR, TRUE);
494 SetInputMode(modemFd, INPCK, FALSE);
495
496 SetLocalMode(modemFd, ECHO, FALSE);
497 SetLocalMode(modemFd, ISIG, FALSE);
498
499 SetLocalMode(modemFd, ICANON, FALSE);
500
501 SetControlMode(modemFd, PARENB, FALSE);
502 SetControlMode(modemFd, CLOCAL, TRUE);
503
504 /* Disable hardware flow control. */
505 #if defined(CRTSCTS)
506
507 SetControlMode(modemFd, CRTSCTS, crtcts);
508 #if defined(CRTSXOFF)
509 SetControlMode(modemFd, CRTSXOFF, crtcts);
510 #endif
511
512 #elif defined(CCTS_OFLOW)
513
514 SetControlMode(modemFd, CCTS_OFLOW, crtcts);
515 SetControlMode(modemFd, CRTS_IFLOW, crtcts);
516
517 #elif defined(CNEW_RTSCTS)
518
519 SetControlMode(modemFd, CNEW_RTSCTS, crtcts);
520
521 #else
522 printf("Cannot set hardware flow control. Set it manually with a terminal program.\n");
523 #endif
524
525 return(TRUE);
526
527 }
528
529 /****************************************************************************
530 *#
531 *# FUNCTION NAME: SetInputMode
532 *#
533 *# PARAMETERS:
534 *#
535 *# DESCRIPTION:
536 *#
537 *#---------------------------------------------------------------------------
538 *# HISTORY
539 *#
540 *# DATE NAME CHANGES
541 *# ---- ---- -------
542 *# 970325 ronny Initial version
543 *#
544 *#***************************************************************************/
545
546 int
547 SetInputMode (FILE *fd, int value, int onoff)
548 {
549 struct termios settings;
550 int result;
551
552 result = tcgetattr(fileno(fd), &settings);
553 if (result < 0)
554 {
555 perror ("error in tcgetattr");
556 return (FALSE);
557 }
558
559 if (onoff)
560 settings.c_iflag |= value;
561 else
562 settings.c_iflag &= ~value;
563
564 result = tcsetattr(fileno(fd), TCSANOW, &settings);
565 if (result < 0)
566 {
567 perror ("error in tcgetattr");
568 return(FALSE);
569 }
570
571 return 1;
572 }
573
574 /****************************************************************************
575 *#
576 *# FUNCTION NAME: SetControlMode
577 *#
578 *# PARAMETERS:
579 *#
580 *# DESCRIPTION:
581 *#
582 *#---------------------------------------------------------------------------
583 *# HISTORY
584 *#
585 *# DATE NAME CHANGES
586 *# ---- ---- -------
587 *# 970325 ronny Initial version
588 *#
589 *#***************************************************************************/
590
591 int
592 SetControlMode (FILE *fd, int value, int onoff)
593 {
594
595 #if !defined(_WIN32)
596
597 struct termios settings;
598 int result;
599
600 result = tcgetattr (fileno(fd), &settings);
601 if (result < 0)
602 {
603 perror ("error in tcgetattr");
604 return (FALSE);
605 }
606
607 if (onoff)
608 settings.c_cflag |= value;
609 else
610 settings.c_cflag &= ~value;
611
612 result = tcsetattr (fileno(fd), TCSANOW, &settings);
613 if (result < 0)
614 {
615 perror ("error in tcgetattr");
616 return(FALSE);
617 }
618
619 #endif
620
621 return (TRUE);
622 }
623 /****************************************************************************
624 *#
625 *# FUNCTION NAME: SetLocalMode
626 *#
627 *# PARAMETERS:
628 *#
629 *# DESCRIPTION:
630 *#
631 *#---------------------------------------------------------------------------
632 *# HISTORY
633 *#
634 *# DATE NAME CHANGES
635 *# ---- ---- -------
636 *# 970325 ronny Initial version
637 *#
638 *#***************************************************************************/
639
640 int
641 SetLocalMode (FILE *fd, int value, int onoff)
642 {
643
644 #if !defined(_WIN32)
645
646 struct termios settings;
647 int result;
648
649 result = tcgetattr (fileno(fd), &settings);
650 if (result < 0)
651 {
652 perror ("error in tcgetattr");
653 return (FALSE);
654 }
655
656 if (onoff)
657 settings.c_lflag |= value;
658 else
659 settings.c_lflag &= ~value;
660
661 result = tcsetattr (fileno(fd), TCSANOW, &settings);
662 if (result < 0)
663 {
664 perror ("error in tcgetattr");
665 return(FALSE);
666 }
667
668 #endif
669
670 return (TRUE);
671 }
672
673 /****************************************************************************
674 *#
675 *# FUNCTION NAME: WaitForRead
676 *#
677 *# PARAMETERS:
678 *#
679 *# DESCRIPTION:
680 *#
681 *#---------------------------------------------------------------------------
682 *# HISTORY
683 *#
684 *# DATE NAME CHANGES
685 *# ---- ---- -------
686 *# 961001 ronny Initial version
687 *# 971204 ronny usecs was a only one tenth of what it should be.
688 *#
689 *#***************************************************************************/
690
691 int
692 WaitForRead(int s, int usecs)
693 {
694 fd_set mask;
695 int ret;
696 struct timeval tm;
697
698 tm.tv_sec = usecs/1000000;
699 tm.tv_usec = usecs%1000000;
700
701 FD_ZERO(&mask);
702 FD_SET(s, &mask);
703
704 if ((ret = select(FD_SETSIZE, &mask, NULL, NULL, &tm)) == -1) {
705 printf("<<< select failed with return: %d.\n", ret);
706 return(FALSE);
707 }
708 else {
709 if (db3) printf("* select returned OK:%d\n", ret);
710 }
711
712 if (FD_ISSET(s, &mask) == 0) {
713 if (db2) printf("<<< WaitForRead. No data to read.\n");
714 return (FALSE);
715 }
716
717 if (db3) printf("<<< WaitForRead OK. Returned:%d.\n", ret);
718
719 return(TRUE);
720 }
721
722 /****************************************************************************
723 *#
724 *# FUNCTION NAME: WaitForWrite
725 *#
726 *# PARAMETERS:
727 *#
728 *# DESCRIPTION:
729 *#
730 *#---------------------------------------------------------------------------
731 *# HISTORY
732 *#
733 *# DATE NAME CHANGES
734 *# ---- ---- -------
735 *# 2000-11-20 ronny Initial version
736 *#
737 *#***************************************************************************/
738
739 int
740 WaitForWrite(int s, int usecs)
741 {
742 fd_set mask;
743 int ret;
744 struct timeval tm;
745
746 tm.tv_sec = usecs/1000000;
747 tm.tv_usec = usecs%1000000;
748
749 FD_ZERO(&mask);
750 FD_SET(s, &mask);
751
752 if ((ret = select(FD_SETSIZE, NULL, &mask, NULL, &tm)) == -1) {
753 printf("<<< select failed with return: %d.\n", ret);
754 return(FALSE);
755 }
756 else {
757 if (db3) printf("* select returned OK:%d\n", ret);
758 }
759
760 if (FD_ISSET(s, &mask) == 0) {
761 if (db2) printf("<<< WaitForWrite. No data to read.\n");
762 return (FALSE);
763 }
764
765 if (db3) printf("<<< WaitForWrite OK. Returned:%d.\n", ret);
766
767 return(TRUE);
768 }
769