gcc41: update README.DELETED
[dragonfly.git] / usr.sbin / i4b / isdntest / main.c
blob6994953d8e1b01cd35b683daf93703579f69fd36
1 /*
2 * Copyright (c) 1997, 1999 Hellmuth Michaelis. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
25 *---------------------------------------------------------------------------
27 * main.c - i4b selftest utility
28 * -----------------------------
30 * $Id: main.c,v 1.16 2000/03/13 16:18:38 hm Exp $
32 * $FreeBSD: src/usr.sbin/i4b/isdntest/main.c,v 1.7.2.1 2001/08/01 17:45:07 obrien Exp $
33 * $DragonFly: src/usr.sbin/i4b/isdntest/main.c,v 1.6 2006/03/18 19:43:18 swildner Exp $
35 * last edit-date: [Mon Mar 13 17:19:26 2000]
37 *---------------------------------------------------------------------------*/
39 #include <stdio.h>
40 #include <signal.h>
41 #include <errno.h>
42 #include <string.h>
43 #include <stdlib.h>
44 #include <unistd.h>
45 #include <fcntl.h>
46 #include <ctype.h>
47 #include <sys/stat.h>
48 #include <sys/wait.h>
49 #include <sys/ioctl.h>
50 #include <sys/types.h>
51 #include <sys/time.h>
53 #include <i4b_machine/i4b_ioctl.h>
54 #include <i4b_machine/i4b_cause.h>
56 static void kbdrdhdl ( void );
57 static void isdnrdhdl (int isdnfd );
59 void handle_connect_ind(unsigned char *ptr);
60 void handle_disconnect(unsigned char *ptr);
61 void handle_connect_active_ind(unsigned char *ptr);
63 int connect_response(int isdnfd, unsigned int cdid, int response);
64 int disconnect_request(int isdnfd, unsigned int cdid);
65 unsigned int get_cdid(int isdnfd);
66 int connect_request(int isdnfd, unsigned int cdid);
67 int do_test(void);
68 static void cleanup(void);
69 static void usage(void);
70 void setup_wrfix(int len, unsigned char *buf);
71 int check_rd(int len, unsigned char *wbuf, unsigned char *rdbuf);
73 static int isdnfd;
74 char outgoingnumber[32];
75 char incomingnumber[32];
76 int debug_level = 0;
78 #define I4BDEVICE "/dev/i4b"
79 #define DATADEV0 "/dev/i4brbch0"
80 #define DATAUNIT0 0
81 #define DATADEV1 "/dev/i4brbch1"
82 #define DATAUNIT1 1
84 unsigned int out_cdid = CDID_UNUSED;
85 unsigned int in_cdid = CDID_UNUSED;
87 int waitchar = 0;
88 int usehdlc = 0;
89 int controller = 0;
90 int dotest = 0;
92 /*---------------------------------------------------------------------------*
93 * usage display and exit
94 *---------------------------------------------------------------------------*/
95 static void
96 usage(void)
98 fprintf(stderr, "\n");
99 fprintf(stderr, "isdntest - i4b selftest, version %d.%d.%d, compiled %s %s\n",VERSION, REL, STEP, __DATE__, __TIME__);
100 fprintf(stderr, "usage: isdntest [-c ctrl] [-d level] [-h] [-i telno] [-o telno] [-t num] [-w]\n");
101 fprintf(stderr, " -c <ctrl> specify controller to use\n");
102 fprintf(stderr, " -d <level> set debug level\n");
103 fprintf(stderr, " -h use HDLC as Bchannel protocol\n");
104 fprintf(stderr, " -i <telno> incoming telephone number\n");
105 fprintf(stderr, " -o <telno> outgoing telephone number\n");
106 fprintf(stderr, " -t <num> send test pattern num times\n");
107 fprintf(stderr, " -w wait for keyboard entry to disconnect\n");
108 fprintf(stderr, "\n");
109 exit(1);
112 /*---------------------------------------------------------------------------*
113 * program entry
114 *---------------------------------------------------------------------------*/
116 main(int argc, char **argv)
118 int i;
119 int c;
120 fd_set set;
121 int ret;
122 char *ptr;
124 incomingnumber[0] = '\0';
125 outgoingnumber[0] = '\0';
127 while ((c = getopt(argc, argv, "c:d:hi:o:t:w")) != -1)
129 switch(c)
131 case 'c':
132 if(isdigit(*optarg))
134 controller = strtoul(optarg, NULL, 10);
136 else
138 fprintf(stderr, "Error: option -c requires a numeric argument!\n");
139 usage();
141 break;
143 case 'd':
144 if(isdigit(*optarg))
146 debug_level = strtoul(optarg, NULL, 10);
148 else
150 fprintf(stderr, "Error: option -d requires a numeric argument!\n");
151 usage();
153 break;
155 case 'o':
156 i = 0;
157 ptr = optarg;
159 while(*ptr)
161 if(isdigit(*ptr))
163 outgoingnumber[i++] = *ptr++;
165 else
167 fprintf(stderr, "Error: option -o requires a numeric argument!\n");
168 usage();
171 outgoingnumber[i] = '\0';
172 break;
174 case 'i':
175 i = 0;
176 ptr = optarg;
178 while(*ptr)
180 if(isdigit(*ptr))
182 incomingnumber[i++] = *ptr++;
184 else
186 fprintf(stderr, "Error: option -i requires a numeric argument!\n");
187 usage();
190 incomingnumber[i] = '\0';
191 break;
193 case 'w':
194 waitchar = 1;
195 break;
197 case 'h':
198 usehdlc = 1;
199 break;
201 case 't':
202 if(isdigit(*optarg))
204 dotest = strtoul(optarg, NULL, 10);
206 else
208 fprintf(stderr, "Error: option -t requires a numeric argument!\n");
209 usage();
211 break;
213 case '?':
214 default:
215 usage();
216 break;
220 if((strlen(incomingnumber) == 0) || (strlen(outgoingnumber) == 0))
221 usage();
223 fprintf(stderr, "isdntest: accepting calls from telephone number [%s] \n", incomingnumber);
224 fprintf(stderr, "isdntest: calling out telephone number [%s] \n", outgoingnumber);
226 if((atexit(cleanup)) != 0)
228 fprintf(stderr, "isdntest: atexit error: %s\n", strerror(errno));
229 exit(1);
232 /* open isdn device */
234 if((isdnfd = open(I4BDEVICE, O_RDWR)) < 0)
236 fprintf(stderr, "\nisdntest: cannot open %s: %s\n", I4BDEVICE, strerror(errno));
237 fprintf(stderr, " isdnd is probably running, to use isdntest,\n");
238 fprintf(stderr, " terminate isdnd and then run isdntest again!\n");
239 exit(1);
242 if((out_cdid = get_cdid(isdnfd)) == 0)
244 fprintf(stderr, "isdntest: error getting cdid: %s\n", strerror(errno));
245 exit(1);
248 if((connect_request(isdnfd, out_cdid)) == -1)
250 fprintf(stderr, "isdntest: error, outgoing call failed!\n");
251 exit(1);
254 for(;;)
256 FD_ZERO(&set);
258 FD_SET(0, &set);
260 FD_SET(isdnfd, &set);
262 ret = select(isdnfd + 1, &set, NULL, NULL, NULL);
264 if(ret > 0)
266 if(FD_ISSET(isdnfd, &set))
267 isdnrdhdl(isdnfd);
269 if(FD_ISSET(0, &set))
270 kbdrdhdl();
272 else
274 fprintf(stderr, "isdntest: select error: %s\n", strerror(errno));
279 /*---------------------------------------------------------------------------*
280 * data from keyboard available
281 *---------------------------------------------------------------------------*/
282 static void
283 kbdrdhdl(void)
285 cleanup();
286 exit(2);
289 /*---------------------------------------------------------------------------*
290 * data from /dev/isdn available, read and process them
291 *---------------------------------------------------------------------------*/
292 static void
293 isdnrdhdl(int isdnfd)
295 static unsigned char buf[1024];
296 int len;
298 if((len = read(isdnfd, buf, 1024 - 1)) > 0)
300 switch (buf[0])
302 case MSG_CONNECT_IND:
303 handle_connect_ind(&buf[0]);
304 break;
306 case MSG_CONNECT_ACTIVE_IND:
307 handle_connect_active_ind(&buf[0]);
308 break;
310 case MSG_DISCONNECT_IND:
311 handle_disconnect(&buf[0]);
312 break;
314 default:
315 if(debug_level)
316 fprintf(stderr, "isdntest: unknown message 0x%x = %c\n", buf[0], buf[0]);
317 break;
320 else
322 fprintf(stderr, "isdntest: read error, errno = %d, length = %d", errno, len);
326 /*---------------------------------------------------------------------------*
327 * initiate an outgoing connection
328 *---------------------------------------------------------------------------*/
330 connect_request(int isdnfd, unsigned int cdid)
332 msg_connect_req_t mcr;
333 int ret;
335 bzero(&mcr, sizeof(msg_connect_req_t));
337 mcr.controller = controller;
338 mcr.channel = CHAN_ANY; /* any channel */
339 mcr.cdid = cdid; /* cdid from get_cdid() */
341 if(usehdlc)
342 mcr.bprot = BPROT_RHDLC;/* b channel protocol */
343 else
344 mcr.bprot = BPROT_NONE; /* b channel protocol */
346 mcr.driver = BDRV_RBCH; /* raw b channel driver */
347 mcr.driver_unit = DATAUNIT0; /* raw b channel driver unit */
349 strcpy(mcr.dst_telno, outgoingnumber);
350 strcpy(mcr.src_telno, incomingnumber);
352 if((ret = ioctl(isdnfd, I4B_CONNECT_REQ, &mcr)) < 0)
354 fprintf(stderr, "ioctl I4B_CONNECT_REQ failed: %s", strerror(errno));
355 return(-1);
357 fprintf(stderr, "isdntest: calling out to telephone number [%s] \n", outgoingnumber);
358 return(0);
361 /*---------------------------------------------------------------------------*
362 * handle setup indicator
363 *---------------------------------------------------------------------------*/
364 void
365 handle_connect_ind(unsigned char *ptr)
367 msg_connect_ind_t *msi = (msg_connect_ind_t *)ptr;
369 fprintf(stderr, "isdntest: incoming SETUP: from %s to %s\n",
370 msi->src_telno,
371 msi->dst_telno);
373 fprintf(stderr, " channel %d, controller %d, bprot %d, cdid %d\n",
374 msi->channel,
375 msi->controller,
376 msi->bprot,
377 msi->header.cdid);
379 in_cdid = msi->header.cdid;
381 if(strcmp(msi->dst_telno, outgoingnumber))
383 msg_connect_resp_t msr;
384 int ret;
386 fprintf(stderr, "isdntest: ignoring incoming SETUP: my number [%s] != outgoing [%s]\n",
387 msi->dst_telno, outgoingnumber);
389 msr.cdid = in_cdid;
390 msr.response = SETUP_RESP_DNTCRE;
392 if((ret = ioctl(isdnfd, I4B_CONNECT_RESP, &msr)) < 0)
394 fprintf(stderr, "ioctl I4B_CONNECT_RESP ignore failed: %s", strerror(errno));
395 exit(1);
399 else
401 msg_connect_resp_t msr;
402 int ret;
404 fprintf(stderr, "isdntest: accepting call, sending CONNECT_RESPONSE .....\n");
406 msr.cdid = in_cdid;
407 msr.response = SETUP_RESP_ACCEPT;
409 if(usehdlc)
410 msr.bprot = BPROT_RHDLC;
411 else
412 msr.bprot = BPROT_NONE;
414 msr.driver = BDRV_RBCH;
415 msr.driver_unit = DATAUNIT1;
417 if((ret = ioctl(isdnfd, I4B_CONNECT_RESP, &msr)) < 0)
419 fprintf(stderr, "ioctl I4B_CONNECT_RESP accept failed: %s", strerror(errno));
420 exit(1);
425 #define SLEEPTIME 5
427 /*---------------------------------------------------------------------------*
428 * handle connection active
429 *---------------------------------------------------------------------------*/
430 void
431 handle_connect_active_ind(unsigned char *ptr)
433 msg_connect_active_ind_t *msi = (msg_connect_active_ind_t *)ptr;
434 int i;
436 fprintf(stderr, "isdntest: connection active, cdid %d\n", msi->header.cdid);
438 if(out_cdid == msi->header.cdid)
440 if(waitchar)
442 fprintf(stderr, "isdntest: press any key to disconnect ...%c%c%c\n", 0x07, 0x07, 0x07);
443 getchar();
445 else
447 if(dotest)
449 do_test();
451 else
453 fprintf(stderr, "isdntest: %d secs delay until disconnect:", SLEEPTIME);
455 for(i=0; i < SLEEPTIME;i++)
457 fprintf(stderr, " .");
458 sleep(1);
460 fprintf(stderr, "\n");
462 cleanup();
463 exit(0);
468 /*---------------------------------------------------------------------------*
469 * handle disconnect indication
470 *---------------------------------------------------------------------------*/
471 void
472 handle_disconnect(unsigned char *ptr)
474 msg_disconnect_ind_t *mdi = (msg_disconnect_ind_t *)ptr;
476 if(mdi->header.cdid == out_cdid)
478 fprintf(stderr, "isdntest: incoming disconnect indication, cdid %d (out_cdid), cause %d\n",
479 mdi->header.cdid, mdi->cause);
481 out_cdid = CDID_UNUSED;
483 else if(mdi->header.cdid == in_cdid)
485 fprintf(stderr, "isdntest: incoming disconnect indication, cdid %d (in_cdid), cause %d\n",
486 mdi->header.cdid, mdi->cause);
487 in_cdid = CDID_UNUSED;
489 else
491 fprintf(stderr, "isdntest: incoming disconnect indication, cdid %d (??\?), cause %d\n",
492 mdi->header.cdid, mdi->cause);
496 /*---------------------------------------------------------------------------*
497 * hang up
498 *---------------------------------------------------------------------------*/
500 disconnect_request(int isdnfd, unsigned int cdid)
502 msg_discon_req_t mdr;
503 int ret;
505 mdr.cdid = cdid;
506 mdr.cause = (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL;
508 if((ret = ioctl(isdnfd, I4B_DISCONNECT_REQ, &mdr)) < 0)
510 fprintf(stderr, "ioctl I4B_DISCONNECT_REQ failed: %s", strerror(errno));
511 return(-1);
513 fprintf(stderr, "isdntest: sending disconnect request\n");
514 return(0);
517 /*---------------------------------------------------------------------------*
518 * get cdid from kernel
519 *---------------------------------------------------------------------------*/
520 unsigned int
521 get_cdid(int isdnfd)
523 msg_cdid_req_t mcr;
524 int ret;
526 mcr.cdid = 0;
528 if((ret = ioctl(isdnfd, I4B_CDID_REQ, &mcr)) < 0)
530 fprintf(stderr, "ioctl I4B_CDID_REQ failed: %s", strerror(errno));
531 return(0);
533 fprintf(stderr, "isdntest: got cdid %d from kernel\n", mcr.cdid);
534 return(mcr.cdid);
537 /*---------------------------------------------------------------------------*
538 * make shure all cdid's are inactive before leaving
539 *---------------------------------------------------------------------------*/
540 void
541 cleanup(void)
543 int len;
544 char buf[1024];
546 if(out_cdid != CDID_UNUSED)
548 fprintf(stderr, "isdntest: cleanup, send disconnect req for out_cdid %d, in_cdid %d\n", out_cdid, in_cdid);
549 disconnect_request(isdnfd, out_cdid);
552 while((out_cdid != CDID_UNUSED) || (in_cdid != CDID_UNUSED))
554 if(debug_level)
555 fprintf(stderr, "isdntest: cleanup, out_cdid %d, in_cdid %d\n", out_cdid, in_cdid);
557 if((len = read(isdnfd, buf, 1024 - 1)) > 0)
559 switch (buf[0])
561 case MSG_CONNECT_IND:
562 handle_connect_ind(&buf[0]);
563 break;
565 case MSG_CONNECT_ACTIVE_IND:
566 handle_connect_active_ind(&buf[0]);
567 break;
569 case MSG_DISCONNECT_IND:
570 handle_disconnect(&buf[0]);
571 break;
573 default:
574 if(debug_level)
575 fprintf(stderr, "isdntest: unknown message 0x%x = %c\n", buf[0], buf[0]);
576 break;
579 else
581 fprintf(stderr, "isdntest: read error, errno = %d, length = %d", errno, len);
584 if(debug_level)
585 fprintf(stderr, "isdntest: exit cleanup, out_cdid %d, in_cdid %d\n", out_cdid, in_cdid);
588 /*---------------------------------------------------------------------------*
589 * test the b-channels
590 *---------------------------------------------------------------------------*/
592 do_test(void)
595 #define FPH 0x3c
596 #define FPL 0x66
598 int fd0, fd1;
599 unsigned char wrbuf[2048];
600 unsigned char rdbuf[2048];
601 int sz;
602 fd_set set;
603 struct timeval timeout;
604 int ret;
605 int frame;
606 int errcnt;
607 int frm_len;
608 int bytecnt = 0;
609 time_t start_time;
610 time_t cur_time;
611 time_t run_time;
613 if((fd0 = open(DATADEV0, O_RDWR)) == -1)
615 fprintf(stderr, "open of %s failed: %s", DATADEV0, strerror(errno));
616 return(-1);
619 if((fd1 = open(DATADEV1, O_RDWR)) == -1)
621 fprintf(stderr, "open of %s failed: %s", DATADEV1, strerror(errno));
622 return(-1);
625 printf("\n");
626 frame = 0;
627 errcnt = 0;
629 frm_len = 2;
631 start_time = time(NULL);
633 printf(" frame size errors totalbytes bps elapsedtime\n");
635 for(;dotest > 0; dotest--)
637 setup_wrfix(frm_len, &wrbuf[0]);
639 frame++;
641 bytecnt += frm_len;
643 printf("%6d %4d", frame, frm_len);
644 fflush(stdout);
646 if((sz = write(fd0, wrbuf, frm_len)) != frm_len)
648 fprintf(stderr, "write (%d of %d bytes) to %s failed: %s\n", sz, frm_len, DATADEV0, strerror(errno));
651 timeout.tv_sec = 2;
652 timeout.tv_usec = 0;
654 FD_ZERO(&set);
656 FD_SET(0, &set);
657 FD_SET(fd1, &set);
659 ret = select(fd1+1, &set, NULL, NULL, &timeout);
661 if(ret > 0)
663 if(FD_ISSET(fd1, &set))
665 if((sz = read(fd1, rdbuf, 2048)) != frm_len)
667 fprintf(stderr, "read (%d bytes) from %s failed: %s\n", sz, DATADEV1, strerror(errno));
670 cur_time = time(NULL);
671 run_time = difftime(cur_time, start_time);
673 if(run_time == 0)
674 run_time = 1;
676 printf(" %6d %10d %4d %2.2d:%2.2d:%2.2d \r",
677 errcnt, bytecnt,
678 (int)((int)bytecnt/(int)run_time),
679 (int)run_time/3600, (int)run_time/60, (int)run_time%60);
680 fflush(stdout);
682 errcnt += check_rd(frm_len, &wrbuf[0], &rdbuf[0]);
684 #ifdef NOTDEF
685 for(i=0; i<sz; i++)
687 printf("0x%02x ", (unsigned char)rdbuf[i]);
689 printf("\n");
690 #endif
693 if(FD_ISSET(0, &set))
695 return(0);
696 printf("\n\n");
699 else
701 fprintf(stderr, "isdntest, do_test: select error: %s\n", strerror(errno));
704 frm_len = frm_len*2;
705 if(frm_len > 2048)
706 frm_len = 2;
709 printf("\n\n");
710 return(0);
713 void
714 setup_wrfix(int len, unsigned char *buf)
716 int i;
718 for(i=0; i<len;)
720 *buf = FPH;
721 buf++;
722 *buf = FPL;
723 buf++;
724 i+=2;
728 int
729 check_rd(int len, unsigned char *wbuf, unsigned char *rbuf)
731 int i;
732 int ret = 0;
734 for(i=0; i<len; i++)
736 if(*wbuf != *rbuf)
738 fprintf(stderr, "\nERROR, byte %d, written 0x%02x, read 0x%02x\n", i, *wbuf, *rbuf);
739 ret++;
741 wbuf++;
742 rbuf++;
744 return(ret);
748 /* EOF */