]> sigrok.org Git - libsigrok.git/blob - src/hardware/ftdi-la/api.c
ftdi-la: Move ftdi_la_set_samplerate() to protocol.c.
[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 <ftdi.h>
21 #include <libusb.h>
22 #include "protocol.h"
23
24 SR_PRIV struct sr_dev_driver ftdi_la_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 config_set(uint32_t key, GVariant *data,
302         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
303 {
304         int ret;
305         struct dev_context *devc;
306         uint64_t value;
307
308         (void)cg;
309
310         if (sdi->status != SR_ST_ACTIVE)
311                 return SR_ERR_DEV_CLOSED;
312
313         devc = sdi->priv;
314
315         ret = SR_OK;
316         switch (key) {
317         case SR_CONF_LIMIT_MSEC:
318                 value = g_variant_get_uint64(data);
319                 /* TODO: Implement. */
320                 ret = SR_ERR_NA;
321                 break;
322         case SR_CONF_LIMIT_SAMPLES:
323                 if (g_variant_get_uint64(data) == 0)
324                         return SR_ERR_ARG;
325                 devc->limit_samples = g_variant_get_uint64(data);
326                 break;
327         case SR_CONF_SAMPLERATE:
328                 value = g_variant_get_uint64(data);
329                 if (value < 3600)
330                         return SR_ERR_SAMPLERATE;
331                 devc->cur_samplerate = value;
332                 return ftdi_la_set_samplerate(devc);
333         default:
334                 ret = SR_ERR_NA;
335         }
336
337         return ret;
338 }
339
340 static int config_list(uint32_t key, GVariant **data,
341         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
342 {
343         int ret;
344         GVariant *gvar;
345         GVariantBuilder gvb;
346
347         (void)sdi;
348         (void)cg;
349
350         ret = SR_OK;
351         switch (key) {
352         case SR_CONF_SCAN_OPTIONS:
353                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
354                         scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
355                 break;
356         case SR_CONF_DEVICE_OPTIONS:
357                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
358                         devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
359                 break;
360         case SR_CONF_SAMPLERATE:
361                 g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
362                 gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"),
363                         samplerates, ARRAY_SIZE(samplerates), sizeof(uint64_t));
364                 g_variant_builder_add(&gvb, "{sv}", "samplerate-steps", gvar);
365                 *data = g_variant_builder_end(&gvb);
366                 break;
367         default:
368                 return SR_ERR_NA;
369         }
370
371         return ret;
372 }
373
374 static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
375 {
376         struct dev_context *devc;
377
378         (void)cb_data;
379
380         devc = sdi->priv;
381
382         if (sdi->status != SR_ST_ACTIVE)
383                 return SR_ERR_DEV_CLOSED;
384
385         if (!devc->ftdic)
386                 return SR_ERR_BUG;
387
388         ftdi_set_bitmode(devc->ftdic, 0, BITMODE_BITBANG);
389
390         devc->cb_data = cb_data;
391
392         /* Properly reset internal variables before every new acquisition. */
393         devc->samples_sent = 0;
394         devc->bytes_received = 0;
395
396         /* Send header packet to the session bus. */
397         std_session_send_df_header(sdi, LOG_PREFIX);
398
399         /* Hook up a dummy handler to receive data from the device. */
400         sr_session_source_add(sdi->session, -1, G_IO_IN, 0,
401                               ftdi_la_receive_data, (void *)sdi);
402
403         return SR_OK;
404 }
405
406 static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
407 {
408         struct sr_datafeed_packet packet;
409
410         (void)cb_data;
411
412         if (sdi->status != SR_ST_ACTIVE)
413                 return SR_ERR_DEV_CLOSED;
414
415         sr_dbg("Stopping acquisition.");
416         sr_session_source_remove(sdi->session, -1);
417
418         /* Send end packet to the session bus. */
419         sr_dbg("Sending SR_DF_END.");
420         packet.type = SR_DF_END;
421         sr_session_send(sdi, &packet);
422
423         return SR_OK;
424 }
425
426 SR_PRIV struct sr_dev_driver ftdi_la_driver_info = {
427         .name = "ftdi-la",
428         .longname = "FTDI LA",
429         .api_version = 1,
430         .init = init,
431         .cleanup = cleanup,
432         .scan = scan,
433         .dev_list = dev_list,
434         .dev_clear = dev_clear,
435         .config_get = config_get,
436         .config_set = config_set,
437         .config_list = config_list,
438         .dev_open = dev_open,
439         .dev_close = dev_close,
440         .dev_acquisition_start = dev_acquisition_start,
441         .dev_acquisition_stop = dev_acquisition_stop,
442         .context = NULL,
443 };