]> sigrok.org Git - libsigrok.git/blob - src/hardware/ftdi-la/api.c
drivers: Use ARRAY_AND_SIZE where possible.
[libsigrok.git] / src / hardware / ftdi-la / api.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2015 Sergey Alirzaev <zl29ah@gmail.com>
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <ftdi.h>
22 #include <libusb.h>
23 #include <libsigrok/libsigrok.h>
24 #include "libsigrok-internal.h"
25 #include "protocol.h"
26
27 static const uint32_t scanopts[] = {
28         SR_CONF_CONN,
29 };
30
31 static const uint32_t drvopts[] = {
32         SR_CONF_LOGIC_ANALYZER,
33 };
34
35 static const uint32_t devopts[] = {
36         SR_CONF_CONTINUOUS,
37         SR_CONF_LIMIT_SAMPLES | SR_CONF_SET,
38         SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
39         SR_CONF_CONN | SR_CONF_GET,
40 };
41
42 static const uint64_t samplerates[] = {
43         SR_HZ(3600),
44         SR_MHZ(10),
45         SR_HZ(1),
46 };
47
48 static const struct ftdi_chip_desc ft2232h_desc = {
49         .vendor = 0x0403,
50         .product = 0x6010,
51         .samplerate_div = 20,
52         .channel_names = {
53                 "ADBUS0",
54                 "ADBUS1",
55                 "ADBUS2",
56                 "ADBUS3",
57                 "ADBUS4",
58                 "ADBUS5",
59                 "ADBUS6",
60                 "ADBUS7",
61                 /* TODO: BDBUS[0..7] channels. */
62                 NULL
63         }
64 };
65
66 static const struct ftdi_chip_desc ft232r_desc = {
67         .vendor = 0x0403,
68         .product = 0x6001,
69         .samplerate_div = 30,
70         .channel_names = {
71                 "TXD",
72                 "RXD",
73                 "RTS#",
74                 "CTS#",
75                 "DTR#",
76                 "DSR#",
77                 "DCD#",
78                 "RI#",
79                 NULL
80         }
81 };
82
83 static const struct ftdi_chip_desc *chip_descs[] = {
84         &ft2232h_desc,
85         &ft232r_desc,
86 };
87
88 static void scan_device(struct ftdi_context *ftdic,
89         struct libusb_device *dev, GSList **devices)
90 {
91         struct libusb_device_descriptor usb_desc;
92         const struct ftdi_chip_desc *desc;
93         struct dev_context *devc;
94         char *vendor, *model, *serial_num;
95         struct sr_dev_inst *sdi;
96         int rv;
97
98         libusb_get_device_descriptor(dev, &usb_desc);
99
100         desc = NULL;
101         for (unsigned long i = 0; i < ARRAY_SIZE(chip_descs); i++) {
102                 desc = chip_descs[i];
103                 if (desc->vendor == usb_desc.idVendor &&
104                         desc->product == usb_desc.idProduct)
105                         break;
106         }
107
108         if (!desc) {
109                 sr_spew("Unsupported FTDI device 0x%4x:0x%4x.",
110                         usb_desc.idVendor, usb_desc.idProduct);
111                 return;
112         }
113
114         devc = g_malloc0(sizeof(struct dev_context));
115
116         /* Allocate memory for the incoming data. */
117         devc->data_buf = g_malloc0(DATA_BUF_SIZE);
118
119         devc->desc = desc;
120
121         vendor = g_malloc(32);
122         model = g_malloc(32);
123         serial_num = g_malloc(32);
124         rv = ftdi_usb_get_strings(ftdic, dev, vendor, 32,
125                         model, 32, serial_num, 32);
126         switch (rv) {
127         case 0:
128                 break;
129         case -9:
130                 sr_dbg("The device lacks a serial number.");
131                 g_free(serial_num);
132                 serial_num = NULL;
133                 break;
134         default:
135                 sr_err("Failed to get the FTDI strings: %d", rv);
136                 goto err_free_strings;
137         }
138         sr_dbg("Found an FTDI device: %s.", model);
139
140         sdi = g_malloc0(sizeof(struct sr_dev_inst));
141         sdi->status = SR_ST_INACTIVE;
142         sdi->vendor = vendor;
143         sdi->model = model;
144         sdi->serial_num = serial_num;
145         sdi->priv = devc;
146         sdi->connection_id = g_strdup_printf("d:%u/%u",
147                 libusb_get_bus_number(dev), libusb_get_device_address(dev));
148
149         for (char *const *chan = &(desc->channel_names[0]); *chan; chan++)
150                 sr_channel_new(sdi, chan - &(desc->channel_names[0]),
151                                 SR_CHANNEL_LOGIC, TRUE, *chan);
152
153         *devices = g_slist_append(*devices, sdi);
154         return;
155
156 err_free_strings:
157         g_free(vendor);
158         g_free(model);
159         g_free(serial_num);
160         g_free(devc->data_buf);
161         g_free(devc);
162 }
163
164 static GSList *scan_all(struct ftdi_context *ftdic, GSList *options)
165 {
166         GSList *devices;
167         struct ftdi_device_list *devlist = 0;
168         struct ftdi_device_list *curdev;
169         int ret;
170
171         (void)options;
172
173         devices = NULL;
174
175         ret = ftdi_usb_find_all(ftdic, &devlist, 0, 0);
176         if (ret < 0) {
177                 sr_err("Failed to list devices (%d): %s", ret,
178                        ftdi_get_error_string(ftdic));
179                 return NULL;
180         }
181
182         curdev = devlist;
183         while (curdev) {
184                 scan_device(ftdic, curdev->dev, &devices);
185                 curdev = curdev->next;
186         }
187
188         ftdi_list_free(&devlist);
189
190         return devices;
191 }
192
193 static GSList *scan(struct sr_dev_driver *di, GSList *options)
194 {
195         struct ftdi_context *ftdic;
196         struct sr_config *src;
197         struct sr_usb_dev_inst *usb;
198         const char *conn;
199         GSList *l, *conn_devices;
200         GSList *devices;
201         struct drv_context *drvc;
202         libusb_device **devlist;
203         int i;
204
205         drvc = di->context;
206         conn = NULL;
207         for (l = options; l; l = l->next) {
208                 src = l->data;
209                 if (src->key == SR_CONF_CONN) {
210                         conn = g_variant_get_string(src->data, NULL);
211                         break;
212                 }
213         }
214
215         ftdic = ftdi_new();
216         if (!ftdic) {
217                 sr_err("Failed to initialize libftdi.");
218                 return NULL;
219         }
220
221         if (conn) {
222                 devices = NULL;
223                 libusb_get_device_list(drvc->sr_ctx->libusb_ctx, &devlist);
224                 for (i = 0; devlist[i]; i++) {
225                         conn_devices = sr_usb_find(drvc->sr_ctx->libusb_ctx, conn);
226                         for (l = conn_devices; l; l = l->next) {
227                                 usb = l->data;
228                                 if (usb->bus == libusb_get_bus_number(devlist[i])
229                                         && usb->address == libusb_get_device_address(devlist[i])) {
230                                         scan_device(ftdic, devlist[i], &devices);
231                                 }
232                         }
233                 }
234                 libusb_free_device_list(devlist, 1);
235         } else
236                 devices = scan_all(ftdic, options);
237
238         ftdi_free(ftdic);
239
240         return std_scan_complete(di, devices);
241 }
242
243 static void clear_helper(struct dev_context *devc)
244 {
245         g_free(devc->data_buf);
246 }
247
248 static int dev_clear(const struct sr_dev_driver *di)
249 {
250         return std_dev_clear_with_callback(di, (std_dev_clear_callback)clear_helper);
251 }
252
253 static int dev_open(struct sr_dev_inst *sdi)
254 {
255         struct dev_context *devc;
256         int ret = SR_OK;
257
258         devc = sdi->priv;
259
260         devc->ftdic = ftdi_new();
261         if (!devc->ftdic)
262                 return SR_ERR;
263
264         ret = ftdi_usb_open_string(devc->ftdic, sdi->connection_id);
265         if (ret < 0) {
266                 /* Log errors, except for -3 ("device not found"). */
267                 if (ret != -3)
268                         sr_err("Failed to open device (%d): %s", ret,
269                                ftdi_get_error_string(devc->ftdic));
270                 goto err_ftdi_free;
271         }
272
273         ret = ftdi_usb_purge_buffers(devc->ftdic);
274         if (ret < 0) {
275                 sr_err("Failed to purge FTDI RX/TX buffers (%d): %s.",
276                        ret, ftdi_get_error_string(devc->ftdic));
277                 goto err_dev_open_close_ftdic;
278         }
279
280         ret = ftdi_set_bitmode(devc->ftdic, 0x00, BITMODE_RESET);
281         if (ret < 0) {
282                 sr_err("Failed to reset the FTDI chip bitmode (%d): %s.",
283                        ret, ftdi_get_error_string(devc->ftdic));
284                 goto err_dev_open_close_ftdic;
285         }
286
287         ret = ftdi_set_bitmode(devc->ftdic, 0x00, BITMODE_BITBANG);
288         if (ret < 0) {
289                 sr_err("Failed to put FTDI chip into bitbang mode (%d): %s.",
290                        ret, ftdi_get_error_string(devc->ftdic));
291                 goto err_dev_open_close_ftdic;
292         }
293
294         return SR_OK;
295
296 err_dev_open_close_ftdic:
297         ftdi_usb_close(devc->ftdic);
298
299 err_ftdi_free:
300         ftdi_free(devc->ftdic);
301
302         return SR_ERR;
303 }
304
305 static int dev_close(struct sr_dev_inst *sdi)
306 {
307         struct dev_context *devc;
308
309         devc = sdi->priv;
310
311         if (!devc->ftdic)
312                 return SR_ERR_BUG;
313
314         ftdi_usb_close(devc->ftdic);
315         ftdi_free(devc->ftdic);
316         devc->ftdic = NULL;
317
318         return SR_OK;
319 }
320
321 static int config_get(uint32_t key, GVariant **data,
322         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
323 {
324         struct dev_context *devc;
325         struct sr_usb_dev_inst *usb;
326         char str[128];
327
328         (void)cg;
329
330         devc = sdi->priv;
331
332         switch (key) {
333         case SR_CONF_SAMPLERATE:
334                 *data = g_variant_new_uint64(devc->cur_samplerate);
335                 break;
336         case SR_CONF_CONN:
337                 if (!sdi || !sdi->conn)
338                         return SR_ERR_ARG;
339                 usb = sdi->conn;
340                 snprintf(str, 128, "%d.%d", usb->bus, usb->address);
341                 *data = g_variant_new_string(str);
342                 break;
343         default:
344                 return SR_ERR_NA;
345         }
346
347         return SR_OK;
348 }
349
350 static int config_set(uint32_t key, GVariant *data,
351         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
352 {
353         struct dev_context *devc;
354         uint64_t value;
355
356         (void)cg;
357
358         devc = sdi->priv;
359
360         switch (key) {
361         case SR_CONF_LIMIT_MSEC:
362                 value = g_variant_get_uint64(data);
363                 /* TODO: Implement. */
364                 return SR_ERR_NA;
365         case SR_CONF_LIMIT_SAMPLES:
366                 if (g_variant_get_uint64(data) == 0)
367                         return SR_ERR_ARG;
368                 devc->limit_samples = g_variant_get_uint64(data);
369                 break;
370         case SR_CONF_SAMPLERATE:
371                 value = g_variant_get_uint64(data);
372                 if (value < 3600)
373                         return SR_ERR_SAMPLERATE;
374                 devc->cur_samplerate = value;
375                 return ftdi_la_set_samplerate(devc);
376         default:
377                 return SR_ERR_NA;
378         }
379
380         return SR_OK;
381 }
382
383 static int config_list(uint32_t key, GVariant **data,
384         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
385 {
386         switch (key) {
387         case SR_CONF_SCAN_OPTIONS:
388         case SR_CONF_DEVICE_OPTIONS:
389                 return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts);
390         case SR_CONF_SAMPLERATE:
391                 *data = std_gvar_samplerates_steps(ARRAY_AND_SIZE(samplerates));
392                 break;
393         default:
394                 return SR_ERR_NA;
395         }
396
397         return SR_OK;
398 }
399
400 static int dev_acquisition_start(const struct sr_dev_inst *sdi)
401 {
402         struct dev_context *devc;
403
404         devc = sdi->priv;
405
406         if (!devc->ftdic)
407                 return SR_ERR_BUG;
408
409         ftdi_set_bitmode(devc->ftdic, 0, BITMODE_BITBANG);
410
411         /* Properly reset internal variables before every new acquisition. */
412         devc->samples_sent = 0;
413         devc->bytes_received = 0;
414
415         std_session_send_df_header(sdi);
416
417         /* Hook up a dummy handler to receive data from the device. */
418         sr_session_source_add(sdi->session, -1, G_IO_IN, 0,
419                               ftdi_la_receive_data, (void *)sdi);
420
421         return SR_OK;
422 }
423
424 static int dev_acquisition_stop(struct sr_dev_inst *sdi)
425 {
426         sr_session_source_remove(sdi->session, -1);
427
428         std_session_send_df_end(sdi);
429
430         return SR_OK;
431 }
432
433 static struct sr_dev_driver ftdi_la_driver_info = {
434         .name = "ftdi-la",
435         .longname = "FTDI LA",
436         .api_version = 1,
437         .init = std_init,
438         .cleanup = std_cleanup,
439         .scan = scan,
440         .dev_list = std_dev_list,
441         .dev_clear = dev_clear,
442         .config_get = config_get,
443         .config_set = config_set,
444         .config_list = config_list,
445         .dev_open = dev_open,
446         .dev_close = dev_close,
447         .dev_acquisition_start = dev_acquisition_start,
448         .dev_acquisition_stop = dev_acquisition_stop,
449         .context = NULL,
450 };
451 SR_REGISTER_DEV_DRIVER(ftdi_la_driver_info);