Implement tc[io]flush methods & deprecate broken purge_buffers methods.
[libftdi] / examples / async.c
1 /* Libftdi example for asynchronous read/write.
2
3    This program is distributed under the GPL, version 2
4 */
5
6 /* This programm switches to MPSSE mode, and sets and then reads back
7  * the high byte 3 times with three different values.
8  * The expected read values are hard coded in ftdi_init
9  * with 0x00, 0x55 and 0xaa
10  *
11  * Make sure that that nothing else drives some bit of the high byte
12  * or expect a collision for a very short time and some differences
13  * in the data read back.
14  *
15  * Result should be the same without any option or with either
16  * -r or -w or -b.
17  */
18
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <ctype.h>
24 #include <unistd.h>
25 #include <getopt.h>
26 #include <ftdi.h>
27
28 int main(int argc, char **argv)
29 {
30     struct ftdi_context *ftdi;
31     int do_read = 0;
32     int do_write = 0;
33     int i, f, retval;
34
35     if ((ftdi = ftdi_new()) == 0)
36     {
37         fprintf(stderr, "Failed to allocate ftdi structure :%s \n",
38                 ftdi_get_error_string(ftdi));
39         return EXIT_FAILURE;
40     }
41
42     while ((i = getopt(argc, argv, "brw")) != -1)
43     {
44         switch (i)
45         {
46             case 'b':
47                 do_read = 1;
48                 do_write = 1;
49                 break;
50             case 'r':
51                 do_read = 1;
52                 break;
53             case 'w':
54                 do_write  = 1;
55                 break;
56             default:
57                 fprintf(stderr, "usage: %s [options]\n", *argv);
58                 fprintf(stderr, "\t-b do synchronous read and write\n");
59                 fprintf(stderr, "\t-r do synchronous read\n");
60                 fprintf(stderr, "\t-w do synchronous write\n");
61                 retval = -1;
62                 goto done;
63         }
64     }
65
66     /* Select first free interface */
67     ftdi_set_interface(ftdi, INTERFACE_ANY);
68
69     struct ftdi_device_list *devlist;
70     int res;
71     if ((res = ftdi_usb_find_all(ftdi, &devlist, 0, 0)) < 0)
72     {
73         fprintf(stderr, "No FTDI with default VID/PID found\n");
74         retval =  EXIT_FAILURE;
75         goto do_deinit;
76     }
77     if (res > 0)
78     {
79         int i = 1;
80         f = ftdi_usb_open_dev(ftdi, devlist[0].dev);
81         if (f < 0)
82         {
83             fprintf(stderr, "Unable to open device %d: (%s)",
84                     i, ftdi_get_error_string(ftdi));
85             retval = -1;
86             goto do_deinit;
87         }
88     }
89     else
90     {
91         fprintf(stderr, "No devices found\n");
92         retval = -1;
93         goto do_deinit;
94     }
95     ftdi_list_free(&devlist);
96     int err = ftdi_tcioflush(ftdi);
97     if (err != 0) {
98         fprintf(stderr, "ftdi_tcioflush: %d: %s\n",
99                 err, ftdi_get_error_string(ftdi));
100         retval = -1;
101         goto do_deinit;
102     }
103     /* Reset MPSSE controller. */
104     err = ftdi_set_bitmode(ftdi, 0,  BITMODE_RESET);
105     if (err != 0) {
106         fprintf(stderr, "ftdi_set_bitmode: %d: %s\n",
107                 err, ftdi_get_error_string(ftdi));
108         retval = -1;
109         goto do_deinit;
110    }
111     /* Enable MPSSE controller. Pin directions are set later.*/
112     err = ftdi_set_bitmode(ftdi, 0, BITMODE_MPSSE);
113     if (err != 0) {
114         fprintf(stderr, "ftdi_set_bitmode: %d: %s\n",
115                 err, ftdi_get_error_string(ftdi));
116         return -1;
117     }
118 #define DATA_TO_READ 3
119     uint8_t ftdi_init[] = {TCK_DIVISOR, 0x00, 0x00,
120                              /* Set High byte to zero.*/
121                              SET_BITS_HIGH, 0, 0xff,
122                              GET_BITS_HIGH,
123                              /* Set High byte to 0x55.*/
124                              SET_BITS_HIGH, 0x55, 0xff,
125                              GET_BITS_HIGH,
126                              /* Set High byte to 0xaa.*/
127                              SET_BITS_HIGH, 0xaa, 0xff,
128                              GET_BITS_HIGH,
129                              /* Set back to high impedance.*/
130                              SET_BITS_HIGH, 0x00, 0x00 };
131     struct ftdi_transfer_control *tc_read;
132     struct ftdi_transfer_control *tc_write;
133     uint8_t data[3];
134     if (do_read) {
135         tc_read = ftdi_read_data_submit(ftdi, data, DATA_TO_READ);
136     }
137     if (do_write) {
138         tc_write = ftdi_write_data_submit(ftdi, ftdi_init, sizeof(ftdi_init));
139         int transfer = ftdi_transfer_data_done(tc_write);
140         if (transfer != sizeof(ftdi_init)) {
141             printf("Async write failed : %d\n", transfer);
142         }
143     } else {
144         int written = ftdi_write_data(ftdi, ftdi_init, sizeof(ftdi_init));
145         if (written != sizeof(ftdi_init)) {
146             printf("Sync write failed: %d\n", written);
147         }
148     }
149     if (do_read) {
150         int transfer = ftdi_transfer_data_done(tc_read);
151         if (transfer != DATA_TO_READ) {
152             printf("Async Read failed:%d\n", transfer);
153         }
154     } else {
155         int index = 0;
156         ftdi->usb_read_timeout = 1;
157         int i = 1000; /* Fail if read did not succeed in 1 second.*/
158         while (i--) {
159             int res = ftdi_read_data(ftdi, data + index, 3 - index);
160             if (res < 0) {
161                 printf("Async read failure at %d\n", index);
162             } else {
163                 index += res;
164             }
165             if (res == 3) {
166                 break;
167             }
168         }
169         if (i < 1) {
170             printf("Async read unsuccessfull\n");
171         }
172     }
173     printf("Read %02x %02x %02x\n", data[0], data[1], data[2]);
174 done:
175     ftdi_usb_close(ftdi);
176 do_deinit:
177     ftdi_free(ftdi);
178     return retval;
179 }