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 $
34 * last edit-date: [Mon Mar 13 17:19:26 2000]
36 *---------------------------------------------------------------------------*/
48 #include <sys/ioctl.h>
49 #include <sys/types.h>
52 #include <machine/i4b_ioctl.h>
53 #include <machine/i4b_cause.h>
55 static void kbdrdhdl ( void );
56 static void isdnrdhdl (int isdnfd );
58 void handle_connect_ind(unsigned char *ptr);
59 void handle_disconnect(unsigned char *ptr);
60 void handle_connect_active_ind(unsigned char *ptr);
62 int connect_response(int isdnfd, unsigned int cdid, int response);
63 int disconnect_request(int isdnfd, unsigned int cdid);
64 unsigned int get_cdid(int isdnfd);
65 int connect_request(int isdnfd, unsigned int cdid);
67 static void cleanup(void);
68 static void usage(void);
69 void setup_wrfix(int len, unsigned char *buf);
70 int check_rd(int len, unsigned char *wbuf, unsigned char *rdbuf);
73 char outgoingnumber[32];
74 char incomingnumber[32];
77 #define I4BDEVICE "/dev/i4b"
78 #define DATADEV0 "/dev/i4brbch0"
80 #define DATADEV1 "/dev/i4brbch1"
83 unsigned int out_cdid = CDID_UNUSED;
84 unsigned int in_cdid = CDID_UNUSED;
91 /*---------------------------------------------------------------------------*
92 * usage display and exit
93 *---------------------------------------------------------------------------*/
97 fprintf(stderr, "\n");
98 fprintf(stderr, "isdntest - i4b selftest, version %d.%d.%d, compiled %s %s\n",VERSION, REL, STEP, __DATE__, __TIME__);
99 fprintf(stderr, "usage: isdntest [-c ctrl] [-d level] [-h] [-i telno] [-o telno] [-t num] [-w]\n");
100 fprintf(stderr, " -c <ctrl> specify controller to use\n");
101 fprintf(stderr, " -d <level> set debug level\n");
102 fprintf(stderr, " -h use HDLC as Bchannel protocol\n");
103 fprintf(stderr, " -i <telno> incoming telephone number\n");
104 fprintf(stderr, " -o <telno> outgoing telephone number\n");
105 fprintf(stderr, " -t <num> send test pattern num times\n");
106 fprintf(stderr, " -w wait for keyboard entry to disconnect\n");
107 fprintf(stderr, "\n");
111 /*---------------------------------------------------------------------------*
113 *---------------------------------------------------------------------------*/
115 main(int argc, char **argv)
123 incomingnumber[0] = '\0';
124 outgoingnumber[0] = '\0';
126 while ((c = getopt(argc, argv, "c:d:hi:o:t:w")) != -1)
133 controller = strtoul(optarg, NULL, 10);
137 fprintf(stderr, "Error: option -c requires a numeric argument!\n");
145 debug_level = strtoul(optarg, NULL, 10);
149 fprintf(stderr, "Error: option -d requires a numeric argument!\n");
162 outgoingnumber[i++] = *ptr++;
166 fprintf(stderr, "Error: option -o requires a numeric argument!\n");
170 outgoingnumber[i] = '\0';
181 incomingnumber[i++] = *ptr++;
185 fprintf(stderr, "Error: option -i requires a numeric argument!\n");
189 incomingnumber[i] = '\0';
203 dotest = strtoul(optarg, NULL, 10);
207 fprintf(stderr, "Error: option -t requires a numeric argument!\n");
219 if((strlen(incomingnumber) == 0) || (strlen(outgoingnumber) == 0))
222 fprintf(stderr, "isdntest: accepting calls from telephone number [%s] \n", incomingnumber);
223 fprintf(stderr, "isdntest: calling out telephone number [%s] \n", outgoingnumber);
225 if((atexit(cleanup)) != 0)
227 fprintf(stderr, "isdntest: atexit error: %s\n", strerror(errno));
231 /* open isdn device */
233 if((isdnfd = open(I4BDEVICE, O_RDWR)) < 0)
235 fprintf(stderr, "\nisdntest: cannot open %s: %s\n", I4BDEVICE, strerror(errno));
236 fprintf(stderr, " isdnd is probably running, to use isdntest,\n");
237 fprintf(stderr, " terminate isdnd and then run isdntest again!\n");
241 if((out_cdid = get_cdid(isdnfd)) == 0)
243 fprintf(stderr, "isdntest: error getting cdid: %s\n", strerror(errno));
247 if((connect_request(isdnfd, out_cdid)) == -1)
249 fprintf(stderr, "isdntest: error, outgoing call failed!\n");
259 FD_SET(isdnfd, &set);
261 ret = select(isdnfd + 1, &set, NULL, NULL, NULL);
265 if(FD_ISSET(isdnfd, &set))
268 if(FD_ISSET(0, &set))
273 fprintf(stderr, "isdntest: select error: %s\n", strerror(errno));
278 /*---------------------------------------------------------------------------*
279 * data from keyboard available
280 *---------------------------------------------------------------------------*/
288 /*---------------------------------------------------------------------------*
289 * data from /dev/isdn available, read and process them
290 *---------------------------------------------------------------------------*/
292 isdnrdhdl(int isdnfd)
294 static unsigned char buf[1024];
297 if((len = read(isdnfd, buf, 1024 - 1)) > 0)
301 case MSG_CONNECT_IND:
302 handle_connect_ind(&buf[0]);
305 case MSG_CONNECT_ACTIVE_IND:
306 handle_connect_active_ind(&buf[0]);
309 case MSG_DISCONNECT_IND:
310 handle_disconnect(&buf[0]);
315 fprintf(stderr, "isdntest: unknown message 0x%x = %c\n", buf[0], buf[0]);
321 fprintf(stderr, "isdntest: read error, errno = %d, length = %d", errno, len);
325 /*---------------------------------------------------------------------------*
326 * initiate an outgoing connection
327 *---------------------------------------------------------------------------*/
329 connect_request(int isdnfd, unsigned int cdid)
331 msg_connect_req_t mcr;
334 bzero(&mcr, sizeof(msg_connect_req_t));
336 mcr.controller = controller;
337 mcr.channel = CHAN_ANY; /* any channel */
338 mcr.cdid = cdid; /* cdid from get_cdid() */
341 mcr.bprot = BPROT_RHDLC;/* b channel protocol */
343 mcr.bprot = BPROT_NONE; /* b channel protocol */
345 mcr.driver = BDRV_RBCH; /* raw b channel driver */
346 mcr.driver_unit = DATAUNIT0; /* raw b channel driver unit */
348 strcpy(mcr.dst_telno, outgoingnumber);
349 strcpy(mcr.src_telno, incomingnumber);
351 if((ret = ioctl(isdnfd, I4B_CONNECT_REQ, &mcr)) < 0)
353 fprintf(stderr, "ioctl I4B_CONNECT_REQ failed: %s", strerror(errno));
356 fprintf(stderr, "isdntest: calling out to telephone number [%s] \n", outgoingnumber);
360 /*---------------------------------------------------------------------------*
361 * handle setup indicator
362 *---------------------------------------------------------------------------*/
364 handle_connect_ind(unsigned char *ptr)
366 msg_connect_ind_t *msi = (msg_connect_ind_t *)ptr;
368 fprintf(stderr, "isdntest: incoming SETUP: from %s to %s\n",
372 fprintf(stderr, " channel %d, controller %d, bprot %d, cdid %d\n",
378 in_cdid = msi->header.cdid;
380 if(strcmp(msi->dst_telno, outgoingnumber))
382 msg_connect_resp_t msr;
385 fprintf(stderr, "isdntest: ignoring incoming SETUP: my number [%s] != outgoing [%s]\n",
386 msi->dst_telno, outgoingnumber);
389 msr.response = SETUP_RESP_DNTCRE;
391 if((ret = ioctl(isdnfd, I4B_CONNECT_RESP, &msr)) < 0)
393 fprintf(stderr, "ioctl I4B_CONNECT_RESP ignore failed: %s", strerror(errno));
400 msg_connect_resp_t msr;
403 fprintf(stderr, "isdntest: accepting call, sending CONNECT_RESPONSE .....\n");
406 msr.response = SETUP_RESP_ACCEPT;
409 msr.bprot = BPROT_RHDLC;
411 msr.bprot = BPROT_NONE;
413 msr.driver = BDRV_RBCH;
414 msr.driver_unit = DATAUNIT1;
416 if((ret = ioctl(isdnfd, I4B_CONNECT_RESP, &msr)) < 0)
418 fprintf(stderr, "ioctl I4B_CONNECT_RESP accept failed: %s", strerror(errno));
426 /*---------------------------------------------------------------------------*
427 * handle connection active
428 *---------------------------------------------------------------------------*/
430 handle_connect_active_ind(unsigned char *ptr)
432 msg_connect_active_ind_t *msi = (msg_connect_active_ind_t *)ptr;
435 fprintf(stderr, "isdntest: connection active, cdid %d\n", msi->header.cdid);
437 if(out_cdid == msi->header.cdid)
441 fprintf(stderr, "isdntest: press any key to disconnect ...%c%c%c\n", 0x07, 0x07, 0x07);
452 fprintf(stderr, "isdntest: %d secs delay until disconnect:", SLEEPTIME);
454 for(i=0; i < SLEEPTIME;i++)
456 fprintf(stderr, " .");
459 fprintf(stderr, "\n");
467 /*---------------------------------------------------------------------------*
468 * handle disconnect indication
469 *---------------------------------------------------------------------------*/
471 handle_disconnect(unsigned char *ptr)
473 msg_disconnect_ind_t *mdi = (msg_disconnect_ind_t *)ptr;
475 if(mdi->header.cdid == out_cdid)
477 fprintf(stderr, "isdntest: incoming disconnect indication, cdid %d (out_cdid), cause %d\n",
478 mdi->header.cdid, mdi->cause);
480 out_cdid = CDID_UNUSED;
482 else if(mdi->header.cdid == in_cdid)
484 fprintf(stderr, "isdntest: incoming disconnect indication, cdid %d (in_cdid), cause %d\n",
485 mdi->header.cdid, mdi->cause);
486 in_cdid = CDID_UNUSED;
490 fprintf(stderr, "isdntest: incoming disconnect indication, cdid %d (???), cause %d\n",
491 mdi->header.cdid, mdi->cause);
495 /*---------------------------------------------------------------------------*
497 *---------------------------------------------------------------------------*/
499 disconnect_request(int isdnfd, unsigned int cdid)
501 msg_discon_req_t mdr;
505 mdr.cause = (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL;
507 if((ret = ioctl(isdnfd, I4B_DISCONNECT_REQ, &mdr)) < 0)
509 fprintf(stderr, "ioctl I4B_DISCONNECT_REQ failed: %s", strerror(errno));
512 fprintf(stderr, "isdntest: sending disconnect request\n");
516 /*---------------------------------------------------------------------------*
517 * get cdid from kernel
518 *---------------------------------------------------------------------------*/
527 if((ret = ioctl(isdnfd, I4B_CDID_REQ, &mcr)) < 0)
529 fprintf(stderr, "ioctl I4B_CDID_REQ failed: %s", strerror(errno));
532 fprintf(stderr, "isdntest: got cdid %d from kernel\n", mcr.cdid);
536 /*---------------------------------------------------------------------------*
537 * make shure all cdid's are inactive before leaving
538 *---------------------------------------------------------------------------*/
544 if(out_cdid != CDID_UNUSED)
546 fprintf(stderr, "isdntest: cleanup, send disconnect req for out_cdid %d, in_cdid %d\n", out_cdid, in_cdid);
547 disconnect_request(isdnfd, out_cdid);
550 while((out_cdid != CDID_UNUSED) || (in_cdid != CDID_UNUSED))
553 fprintf(stderr, "isdntest: cleanup, out_cdid %d, in_cdid %d\n", out_cdid, in_cdid);
555 if((len = read(isdnfd, buf, 1024 - 1)) > 0)
559 case MSG_CONNECT_IND:
560 handle_connect_ind(&buf[0]);
563 case MSG_CONNECT_ACTIVE_IND:
564 handle_connect_active_ind(&buf[0]);
567 case MSG_DISCONNECT_IND:
568 handle_disconnect(&buf[0]);
573 fprintf(stderr, "isdntest: unknown message 0x%x = %c\n", buf[0], buf[0]);
579 fprintf(stderr, "isdntest: read error, errno = %d, length = %d", errno, len);
583 fprintf(stderr, "isdntest: exit cleanup, out_cdid %d, in_cdid %d\n", out_cdid, in_cdid);
586 /*---------------------------------------------------------------------------*
587 * test the b-channels
588 *---------------------------------------------------------------------------*/
596 unsigned char wrbuf[2048];
597 unsigned char rdbuf[2048];
600 struct timeval timeout;
610 if((fd0 = open(DATADEV0, O_RDWR)) == -1)
612 fprintf(stderr, "open of %s failed: %s", DATADEV0, strerror(errno));
616 if((fd1 = open(DATADEV1, O_RDWR)) == -1)
618 fprintf(stderr, "open of %s failed: %s", DATADEV1, strerror(errno));
628 start_time = time(NULL);
630 printf(" frame size errors totalbytes bps elapsedtime\n");
632 for(;dotest > 0; dotest--)
634 setup_wrfix(frm_len, &wrbuf[0]);
640 printf("%6d %4d", frame, frm_len);
643 if((sz = write(fd0, wrbuf, frm_len)) != frm_len)
645 fprintf(stderr, "write (%d of %d bytes) to %s failed: %s\n", sz, frm_len, DATADEV0, strerror(errno));
656 ret = select(fd1+1, &set, NULL, NULL, &timeout);
660 if(FD_ISSET(fd1, &set))
662 if((sz = read(fd1, rdbuf, 2048)) != frm_len)
664 fprintf(stderr, "read (%d bytes) from %s failed: %s\n", sz, DATADEV1, strerror(errno));
667 cur_time = time(NULL);
668 run_time = difftime(cur_time, start_time);
673 printf(" %6d %10d %4d %2.2d:%2.2d:%2.2d \r",
675 (int)((int)bytecnt/(int)run_time),
676 (int)run_time/3600, (int)run_time/60, (int)run_time%60);
679 errcnt += check_rd(frm_len, &wrbuf[0], &rdbuf[0]);
684 printf("0x%02x ", (unsigned char)rdbuf[i]);
690 if(FD_ISSET(0, &set))
698 fprintf(stderr, "isdntest, do_test: select error: %s\n", strerror(errno));
711 setup_wrfix(int len, unsigned char *buf)
726 check_rd(int len, unsigned char *wbuf, unsigned char *rbuf)
735 fprintf(stderr, "\nERROR, byte %d, written 0x%02x, read 0x%02x\n", i, *wbuf, *rbuf);