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
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
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 *---------------------------------------------------------------------------*/
49 #include <sys/ioctl.h>
50 #include <sys/types.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);
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);
74 char outgoingnumber[32];
75 char incomingnumber[32];
78 #define I4BDEVICE "/dev/i4b"
79 #define DATADEV0 "/dev/i4brbch0"
81 #define DATADEV1 "/dev/i4brbch1"
84 unsigned int out_cdid = CDID_UNUSED;
85 unsigned int in_cdid = CDID_UNUSED;
92 /*---------------------------------------------------------------------------*
93 * usage display and exit
94 *---------------------------------------------------------------------------*/
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");
112 /*---------------------------------------------------------------------------*
114 *---------------------------------------------------------------------------*/
116 main(int argc, char **argv)
124 incomingnumber[0] = '\0';
125 outgoingnumber[0] = '\0';
127 while ((c = getopt(argc, argv, "c:d:hi:o:t:w")) != -1)
134 controller = strtoul(optarg, NULL, 10);
138 fprintf(stderr, "Error: option -c requires a numeric argument!\n");
146 debug_level = strtoul(optarg, NULL, 10);
150 fprintf(stderr, "Error: option -d requires a numeric argument!\n");
163 outgoingnumber[i++] = *ptr++;
167 fprintf(stderr, "Error: option -o requires a numeric argument!\n");
171 outgoingnumber[i] = '\0';
182 incomingnumber[i++] = *ptr++;
186 fprintf(stderr, "Error: option -i requires a numeric argument!\n");
190 incomingnumber[i] = '\0';
204 dotest = strtoul(optarg, NULL, 10);
208 fprintf(stderr, "Error: option -t requires a numeric argument!\n");
220 if((strlen(incomingnumber) == 0) || (strlen(outgoingnumber) == 0))
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));
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");
242 if((out_cdid = get_cdid(isdnfd)) == 0)
244 fprintf(stderr, "isdntest: error getting cdid: %s\n", strerror(errno));
248 if((connect_request(isdnfd, out_cdid)) == -1)
250 fprintf(stderr, "isdntest: error, outgoing call failed!\n");
260 FD_SET(isdnfd, &set);
262 ret = select(isdnfd + 1, &set, NULL, NULL, NULL);
266 if(FD_ISSET(isdnfd, &set))
269 if(FD_ISSET(0, &set))
274 fprintf(stderr, "isdntest: select error: %s\n", strerror(errno));
279 /*---------------------------------------------------------------------------*
280 * data from keyboard available
281 *---------------------------------------------------------------------------*/
289 /*---------------------------------------------------------------------------*
290 * data from /dev/isdn available, read and process them
291 *---------------------------------------------------------------------------*/
293 isdnrdhdl(int isdnfd)
295 static unsigned char buf[1024];
298 if((len = read(isdnfd, buf, 1024 - 1)) > 0)
302 case MSG_CONNECT_IND:
303 handle_connect_ind(&buf[0]);
306 case MSG_CONNECT_ACTIVE_IND:
307 handle_connect_active_ind(&buf[0]);
310 case MSG_DISCONNECT_IND:
311 handle_disconnect(&buf[0]);
316 fprintf(stderr, "isdntest: unknown message 0x%x = %c\n", buf[0], buf[0]);
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;
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() */
342 mcr.bprot = BPROT_RHDLC;/* b channel protocol */
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));
357 fprintf(stderr, "isdntest: calling out to telephone number [%s] \n", outgoingnumber);
361 /*---------------------------------------------------------------------------*
362 * handle setup indicator
363 *---------------------------------------------------------------------------*/
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",
373 fprintf(stderr, " channel %d, controller %d, bprot %d, cdid %d\n",
379 in_cdid = msi->header.cdid;
381 if(strcmp(msi->dst_telno, outgoingnumber))
383 msg_connect_resp_t msr;
386 fprintf(stderr, "isdntest: ignoring incoming SETUP: my number [%s] != outgoing [%s]\n",
387 msi->dst_telno, outgoingnumber);
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));
401 msg_connect_resp_t msr;
404 fprintf(stderr, "isdntest: accepting call, sending CONNECT_RESPONSE .....\n");
407 msr.response = SETUP_RESP_ACCEPT;
410 msr.bprot = BPROT_RHDLC;
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));
427 /*---------------------------------------------------------------------------*
428 * handle connection active
429 *---------------------------------------------------------------------------*/
431 handle_connect_active_ind(unsigned char *ptr)
433 msg_connect_active_ind_t *msi = (msg_connect_active_ind_t *)ptr;
436 fprintf(stderr, "isdntest: connection active, cdid %d\n", msi->header.cdid);
438 if(out_cdid == msi->header.cdid)
442 fprintf(stderr, "isdntest: press any key to disconnect ...%c%c%c\n", 0x07, 0x07, 0x07);
453 fprintf(stderr, "isdntest: %d secs delay until disconnect:", SLEEPTIME);
455 for(i=0; i < SLEEPTIME;i++)
457 fprintf(stderr, " .");
460 fprintf(stderr, "\n");
468 /*---------------------------------------------------------------------------*
469 * handle disconnect indication
470 *---------------------------------------------------------------------------*/
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;
491 fprintf(stderr, "isdntest: incoming disconnect indication, cdid %d (??\?), cause %d\n",
492 mdi->header.cdid, mdi->cause);
496 /*---------------------------------------------------------------------------*
498 *---------------------------------------------------------------------------*/
500 disconnect_request(int isdnfd, unsigned int cdid)
502 msg_discon_req_t mdr;
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));
513 fprintf(stderr, "isdntest: sending disconnect request\n");
517 /*---------------------------------------------------------------------------*
518 * get cdid from kernel
519 *---------------------------------------------------------------------------*/
528 if((ret = ioctl(isdnfd, I4B_CDID_REQ, &mcr)) < 0)
530 fprintf(stderr, "ioctl I4B_CDID_REQ failed: %s", strerror(errno));
533 fprintf(stderr, "isdntest: got cdid %d from kernel\n", mcr.cdid);
537 /*---------------------------------------------------------------------------*
538 * make shure all cdid's are inactive before leaving
539 *---------------------------------------------------------------------------*/
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))
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)
561 case MSG_CONNECT_IND:
562 handle_connect_ind(&buf[0]);
565 case MSG_CONNECT_ACTIVE_IND:
566 handle_connect_active_ind(&buf[0]);
569 case MSG_DISCONNECT_IND:
570 handle_disconnect(&buf[0]);
575 fprintf(stderr, "isdntest: unknown message 0x%x = %c\n", buf[0], buf[0]);
581 fprintf(stderr, "isdntest: read error, errno = %d, length = %d", errno, len);
585 fprintf(stderr, "isdntest: exit cleanup, out_cdid %d, in_cdid %d\n", out_cdid, in_cdid);
588 /*---------------------------------------------------------------------------*
589 * test the b-channels
590 *---------------------------------------------------------------------------*/
599 unsigned char wrbuf[2048];
600 unsigned char rdbuf[2048];
603 struct timeval timeout;
613 if((fd0 = open(DATADEV0, O_RDWR)) == -1)
615 fprintf(stderr, "open of %s failed: %s", DATADEV0, strerror(errno));
619 if((fd1 = open(DATADEV1, O_RDWR)) == -1)
621 fprintf(stderr, "open of %s failed: %s", DATADEV1, strerror(errno));
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]);
643 printf("%6d %4d", frame, frm_len);
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));
659 ret = select(fd1+1, &set, NULL, NULL, &timeout);
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);
676 printf(" %6d %10d %4d %2.2d:%2.2d:%2.2d \r",
678 (int)((int)bytecnt/(int)run_time),
679 (int)run_time/3600, (int)run_time/60, (int)run_time%60);
682 errcnt += check_rd(frm_len, &wrbuf[0], &rdbuf[0]);
687 printf("0x%02x ", (unsigned char)rdbuf[i]);
693 if(FD_ISSET(0, &set))
701 fprintf(stderr, "isdntest, do_test: select error: %s\n", strerror(errno));
714 setup_wrfix(int len, unsigned char *buf)
729 check_rd(int len, unsigned char *wbuf, unsigned char *rbuf)
738 fprintf(stderr, "\nERROR, byte %d, written 0x%02x, read 0x%02x\n", i, *wbuf, *rbuf);