]> sigrok.org Git - libsigrok.git/blob - output/ols.c
probe_groups: API changes required to implement probe groups.
[libsigrok.git] / output / ols.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2011 Uwe Hermann <uwe@hermann-uwe.de>
5  * Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
20  */
21
22 /*
23  * This implements version 1.3 of the output format for the OpenBench Logic
24  * Sniffer "Alternative" Java client. Details:
25  * https://github.com/jawi/ols/wiki/OLS-data-file-format
26  */
27
28 #include <stdlib.h>
29 #include <string.h>
30 #include <glib.h>
31 #include "libsigrok.h"
32 #include "libsigrok-internal.h"
33
34 /* Message logging helpers with subsystem-specific prefix string. */
35 #define LOG_PREFIX "output/ols: "
36 #define sr_log(l, s, args...) sr_log(l, LOG_PREFIX s, ## args)
37 #define sr_spew(s, args...) sr_spew(LOG_PREFIX s, ## args)
38 #define sr_dbg(s, args...) sr_dbg(LOG_PREFIX s, ## args)
39 #define sr_info(s, args...) sr_info(LOG_PREFIX s, ## args)
40 #define sr_warn(s, args...) sr_warn(LOG_PREFIX s, ## args)
41 #define sr_err(s, args...) sr_err(LOG_PREFIX s, ## args)
42
43 struct context {
44         uint64_t samplerate;
45         uint64_t num_samples;
46 };
47
48 static int init(struct sr_output *o)
49 {
50         struct context *ctx;
51
52         if (!(ctx = g_try_malloc(sizeof(struct context)))) {
53                 sr_err("%s: ctx malloc failed", __func__);
54                 return SR_ERR_MALLOC;
55         }
56         o->internal = ctx;
57
58         ctx->samplerate = 0;
59         ctx->num_samples = 0;
60
61         return SR_OK;
62 }
63
64 static GString *gen_header(const struct sr_dev_inst *sdi, struct context *ctx)
65 {
66         struct sr_probe *probe;
67         GSList *l;
68         GString *s;
69         GVariant *gvar;
70         int num_enabled_probes;
71
72         if (!ctx->samplerate && sr_config_get(sdi->driver, sdi, NULL,
73                         SR_CONF_SAMPLERATE, &gvar) == SR_OK) {
74                 ctx->samplerate = g_variant_get_uint64(gvar);
75                 g_variant_unref(gvar);
76         }
77
78         num_enabled_probes = 0;
79         for (l = sdi->probes; l; l = l->next) {
80                 probe = l->data;
81                 if (probe->enabled)
82                         num_enabled_probes++;
83         }
84
85         s = g_string_sized_new(512);
86         g_string_append_printf(s, ";Rate: %"PRIu64"\n", ctx->samplerate);
87         g_string_append_printf(s, ";Channels: %d\n", num_enabled_probes);
88         g_string_append_printf(s, ";EnabledChannels: -1\n");
89         g_string_append_printf(s, ";Compressed: true\n");
90         g_string_append_printf(s, ";CursorEnabled: false\n");
91
92         return s;
93 }
94
95 static int receive(struct sr_output *o, const struct sr_dev_inst *sdi,
96                 const struct sr_datafeed_packet *packet, GString **out)
97 {
98         struct context *ctx;
99         const struct sr_datafeed_meta *meta;
100         const struct sr_datafeed_logic *logic;
101         const struct sr_config *src;
102         GSList *l;
103         unsigned int i, j;
104         uint8_t c;
105
106         *out = NULL;
107         if (!o || !o->sdi)
108                 return SR_ERR_ARG;
109         ctx = o->internal;
110
111         switch (packet->type) {
112         case SR_DF_META:
113                 meta = packet->payload;
114                 for (l = meta->config; l; l = l->next) {
115                         src = l->data;
116                         if (src->key == SR_CONF_SAMPLERATE)
117                                 ctx->samplerate = g_variant_get_uint64(src->data);
118                 }
119                 break;
120         case SR_DF_LOGIC:
121                 logic = packet->payload;
122                 if (ctx->num_samples == 0) {
123                         /* First logic packet in the feed. */
124                         *out = gen_header(sdi, ctx);
125                 } else
126                         *out = g_string_sized_new(512);
127                 for (i = 0; i <= logic->length - logic->unitsize; i += logic->unitsize) {
128                         for (j = 0; j < logic->unitsize; j++) {
129                                 /* The OLS format wants the samples presented MSB first. */
130                                 c = *((uint8_t *)logic->data + i + logic->unitsize - 1 - j);
131                                 g_string_append_printf(*out, "%02x", c);
132                         }
133                         g_string_append_printf(*out, "@%"PRIu64"\n", ctx->num_samples++);
134                 }
135                 break;
136         }
137
138         return SR_OK;
139 }
140
141 static int cleanup(struct sr_output *o)
142 {
143         struct context *ctx;
144
145         if (!o || !o->sdi)
146                 return SR_ERR_ARG;
147
148         ctx = o->internal;
149         g_free(ctx);
150         o->internal = NULL;
151
152         return SR_OK;
153 }
154
155 SR_PRIV struct sr_output_format output_ols = {
156         .id = "ols",
157         .description = "OpenBench Logic Sniffer",
158         .df_type = SR_DF_LOGIC,
159         .init = init,
160         .receive = receive,
161         .cleanup = cleanup
162 };