Solved another TODO entry
[libftdi] / examples / stream_test.c
CommitLineData
40da63b1
UB
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>
27void check_outfile(char *);
28
29static FILE *outputFile;
30
31static int check = 1;
32static int exitRequested = 0;
33/*
34 * sigintHandler --
35 *
36 * SIGINT handler, so we can gracefully exit when the user hits ctrl-C.
37 */
38
39static void
40sigintHandler(int signum)
41{
42 exitRequested = 1;
43}
44
45static void
46usage(const char *argv0)
47{
48 fprintf(stderr,
36335b92 49 "Usage: %s [options...] \n"
40da63b1 50 "Test streaming read from FT2232H\n"
36335b92
UB
51 "[-P string] only look for product with given string\n"
52 "[-n] don't check for special block structure\n"
40da63b1
UB
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"
36335b92 60 "Copyright (C) 2009 Micah Dowty <micah@navi.cx>\n"
40da63b1
UB
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
66static uint32_t start = 0;
67static uint32_t offset = 0;
705f012d 68static uint64_t blocks = 0;
40da63b1
UB
69static uint32_t skips = 0;
70static uint32_t n_err = 0;
71static int
72readCallback(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;
d042a097
UB
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);
40da63b1
UB
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;
d042a097
UB
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);
40da63b1
UB
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 {
705f012d 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",
40da63b1
UB
128 progress->totalTime,
129 progress->current.totalBytes / (1024.0 * 1024.0),
130 progress->currentRate / 1024.0,
705f012d
UB
131 progress->totalRate / 1024.0,
132 n_err);
40da63b1
UB
133 }
134 return exitRequested ? 1 : 0;
135}
136
137int 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");
ae6585f1 184 ftdi_deinit(&ftdic);
40da63b1
UB
185 return EXIT_FAILURE;
186 }
187
188 if (ftdi_usb_open_desc(&ftdic, 0x0403, 0x6010, descstring, NULL) < 0)
189 {
190 fprintf(stderr,"Can't open ftdi device: %s\n",ftdi_get_error_string(&ftdic));
ae6585f1 191 ftdi_deinit(&ftdic);
40da63b1
UB
192 return EXIT_FAILURE;
193 }
194
195 /* A timeout value of 1 results in may skipped blocks */
196 if(ftdi_set_latency_timer(&ftdic, 2))
197 {
705f012d 198 fprintf(stderr,"Can't set latency, Error %s\n",ftdi_get_error_string(&ftdic));
ae6585f1
UB
199 ftdi_usb_close(&ftdic);
200 ftdi_deinit(&ftdic);
40da63b1
UB
201 return EXIT_FAILURE;
202 }
203
204/* if(ftdi_usb_purge_rx_buffer(&ftdic) < 0)
205 {
206 fprintf(stderr,"Can't rx purge\n",ftdi_get_error_string(&ftdic));
207 return EXIT_FAILURE;
208 }*/
209 if (outfile)
210 if ((of = fopen(outfile,"w+")) == 0)
211 fprintf(stderr,"Can't open logfile %s, Error %s\n", outfile, strerror(errno));
212 if (of)
213 if (setvbuf(of, NULL, _IOFBF , 1<<16) == 0)
214 outputFile = of;
215 signal(SIGINT, sigintHandler);
216
217 err = ftdi_readstream(&ftdic, readCallback, NULL, 8, 256);
218 if (err < 0 && !exitRequested)
219 exit(1);
220
221 if (outputFile) {
222 fclose(outputFile);
223 outputFile = NULL;
224 }
225 fprintf(stderr, "Capture ended.\n");
226
227 if (ftdi_set_bitmode(&ftdic, 0xff, BITMODE_RESET) < 0)
228 {
705f012d 229 fprintf(stderr,"Can't set synchronous fifo mode, Error %s\n",ftdi_get_error_string(&ftdic));
ae6585f1
UB
230 ftdi_usb_close(&ftdic);
231 ftdi_deinit(&ftdic);
40da63b1
UB
232 return EXIT_FAILURE;
233 }
234 ftdi_usb_close(&ftdic);
235 ftdi_deinit(&ftdic);
236 signal(SIGINT, SIG_DFL);
237 if (check && outfile)
238 {
239 if ((outputFile = fopen(outfile,"r")) == 0)
240 {
241 fprintf(stderr,"Can't open logfile %s, Error %s\n", outfile, strerror(errno));
ae6585f1
UB
242 ftdi_usb_close(&ftdic);
243 ftdi_deinit(&ftdic);
40da63b1
UB
244 return EXIT_FAILURE;
245 }
246 check_outfile(descstring);
247 fclose(outputFile);
248 }
249 else if (check)
d042a097
UB
250 fprintf(stderr,"%d errors of %llu blocks (%Le), %d (%Le) blocks skipped\n",
251 n_err, (unsigned long long) blocks, (long double)n_err/(long double) blocks,
40da63b1
UB
252 skips, (long double)skips/(long double) blocks);
253 exit (0);
254}
255
256void check_outfile(char *descstring)
257{
258 if(strcmp(descstring,"FT2232HTEST") == 0)
259 {
260 char buf0[1024];
261 char buf1[1024];
262 char bufr[1024];
263 char *pa, *pb, *pc;
264 unsigned int num_lines = 0, line_num = 1;
265 int err_count = 0;
266 unsigned int num_start, num_end;
267
40da63b1
UB
268 pa = buf0;
269 pb = buf1;
270 pc = buf0;
271 if(fgets(pa, 1023, outputFile) == NULL)
272 {
273 fprintf(stderr,"Empty output file\n");
274 return;
275 }
276 while(fgets(pb, 1023, outputFile) != NULL)
277 {
278 num_lines++;
279 unsigned int num_save = num_start;
280 if( sscanf(pa,"%6u%94s%6u",&num_start, bufr,&num_end) !=3)
281 {
282 fprintf(stdout,"Format doesn't match at line %8d \"%s",
283 num_lines, pa);
284 err_count++;
285 line_num = num_save +2;
286 }
287 else
288 {
289 if ((num_start+1)%100000 != num_end)
290 {
291 if (err_count < 20)
292 fprintf(stdout,"Malformed line %d \"%s\"\n",
293 num_lines, pa);
294 err_count++;
295 }
296 else if(num_start != line_num)
297 {
298 if (err_count < 20)
299 fprintf(stdout,"Skipping from %d to %d\n",
300 line_num, num_start);
301 err_count++;
302
303 }
304 line_num = num_end;
305 }
306 pa = pb;
307 pb = pc;
308 pc = pa;
309 }
310 if(err_count)
311 fprintf(stdout,"\n%d errors of %d data sets %f\n", err_count, num_lines, (double) err_count/(double)num_lines);
312 else
313 fprintf(stdout,"No errors for %d lines\n",num_lines);
314 }
315 else if(strcmp(descstring,"LLBBC10") == 0)
316 {
317 uint32_t block0[4];
318 uint32_t block1[4];
319 uint32_t *pa = block0;
320 uint32_t *pb = block1;
321 uint32_t *pc = block0;
322 uint32_t start= 0;
323 uint32_t nread = 0;
40da63b1
UB
324 int n_shown = 0;
325 int n_errors = 0;
326 if (fread(pa, sizeof(uint32_t), 4,outputFile) < 4)
327 {
328 fprintf(stderr,"Empty result file\n");
329 return;
330 }
331 while(fread(pb, sizeof(uint32_t), 4,outputFile) != 0)
332 {
333 blocks++;
334 nread = pa[0];
335 if(start>0 && (nread != start))
336 {
337 if(n_shown < 30)
338 {
d042a097
UB
339 fprintf(stderr, "Skip %7d blocks from 0x%08x to 0x%08x at blocks %10llu \n",
340 (nread-start)/0x4000, start -0x4000, nread, (unsigned long long) blocks);
40da63b1
UB
341 n_shown ++;
342 }
343 n_errors++;
344 }
345 else if (n_shown >0)
346 n_shown--;
347 start = nread + 0x4000;
348 pa = pb;
349 pb = pc;
350 pc = pa;
351 }
352 if(n_errors)
d042a097
UB
353 fprintf(stderr, "%d blocks wrong from %llu blocks read\n",
354 n_errors, (unsigned long long) blocks);
40da63b1 355 else
d042a097 356 fprintf(stderr, "%llu blocks all fine\n", (unsigned long long) blocks);
40da63b1
UB
357 }
358}