3da6ca514c7a40856ae5cc23b7a868b0993385c1
[dragonfly.git] / usr.sbin / i4b / isdntest / main.c
1 /*
2  * Copyright (c) 1997, 1999 Hellmuth Michaelis. All rights reserved.
3  *
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.
12  *
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.
24  *
25  *---------------------------------------------------------------------------
26  *
27  *      main.c - i4b selftest utility
28  *      -----------------------------
29  *
30  *      $Id: main.c,v 1.16 2000/03/13 16:18:38 hm Exp $ 
31  *
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.5 2005/11/25 00:58:52 swildner Exp $
34  *
35  *      last edit-date: [Mon Mar 13 17:19:26 2000]
36  *
37  *---------------------------------------------------------------------------*/
38
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>
52
53 #include <i4b_machine/i4b_ioctl.h>
54 #include <i4b_machine/i4b_cause.h>
55
56 static void kbdrdhdl ( void );
57 static void isdnrdhdl (int isdnfd );
58
59 void handle_connect_ind(unsigned char *ptr);
60 void handle_disconnect(unsigned char *ptr);
61 void handle_connect_active_ind(unsigned char *ptr);
62
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);
72
73 static int isdnfd;
74 char outgoingnumber[32];
75 char incomingnumber[32];
76 int debug_level = 0;
77
78 #define I4BDEVICE       "/dev/i4b"
79 #define DATADEV0        "/dev/i4brbch0"
80 #define DATAUNIT0       0
81 #define DATADEV1        "/dev/i4brbch1"
82 #define DATAUNIT1       1
83
84 unsigned int out_cdid = CDID_UNUSED;
85 unsigned int in_cdid = CDID_UNUSED;
86
87 int waitchar = 0;
88 int usehdlc = 0;
89 int controller = 0;
90 int dotest = 0;
91
92 /*---------------------------------------------------------------------------*
93  *      usage display and exit
94  *---------------------------------------------------------------------------*/
95 static void
96 usage(void)
97 {
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);
110 }
111
112 /*---------------------------------------------------------------------------*
113  *      program entry
114  *---------------------------------------------------------------------------*/
115 int
116 main(int argc, char **argv)
117 {
118         int i;
119         int c;
120         fd_set set;
121         int ret;
122         char *ptr;
123         
124         incomingnumber[0] = '\0';
125         outgoingnumber[0] = '\0';       
126         
127         while ((c = getopt(argc, argv, "c:d:hi:o:t:w")) != -1)
128         {
129                 switch(c)
130                 {
131                         case 'c':
132                                 if(isdigit(*optarg))
133                                 {
134                                         controller = strtoul(optarg, NULL, 10);
135                                 }
136                                 else
137                                 {
138                                         fprintf(stderr, "Error: option -c requires a numeric argument!\n");
139                                         usage();
140                                 }
141                                 break;
142
143                         case 'd':
144                                 if(isdigit(*optarg))
145                                 {
146                                         debug_level = strtoul(optarg, NULL, 10);
147                                 }
148                                 else
149                                 {
150                                         fprintf(stderr, "Error: option -d requires a numeric argument!\n");
151                                         usage();
152                                 }
153                                 break;
154
155                         case 'o':
156                                 i = 0;
157                                 ptr = optarg;
158
159                                 while(*ptr)
160                                 {
161                                         if(isdigit(*ptr))
162                                         {
163                                                 outgoingnumber[i++] = *ptr++;
164                                         }
165                                         else
166                                         {
167                                                 fprintf(stderr, "Error: option -o requires a numeric argument!\n");
168                                                 usage();
169                                         }
170                                 }                                       
171                                 outgoingnumber[i] = '\0';
172                                 break;
173
174                         case 'i':
175                                 i = 0;
176                                 ptr = optarg;
177
178                                 while(*ptr)
179                                 {
180                                         if(isdigit(*ptr))
181                                         {
182                                                 incomingnumber[i++] = *ptr++;
183                                         }
184                                         else
185                                         {
186                                                 fprintf(stderr, "Error: option -i requires a numeric argument!\n");
187                                                 usage();
188                                         }
189                                 }                                       
190                                 incomingnumber[i] = '\0';
191                                 break;
192
193                         case 'w':
194                                 waitchar = 1;
195                                 break;
196                                 
197                         case 'h':
198                                 usehdlc = 1;
199                                 break;
200                                 
201                         case 't':
202                                 if(isdigit(*optarg))
203                                 {
204                                         dotest = strtoul(optarg, NULL, 10);
205                                 }
206                                 else
207                                 {
208                                         fprintf(stderr, "Error: option -t requires a numeric argument!\n");
209                                         usage();
210                                 }
211                                 break;
212
213                         case '?':
214                         default:
215                                 usage();
216                                 break;
217                 }
218         }
219
220         if((strlen(incomingnumber) == 0) || (strlen(outgoingnumber) == 0))
221                 usage();
222
223         fprintf(stderr, "isdntest: accepting calls from telephone number [%s] \n", incomingnumber);
224         fprintf(stderr, "isdntest:          calling out telephone number [%s] \n", outgoingnumber);
225
226         if((atexit(cleanup)) != 0)
227         {
228                 fprintf(stderr, "isdntest: atexit error: %s\n", strerror(errno));
229                 exit(1);
230         }
231         
232         /* open isdn device */
233         
234         if((isdnfd = open(I4BDEVICE, O_RDWR)) < 0)
235         {
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);
240         }
241
242         if((out_cdid = get_cdid(isdnfd)) == 0)
243         {
244                 fprintf(stderr, "isdntest: error getting cdid: %s\n", strerror(errno));
245                 exit(1);
246         }
247
248         if((connect_request(isdnfd, out_cdid)) == -1)
249         {
250                 fprintf(stderr, "isdntest: error, outgoing call failed!\n");
251                 exit(1);
252         }
253         
254         for(;;)
255         {
256                 FD_ZERO(&set);
257
258                 FD_SET(0, &set);
259
260                 FD_SET(isdnfd, &set);
261
262                 ret = select(isdnfd + 1, &set, NULL, NULL, NULL);
263
264                 if(ret > 0)
265                 {
266                         if(FD_ISSET(isdnfd, &set))
267                                 isdnrdhdl(isdnfd);
268
269                         if(FD_ISSET(0, &set))
270                                 kbdrdhdl();
271                 }
272                 else
273                 {
274                         fprintf(stderr, "isdntest: select error: %s\n", strerror(errno));
275                 }                       
276         }
277 }
278
279 /*---------------------------------------------------------------------------*
280  *      data from keyboard available
281  *---------------------------------------------------------------------------*/
282 static void
283 kbdrdhdl(void)
284 {
285         cleanup();
286         exit(2);
287 }
288
289 /*---------------------------------------------------------------------------*
290  *      data from /dev/isdn available, read and process them
291  *---------------------------------------------------------------------------*/
292 static void
293 isdnrdhdl(int isdnfd)
294 {
295         static unsigned char buf[1024];
296         int len;
297
298         if((len = read(isdnfd, buf, 1024 - 1)) > 0)
299         {
300                 switch (buf[0])
301                 {
302                         case MSG_CONNECT_IND:
303                                 handle_connect_ind(&buf[0]); 
304                                 break;
305                                 
306                         case MSG_CONNECT_ACTIVE_IND:
307                                 handle_connect_active_ind(&buf[0]); 
308                                 break;
309                                 
310                         case MSG_DISCONNECT_IND:
311                                 handle_disconnect(&buf[0]); 
312                                 break;
313                                 
314                         default:
315                                 if(debug_level)
316                                         fprintf(stderr, "isdntest: unknown message 0x%x = %c\n", buf[0], buf[0]);
317                                 break;
318                 }
319         }
320         else
321         {
322                 fprintf(stderr, "isdntest: read error, errno = %d, length = %d", errno, len);
323         }
324 }
325
326 /*---------------------------------------------------------------------------*
327  *      initiate an outgoing connection
328  *---------------------------------------------------------------------------*/
329 int
330 connect_request(int isdnfd, unsigned int cdid)
331 {
332         msg_connect_req_t mcr;
333         int ret;
334
335         bzero(&mcr, sizeof(msg_connect_req_t));
336         
337         mcr.controller = controller;
338         mcr.channel = CHAN_ANY; /* any channel */
339         mcr.cdid = cdid;        /* cdid from get_cdid() */      
340
341         if(usehdlc)
342                 mcr.bprot = BPROT_RHDLC;/* b channel protocol */
343         else
344                 mcr.bprot = BPROT_NONE; /* b channel protocol */        
345
346         mcr.driver = BDRV_RBCH;         /* raw b channel driver */
347         mcr.driver_unit = DATAUNIT0;    /* raw b channel driver unit */ 
348
349         strcpy(mcr.dst_telno, outgoingnumber);
350         strcpy(mcr.src_telno, incomingnumber);
351         
352         if((ret = ioctl(isdnfd, I4B_CONNECT_REQ, &mcr)) < 0)
353         {
354                 fprintf(stderr, "ioctl I4B_CONNECT_REQ failed: %s", strerror(errno));
355                 return(-1);
356         }
357         fprintf(stderr, "isdntest: calling out to telephone number [%s] \n", outgoingnumber);
358         return(0);
359 }
360
361 /*---------------------------------------------------------------------------*
362  *      handle setup indicator
363  *---------------------------------------------------------------------------*/
364 void
365 handle_connect_ind(unsigned char *ptr)
366 {
367         msg_connect_ind_t *msi = (msg_connect_ind_t *)ptr;
368
369         fprintf(stderr, "isdntest: incoming SETUP: from %s to %s\n",
370                                 msi->src_telno,
371                                 msi->dst_telno);
372
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);
378
379         in_cdid = msi->header.cdid;
380         
381         if(strcmp(msi->dst_telno, outgoingnumber))
382         {
383                 msg_connect_resp_t msr;
384                 int ret;
385
386                 fprintf(stderr, "isdntest: ignoring incoming SETUP: my number [%s] != outgoing [%s]\n",
387                         msi->dst_telno, outgoingnumber);
388
389                 msr.cdid = in_cdid;
390                 msr.response = SETUP_RESP_DNTCRE;
391
392                 if((ret = ioctl(isdnfd, I4B_CONNECT_RESP, &msr)) < 0)
393                 {
394                         fprintf(stderr, "ioctl I4B_CONNECT_RESP ignore failed: %s", strerror(errno));
395                         exit(1);
396                 }
397
398         }
399         else
400         {
401                 msg_connect_resp_t msr;
402                 int ret;
403
404                 fprintf(stderr, "isdntest: accepting call, sending CONNECT_RESPONSE .....\n");
405
406                 msr.cdid = in_cdid;
407                 msr.response = SETUP_RESP_ACCEPT;
408
409                 if(usehdlc)
410                         msr.bprot = BPROT_RHDLC;
411                 else
412                         msr.bprot = BPROT_NONE;
413         
414                 msr.driver = BDRV_RBCH;
415                 msr.driver_unit = DATAUNIT1;
416                 
417                 if((ret = ioctl(isdnfd, I4B_CONNECT_RESP, &msr)) < 0)
418                 {
419                         fprintf(stderr, "ioctl I4B_CONNECT_RESP accept failed: %s", strerror(errno));
420                         exit(1);
421                 }
422         }
423 }
424
425 #define SLEEPTIME 5
426
427 /*---------------------------------------------------------------------------*
428  *      handle connection active
429  *---------------------------------------------------------------------------*/
430 void
431 handle_connect_active_ind(unsigned char *ptr)
432 {
433         msg_connect_active_ind_t *msi = (msg_connect_active_ind_t *)ptr;
434         int i;
435         
436         fprintf(stderr, "isdntest: connection active, cdid %d\n", msi->header.cdid);
437
438         if(out_cdid == msi->header.cdid)
439         {
440                 if(waitchar)
441                 {
442                         fprintf(stderr, "isdntest: press any key to disconnect ...%c%c%c\n", 0x07, 0x07, 0x07);
443                         getchar();
444                 }
445                 else
446                 {
447                         if(dotest)
448                         {
449                                 do_test();
450                         }
451                         else
452                         {
453                                 fprintf(stderr, "isdntest: %d secs delay until disconnect:", SLEEPTIME);
454         
455                                 for(i=0; i < SLEEPTIME;i++)
456                                 {
457                                         fprintf(stderr, " .");
458                                         sleep(1);
459                                 }
460                                 fprintf(stderr, "\n");
461                         }
462                         cleanup();
463                         exit(0);
464                 }
465         }
466 }
467
468 /*---------------------------------------------------------------------------*
469  *      handle disconnect indication
470  *---------------------------------------------------------------------------*/
471 void
472 handle_disconnect(unsigned char *ptr)
473 {
474         msg_disconnect_ind_t *mdi = (msg_disconnect_ind_t *)ptr;
475         
476         if(mdi->header.cdid == out_cdid)
477         {
478                 fprintf(stderr, "isdntest: incoming disconnect indication, cdid %d (out_cdid), cause %d\n",
479                         mdi->header.cdid, mdi->cause);
480
481                 out_cdid = CDID_UNUSED;
482         }
483         else if(mdi->header.cdid == in_cdid)
484         {
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;
488         }
489         else
490         {
491                 fprintf(stderr, "isdntest: incoming disconnect indication, cdid %d (???), cause %d\n",
492                         mdi->header.cdid, mdi->cause);
493         }               
494 }
495         
496 /*---------------------------------------------------------------------------*
497  *      hang up
498  *---------------------------------------------------------------------------*/
499 int
500 disconnect_request(int isdnfd, unsigned int cdid)
501 {
502         msg_discon_req_t mdr;
503         int ret;
504
505         mdr.cdid = cdid;
506         mdr.cause = (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL;
507         
508         if((ret = ioctl(isdnfd, I4B_DISCONNECT_REQ, &mdr)) < 0)
509         {
510                 fprintf(stderr, "ioctl I4B_DISCONNECT_REQ failed: %s", strerror(errno));
511                 return(-1);
512         }
513         fprintf(stderr, "isdntest: sending disconnect request\n");
514         return(0);
515 }
516
517 /*---------------------------------------------------------------------------*
518  *      get cdid from kernel
519  *---------------------------------------------------------------------------*/
520 unsigned int
521 get_cdid(int isdnfd)
522 {
523         msg_cdid_req_t mcr;
524         int ret;
525         
526         mcr.cdid = 0;
527         
528         if((ret = ioctl(isdnfd, I4B_CDID_REQ, &mcr)) < 0)
529         {
530                 fprintf(stderr, "ioctl I4B_CDID_REQ failed: %s", strerror(errno));
531                 return(0);
532         }
533         fprintf(stderr, "isdntest: got cdid %d from kernel\n", mcr.cdid);
534         return(mcr.cdid);
535 }
536
537 /*---------------------------------------------------------------------------*
538  *      make shure all cdid's are inactive before leaving
539  *---------------------------------------------------------------------------*/
540 void
541 cleanup(void)
542 {
543         int len;
544         char buf[1024];
545         
546         if(out_cdid != CDID_UNUSED)
547         {
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);
550         }
551
552         while((out_cdid != CDID_UNUSED) || (in_cdid != CDID_UNUSED))
553         {
554                 if(debug_level)
555                         fprintf(stderr, "isdntest: cleanup, out_cdid %d, in_cdid %d\n", out_cdid, in_cdid);
556
557                 if((len = read(isdnfd, buf, 1024 - 1)) > 0)
558                 {
559                         switch (buf[0])
560                         {
561                                 case MSG_CONNECT_IND:
562                                         handle_connect_ind(&buf[0]); 
563                                         break;
564                                         
565                                 case MSG_CONNECT_ACTIVE_IND:
566                                         handle_connect_active_ind(&buf[0]); 
567                                         break;
568                                         
569                                 case MSG_DISCONNECT_IND:
570                                         handle_disconnect(&buf[0]); 
571                                         break;
572                                         
573                                 default:
574                                         if(debug_level)                         
575                                                 fprintf(stderr, "isdntest: unknown message 0x%x = %c\n", buf[0], buf[0]);
576                                         break;
577                         }
578                 }
579                 else
580                 {
581                         fprintf(stderr, "isdntest: read error, errno = %d, length = %d", errno, len);
582                 }
583         }
584         if(debug_level) 
585                 fprintf(stderr, "isdntest: exit cleanup, out_cdid %d, in_cdid %d\n", out_cdid, in_cdid);
586 }
587
588 /*---------------------------------------------------------------------------*
589  *      test the b-channels
590  *---------------------------------------------------------------------------*/
591 int
592 do_test(void)
593 {
594
595 #define FPH 0x3c
596 #define FPL 0x66
597
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;
612         
613         if((fd0 = open(DATADEV0, O_RDWR)) == -1)
614         {
615                 fprintf(stderr, "open of %s failed: %s", DATADEV0, strerror(errno));
616                 return(-1);
617         }               
618
619         if((fd1 = open(DATADEV1, O_RDWR)) == -1)
620         {
621                 fprintf(stderr, "open of %s failed: %s", DATADEV1, strerror(errno));
622                 return(-1);
623         }               
624
625         printf("\n");
626         frame = 0;
627         errcnt = 0;     
628
629         frm_len = 2;
630
631         start_time = time(NULL);
632
633         printf(" frame size errors totalbytes  bps elapsedtime\n");
634         
635         for(;dotest > 0; dotest--)
636         {       
637                 setup_wrfix(frm_len, &wrbuf[0]);
638
639                 frame++;
640
641                 bytecnt += frm_len;
642                 
643                 printf("%6d %4d", frame, frm_len);
644                 fflush(stdout);
645                 
646                 if((sz = write(fd0, wrbuf, frm_len)) != frm_len)
647                 {
648                         fprintf(stderr, "write (%d of %d bytes) to %s failed: %s\n", sz, frm_len, DATADEV0, strerror(errno));
649                 }
650
651                 timeout.tv_sec =  2;
652                 timeout.tv_usec = 0;
653                                 
654                 FD_ZERO(&set);
655
656                 FD_SET(0, &set);
657                 FD_SET(fd1, &set);              
658
659                 ret = select(fd1+1, &set, NULL, NULL, &timeout);
660
661                 if(ret > 0)
662                 {
663                         if(FD_ISSET(fd1, &set))
664                         {
665                                 if((sz = read(fd1, rdbuf, 2048)) != frm_len)
666                                 {
667                                         fprintf(stderr, "read (%d bytes) from %s failed: %s\n", sz, DATADEV1, strerror(errno));
668                                 }
669
670                                 cur_time = time(NULL);
671                                 run_time = difftime(cur_time, start_time);
672
673                                 if(run_time == 0)
674                                         run_time = 1;
675                                 
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);
681
682                                 errcnt += check_rd(frm_len, &wrbuf[0], &rdbuf[0]);
683                                 
684 #ifdef NOTDEF
685                                 for(i=0; i<sz; i++)
686                                 {
687                                         printf("0x%02x ", (unsigned char)rdbuf[i]);
688                                 }
689                                 printf("\n");
690 #endif                          
691                         }
692
693                         if(FD_ISSET(0, &set))
694                         {
695                                 return(0);
696                                 printf("\n\n");
697                         }
698                 }
699                 else
700                 {
701                         fprintf(stderr, "isdntest, do_test: select error: %s\n", strerror(errno));
702                 }
703
704                 frm_len = frm_len*2;
705                 if(frm_len > 2048)
706                         frm_len = 2;
707
708         }
709         printf("\n\n");
710         return(0);
711 }
712
713 void
714 setup_wrfix(int len, unsigned char *buf)
715 {
716         int i;
717         
718         for(i=0; i<len;)
719         {
720                 *buf = FPH;
721                 buf++;
722                 *buf = FPL;
723                 buf++;
724                 i+=2;
725         }
726 }
727
728 int             
729 check_rd(int len, unsigned char *wbuf, unsigned char *rbuf)
730 {
731         int i;
732         int ret = 0;
733         
734         for(i=0; i<len; i++)
735         {
736                 if(*wbuf != *rbuf)
737                 {
738                         fprintf(stderr, "\nERROR, byte %d, written 0x%02x, read 0x%02x\n", i, *wbuf, *rbuf);
739                         ret++;
740                 }
741                 wbuf++;
742                 rbuf++;
743         }
744         return(ret);
745 }
746
747
748 /* EOF */