Fix typos
[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
db9c7eba 13 * Progress information will be printed out
40da63b1
UB
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"
db9c7eba 55 "Progress information is printed each second\n"
40da63b1
UB
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;
19382a28 110 if (rem != 0)
40da63b1
UB
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{
cd2ead2f 139 struct ftdi_context *ftdi;
40da63b1
UB
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
cd2ead2f 175 if ((ftdi = ftdi_new()) == 0)
40da63b1 176 {
cd2ead2f 177 fprintf(stderr, "ftdi_new failed\n");
40da63b1
UB
178 return EXIT_FAILURE;
179 }
180
cd2ead2f 181 if (ftdi_set_interface(ftdi, INTERFACE_A) < 0)
40da63b1
UB
182 {
183 fprintf(stderr, "ftdi_set_interface failed\n");
cd2ead2f 184 ftdi_free(ftdi);
40da63b1
UB
185 return EXIT_FAILURE;
186 }
187
cd2ead2f 188 if (ftdi_usb_open_desc(ftdi, 0x0403, 0x6010, descstring, NULL) < 0)
40da63b1 189 {
cd2ead2f
UB
190 fprintf(stderr,"Can't open ftdi device: %s\n",ftdi_get_error_string(ftdi));
191 ftdi_free(ftdi);
40da63b1
UB
192 return EXIT_FAILURE;
193 }
194
195 /* A timeout value of 1 results in may skipped blocks */
cd2ead2f 196 if(ftdi_set_latency_timer(ftdi, 2))
40da63b1 197 {
cd2ead2f
UB
198 fprintf(stderr,"Can't set latency, Error %s\n",ftdi_get_error_string(ftdi));
199 ftdi_usb_close(ftdi);
200 ftdi_free(ftdi);
40da63b1
UB
201 return EXIT_FAILURE;
202 }
203
cd2ead2f 204/* if(ftdi_usb_purge_rx_buffer(ftdi) < 0)
40da63b1 205 {
cd2ead2f 206 fprintf(stderr,"Can't rx purge\n",ftdi_get_error_string(ftdi));
40da63b1
UB
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
cd2ead2f 217 err = ftdi_readstream(ftdi, readCallback, NULL, 8, 256);
40da63b1
UB
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
cd2ead2f 227 if (ftdi_set_bitmode(ftdi, 0xff, BITMODE_RESET) < 0)
40da63b1 228 {
cd2ead2f
UB
229 fprintf(stderr,"Can't set synchronous fifo mode, Error %s\n",ftdi_get_error_string(ftdi));
230 ftdi_usb_close(ftdi);
231 ftdi_free(ftdi);
40da63b1
UB
232 return EXIT_FAILURE;
233 }
cd2ead2f
UB
234 ftdi_usb_close(ftdi);
235 ftdi_free(ftdi);
40da63b1
UB
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));
cd2ead2f
UB
242 ftdi_usb_close(ftdi);
243 ftdi_free(ftdi);
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}