Reformat example code to match libftdi style:
[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 [options...] \n"
50             "Test streaming read from FT2232H\n"
51             "[-P string] only look for product with given string\n"
52             "[-n] don't check for special block structure\n"
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 %10llu\n",
87                             delta, start -0x4000, num, (unsigned long long)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 %10llu\n",
102                             delta, start -0x4000, num, (unsigned long long) 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     {
219         fclose(outputFile);
220         outputFile = NULL;
221     }
222     fprintf(stderr, "Capture ended.\n");
223
224     if (ftdi_set_bitmode(&ftdic,  0xff, BITMODE_RESET) < 0)
225     {
226         fprintf(stderr,"Can't set synchronous fifo mode, Error %s\n",ftdi_get_error_string(&ftdic));
227         return EXIT_FAILURE;
228     }
229     ftdi_usb_close(&ftdic);
230     ftdi_deinit(&ftdic);
231     signal(SIGINT, SIG_DFL);
232     if (check && outfile)
233     {
234         if ((outputFile = fopen(outfile,"r")) == 0)
235         {
236             fprintf(stderr,"Can't open logfile %s, Error %s\n", outfile, strerror(errno));
237             return EXIT_FAILURE;
238         }
239         check_outfile(descstring);
240         fclose(outputFile);
241     }
242     else if (check)
243         fprintf(stderr,"%d errors of %llu blocks (%Le), %d (%Le) blocks skipped\n",
244                 n_err, (unsigned long long) blocks, (long double)n_err/(long double) blocks,
245                 skips, (long double)skips/(long double) blocks);
246     exit (0);
247 }
248
249 void check_outfile(char *descstring)
250 {
251     if (strcmp(descstring,"FT2232HTEST") == 0)
252     {
253         char buf0[1024];
254         char buf1[1024];
255         char bufr[1024];
256         char *pa, *pb, *pc;
257         unsigned int num_lines = 0, line_num = 1;
258         int err_count = 0;
259         unsigned int num_start, num_end;
260
261         pa = buf0;
262         pb = buf1;
263         pc = buf0;
264         if (fgets(pa, 1023, outputFile) == NULL)
265         {
266             fprintf(stderr,"Empty output file\n");
267             return;
268         }
269         while (fgets(pb, 1023, outputFile) != NULL)
270         {
271             num_lines++;
272             unsigned int num_save = num_start;
273             if ( sscanf(pa,"%6u%94s%6u",&num_start, bufr,&num_end) !=3)
274             {
275                 fprintf(stdout,"Format doesn't match at line %8d \"%s",
276                         num_lines, pa);
277                 err_count++;
278                 line_num = num_save +2;
279             }
280             else
281             {
282                 if ((num_start+1)%100000 != num_end)
283                 {
284                     if (err_count < 20)
285                         fprintf(stdout,"Malformed line %d \"%s\"\n",
286                                 num_lines, pa);
287                     err_count++;
288                 }
289                 else if (num_start != line_num)
290                 {
291                     if (err_count < 20)
292                         fprintf(stdout,"Skipping from %d to %d\n",
293                                 line_num, num_start);
294                     err_count++;
295
296                 }
297                 line_num = num_end;
298             }
299             pa = pb;
300             pb = pc;
301             pc = pa;
302         }
303         if (err_count)
304             fprintf(stdout,"\n%d errors of %d data sets %f\n", err_count, num_lines, (double) err_count/(double)num_lines);
305         else
306             fprintf(stdout,"No errors for %d lines\n",num_lines);
307     }
308     else if (strcmp(descstring,"LLBBC10") == 0)
309     {
310         uint32_t block0[4];
311         uint32_t block1[4];
312         uint32_t *pa = block0;
313         uint32_t *pb = block1;
314         uint32_t *pc = block0;
315         uint32_t start= 0;
316         uint32_t nread = 0;
317         int n_shown = 0;
318         int n_errors = 0;
319         if (fread(pa, sizeof(uint32_t), 4,outputFile) < 4)
320         {
321             fprintf(stderr,"Empty result file\n");
322             return;
323         }
324         while (fread(pb, sizeof(uint32_t), 4,outputFile) != 0)
325         {
326             blocks++;
327             nread =  pa[0];
328             if (start>0 && (nread != start))
329             {
330                 if (n_shown < 30)
331                 {
332                     fprintf(stderr, "Skip %7d blocks from 0x%08x to 0x%08x at blocks %10llu \n",
333                             (nread-start)/0x4000, start -0x4000, nread, (unsigned long long) blocks);
334                     n_shown ++;
335                 }
336                 n_errors++;
337             }
338             else if (n_shown >0)
339                 n_shown--;
340             start = nread + 0x4000;
341             pa = pb;
342             pb = pc;
343             pc = pa;
344         }
345         if (n_errors)
346             fprintf(stderr, "%d blocks wrong from %llu blocks read\n",
347                     n_errors, (unsigned long long) blocks);
348         else
349             fprintf(stderr, "%llu blocks all fine\n", (unsigned long long) blocks);
350     }
351 }