63933c82b2bee7c9cf01e0b22afd59a63d2f651a
[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 program 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 <unistd.h>
23 #include <getopt.h>
24 #include <ftdi.h>
25
26 int main(int argc, char **argv)
27 {
28     struct ftdi_context *ftdi;
29     int do_read = 0;
30     int do_write = 0;
31     int i, f, retval = EXIT_SUCCESS;
32
33     if ((ftdi = ftdi_new()) == 0)
34     {
35         fprintf(stderr, "Failed to allocate ftdi structure :%s \n",
36                 ftdi_get_error_string(ftdi));
37         return EXIT_FAILURE;
38     }
39
40     while ((i = getopt(argc, argv, "brw")) != -1)
41     {
42         switch (i)
43         {
44             case 'b':
45                 do_read = 1;
46                 do_write = 1;
47                 break;
48             case 'r':
49                 do_read = 1;
50                 break;
51             case 'w':
52                 do_write  = 1;
53                 break;
54             default:
55                 fprintf(stderr, "usage: %s [options]\n", *argv);
56                 fprintf(stderr, "\t-b do synchronous read and write\n");
57                 fprintf(stderr, "\t-r do synchronous read\n");
58                 fprintf(stderr, "\t-w do synchronous write\n");
59                 retval = -1;
60                 goto done;
61         }
62     }
63
64     /* Select first free interface */
65     ftdi_set_interface(ftdi, INTERFACE_ANY);
66
67     struct ftdi_device_list *devlist;
68     int res;
69     if ((res = ftdi_usb_find_all(ftdi, &devlist, 0, 0)) < 0)
70     {
71         fprintf(stderr, "No FTDI with default VID/PID found\n");
72         retval =  EXIT_FAILURE;
73         goto do_deinit;
74     }
75     if (res > 0)
76     {
77         int i = 1;
78         f = ftdi_usb_open_dev(ftdi, devlist[0].dev);
79         if (f < 0)
80         {
81             fprintf(stderr, "Unable to open device %d: (%s)",
82                     i, ftdi_get_error_string(ftdi));
83             retval = -1;
84             goto do_deinit;
85         }
86     }
87     else
88     {
89         fprintf(stderr, "No devices found\n");
90         retval = -1;
91         goto do_deinit;
92     }
93     ftdi_list_free(&devlist);
94     int err = ftdi_tcioflush(ftdi);
95     if (err != 0) {
96         fprintf(stderr, "ftdi_tcioflush: %d: %s\n",
97                 err, ftdi_get_error_string(ftdi));
98         retval = -1;
99         goto do_deinit;
100     }
101     /* Reset MPSSE controller. */
102     err = ftdi_set_bitmode(ftdi, 0,  BITMODE_RESET);
103     if (err != 0) {
104         fprintf(stderr, "ftdi_set_bitmode: %d: %s\n",
105                 err, ftdi_get_error_string(ftdi));
106         retval = -1;
107         goto do_deinit;
108    }
109     /* Enable MPSSE controller. Pin directions are set later.*/
110     err = ftdi_set_bitmode(ftdi, 0, BITMODE_MPSSE);
111     if (err != 0) {
112         fprintf(stderr, "ftdi_set_bitmode: %d: %s\n",
113                 err, ftdi_get_error_string(ftdi));
114         return -1;
115     }
116 #define DATA_TO_READ 3
117     uint8_t ftdi_init[] = {TCK_DIVISOR, 0x00, 0x00,
118                              /* Set High byte to zero.*/
119                              SET_BITS_HIGH, 0, 0xff,
120                              GET_BITS_HIGH,
121                              /* Set High byte to 0x55.*/
122                              SET_BITS_HIGH, 0x55, 0xff,
123                              GET_BITS_HIGH,
124                              /* Set High byte to 0xaa.*/
125                              SET_BITS_HIGH, 0xaa, 0xff,
126                              GET_BITS_HIGH,
127                              /* Set back to high impedance.*/
128                              SET_BITS_HIGH, 0x00, 0x00 };
129     struct ftdi_transfer_control *tc_read;
130     struct ftdi_transfer_control *tc_write;
131     uint8_t data[3];
132     if (do_read) {
133         tc_read = ftdi_read_data_submit(ftdi, data, DATA_TO_READ);
134     }
135     if (do_write) {
136         tc_write = ftdi_write_data_submit(ftdi, ftdi_init, sizeof(ftdi_init));
137         int transfer = ftdi_transfer_data_done(tc_write);
138         if (transfer != sizeof(ftdi_init)) {
139             printf("Async write failed : %d\n", transfer);
140         }
141     } else {
142         int written = ftdi_write_data(ftdi, ftdi_init, sizeof(ftdi_init));
143         if (written != sizeof(ftdi_init)) {
144             printf("Sync write failed: %d\n", written);
145         }
146     }
147     if (do_read) {
148         int transfer = ftdi_transfer_data_done(tc_read);
149         if (transfer != DATA_TO_READ) {
150             printf("Async Read failed:%d\n", transfer);
151         }
152     } else {
153         int index = 0;
154         ftdi->usb_read_timeout = 1;
155         int i = 1000; /* Fail if read did not succeed in 1 second.*/
156         while (i--) {
157             int res = ftdi_read_data(ftdi, data + index, 3 - index);
158             if (res < 0) {
159                 printf("Async read failure at %d\n", index);
160             } else {
161                 index += res;
162             }
163             if (res == 3) {
164                 break;
165             }
166         }
167         if (i < 1) {
168             printf("Async read unsuccessful\n");
169         }
170     }
171     printf("Read %02x %02x %02x\n", data[0], data[1], data[2]);
172 done:
173     ftdi_usb_close(ftdi);
174 do_deinit:
175     ftdi_free(ftdi);
176     return retval;
177 }