]> sigrok.org Git - libsigrok.git/blob - output/output_ols.c
acf10af66981a0224aeb37b91d96f0fd5c9988a1
[libsigrok.git] / output / output_ols.c
1 /*
2  * This file is part of the sigrok project.
3  *
4  * Copyright (C) 2011 Uwe Hermann <uwe@hermann-uwe.de>
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, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
19  */
20
21 /*
22  * Output format for the OpenBench Logic Sniffer "Alternative" Java client.
23  * Details: https://github.com/jawi/ols/wiki/OLS-data-file-format
24  */
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include <glib.h>
29 #include <sigrok.h>
30 #include "config.h"
31
32 struct context {
33         unsigned int num_enabled_probes;
34         unsigned int unitsize;
35         char *probelist[MAX_NUM_PROBES + 1];
36         char *header;
37 };
38
39 /* FIXME */
40 #define MAX_HEADER_LEN 2048
41
42 /* TODO: Support cursors? */
43 #define OLS_HEADER \
44 "# Generated by: %s on %s%s\n" \
45 "# Probe list used for capturing:\n" \
46 "# Number:\tName:\n" \
47 "%s" \
48 ";Size: %" PRIu64 "\n" \
49 ";Rate: %" PRIu64 "\n" \
50 ";Channels: %d\n" \
51 ";EnabledChannels: -1\n" \
52 ";Compressed: true\n" \
53 ";AbsoluteLength: %" PRIu64 "\n" \
54 ";CursorEnabled: false\n" \
55 ";Cursor0: -9223372036854775808\n" \
56 ";Cursor1: -9223372036854775808\n" \
57 ";Cursor2: -9223372036854775808\n" \
58 ";Cursor3: -9223372036854775808\n" \
59 ";Cursor4: -9223372036854775808\n" \
60 ";Cursor5: -9223372036854775808\n" \
61 ";Cursor6: -9223372036854775808\n" \
62 ";Cursor7: -9223372036854775808\n" \
63 ";Cursor8: -9223372036854775808\n" \
64 ";Cursor9: -9223372036854775808\n"
65
66 const char *ols_header_comment = "\
67 # Comment: Acquisition with %d/%d probes at %s";
68
69 static int init(struct output *o)
70 {
71         struct context *ctx;
72         struct probe *probe;
73         GSList *l;
74         uint64_t samplerate;
75         unsigned int i;
76         int b, num_probes;
77         char *c, *frequency_s;
78         char wbuf[1000], comment[128];
79         time_t t;
80
81         if (!(ctx = calloc(1, sizeof(struct context))))
82                 return SR_ERR_MALLOC;
83
84         if (!(ctx->header = calloc(1, MAX_HEADER_LEN + 1))) {
85                 free(ctx);
86                 return SR_ERR_MALLOC;
87         }
88
89         o->internal = ctx;
90         ctx->num_enabled_probes = 0;
91         for (l = o->device->probes; l; l = l->next) {
92                 probe = l->data;
93                 if (!probe->enabled)
94                         continue;
95                 ctx->probelist[ctx->num_enabled_probes++] = probe->name;
96         }
97         ctx->probelist[ctx->num_enabled_probes] = 0;
98         ctx->unitsize = (ctx->num_enabled_probes + 7) / 8;
99
100         num_probes = g_slist_length(o->device->probes);
101         comment[0] = '\0';
102
103         /* TODO: Currently not available in the demo module. */
104
105         if (o->device->plugin) {
106                 samplerate = *((uint64_t *) o->device->plugin->get_device_info(
107                                 o->device->plugin_index, DI_CUR_SAMPLERATE));
108                 if (!(frequency_s = sigrok_samplerate_string(samplerate))) {
109                         free(ctx->header);
110                         free(ctx);
111                         return SR_ERR;
112                 }
113                 snprintf(comment, 127, ols_header_comment,
114                          ctx->num_enabled_probes, num_probes, frequency_s);
115                 free(frequency_s);
116         }
117
118         /* Columns / channels */
119         wbuf[0] = '\0';
120         for (i = 0; i < ctx->num_enabled_probes; i++) {
121                 c = (char *)&wbuf + strlen((char *)&wbuf);
122                 sprintf(c, "# %d\t\t%s\n", i + 1, ctx->probelist[i]);
123         }
124
125         if (!(frequency_s = sigrok_period_string(samplerate))) {
126                 free(ctx->header);
127                 free(ctx);
128                 return SR_ERR;
129         }
130
131         t = time(NULL);
132
133         /* TODO: Special handling for the demo driver. */
134         /* TODO: Don't hardcode numsamples! */
135         /* TODO: Check if num_enabled_probes/channels setting is correct. */
136         b = snprintf(ctx->header, MAX_HEADER_LEN, OLS_HEADER,
137                      PACKAGE_STRING, ctime(&t),
138                      comment,
139                      (const char *)&wbuf,
140                      (uint64_t)10000 /* numsamples */,
141                      samplerate,
142                      ctx->num_enabled_probes,
143                      (uint64_t)10000 /* numsamples */);
144
145         /* TODO: Yield errors on stuff the OLS format doesn't support. */
146
147         free(frequency_s);
148
149         if (b < 0) {
150                 free(ctx->header);
151                 free(ctx);
152                 return SR_ERR;
153         }
154
155         return 0;
156 }
157
158 static int event(struct output *o, int event_type, char **data_out,
159                  uint64_t *length_out)
160 {
161         struct context *ctx;
162
163         ctx = o->internal;
164         switch (event_type) {
165         case DF_TRIGGER:
166                 /* TODO */
167                 break;
168         case DF_END:
169                 free(o->internal);
170                 o->internal = NULL;
171                 break;
172         }
173
174         *data_out = NULL;
175         *length_out = 0;
176
177         return SR_OK;
178 }
179
180 static int data(struct output *o, char *data_in, uint64_t length_in,
181                 char **data_out, uint64_t *length_out)
182 {
183         struct context *ctx;
184         unsigned int max_linelen, outsize, i;
185         uint64_t sample;
186         static uint64_t samplecount = 0;
187         char *outbuf, *c;
188
189         ctx = o->internal;
190         max_linelen = 100; /* FIXME */
191         outsize = length_in / ctx->unitsize * max_linelen;
192         if (ctx->header)
193                 outsize += strlen(ctx->header);
194
195         if (!(outbuf = calloc(1, outsize)))
196                 return SR_ERR_MALLOC;
197
198         outbuf[0] = '\0';
199         if (ctx->header) {
200                 /* The header is still here, this must be the first packet. */
201                 strncpy(outbuf, ctx->header, outsize);
202                 free(ctx->header);
203                 ctx->header = NULL;
204         }
205
206         for (i = 0; i <= length_in - ctx->unitsize; i += ctx->unitsize) {
207                 memcpy(&sample, data_in + i, ctx->unitsize);
208
209                 c = outbuf + strlen(outbuf);
210                 /* FIXME: OLS seems to only support 2^31 total samples? */
211                 sprintf(c, "%08x@%" PRIu64 "\n", (uint32_t)sample,
212                         samplecount++);
213         }
214
215         *data_out = outbuf;
216         *length_out = strlen(outbuf);
217
218         return SR_OK;
219 }
220
221 struct output_format output_ols = {
222         "ols",
223         "OpenBench Logic Sniffer",
224         DF_LOGIC,
225         init,
226         data,
227         event,
228 };