]> sigrok.org Git - libsigrok.git/blame - src/hardware/ft2232h/api.c
configure.ac: The ft2232h driver also depends on libusb.
[libsigrok.git] / src / hardware / ft2232h / api.c
CommitLineData
4f7fdcdd
SA
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
24SR_PRIV struct sr_dev_driver ft2232h_driver_info;
25
26static const uint32_t scanopts[] = {
27 /* TODO: SR_CONF_CONN to be able to specify the USB address. */
28};
29
30static 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
36static const uint64_t samplerates[] = {
37 SR_HZ(3600),
38 SR_MHZ(10),
39 SR_HZ(1),
40};
41
42static 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
60static 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
77static const struct ftdi_chip_desc *chip_descs[] = {
78 &ft2232h_desc,
79 &ft232r_desc,
80};
81
82static int init(struct sr_dev_driver *di, struct sr_context *sr_ctx)
83{
84 return std_init(sr_ctx, di, LOG_PREFIX);
85}
86
87static 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
176err_free_ftdic:
177 ftdi_free(devc->ftdic); /* NOT free() or g_free()! */
178err_free_data_buf:
179 g_free(devc->data_buf);
180 g_free(devc);
181
182 return NULL;
183}
184
185static GSList *dev_list(const struct sr_dev_driver *di)
186{
187 return ((struct drv_context *)(di->context))->instances;
188}
189
190static 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
201static int dev_clear(const struct sr_dev_driver *di)
202{
203 return std_dev_clear(di, clear_helper);
204}
205
206static 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
252err_dev_open_close_ftdic:
253 ftdi_usb_close(devc->ftdic);
254 return SR_ERR;
255}
256
257static 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
270static 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
279static 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
301static 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
315static 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
354static 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
388static 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
420static 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
440SR_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};