Kernel tree reorganization stage 2: Major cvs repository work.
[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.3 2003/08/08 04:18:45 dillon 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 cleanup(void)
541 {
542         int len;
543         char buf[1024];
544         
545         if(out_cdid != CDID_UNUSED)
546         {
547                 fprintf(stderr, "isdntest: cleanup, send disconnect req for out_cdid %d, in_cdid %d\n", out_cdid, in_cdid);
548                 disconnect_request(isdnfd, out_cdid);
549         }
550
551         while((out_cdid != CDID_UNUSED) || (in_cdid != CDID_UNUSED))
552         {
553                 if(debug_level)
554                         fprintf(stderr, "isdntest: cleanup, out_cdid %d, in_cdid %d\n", out_cdid, in_cdid);
555
556                 if((len = read(isdnfd, buf, 1024 - 1)) > 0)
557                 {
558                         switch (buf[0])
559                         {
560                                 case MSG_CONNECT_IND:
561                                         handle_connect_ind(&buf[0]); 
562                                         break;
563                                         
564                                 case MSG_CONNECT_ACTIVE_IND:
565                                         handle_connect_active_ind(&buf[0]); 
566                                         break;
567                                         
568                                 case MSG_DISCONNECT_IND:
569                                         handle_disconnect(&buf[0]); 
570                                         break;
571                                         
572                                 default:
573                                         if(debug_level)                         
574                                                 fprintf(stderr, "isdntest: unknown message 0x%x = %c\n", buf[0], buf[0]);
575                                         break;
576                         }
577                 }
578                 else
579                 {
580                         fprintf(stderr, "isdntest: read error, errno = %d, length = %d", errno, len);
581                 }
582         }
583         if(debug_level) 
584                 fprintf(stderr, "isdntest: exit cleanup, out_cdid %d, in_cdid %d\n", out_cdid, in_cdid);
585 }
586
587 /*---------------------------------------------------------------------------*
588  *      test the b-channels
589  *---------------------------------------------------------------------------*/
590 int do_test(void)
591 {
592
593 #define FPH 0x3c
594 #define FPL 0x66
595
596         int fd0, fd1;
597         unsigned char wrbuf[2048];
598         unsigned char rdbuf[2048];
599         int sz;
600         fd_set set;
601         struct timeval timeout;
602         int ret;
603         int frame;
604         int errcnt;
605         int frm_len;
606         int bytecnt = 0;
607         time_t start_time;
608         time_t cur_time;
609         time_t run_time;
610         
611         if((fd0 = open(DATADEV0, O_RDWR)) == -1)
612         {
613                 fprintf(stderr, "open of %s failed: %s", DATADEV0, strerror(errno));
614                 return(-1);
615         }               
616
617         if((fd1 = open(DATADEV1, O_RDWR)) == -1)
618         {
619                 fprintf(stderr, "open of %s failed: %s", DATADEV1, strerror(errno));
620                 return(-1);
621         }               
622
623         printf("\n");
624         frame = 0;
625         errcnt = 0;     
626
627         frm_len = 2;
628
629         start_time = time(NULL);
630
631         printf(" frame size errors totalbytes  bps elapsedtime\n");
632         
633         for(;dotest > 0; dotest--)
634         {       
635                 setup_wrfix(frm_len, &wrbuf[0]);
636
637                 frame++;
638
639                 bytecnt += frm_len;
640                 
641                 printf("%6d %4d", frame, frm_len);
642                 fflush(stdout);
643                 
644                 if((sz = write(fd0, wrbuf, frm_len)) != frm_len)
645                 {
646                         fprintf(stderr, "write (%d of %d bytes) to %s failed: %s\n", sz, frm_len, DATADEV0, strerror(errno));
647                 }
648
649                 timeout.tv_sec =  2;
650                 timeout.tv_usec = 0;
651                                 
652                 FD_ZERO(&set);
653
654                 FD_SET(0, &set);
655                 FD_SET(fd1, &set);              
656
657                 ret = select(fd1+1, &set, NULL, NULL, &timeout);
658
659                 if(ret > 0)
660                 {
661                         if(FD_ISSET(fd1, &set))
662                         {
663                                 if((sz = read(fd1, rdbuf, 2048)) != frm_len)
664                                 {
665                                         fprintf(stderr, "read (%d bytes) from %s failed: %s\n", sz, DATADEV1, strerror(errno));
666                                 }
667
668                                 cur_time = time(NULL);
669                                 run_time = difftime(cur_time, start_time);
670
671                                 if(run_time == 0)
672                                         run_time = 1;
673                                 
674                                 printf(" %6d %10d %4d %2.2d:%2.2d:%2.2d     \r",
675                                         errcnt, bytecnt,
676                                         (int)((int)bytecnt/(int)run_time),
677                                         (int)run_time/3600, (int)run_time/60, (int)run_time%60);
678                                 fflush(stdout);
679
680                                 errcnt += check_rd(frm_len, &wrbuf[0], &rdbuf[0]);
681                                 
682 #ifdef NOTDEF
683                                 for(i=0; i<sz; i++)
684                                 {
685                                         printf("0x%02x ", (unsigned char)rdbuf[i]);
686                                 }
687                                 printf("\n");
688 #endif                          
689                         }
690
691                         if(FD_ISSET(0, &set))
692                         {
693                                 return(0);
694                                 printf("\n\n");
695                         }
696                 }
697                 else
698                 {
699                         fprintf(stderr, "isdntest, do_test: select error: %s\n", strerror(errno));
700                 }
701
702                 frm_len = frm_len*2;
703                 if(frm_len > 2048)
704                         frm_len = 2;
705
706         }
707         printf("\n\n");
708         return(0);
709 }
710
711 void
712 setup_wrfix(int len, unsigned char *buf)
713 {
714         register int i;
715         
716         for(i=0; i<len;)
717         {
718                 *buf = FPH;
719                 buf++;
720                 *buf = FPL;
721                 buf++;
722                 i+=2;
723         }
724 }
725
726 int             
727 check_rd(int len, unsigned char *wbuf, unsigned char *rbuf)
728 {
729         register int i;
730         int ret = 0;
731         
732         for(i=0; i<len; i++)
733         {
734                 if(*wbuf != *rbuf)
735                 {
736                         fprintf(stderr, "\nERROR, byte %d, written 0x%02x, read 0x%02x\n", i, *wbuf, *rbuf);
737                         ret++;
738                 }
739                 wbuf++;
740                 rbuf++;
741         }
742         return(ret);
743 }
744
745
746 /* EOF */