PPP: Fix an incorrect function call that was causing dahdi.so to fail to load
[dahdi/tools.git] / patlooptest.c
1 /*
2  * Written by Mark Spencer <markster@digium.com>
3  * Based on previous works, designs, and architectures conceived and
4  * written by Jim Dixon <jim@lambdatel.com>.
5  *
6  * Copyright (C) 2001 Jim Dixon / Zapata Telephony.
7  * Copyright (C) 2001-2008 Digium, Inc.
8  *
9  * All rights reserved.
10  *
11  * Primary Author: Mark Spencer <markster@digium.com>
12  * Radio Support by Jim Dixon <jim@lambdatel.com>
13  */
14
15 /*
16  * See http://www.asterisk.org for more information about
17  * the Asterisk project. Please do not directly contact
18  * any of the maintainers of this project for assistance;
19  * the project provides a web site, mailing lists and IRC
20  * channels for your use.
21  *
22  * This program is free software, distributed under the terms of
23  * the GNU General Public License Version 2 as published by the
24  * Free Software Foundation. See the LICENSE file included with
25  * this program for more details.
26  */
27
28 /*
29  *      This test sends a set of incrementing byte values out the specified
30  * dadhi device.  The device is then read back and the read back characters
31  * are verified that they increment as well.
32  *      If there is a break in the incrementing pattern, an error is flagged 
33  * and the comparison starts at the last value read. 
34  */
35
36 #include <stdio.h>
37 #include <fcntl.h>
38 #include <string.h>
39 #include <errno.h>
40 #include <stdio.h>
41 #include <sys/ioctl.h>
42 #include <unistd.h>
43 #include <stdlib.h>
44 #include <time.h>
45
46 #include <dahdi/user.h>
47 #include "dahdi_tools_version.h"
48
49 #define BLOCK_SIZE      2039
50
51 #define CONTEXT_SIZE    7
52 /* Prints a set of bytes in hex format */
53 static void print_packet(unsigned char *buf, int len)
54 {
55         int x;
56         printf("{ ");
57         for (x=0;x<len;x++)
58                 printf("%02x ",buf[x]);
59         printf("}\n");
60 }
61
62 /* Shows data immediately before and after the specified byte to provide context for an error */
63 static void show_error_context(unsigned char *buf, int offset, int bufsize)
64 {
65         int low;
66         int total = CONTEXT_SIZE;
67
68         if (offset >= bufsize || 0 >= bufsize || 0 > offset ) {
69                 return;
70         }
71         
72         low = offset - (CONTEXT_SIZE-1)/2;
73         if (0 > low) {
74                 total += low;
75                 low = 0;
76         }
77         if (low + total > bufsize) {
78                 total = bufsize - low;
79         }
80         buf += low;
81         printf("Offset %d  ", low);
82         print_packet(buf, total);
83         return;
84 }
85
86 /* Shows how the program can be invoked */
87 static void usage(const char * progname)
88 {
89         printf("%s: Pattern loop test\n", progname);
90         printf("Usage:  %s <dahdi device> [-t <secs>] [-r <count>] [-b <count>] [-vh?] \n", progname);
91         printf("\t-? - Print this usage summary\n");
92         printf("\t-t <secs> - # of seconds for the test to run\n");
93         printf("\t-r <count> - # of test loops to run before a summary is printed\n");
94         printf("\t-s <count> - # of writes to skip before testing for results\n");
95         printf("\t-v - Verbosity (repetitive v's add to the verbosity level e.g. -vvvv)\n");
96         printf("\t-b <# buffer bytes> - # of bytes to display from buffers on each pass\n");
97         printf("\n\t Also accepts old style usage:\n\t  %s <device name> [<timeout in secs>]\n", progname);
98 }
99
100 int main(int argc, char *argv[])
101 {
102         int fd;
103         int res, x;
104         int i;
105         struct dahdi_params tp;
106         int bs = BLOCK_SIZE;
107         int skipcount = 10;
108         unsigned char c=0,c1=0;
109         unsigned char inbuf[BLOCK_SIZE];
110         unsigned char outbuf[BLOCK_SIZE];
111         int setup=0;
112         unsigned long bytes=0;
113         int timeout=0;
114         int loop_errorcount;
115         int reportloops = 0;
116         int buff_disp = 0; 
117         unsigned long currentloop = 0;
118         unsigned long total_errorcount = 0;
119         int verbose = 0; 
120         char * device;
121         int opt;
122         int oldstyle_cmdline = 1;
123
124         /* Parse the command line arguments */
125         while((opt = getopt(argc, argv, "b:s:t:r:v?h")) != -1) {
126                 switch(opt) {
127                 case 'h':
128                 case '?':
129                         usage(argv[0]);
130                         exit(1);
131                         break;
132                 case 'b':
133                         buff_disp = strtoul(optarg, NULL, 10);
134                         if (BLOCK_SIZE < buff_disp) {
135                                 buff_disp = BLOCK_SIZE;
136                         }
137                         oldstyle_cmdline = 0;
138                         break;
139                 case 'r':
140                         reportloops = strtoul(optarg, NULL, 10);
141                         oldstyle_cmdline = 0;
142                         break;
143                 case 's':
144                         skipcount = strtoul(optarg, NULL, 10);
145                         oldstyle_cmdline = 0;
146                         break;
147                 case 't':
148                         timeout = strtoul(optarg, NULL, 10);
149                         oldstyle_cmdline = 0;
150                         break;
151                 case 'v':
152                         verbose++;
153                         oldstyle_cmdline = 0;
154                         break;
155                 }
156         }
157
158         /* If no device was specified */
159         if(NULL == argv[optind]) {
160                 printf("You need to supply a dahdi device to test\n");
161                 usage(argv[0]);
162                 exit (1);
163         }
164
165         /* Get the dahdi device name */
166         if (argv[optind])
167                 device = argv[optind];
168
169         /* To maintain backward compatibility with previous versions process old style command line */
170         if (oldstyle_cmdline && argc > optind +1) {
171                 timeout = strtoul(argv[optind+1], NULL, 10);
172         }
173         
174         time_t start_time = 0;
175
176         fd = open(device, O_RDWR, 0600);
177         if (fd < 0) {
178                 fprintf(stderr, "Unable to open %s: %s\n", device, strerror(errno));
179                 exit(1);
180         }
181         if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs)) {
182                 fprintf(stderr, "Unable to set block size to %d: %s\n", bs, strerror(errno));
183                 exit(1);
184         }
185         if (ioctl(fd, DAHDI_GET_PARAMS, &tp)) {
186                 fprintf(stderr, "Unable to get channel parameters\n");
187                 exit(1);
188         }
189         ioctl(fd, DAHDI_GETEVENT);
190
191         i = DAHDI_FLUSH_ALL;
192         if (ioctl(fd,DAHDI_FLUSH,&i) == -1) {
193                 perror("DAHDI_FLUSH");
194                 exit(255);
195         }
196
197         /* Mark time if program has a specified timeout */
198         if(0 < timeout){
199                 start_time = time(NULL);
200                 printf("Using Timeout of %d Seconds\n",timeout);
201         }
202
203         /* ********* MAIN TESTING LOOP ************ */
204         for(;;) {
205                 /* Prep the data and write it out to dahdi device */
206                 res = bs;
207                 for (x = 0; x < bs; x++) {
208                         outbuf[x] = c1++;
209                 }
210
211                 res = write(fd,outbuf,bs);
212                 if (res != bs) {
213                         printf("Res is %d: %s\n", res, strerror(errno));
214                         ioctl(fd, DAHDI_GETEVENT, &x);
215                         printf("Event: %d\n", x);
216                         exit(1);
217                 }
218
219                 /* If this is the start of the test then skip a number of packets before test results */
220                 if (skipcount) {
221                         if (skipcount > 1) {
222                                 res = read(fd,inbuf,bs);
223                         }
224                         skipcount--;
225                         if (!skipcount) {
226                                 printf("Going for it...\n");
227                         }
228                         continue;
229                 }
230
231                 res = read(fd, inbuf, bs);
232                 if (res < bs) {
233                         printf("read error: returned %d\n", res);
234                         exit(1);
235                 }
236                 /* If first time through, set byte that is used to test further bytes */
237                 if (!setup) {
238                         c = inbuf[0];
239                         setup++;
240                 }
241                 /* Test the packet read back for data pattern */
242                 loop_errorcount = 0;
243                 for (x = 0; x < bs; x++)  {
244                         /* if error */
245                         if (inbuf[x] != c) {
246                                 total_errorcount++;
247                                 loop_errorcount++;
248                                 if (oldstyle_cmdline) {
249                                         printf("(Error %ld): Unexpected result, %d != %d, %ld bytes since last error.\n", total_errorcount, inbuf[x],c, bytes);
250                                 } else {
251                                         if (1 <= verbose) {
252                                                 printf("Error %ld (loop %ld, offset %d, error %d): Unexpected result, Read: 0x%02x, Expected 0x%02x.\n",
253                                                         total_errorcount,
254                                                         currentloop,
255                                                         x,
256                                                         loop_errorcount,
257                                                         inbuf[x],
258                                                         c);
259                                         }
260                                         if (2 <= verbose) {
261                                                 show_error_context(inbuf, x, bs);
262                                         }
263                                 }
264                                 /* Reset the expected data to what was just read.  so test can resynch on skipped data */
265                                 c = inbuf[x];
266                                 bytes=0;  /* Reset the count from the last encountered error */
267                         }
268                         c++;
269                         bytes++;
270                 }
271                 /* If the user wants to see some of each buffer transaction */
272                 if (0 < buff_disp) {
273                         printf("Buffer Display %d (errors =%d)\nIN: ", buff_disp, loop_errorcount);
274                         print_packet(inbuf, 64);
275                         printf("OUT:");
276                         print_packet(outbuf, 64);
277                 }
278                 
279                 currentloop++;
280                 /* Update stats if the user has specified it */
281                 if (0 < reportloops && 0 == (currentloop % reportloops)) {
282                         printf("Status on loop %lu:  Total errors = %lu\n", currentloop, total_errorcount);
283                         
284                 }
285 #if 0
286                 printf("(%d) Wrote %d bytes\n", packets++, res);
287 #endif
288                 if(timeout && (time(NULL)-start_time) > timeout){
289                         printf("Timeout achieved Ending Program\n");
290                         printf("Test ran %ld loops of %d bytes/loop with %ld errors\n", currentloop, bs, total_errorcount);
291                         return total_errorcount;
292                 }
293         }
294         
295 }