/* * Written by Mark Spencer * Based on previous works, designs, and architectures conceived and * written by Jim Dixon . * * Copyright (C) 2001 Jim Dixon / Zapata Telephony. * Copyright (C) 2001-2008 Digium, Inc. * * All rights reserved. * * Primary Author: Mark Spencer * Radio Support by Jim Dixon */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ /* * This test sends a set of incrementing byte values out the specified * dadhi device. The device is then read back and the read back characters * are verified that they increment as well. * If there is a break in the incrementing pattern, an error is flagged * and the comparison starts at the last value read. */ #include #include #include #include #include #include #include #include #include #include #include #include "dahdi_tools_version.h" #define BLOCK_SIZE 2039 #define DEVICE "/dev/dahdi/channel" #define CONTEXT_SIZE 7 /* Prints a set of bytes in hex format */ static void print_packet(unsigned char *buf, int len) { int x; printf("{ "); for (x=0;x= bufsize || 0 >= bufsize || 0 > offset ) { return; } low = offset - (CONTEXT_SIZE-1)/2; if (0 > low) { total += low; low = 0; } if (low + total > bufsize) { total = bufsize - low; } buf += low; printf("Offset %d ", low); print_packet(buf, total); return; } /* Shows how the program can be invoked */ static void usage(const char * progname) { printf("%s: Pattern loop test\n", progname); printf("Usage: %s [-t ] [-r ] [-b ] [-vh?] \n", progname); printf("\t-? - Print this usage summary\n"); printf("\t-t - # of seconds for the test to run\n"); printf("\t-r - # of test loops to run before a summary is printed\n"); printf("\t-s - # of writes to skip before testing for results\n"); printf("\t-v - Verbosity (repetitive v's add to the verbosity level e.g. -vvvv)\n"); printf("\t-b <# buffer bytes> - # of bytes to display from buffers on each pass\n"); printf("\n\t Also accepts old style usage:\n\t %s []\n", progname); } int channel_open(const char *name, int *bs) { int channo, fd; struct dahdi_params tp; struct stat filestat; /* stat file, if character device, open it */ channo = strtoul(name, NULL, 10); fd = stat(name, &filestat); if (!fd && S_ISCHR(filestat.st_mode)) { fd = open(name, O_RDWR, 0600); if (fd < 0) { perror(name); return -1; } /* try out the dahdi_specify interface */ } else if (channo > 0) { fd = open(DEVICE, O_RDWR, 0600); if (fd < 0) { perror(DEVICE); return -1; } if (ioctl(fd, DAHDI_SPECIFY, &channo) < 0) { perror("DAHDI_SPECIFY ioctl failed"); return -1; } /* die */ } else { fprintf(stderr, "Specified channel is not a valid character " "device or channel number"); return -1; } if (ioctl(fd, DAHDI_SET_BLOCKSIZE, bs) < 0) { perror("SET_BLOCKSIZE"); return -1; } if (ioctl(fd, DAHDI_GET_PARAMS, &tp)) { fprintf(stderr, "Unable to get channel parameters\n"); return -1; } return fd; } int main(int argc, char *argv[]) { int fd; int res, x; int i; int bs = BLOCK_SIZE; int skipcount = 10; unsigned char c=0,c1=0; unsigned char inbuf[BLOCK_SIZE]; unsigned char outbuf[BLOCK_SIZE]; int setup=0; unsigned long bytes=0; int timeout=0; int loop_errorcount; int reportloops = 0; int buff_disp = 0; unsigned long currentloop = 0; unsigned long total_errorcount = 0; int verbose = 0; char * device; int opt; int oldstyle_cmdline = 1; unsigned int event_count = 0; time_t start_time = 0; /* Parse the command line arguments */ while((opt = getopt(argc, argv, "b:s:t:r:v?h")) != -1) { switch(opt) { case 'h': case '?': usage(argv[0]); exit(1); break; case 'b': buff_disp = strtoul(optarg, NULL, 10); if (BLOCK_SIZE < buff_disp) { buff_disp = BLOCK_SIZE; } oldstyle_cmdline = 0; break; case 'r': reportloops = strtoul(optarg, NULL, 10); oldstyle_cmdline = 0; break; case 's': skipcount = strtoul(optarg, NULL, 10); oldstyle_cmdline = 0; break; case 't': timeout = strtoul(optarg, NULL, 10); oldstyle_cmdline = 0; break; case 'v': verbose++; oldstyle_cmdline = 0; break; } } /* If no device was specified */ if(NULL == argv[optind]) { printf("You need to supply a dahdi device to test\n"); usage(argv[0]); exit (1); } /* Get the dahdi device name */ if (argv[optind]) device = argv[optind]; /* To maintain backward compatibility with previous versions process old style command line */ if (oldstyle_cmdline && argc > optind +1) { timeout = strtoul(argv[optind+1], NULL, 10); } fd = channel_open(device, &bs); if (fd < 0) exit(1); ioctl(fd, DAHDI_GETEVENT); i = DAHDI_FLUSH_ALL; if (ioctl(fd,DAHDI_FLUSH,&i) == -1) { perror("DAHDI_FLUSH"); exit(255); } /* Mark time if program has a specified timeout */ if(0 < timeout){ start_time = time(NULL); printf("Using Timeout of %d Seconds\n",timeout); } /* ********* MAIN TESTING LOOP ************ */ for(;;) { /* Prep the data and write it out to dahdi device */ res = bs; for (x = 0; x < bs; x++) { outbuf[x] = c1++; } write_again: res = write(fd,outbuf,bs); if (res != bs) { if (ELAST == errno) { ioctl(fd, DAHDI_GETEVENT, &x); if (event_count > 0) printf("Event: %d\n", x); ++event_count; } else { printf("W: Res is %d: %s\n", res, strerror(errno)); } goto write_again; } /* If this is the start of the test then skip a number of packets before test results */ if (skipcount) { if (skipcount > 1) { res = read(fd,inbuf,bs); } skipcount--; if (!skipcount) { printf("Going for it...\n"); } i = 1; ioctl(fd,DAHDI_BUFFER_EVENTS, &i); continue; } read_again: res = read(fd, inbuf, bs); if (res < bs) { printf("R: Res is %d\n", res); ioctl(fd, DAHDI_GETEVENT, &x); printf("Event: %d\n", x); goto read_again; } /* If first time through, set byte that is used to test further bytes */ if (!setup) { c = inbuf[0]; setup++; } /* Test the packet read back for data pattern */ loop_errorcount = 0; for (x = 0; x < bs; x++) { /* if error */ if (inbuf[x] != c) { total_errorcount++; loop_errorcount++; if (oldstyle_cmdline) { printf("(Error %ld): Unexpected result, %d != %d, %ld bytes since last error.\n", total_errorcount, inbuf[x],c, bytes); } else { if (1 <= verbose) { printf("Error %ld (loop %ld, offset %d, error %d): Unexpected result, Read: 0x%02x, Expected 0x%02x.\n", total_errorcount, currentloop, x, loop_errorcount, inbuf[x], c); } if (2 <= verbose) { show_error_context(inbuf, x, bs); } } /* Reset the expected data to what was just read. so test can resynch on skipped data */ c = inbuf[x]; bytes=0; /* Reset the count from the last encountered error */ } c++; bytes++; } /* If the user wants to see some of each buffer transaction */ if (0 < buff_disp) { printf("Buffer Display %d (errors =%d)\nIN: ", buff_disp, loop_errorcount); print_packet(inbuf, 64); printf("OUT:"); print_packet(outbuf, 64); } currentloop++; /* Update stats if the user has specified it */ if (0 < reportloops && 0 == (currentloop % reportloops)) { printf("Status on loop %lu: Total errors = %lu\n", currentloop, total_errorcount); } #if 0 printf("(%d) Wrote %d bytes\n", packets++, res); #endif if(timeout && (time(NULL)-start_time) > timeout){ printf("Timeout achieved Ending Program\n"); printf("Test ran %ld loops of %d bytes/loop with %ld errors\n", currentloop, bs, total_errorcount); return total_errorcount; } } }