Fix up string formatting for long long integers (64 bits)
[libftdi] / examples / stream_test.c
1 /* stream_test.c
2  *
3  * Test reading  from FT2232H in synchronous FIFO mode.
4  *
5  * The FT2232H must supply data due to an appropriate circuit
6  *
7  * To check for skipped block with appended code, 
8  *     a structure as follows is assumed
9  * 1* uint32_t num (incremented in 0x4000 steps)
10  * 3* uint32_t dont_care
11  *
12  * After start, data will be read in streaming until the program is aborted
13  * Progess information wil be printed out
14  * If a filename is given on the command line, the data read will be
15  * written to that file
16  *
17  */
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <stdint.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include <getopt.h>
24 #include <signal.h>
25 #include <errno.h>
26 #include <ftdi.h>
27 void check_outfile(char *);
28
29 static FILE *outputFile;
30
31 static int check = 1;
32 static int exitRequested = 0;
33 /*
34  * sigintHandler --
35  *
36  *    SIGINT handler, so we can gracefully exit when the user hits ctrl-C.
37  */
38
39 static void
40 sigintHandler(int signum)
41 {
42    exitRequested = 1;
43 }
44
45 static void
46 usage(const char *argv0)
47 {
48    fprintf(stderr,
49            "Usage: %s [tions...] \n"
50            "Test streaming read from FT2232H\n"
51            "[-P string] only look for product with given string"
52            "[-n] don't check for special block structure"
53            "\n"
54            "If some filename is given, write data read to that file\n"
55            "Progess information is printed each second\n"
56            "Abort with ^C\n"
57            "\n"
58            "Options:\n"
59            "\n"
60            "Copyright (C) 2009 Micah Dowty <micah@navi.cx>\n",
61            "Adapted for use with libftdi (C) 2010 Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>\n",
62            argv0);
63    exit(1);
64 }
65
66 static uint32_t start = 0;
67 static uint32_t offset = 0;
68 static uint64_t blocks = 0;
69 static uint32_t skips = 0;
70 static uint32_t n_err = 0;
71 static int
72 readCallback(uint8_t *buffer, int length, FTDIProgressInfo *progress, void *userdata)
73 {
74    if (length)
75    {
76        if (check)
77        {
78            int i,rem;
79            uint32_t num;
80            for (i= offset; i<length-16; i+=16)
81            {
82                num = *(uint32_t*) (buffer+i);
83                if (start && (num != start +0x4000))
84                {
85                    uint32_t delta = ((num-start)/0x4000)-1;
86                    fprintf(stderr, "Skip %7d blocks from 0x%08x to 0x%08x at blocks %10lld \n",
87                            delta, start -0x4000, num, blocks);
88                    n_err++;
89                    skips += delta;
90                }
91                blocks ++;
92                start = num;
93            }
94            rem = length -i;
95            if (rem >3)
96            {
97                num = *(uint32_t*) (buffer+i);
98                if (start && (num != start +0x4000))
99                {
100                    uint32_t delta = ((num-start)/0x4000)-1;
101                    fprintf(stderr, "Skip %7d blocks from 0x%08x to 0x%08x at blocks %10lld \n",
102                            delta, start -0x4000, num, blocks);
103                    n_err++;
104                    skips += delta;
105                }
106                start = num;
107            }
108            else if (rem)
109                start += 0x4000;
110            if (rem != 0);
111            {
112                blocks ++;
113                offset = 16-rem;
114            }
115        }
116        if (outputFile)
117        {
118            if (fwrite(buffer, length, 1, outputFile) != 1)
119            {
120                perror("Write error");
121                return 1;
122            }
123        }
124    }
125    if (progress)
126    {
127        fprintf(stderr, "%10.02fs total time %9.3f MiB captured %7.1f kB/s curr rate %7.1f kB/s totalrate %d dropouts\n",
128                progress->totalTime,
129                progress->current.totalBytes / (1024.0 * 1024.0),
130                progress->currentRate / 1024.0,
131                progress->totalRate / 1024.0,
132                n_err);
133    }
134    return exitRequested ? 1 : 0;
135 }
136
137 int main(int argc, char **argv)
138 {
139    struct ftdi_context ftdic;
140    int err, c;
141    FILE *of = NULL;
142    char const *outfile  = 0;
143    outputFile =0;
144    exitRequested = 0;
145    char *descstring = NULL;
146    int option_index;
147    static struct option long_options[] = {{NULL},};
148
149    while ((c = getopt_long(argc, argv, "P:n", long_options, &option_index)) !=- 1)
150        switch (c) 
151        {
152        case -1:
153            break;
154        case 'P':
155            descstring = optarg;
156            break;
157        case 'n':
158            check = 0;
159            break;
160        default:
161            usage(argv[0]);
162        }
163    
164    if (optind == argc - 1)
165    {
166        // Exactly one extra argument- a dump file
167        outfile = argv[optind];
168    }
169    else if (optind < argc)
170    {
171        // Too many extra args
172        usage(argv[0]);
173    }
174    
175    if (ftdi_init(&ftdic) < 0)
176    {
177        fprintf(stderr, "ftdi_init failed\n");
178        return EXIT_FAILURE;
179    }
180    
181    if (ftdi_set_interface(&ftdic, INTERFACE_A) < 0)
182    {
183        fprintf(stderr, "ftdi_set_interface failed\n");
184        return EXIT_FAILURE;
185    }
186    
187    if (ftdi_usb_open_desc(&ftdic, 0x0403, 0x6010, descstring, NULL) < 0)
188    {
189        fprintf(stderr,"Can't open ftdi device: %s\n",ftdi_get_error_string(&ftdic));
190        return EXIT_FAILURE;
191    }
192    
193    /* A timeout value of 1 results in may skipped blocks */
194    if(ftdi_set_latency_timer(&ftdic, 2))
195    {
196        fprintf(stderr,"Can't set latency, Error %s\n",ftdi_get_error_string(&ftdic));
197        return EXIT_FAILURE;
198    }
199    
200 /*   if(ftdi_usb_purge_rx_buffer(&ftdic) < 0)
201    {
202        fprintf(stderr,"Can't rx purge\n",ftdi_get_error_string(&ftdic));
203        return EXIT_FAILURE;
204        }*/
205    if (outfile)
206        if ((of = fopen(outfile,"w+")) == 0)
207            fprintf(stderr,"Can't open logfile %s, Error %s\n", outfile, strerror(errno));
208    if (of)
209        if (setvbuf(of, NULL, _IOFBF , 1<<16) == 0)
210            outputFile = of;
211    signal(SIGINT, sigintHandler);
212    
213    err = ftdi_readstream(&ftdic, readCallback, NULL, 8, 256);
214    if (err < 0 && !exitRequested)
215        exit(1);
216    
217    if (outputFile) {
218        fclose(outputFile);
219        outputFile = NULL;
220    }
221    fprintf(stderr, "Capture ended.\n");
222    
223    if (ftdi_set_bitmode(&ftdic,  0xff, BITMODE_RESET) < 0)
224    {
225        fprintf(stderr,"Can't set synchronous fifo mode, Error %s\n",ftdi_get_error_string(&ftdic));
226        return EXIT_FAILURE;
227    }
228    ftdi_usb_close(&ftdic);
229    ftdi_deinit(&ftdic);
230    signal(SIGINT, SIG_DFL);
231    if (check && outfile)
232    {
233        if ((outputFile = fopen(outfile,"r")) == 0)
234        {
235            fprintf(stderr,"Can't open logfile %s, Error %s\n", outfile, strerror(errno));
236            return EXIT_FAILURE;
237        }
238        check_outfile(descstring);
239        fclose(outputFile);
240    }
241    else if (check)
242        fprintf(stderr,"%d errors of %lld blocks (%Le), %d (%Le) blocks skipped\n",
243                n_err, blocks, (long double)n_err/(long double) blocks,
244                skips, (long double)skips/(long double) blocks);
245    exit (0);
246 }
247
248 void check_outfile(char *descstring)
249 {
250     if(strcmp(descstring,"FT2232HTEST") == 0)
251     {
252        char buf0[1024];
253        char buf1[1024];
254        char bufr[1024];
255        char *pa, *pb, *pc;
256        unsigned int num_lines = 0, line_num = 1;
257        int err_count = 0;
258        unsigned int num_start, num_end;
259
260        pa = buf0;
261        pb = buf1;
262        pc = buf0;
263        if(fgets(pa, 1023, outputFile) == NULL)
264        {
265            fprintf(stderr,"Empty output file\n");
266            return;
267        }
268        while(fgets(pb, 1023, outputFile) != NULL)
269        {
270            num_lines++;
271            unsigned int num_save = num_start;
272            if( sscanf(pa,"%6u%94s%6u",&num_start, bufr,&num_end) !=3)
273            {
274                fprintf(stdout,"Format doesn't match at line %8d \"%s",
275                        num_lines, pa);
276                err_count++;
277                line_num = num_save +2;
278            }
279            else
280            {
281                if ((num_start+1)%100000 != num_end)
282                {
283                    if (err_count < 20)
284                        fprintf(stdout,"Malformed line %d \"%s\"\n", 
285                                num_lines, pa);
286                    err_count++;
287                }
288                else if(num_start != line_num)
289                {
290                    if (err_count < 20)
291                        fprintf(stdout,"Skipping from %d to %d\n", 
292                                line_num, num_start);
293                    err_count++;
294                   
295                }
296                line_num = num_end;
297            }
298            pa = pb;
299            pb = pc;
300            pc = pa;
301        }
302        if(err_count)
303            fprintf(stdout,"\n%d errors of %d data sets %f\n", err_count, num_lines, (double) err_count/(double)num_lines);
304        else
305            fprintf(stdout,"No errors for %d lines\n",num_lines);
306    }
307     else if(strcmp(descstring,"LLBBC10") == 0)
308     { 
309         uint32_t block0[4];
310         uint32_t block1[4];
311         uint32_t *pa = block0;
312         uint32_t *pb = block1;
313         uint32_t *pc = block0;
314         uint32_t start= 0;
315         uint32_t nread = 0;
316         int n_shown = 0;
317         int n_errors = 0;
318         if (fread(pa, sizeof(uint32_t), 4,outputFile) < 4)
319         {
320             fprintf(stderr,"Empty result file\n");
321             return;
322         }
323         while(fread(pb, sizeof(uint32_t), 4,outputFile) != 0)
324         {
325             blocks++;
326             nread =  pa[0];
327             if(start>0 && (nread != start))
328             {
329                 if(n_shown < 30)
330                 {
331                     fprintf(stderr, "Skip %7d blocks from 0x%08x to 0x%08x at blocks %10lld \n",
332                             (nread-start)/0x4000, start -0x4000, nread, blocks);
333                     n_shown ++;
334                 }
335                 n_errors++;
336             }
337             else if (n_shown >0) 
338                 n_shown--; 
339             start = nread + 0x4000;
340             pa = pb;
341             pb = pc;
342             pc = pa;
343         }
344         if(n_errors)
345             fprintf(stderr, "%d blocks wrong from %lld blocks read\n",
346                     n_errors, blocks);
347         else
348             fprintf(stderr, "%lld blocks all fine\n",blocks);
349     }
350 }