]> sigrok.org Git - libsigrok.git/blob - src/hardware/ft2232h/api.c
ft2232h: Add support for FTDI FT2232H/FT232R chip as LA.
[libsigrok.git] / src / hardware / ft2232h / 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 <ftdi.h>
21 #include <libusb.h>
22 #include "protocol.h"
23
24 SR_PRIV struct sr_dev_driver ft2232h_driver_info;
25
26 static const uint32_t scanopts[] = {
27         /* TODO: SR_CONF_CONN to be able to specify the USB address. */
28 };
29
30 static const uint32_t devopts[] = {
31         SR_CONF_LOGIC_ANALYZER,
32         SR_CONF_LIMIT_SAMPLES | SR_CONF_SET,
33         SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
34 };
35
36 static const uint64_t samplerates[] = {
37         SR_HZ(3600),
38         SR_MHZ(10),
39         SR_HZ(1),
40 };
41
42 static const struct ftdi_chip_desc ft2232h_desc = {
43         .vendor = 0x0403,
44         .product = 0x6010,
45         .samplerate_div = 20,
46         .channel_names = {
47                 "ADBUS0",
48                 "ADBUS1",
49                 "ADBUS2",
50                 "ADBUS3",
51                 "ADBUS4",
52                 "ADBUS5",
53                 "ADBUS6",
54                 "ADBUS7",
55                 /* TODO: BDBUS[0..7] channels. */
56                 NULL
57         }
58 };
59
60 static const struct ftdi_chip_desc ft232r_desc = {
61         .vendor = 0x0403,
62         .product = 0x6001,
63         .samplerate_div = 30,
64         .channel_names = {
65                 "TXD",
66                 "RI#",
67                 "DCD#",
68                 "DSR#",
69                 "DTR#",
70                 "CTS#",
71                 "RTS#",
72                 "RXD",
73                 NULL
74         }
75 };
76
77 static const struct ftdi_chip_desc *chip_descs[] = {
78         &ft2232h_desc,
79         &ft232r_desc,
80 };
81
82 static int init(struct sr_dev_driver *di, struct sr_context *sr_ctx)
83 {
84         return std_init(sr_ctx, di, LOG_PREFIX);
85 }
86
87 static GSList *scan(struct sr_dev_driver *di, GSList *options)
88 {
89         struct drv_context *drvc;
90         struct dev_context *devc;
91         struct sr_dev_inst *sdi;
92         GSList *devices;
93         struct ftdi_device_list *devlist = 0;
94         struct ftdi_device_list *curdev;
95         struct libusb_device_descriptor usb_desc;
96         const struct ftdi_chip_desc *desc;
97         char *vendor, *model, *serial_num;
98         int ret;
99
100         (void)options;
101
102         devices = NULL;
103         drvc = di->context;
104         drvc->instances = NULL;
105
106         /* Allocate memory for our private device context. */
107         devc = g_malloc0(sizeof(struct dev_context));
108
109         /* Allocate memory for the incoming data. */
110         devc->data_buf = g_malloc0(DATA_BUF_SIZE);
111
112         /* Allocate memory for the FTDI context (ftdic) and initialize it. */
113         devc->ftdic = ftdi_new();
114         if (!devc->ftdic) {
115                 sr_err("Failed to initialize libftdi.");
116                 goto err_free_data_buf;
117         }
118
119         ret = ftdi_usb_find_all(devc->ftdic, &devlist, 0, 0);
120         if (ret < 0) {
121                 sr_err("Failed to list devices (%d): %s", ret,
122                        ftdi_get_error_string(devc->ftdic));
123                 goto err_free_ftdic;
124         }
125
126         sr_dbg("Number of FTDI devices found: %d", ret);
127
128         curdev = devlist;
129         while (curdev) {
130                 libusb_get_device_descriptor(curdev->dev, &usb_desc);
131
132                 desc = NULL;
133                 for (unsigned long i = 0; i < ARRAY_SIZE(chip_descs); i++) {
134                         desc = chip_descs[i];
135                         if (desc->vendor == usb_desc.idVendor &&
136                                 desc->product == usb_desc.idProduct)
137                                 break;
138                 }
139
140                 if (!desc) {
141                         sr_spew("Unsupported FTDI device 0x%4x:0x%4x.",
142                                 usb_desc.idVendor, usb_desc.idProduct);
143                         continue;
144                 }
145                 devc->usbdev = curdev->dev;
146                 devc->desc = desc;
147
148                 vendor = g_malloc(32);
149                 model = g_malloc(32);
150                 serial_num = g_malloc(32);
151                 ftdi_usb_get_strings(devc->ftdic, curdev->dev, vendor, 32,
152                                      model, 32, serial_num, 32);
153                 sr_dbg("Found an FTDI device: %s.", model);
154
155                 /* Register the device with libsigrok. */
156                 sdi = g_malloc0(sizeof(struct sr_dev_inst));
157                 sdi->status = SR_ST_INITIALIZING;
158                 sdi->vendor = vendor;
159                 sdi->model = model;
160                 sdi->serial_num = serial_num;
161                 sdi->driver = di;
162                 sdi->priv = devc;
163
164                 for (char *const *chan = &(desc->channel_names[0]); *chan; chan++)
165                         sr_channel_new(sdi, &(desc->channel_names[0]) - chan,
166                                         SR_CHANNEL_LOGIC, TRUE, *chan);
167
168                 devices = g_slist_append(devices, sdi);
169                 drvc->instances = g_slist_append(drvc->instances, sdi);
170
171                 curdev = curdev->next;
172         }
173
174         return devices;
175
176 err_free_ftdic:
177         ftdi_free(devc->ftdic); /* NOT free() or g_free()! */
178 err_free_data_buf:
179         g_free(devc->data_buf);
180         g_free(devc);
181
182         return NULL;
183 }
184
185 static GSList *dev_list(const struct sr_dev_driver *di)
186 {
187         return ((struct drv_context *)(di->context))->instances;
188 }
189
190 static void clear_helper(void *priv)
191 {
192         struct dev_context *devc;
193
194         devc = priv;
195
196         ftdi_free(devc->ftdic);
197         g_free(devc->data_buf);
198         g_free(devc);
199 }
200
201 static int dev_clear(const struct sr_dev_driver *di)
202 {
203         return std_dev_clear(di, clear_helper);
204 }
205
206 static int dev_open(struct sr_dev_inst *sdi)
207 {
208         struct dev_context *devc;
209         int ret = SR_OK;
210
211         devc = sdi->priv;
212
213         ret = ftdi_usb_open_dev(devc->ftdic, devc->usbdev);
214         if (ret < 0) {
215                 /* Log errors, except for -3 ("device not found"). */
216                 if (ret != -3)
217                         sr_err("Failed to open device (%d): %s", ret,
218                                ftdi_get_error_string(devc->ftdic));
219                 return SR_ERR;
220         }
221
222         /* Purge RX/TX buffers in the FTDI chip. */
223         ret = ftdi_usb_purge_buffers(devc->ftdic);
224         if (ret < 0) {
225                 sr_err("Failed to purge FTDI RX/TX buffers (%d): %s.",
226                        ret, ftdi_get_error_string(devc->ftdic));
227                 goto err_dev_open_close_ftdic;
228         }
229         sr_dbg("FTDI chip buffers purged successfully.");
230
231         /* Reset the FTDI bitmode. */
232         ret = ftdi_set_bitmode(devc->ftdic, 0x00, BITMODE_RESET);
233         if (ret < 0) {
234                 sr_err("Failed to reset the FTDI chip bitmode (%d): %s.",
235                        ret, ftdi_get_error_string(devc->ftdic));
236                 goto err_dev_open_close_ftdic;
237         }
238         sr_dbg("FTDI chip bitmode reset successfully.");
239
240         ret = ftdi_set_bitmode(devc->ftdic, 0x00, BITMODE_BITBANG);
241         if (ret < 0) {
242                 sr_err("Failed to put FTDI chip into bitbang mode (%d): %s.",
243                        ret, ftdi_get_error_string(devc->ftdic));
244                 goto err_dev_open_close_ftdic;
245         }
246         sr_dbg("FTDI chip bitbang mode entered successfully.");
247
248         sdi->status = SR_ST_ACTIVE;
249
250         return SR_OK;
251
252 err_dev_open_close_ftdic:
253         ftdi_usb_close(devc->ftdic);
254         return SR_ERR;
255 }
256
257 static int dev_close(struct sr_dev_inst *sdi)
258 {
259         struct dev_context *devc;
260
261         devc = sdi->priv;
262
263         ftdi_usb_close(devc->ftdic);
264
265         sdi->status = SR_ST_INACTIVE;
266
267         return SR_OK;
268 }
269
270 static int cleanup(const struct sr_dev_driver *di)
271 {
272         dev_clear(di);
273
274         /* TODO: Free other driver resources, if any. */
275
276         return SR_OK;
277 }
278
279 static int config_get(uint32_t key, GVariant **data,
280         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
281 {
282         int ret;
283         struct dev_context *devc;
284
285         (void)cg;
286
287         devc = sdi->priv;
288
289         ret = SR_OK;
290         switch (key) {
291         case SR_CONF_SAMPLERATE:
292                 *data = g_variant_new_uint64(devc->cur_samplerate);
293                 break;
294         default:
295                 return SR_ERR_NA;
296         }
297
298         return ret;
299 }
300
301 static int ft2232h_set_samplerate(struct dev_context *devc)
302 {
303         int ret;
304
305         ret = ftdi_set_baudrate(devc->ftdic,
306                         devc->cur_samplerate / devc->desc->samplerate_div);
307         if (ret < 0) {
308                 sr_err("Failed to set baudrate (%d): %s.", devc->cur_samplerate,
309                        ftdi_get_error_string(devc->ftdic));
310                 return SR_ERR;
311         }
312         return SR_OK;
313 }
314
315 static int config_set(uint32_t key, GVariant *data,
316         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
317 {
318         int ret;
319         struct dev_context *devc;
320         uint64_t value;
321
322         (void)cg;
323
324         if (sdi->status != SR_ST_ACTIVE)
325                 return SR_ERR_DEV_CLOSED;
326
327         devc = sdi->priv;
328
329         ret = SR_OK;
330         switch (key) {
331         case SR_CONF_LIMIT_MSEC:
332                 value = g_variant_get_uint64(data);
333                 /* TODO: Implement. */
334                 ret = SR_ERR_NA;
335                 break;
336         case SR_CONF_LIMIT_SAMPLES:
337                 if (g_variant_get_uint64(data) == 0)
338                         return SR_ERR_ARG;
339                 devc->limit_samples = g_variant_get_uint64(data);
340                 break;
341         case SR_CONF_SAMPLERATE:
342                 value = g_variant_get_uint64(data);
343                 if (value < 3600)
344                         return SR_ERR_SAMPLERATE;
345                 devc->cur_samplerate = value;
346                 return ft2232h_set_samplerate(devc);
347         default:
348                 ret = SR_ERR_NA;
349         }
350
351         return ret;
352 }
353
354 static int config_list(uint32_t key, GVariant **data,
355         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
356 {
357         int ret;
358         GVariant *gvar;
359         GVariantBuilder gvb;
360
361         (void)sdi;
362         (void)cg;
363
364         ret = SR_OK;
365         switch (key) {
366         case SR_CONF_SCAN_OPTIONS:
367                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
368                         scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
369                 break;
370         case SR_CONF_DEVICE_OPTIONS:
371                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
372                         devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
373                 break;
374         case SR_CONF_SAMPLERATE:
375                 g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
376                 gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"),
377                         samplerates, ARRAY_SIZE(samplerates), sizeof(uint64_t));
378                 g_variant_builder_add(&gvb, "{sv}", "samplerate-steps", gvar);
379                 *data = g_variant_builder_end(&gvb);
380                 break;
381         default:
382                 return SR_ERR_NA;
383         }
384
385         return ret;
386 }
387
388 static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
389 {
390         struct dev_context *devc;
391
392         (void)cb_data;
393
394         devc = sdi->priv;
395
396         if (sdi->status != SR_ST_ACTIVE)
397                 return SR_ERR_DEV_CLOSED;
398
399         if (!devc->ftdic)
400                 return SR_ERR_BUG;
401
402         ftdi_set_bitmode(devc->ftdic, 0, BITMODE_BITBANG);
403
404         devc->cb_data = cb_data;
405
406         /* Properly reset internal variables before every new acquisition. */
407         devc->samples_sent = 0;
408         devc->bytes_received = 0;
409
410         /* Send header packet to the session bus. */
411         std_session_send_df_header(sdi, LOG_PREFIX);
412
413         /* Hook up a dummy handler to receive data from the device. */
414         sr_session_source_add(sdi->session, -1, G_IO_IN, 0,
415                               ft2232h_receive_data, (void *)sdi);
416
417         return SR_OK;
418 }
419
420 static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
421 {
422         struct sr_datafeed_packet packet;
423
424         (void)cb_data;
425
426         if (sdi->status != SR_ST_ACTIVE)
427                 return SR_ERR_DEV_CLOSED;
428
429         sr_dbg("Stopping acquisition.");
430         sr_session_source_remove(sdi->session, -1);
431
432         /* Send end packet to the session bus. */
433         sr_dbg("Sending SR_DF_END.");
434         packet.type = SR_DF_END;
435         sr_session_send(sdi, &packet);
436
437         return SR_OK;
438 }
439
440 SR_PRIV struct sr_dev_driver ft2232h_driver_info = {
441         .name = "ft2232h",
442         .longname = "FT2232H",
443         .api_version = 1,
444         .init = init,
445         .cleanup = cleanup,
446         .scan = scan,
447         .dev_list = dev_list,
448         .dev_clear = dev_clear,
449         .config_get = config_get,
450         .config_set = config_set,
451         .config_list = config_list,
452         .dev_open = dev_open,
453         .dev_close = dev_close,
454         .dev_acquisition_start = dev_acquisition_start,
455         .dev_acquisition_stop = dev_acquisition_stop,
456         .context = NULL,
457 };