]> sigrok.org Git - libsigrok.git/blob - src/hardware/chromium-twinkie/api.c
chromium-twinkie: add analog VBUS channels
[libsigrok.git] / src / hardware / chromium-twinkie / api.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright 2017 Google, Inc
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 2 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 <libusb.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <math.h>
25 #include <libsigrok/libsigrok.h>
26 #include "libsigrok-internal.h"
27 #include "protocol.h"
28
29 #define TWINKIE_VID             0x18d1
30 #define TWINKIE_PID             0x500a
31
32 #define USB_INTERFACE           1
33 #define USB_CONFIGURATION       1
34 #define USB_COMMANDS_IFACE      2
35
36 #define MAX_RENUM_DELAY_MS      3000
37 #define NUM_SIMUL_TRANSFERS     32
38
39 #define SAMPLE_RATE             SR_KHZ(2400)
40
41 static const char vbus_cmd[] = "tw vbus";
42
43 /* CC1 & CC2 are always present */
44 #define LOGIC_CHANNELS_COUNT    2
45
46 static const int32_t hwopts[] = {
47         SR_CONF_CONN,
48         SR_CONF_NUM_ANALOG_CHANNELS,
49 };
50
51 static const int32_t hwcaps[] = {
52         SR_CONF_LOGIC_ANALYZER,
53         SR_CONF_CONTINUOUS,
54         SR_CONF_CONN | SR_CONF_GET,
55         SR_CONF_SAMPLERATE | SR_CONF_GET,
56         SR_CONF_LIMIT_SAMPLES | SR_CONF_SET,
57 };
58
59 static const struct chan {
60         char *name;
61         int type;
62 } chan_defs[] = {
63         {"CC1", SR_CHANNEL_LOGIC},
64         {"CC2", SR_CHANNEL_LOGIC},
65         {"VBUS_V", SR_CHANNEL_ANALOG},
66         {"VBUS_A", SR_CHANNEL_ANALOG},
67
68         {NULL, 0}
69 };
70
71 static GSList *scan(struct sr_dev_driver *di, GSList *options)
72 {
73         struct drv_context *drvc;
74         struct dev_context *devc;
75         struct sr_dev_inst *sdi;
76         struct sr_usb_dev_inst *usb;
77         struct sr_channel *ch;
78         struct sr_channel_group *cc_grp, *vbus_grp[VBUS_GRP_COUNT];
79         struct sr_config *src;
80         GSList *l, *devices, *conn_devices;
81         struct libusb_device_descriptor des;
82         struct libusb_config_descriptor *cfg;
83         libusb_device **devlist;
84         int ret, i, j;
85         const char *conn;
86         char connection_id[64];
87         /* By default, disable VBUS analog */
88         int vbus_channels = 0;
89
90         drvc = di->context;
91
92         conn = NULL;
93         for (l = options; l; l = l->next) {
94                 src = l->data;
95                 switch (src->key) {
96                 case SR_CONF_CONN:
97                         conn = g_variant_get_string(src->data, NULL);
98                         break;
99                 case SR_CONF_NUM_ANALOG_CHANNELS:
100                         vbus_channels = MIN(2, g_variant_get_int32(src->data));
101                         break;
102                 }
103         }
104         if (conn)
105                 conn_devices = sr_usb_find(drvc->sr_ctx->libusb_ctx, conn);
106         else
107                 conn_devices = NULL;
108
109         /* Find all Twinkie devices */
110         devices = NULL;
111         libusb_get_device_list(drvc->sr_ctx->libusb_ctx, &devlist);
112         for (i = 0; devlist[i]; i++) {
113                 if (conn) {
114                         usb = NULL;
115                         for (l = conn_devices; l; l = l->next) {
116                                 usb = l->data;
117                                 if (usb->bus == libusb_get_bus_number(devlist[i])
118                                     && usb->address == libusb_get_device_address(devlist[i]))
119                                         break;
120                         }
121                         if (!l)
122                                 /* This device matched none of the ones that
123                                  * matched the conn specification. */
124                                 continue;
125                 }
126
127                 if ((ret = libusb_get_device_descriptor(devlist[i], &des)) != 0) {
128                         sr_warn("Failed to get device descriptor: %s.",
129                                 libusb_error_name(ret));
130                         continue;
131                 }
132
133                 if (des.idVendor != TWINKIE_VID || des.idProduct != TWINKIE_PID)
134                         continue;
135
136                 if ((ret = libusb_get_active_config_descriptor(devlist[i], &cfg)) != 0) {
137                         sr_warn("Failed to get device configuraton: %s.",
138                                 libusb_error_name(ret));
139                         continue;
140                 }
141
142                 usb_get_port_path(devlist[i], connection_id, sizeof(connection_id));
143
144                 sdi = g_malloc0(sizeof(struct sr_dev_inst));
145                 sdi->status = SR_ST_INITIALIZING;
146                 sdi->vendor = g_strdup("Chromium");
147                 sdi->model = g_strdup("Twinkie");
148                 sdi->driver = di;
149                 sdi->connection_id = g_strdup(connection_id);
150
151                 if (vbus_channels && cfg->bNumInterfaces < 3) {
152                         sr_warn("VBUS channels not available in this firmware.");
153                         vbus_channels = 0;
154                 }
155
156                 if (!(devc = g_try_malloc0(sizeof(struct dev_context))))
157                         return NULL;
158                 sdi->priv = devc;
159
160                 cc_grp = g_malloc0(sizeof(struct sr_channel_group));
161                 cc_grp->name = g_strdup("CCx");
162                 for (j = 0; j < vbus_channels; j++) {
163                         vbus_grp[j] = g_malloc0(sizeof(struct sr_channel_group));
164                         vbus_grp[j]->name = g_strdup(j == VBUS_V ? "VBUS_V"
165                                                                  : "VBUS_A");
166                 }
167
168                 for (j = 0; chan_defs[j].name; j++) {
169                         struct sr_channel_group *grp = cc_grp;
170                         if (j >= LOGIC_CHANNELS_COUNT) { /* Analog channels */
171                                 if (j - LOGIC_CHANNELS_COUNT >= vbus_channels)
172                                         break;
173                                 grp = vbus_grp[j - LOGIC_CHANNELS_COUNT];
174                         }
175                         ch = sr_channel_new(sdi, j, chan_defs[j].type, TRUE,
176                                             chan_defs[j].name);
177                         grp->channels = g_slist_append(grp->channels, ch);
178                 }
179                 sdi->channel_groups = g_slist_append(NULL, cc_grp);
180                 for (j = 0; j < vbus_channels; j++) {
181                         sdi->channel_groups = g_slist_append(sdi->channel_groups,
182                                                              vbus_grp[j]);
183                         sr_analog_init(&devc->vbus_packet[j],
184                                        &devc->vbus_encoding,
185                                        &devc->vbus_meaning[j],
186                                        &devc->vbus_spec, 3);
187                         devc->vbus_meaning[j].channels = vbus_grp[j]->channels;
188                 }
189                 /* other encoding default settings in sr_analog_init are OK (eg float) */
190                 devc->vbus_encoding.is_signed = TRUE;
191                 devc->vbus_meaning[VBUS_V].mq = SR_MQ_VOLTAGE;
192                 devc->vbus_meaning[VBUS_V].mqflags = SR_MQFLAG_DC;
193                 devc->vbus_meaning[VBUS_V].unit = SR_UNIT_VOLT;
194                 devc->vbus_meaning[VBUS_A].mq = SR_MQ_CURRENT;
195                 devc->vbus_meaning[VBUS_A].unit = SR_UNIT_AMPERE;
196
197                 devc->vbus_channels = vbus_channels;
198                 drvc->instances = g_slist_append(drvc->instances, sdi);
199                 devices = g_slist_append(devices, sdi);
200
201                 sr_dbg("Found a Twinkie dongle.");
202                 sdi->status = SR_ST_INACTIVE;
203                 sdi->inst_type = SR_INST_USB;
204                 sdi->conn = sr_usb_dev_inst_new(
205                         libusb_get_bus_number(devlist[i]),
206                         libusb_get_device_address(devlist[i]), NULL);
207         }
208         libusb_free_device_list(devlist, 1);
209         g_slist_free_full(conn_devices, (GDestroyNotify)sr_usb_dev_inst_free);
210
211         return devices;
212 }
213
214 static int dev_open(struct sr_dev_inst *sdi)
215 {
216         struct sr_dev_driver *di;
217         libusb_device **devlist;
218         struct sr_usb_dev_inst *usb;
219         struct libusb_device_descriptor des;
220         struct drv_context *drvc;
221         struct dev_context *devc;
222         int ret, i, device_count;
223         char connection_id[64];
224
225         di = sdi->driver;
226         devc = sdi->priv;
227         drvc = di->context;
228         usb = sdi->conn;
229
230         if (sdi->status == SR_ST_ACTIVE)
231                 /* Device is already in use. */
232                 return SR_ERR;
233
234         device_count = libusb_get_device_list(drvc->sr_ctx->libusb_ctx, &devlist);
235         if (device_count < 0) {
236                 sr_err("Failed to get device list: %s.",
237                        libusb_error_name(device_count));
238                 return SR_ERR;
239         }
240
241         for (i = 0; i < device_count; i++) {
242                 if ((ret = libusb_get_device_descriptor(devlist[i], &des))) {
243                         sr_err("Failed to get device descriptor: %s.",
244                                libusb_error_name(ret));
245                         continue;
246                 }
247
248                 if (des.idVendor != TWINKIE_VID || des.idProduct != TWINKIE_PID)
249                         continue;
250
251                 if ((sdi->status == SR_ST_INITIALIZING) ||
252                                 (sdi->status == SR_ST_INACTIVE)) {
253                         /*
254                          * Check device by its physical USB bus/port address.
255                          */
256                         usb_get_port_path(devlist[i], connection_id, sizeof(connection_id));
257                         if (strcmp(sdi->connection_id, connection_id))
258                                 /* This is not the one. */
259                                 continue;
260                 }
261
262                 if (!(ret = libusb_open(devlist[i], &usb->devhdl))) {
263                         if (usb->address == 0xff)
264                                 /*
265                                  * First time we touch this device after FW
266                                  * upload, so we don't know the address yet.
267                                  */
268                                 usb->address = libusb_get_device_address(devlist[i]);
269                 } else {
270                         sr_err("Failed to open device: %s.",
271                                libusb_error_name(ret));
272                         break;
273                 }
274
275                 ret = libusb_claim_interface(usb->devhdl, USB_INTERFACE);
276                 if (ret == LIBUSB_ERROR_BUSY) {
277                         sr_err("Unable to claim USB interface. Another "
278                                "program or driver has already claimed it.");
279                         break;
280                 } else if (ret == LIBUSB_ERROR_NO_DEVICE) {
281                         sr_err("Device has been disconnected.");
282                         break;
283                 } else if (ret != 0) {
284                         sr_err("Unable to claim interface: %s.",
285                                libusb_error_name(ret));
286                         break;
287                 }
288                 if (devc->vbus_channels &&
289                     (ret = libusb_claim_interface(usb->devhdl, USB_COMMANDS_IFACE))) {
290                         sr_err("Unable to claim commands interface %d/%s.", ret,
291                                libusb_error_name(ret));
292                         /* Cannot use the analog channels for VBUS. */
293                         devc->vbus_channels = 0;
294                 }
295
296                 if ((ret = twinkie_init_device(sdi)) != SR_OK) {
297                         sr_err("Failed to init device.");
298                         break;
299                 }
300
301                 sdi->status = SR_ST_ACTIVE;
302                 sr_info("Opened device %d.%d, interface %d.",
303                         usb->bus, usb->address, USB_INTERFACE);
304
305                 break;
306         }
307         libusb_free_device_list(devlist, 1);
308
309         if (sdi->status != SR_ST_ACTIVE) {
310                 if (usb->devhdl) {
311                         libusb_release_interface(usb->devhdl, USB_INTERFACE);
312                         libusb_close(usb->devhdl);
313                         usb->devhdl = NULL;
314                 }
315                 return SR_ERR;
316         }
317
318         return SR_OK;
319 }
320
321 static int dev_close(struct sr_dev_inst *sdi)
322 {
323         struct sr_usb_dev_inst *usb;
324         struct dev_context *devc;
325
326         usb = sdi->conn;
327         if (usb->devhdl == NULL)
328                 return SR_ERR;
329
330         sr_info("Closing device %d.%d.", usb->bus, usb->address);
331         devc = sdi->priv;
332         if (devc->vbus_channels)
333                 libusb_release_interface(usb->devhdl, USB_COMMANDS_IFACE);
334         libusb_release_interface(usb->devhdl, USB_INTERFACE);
335         libusb_close(usb->devhdl);
336         usb->devhdl = NULL;
337         sdi->status = SR_ST_INACTIVE;
338
339         return SR_OK;
340 }
341
342 static int config_get(uint32_t key, GVariant **data,
343                 const struct sr_dev_inst *sdi,
344                 const struct sr_channel_group *cg)
345 {
346         struct sr_usb_dev_inst *usb;
347         char str[128];
348         int ret;
349
350         (void)cg;
351
352         ret = SR_OK;
353         switch (key) {
354         case SR_CONF_CONN:
355                 if (!sdi || !sdi->conn)
356                         return SR_ERR_ARG;
357                 usb = sdi->conn;
358                 if (usb->address == 255)
359                         /* Device still needs to re-enumerate after firmware
360                          * upload, so we don't know its (future) address. */
361                         return SR_ERR;
362                 snprintf(str, 128, "%d.%d", usb->bus, usb->address);
363                 *data = g_variant_new_string(str);
364                 break;
365         case SR_CONF_SAMPLERATE:
366                 *data = g_variant_new_uint64(SAMPLE_RATE);
367                 break;
368         default:
369                 return SR_ERR_NA;
370         }
371
372         return ret;
373 }
374
375 static int config_set(uint32_t key, GVariant *data,
376                 const struct sr_dev_inst *sdi,
377                 const struct sr_channel_group *cg)
378 {
379         struct dev_context *devc;
380         int ret;
381
382         (void)cg;
383
384         if (sdi->status != SR_ST_ACTIVE)
385                 return SR_ERR_DEV_CLOSED;
386
387         devc = sdi->priv;
388
389         ret = SR_OK;
390         switch (key) {
391         case SR_CONF_LIMIT_SAMPLES:
392                 devc->limit_samples = g_variant_get_uint64(data);
393                 break;
394         default:
395                 ret = SR_ERR_NA;
396         }
397
398         return ret;
399 }
400
401 static int config_list(uint32_t key, GVariant **data,
402                 const struct sr_dev_inst *sdi,
403                 const struct sr_channel_group *cg)
404 {
405         int ret;
406
407         (void)sdi;
408         (void)cg;
409
410         ret = SR_OK;
411         switch (key) {
412         case SR_CONF_SCAN_OPTIONS:
413                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
414                                 hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t));
415                 break;
416         case SR_CONF_DEVICE_OPTIONS:
417                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
418                                 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
419                 break;
420         default:
421                 return SR_ERR_NA;
422         }
423
424         return ret;
425 }
426
427 static void abort_acquisition(struct dev_context *devc)
428 {
429         int i;
430
431         devc->sent_samples = -1;
432
433         for (i = devc->num_transfers - 1; i >= 0; i--) {
434                 if (devc->transfers[i])
435                         libusb_cancel_transfer(devc->transfers[i]);
436         }
437 }
438
439 static int receive_data(int fd, int revents, void *cb_data)
440 {
441         struct timeval tv;
442         struct dev_context *devc;
443         struct drv_context *drvc;
444         const struct sr_dev_inst *sdi;
445         struct sr_dev_driver *di;
446
447         (void)fd;
448         (void)revents;
449
450         sdi = cb_data;
451         di = sdi->driver;
452         drvc = di->context;
453         devc = sdi->priv;
454
455         tv.tv_sec = tv.tv_usec = 0;
456         libusb_handle_events_timeout(drvc->sr_ctx->libusb_ctx, &tv);
457
458         if (devc->sent_samples == -2) {
459                 abort_acquisition(devc);
460         }
461
462         return TRUE;
463 }
464
465 static int dev_acquisition_start(const struct sr_dev_inst *sdi)
466 {
467         struct sr_dev_driver *di = sdi->driver;
468         struct dev_context *devc;
469         struct drv_context *drvc;
470         struct sr_usb_dev_inst *usb;
471         struct libusb_transfer *transfer;
472         unsigned int i, timeout, num_transfers, cc_transfers;
473         int ret;
474         unsigned char *buf;
475         size_t size, convsize;
476
477         if (sdi->status != SR_ST_ACTIVE)
478                 return SR_ERR_DEV_CLOSED;
479
480         drvc = di->context;
481         devc = sdi->priv;
482         usb = sdi->conn;
483
484         devc->sent_samples = 0;
485         /* reset per-CC context */
486         memset(devc->cc, 0, sizeof(devc->cc));
487
488         timeout = 1000;
489         cc_transfers = num_transfers = 10;
490         size = 10*1024;
491         convsize = size * 8 * 256 /* largest size : only rollbacks/no edges */;
492         devc->submitted_transfers = 0;
493         if (devc->vbus_channels)
494                 num_transfers += 2;
495
496         devc->convbuffer_size = convsize;
497         if (!(devc->convbuffer = g_try_malloc(convsize))) {
498                 sr_err("Conversion buffer malloc failed.");
499                 return SR_ERR_MALLOC;
500         }
501         memset(devc->convbuffer, 0, devc->convbuffer_size);
502
503         devc->transfers = g_try_malloc0(sizeof(*devc->transfers) * num_transfers);
504         if (!devc->transfers) {
505                 sr_err("USB transfers malloc failed.");
506                 g_free(devc->convbuffer);
507                 return SR_ERR_MALLOC;
508         }
509
510         devc->num_transfers = num_transfers;
511         for (i = 0; i < cc_transfers; i++) {
512                 if (!(buf = g_try_malloc(size))) {
513                         sr_err("USB transfer buffer malloc failed.");
514                         if (devc->submitted_transfers)
515                                 abort_acquisition(devc);
516                         else {
517                                 g_free(devc->transfers);
518                                 g_free(devc->convbuffer);
519                         }
520                         return SR_ERR_MALLOC;
521                 }
522                 transfer = libusb_alloc_transfer(0);
523                 libusb_fill_bulk_transfer(transfer, usb->devhdl,
524                                 3 | LIBUSB_ENDPOINT_IN, buf, size,
525                                 twinkie_receive_transfer, (void *)sdi, timeout);
526                 if ((ret = libusb_submit_transfer(transfer)) != 0) {
527                         sr_err("Failed to submit transfer: %s.",
528                                libusb_error_name(ret));
529                         libusb_free_transfer(transfer);
530                         g_free(buf);
531                         abort_acquisition(devc);
532                         return SR_ERR;
533                 }
534                 devc->transfers[i] = transfer;
535                 devc->submitted_transfers++;
536         }
537         if (devc->vbus_channels) {
538                 struct libusb_transfer *out_xfer = libusb_alloc_transfer(0);
539                 struct libusb_transfer *in_xfer = libusb_alloc_transfer(0);
540                 libusb_fill_bulk_transfer(out_xfer, usb->devhdl,
541                                           2 | LIBUSB_ENDPOINT_OUT, (uint8_t *)vbus_cmd,
542                                           sizeof(vbus_cmd) - 1, twinkie_vbus_sent,
543                                           (void *)sdi, timeout);
544                 libusb_fill_bulk_transfer(in_xfer, usb->devhdl,
545                                           2 | LIBUSB_ENDPOINT_IN, (uint8_t *)devc->vbus_data,
546                                           sizeof(devc->vbus_data),
547                                           twinkie_vbus_recv, (void *)sdi, timeout);
548                 if ((ret = libusb_submit_transfer(out_xfer)) != 0) {
549                         sr_err("Failed to submit VBUS transfer: %s.",
550                                libusb_error_name(ret));
551                         libusb_free_transfer(out_xfer);
552                         abort_acquisition(devc);
553                         return SR_ERR;
554                 }
555                 devc->transfers[cc_transfers + 0] = out_xfer;
556                 devc->transfers[cc_transfers + 1] = in_xfer;
557                 devc->submitted_transfers++;
558         }
559
560         devc->ctx = drvc->sr_ctx;
561
562         usb_source_add(sdi->session, devc->ctx, timeout, receive_data,
563                       (void *)sdi);
564
565         /* Send header packet to the session bus. */
566         std_session_send_df_header(sdi);
567
568         if ((ret = twinkie_start_acquisition(sdi)) != SR_OK) {
569                 abort_acquisition(devc);
570                 return ret;
571         }
572
573         return SR_OK;
574 }
575
576 static int dev_acquisition_stop(struct sr_dev_inst *sdi)
577 {
578         if (sdi->status != SR_ST_ACTIVE)
579                 return SR_ERR_DEV_CLOSED;
580
581         abort_acquisition(sdi->priv);
582
583         return SR_OK;
584 }
585
586 static struct sr_dev_driver chromium_twinkie_driver_info = {
587         .name = "chromium-twinkie",
588         .longname = "Chromium Twinkie",
589         .api_version = 1,
590         .init = std_init,
591         .cleanup = std_cleanup,
592         .scan = scan,
593         .dev_list = std_dev_list,
594         .dev_clear = NULL,
595         .config_get = config_get,
596         .config_set = config_set,
597         .config_list = config_list,
598         .dev_open = dev_open,
599         .dev_close = dev_close,
600         .dev_acquisition_start = dev_acquisition_start,
601         .dev_acquisition_stop = dev_acquisition_stop,
602 };
603 SR_REGISTER_DEV_DRIVER(chromium_twinkie_driver_info);