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
);