]> sigrok.org Git - libsigrok.git/blob - src/input/stf.c
cbf93be4aa9f1a612ad997ed85cd32e040a7ffdb
[libsigrok.git] / src / input / stf.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2017-2021 Gerhard Sittig <gerhard.sittig@gmx.net>
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 /*
21  * The STF input module supports reading "Sigma Test File" archives
22  * which are created by the vendor application for Asix Sigma and Omega
23  * devices. See the "SIGMAP01 - Reading STF File" Application Note for
24  * details on the file format. Example data is available at the Asix
25  * web site.
26  *
27  * http://asix.net/download/analyzers/sigmap01_reading_stf_file.pdf
28  * http://asix.net/dwnld_sigma-omega_examples.htm
29  *
30  * TODO
31  * - The current implementation only supports Sigma files. Support for
32  *   Omega files is currently missing. The ZIP compressed input data
33  *   requires local file I/O in the input module, which currently is
34  *   not available in common infrastructure.
35  * - The current implementation assumes 1-bit trace width, and accepts
36  *   'Input' traces exclusively. No pseudo or decoder traces will be
37  *   imported, neither are multi-bit wide traces supported ('Bus').
38  * - This implementation derives the session feed unit size from the
39  *   set of enabled channels, but assumes an upper limit of 16 channels
40  *   total. Which is sufficient for Sigma, but may no longer be when a
41  *   future version implements support for chained Omega devices. When
42  *   the Omega chain length is limited (the AppNote suggests up to 256
43  *   channels, the user manual lacks specs for synchronization skew
44  *   beyond three Omega devices in a chain), we still might get away
45  *   with simple integer variables, and need not switch to arbitrary
46  *   length byte fields.
47  * - The current implementation merely extracts the signal data from
48  *   the archive (bit patterns, and their sample rate). Other information
49  *   that may be available in the 'Settings' section is discarded (decoder
50  *   configuration, assigned colours for traces, etc). This is acceptable
51  *   because none of these details can get communicated to the session
52  *   feed in useful ways.
53  * - The STF file format involves the lzo1x method for data compression,
54  *   see http://www.oberhumer.com/opensource/lzo/ for the project page.
55  *   The vendor explicitly references the miniLZO library (under GPLv2+
56  *   license). A future implementation might switch to a different lib
57  *   which provides support to uncompress lzo1x content, which would
58  *   eliminate the miniLZO dependency.
59  * - Re-check the trigger marker position's correctness. It may be off
60  *   in the current implementation when the file's first valid timestamp
61  *   does not align with a cluster.
62  */
63
64 /*
65  * Implementor's notes on the input data:
66  * - The input file contains: A magic literal for robust file type
67  *   identification, a "header" section, and a "data" section. The
68  *   input data either resides in a regular file (Sigma), or in a
69  *   ZIP archive (Omega). Some of the Sigma file payload is LZO1x
70  *   compressed, for Omega files ZIP's deflate is transparent.
71  * - The textual header section either ends at its EOF (Omega) or is
72  *   terminated by NUL (Sigma). Header lines are CR/LF terminated
73  *   key=value pairs, where values can be semicolon separated lists
74  *   of colon separated key=value pairs to form deeper nestings for
75  *   complex settings. Unknown keys are non-fatal, their presence
76  *   depends on the system including plugins. All numbers in the
77  *   header section are kept in textual format, typically decimal.
78  * - The (Sigma specific?) data section consists of "records" which
79  *   have two u32 fields (length and checksum) followed by up to
80  *   1MiB of compressed data. The last record has length -1 and a
81  *   checksum value 0. The data is LZO1x compressed and decompresses
82  *   to up to 1MiB. This 1MiB payload contains a number of chunks of
83  *   1440 bytes length. Each chunk has 32 bytes information and 64
84  *   clusters each, and a cluster has one 64bit timestamp and 7 16bit
85  *   sample data items. A 16bit sample data item can carry 1 to 4
86  *   sample sets, depending on the capture's samplerate. A record's
87  *   content concentrates the chunks' info and the timestamps and the
88  *   samples next to each other so that compression can take greater
89  *   effect.
90  * - The Omega specific data layout differs from Sigma, comes in
91  *   different formats (streamable, legacy), and is kept in several
92  *   ZIP member files. Omega Test Files are currently not covered by
93  *   this sigrok input module.
94  * - All numbers in binary data are kept in little endian format.
95  * - All TS count in the units which correspond to the 16bit sample
96  *   items in raw memory. When these 16bit items carry multiple 8bit
97  *   or 4bit sample sets, the TS still counts them as one step.
98  */
99
100 #include <config.h>
101
102 #include <glib.h>
103 #include <libsigrok/libsigrok.h>
104 #include <libsigrok-internal.h>
105 #include <stdint.h>
106 #include <stdlib.h>
107 #include <string.h>
108 #include <strings.h>
109 #include <time.h>
110 #include <zlib.h>
111
112 #include "minilzo/minilzo.h"
113
114 #define LOG_PREFIX "input/stf"
115
116 /*
117  * Magic string literals which correspond to the file formats. Each
118  * literal consists of 15 printables and the terminating NUL character.
119  * Header lines are terminated by CRLF.
120  */
121 #define STF_MAGIC_LENGTH        16
122 #define STF_MAGIC_SIGMA         "Sigma Test File"
123 #define STF_MAGIC_OMEGA         "Omega Test File"
124 #define STF_HEADER_EOL          "\r\n"
125
126 /*
127  * Sample period is specified in "PU" units, where 15015 counts translate
128  * to a period of 1ns. A value of 15016 signals the absence of a known
129  * sample rate (externally clocked acquisition, timing unknown).
130  */
131 #define CLK_TIME_PU_PER1NS      15015
132 #define CLK_TIME_PU_UNKNOWN     15016
133
134 /*
135  * Data is organized in records, with up to 1MiB payload data that is
136  * preceeded by two 32bit header fields.
137  */
138 #define STF_DATA_REC_HDRLEN     (2 * sizeof(uint32_t))
139 #define STF_DATA_REC_PLMAX      (1 * 1024 * 1024)
140
141 /*
142  * Accumulate chunks of sample data before submission to the session feed.
143  */
144 #define CHUNKSIZE               (4 * 1024 * 1024)
145
146 /*
147  * A chunk is associated with 32 bytes of information, and contains
148  * 64 clusters with one 64bit timestamp and 7 sample data items of
149  * 16bit width each. Which results in a chunk size of 1440 bytes. A
150  * records contains several of these chunks (up to 1MiB total size).
151  */
152 #define STF_CHUNK_TOTAL_SIZE    1440
153 #define STF_CHUNK_CLUSTER_COUNT 64
154 #define STF_CHUNK_INFO_SIZE     32
155 #define STF_CHUNK_STAMP_SIZE    8
156 #define STF_CHUNK_SAMPLE_SIZE   14
157
158 struct context {
159         enum stf_stage {
160                 STF_STAGE_MAGIC,
161                 STF_STAGE_HEADER,
162                 STF_STAGE_DATA,
163                 STF_STAGE_DONE,
164         } file_stage;
165         enum stf_format {
166                 STF_FORMAT_NONE,
167                 STF_FORMAT_SIGMA,
168                 STF_FORMAT_OMEGA,
169         } file_format;
170         gboolean header_sent;
171         size_t channel_count;
172         GSList *channels;
173         struct {
174                 uint64_t first_ts;      /* First valid timestamp in the file. */
175                 uint64_t length_ts;     /* Last valid timestamp. */
176                 uint64_t trigger_ts;    /* Timestamp of trigger position. */
177                 uint64_t clk_pu;        /* Clock period, in PU units. */
178                 uint64_t clk_div;       /* Clock divider (when 50MHz). */
179                 char **sigma_clksrc;    /* ClockSource specs (50/100/200MHz). */
180                 char **sigma_inputs;    /* Input pin names. */
181                 size_t input_count;
182                 char **trace_specs;     /* Colon separated Trace description. */
183                 time_t c_date_time;     /* File creation time (Unix epoch). */
184                 char *omega_data_class; /* Chunked or streamed, Omega only. */
185         } header;
186         struct stf_record {
187                 size_t len;             /* Payload length. */
188                 uint32_t crc;           /* Payload checksum. */
189                 uint8_t raw[STF_DATA_REC_PLMAX];        /* Payload data. */
190         } record_data;
191         struct keep_specs {
192                 uint64_t sample_rate;
193                 GSList *prev_sr_channels;
194         } keep;
195         struct {
196                 uint64_t sample_rate;   /* User specified or from header. */
197                 uint64_t sample_count;  /* Samples count as per header. */
198                 uint64_t submit_count;  /* Samples count submitted so far. */
199                 uint64_t samples_to_trigger;    /* Samples until trigger pos. */
200                 uint64_t last_submit_ts;        /* Last submitted timestamp. */
201                 size_t bits_per_sample; /* 1x 16, 2x 8, or 4x 4 per 16bit. */
202                 size_t unit_size;
203                 uint16_t curr_data;     /* Current sample data. */
204                 struct feed_queue_logic *feed;  /* Session feed helper. */
205         } submit;
206 };
207
208 static void keep_header_for_reread(const struct sr_input *in)
209 {
210         struct context *inc;
211
212         inc = in->priv;
213
214         g_slist_free_full(inc->keep.prev_sr_channels, sr_channel_free_cb);
215         inc->keep.prev_sr_channels = in->sdi->channels;
216         in->sdi->channels = NULL;
217 }
218
219 static gboolean check_header_in_reread(const struct sr_input *in)
220 {
221         struct context *inc;
222         GSList *prev, *curr;
223
224         if (!in)
225                 return FALSE;
226         inc = in->priv;
227         if (!inc)
228                 return FALSE;
229         if (!inc->keep.prev_sr_channels)
230                 return TRUE;
231
232         prev = inc->keep.prev_sr_channels;
233         curr = in->sdi->channels;
234         if (sr_channel_lists_differ(prev, curr)) {
235                 sr_err("Channel list change not supported for file re-read.");
236                 return FALSE;
237         }
238
239         g_slist_free_full(curr, sr_channel_free_cb);
240         in->sdi->channels = prev;
241         inc->keep.prev_sr_channels = NULL;
242
243         return TRUE;
244 }
245
246 struct stf_channel {
247         char *name;
248         size_t input_id;        /* Index in the Sigma inputs list. */
249         size_t src_bitpos;      /* Bit position in the input file. */
250         uint16_t src_bitmask;   /* Resulting input bit mask. */
251         size_t dst_bitpos;      /* Bit position in the datafeed image. */
252         uint16_t dst_bitmask;   /* Resulting datafeed bit mask. */
253 };
254
255 static void free_channel(void *data)
256 {
257         struct stf_channel *ch;
258
259         ch = data;
260         g_free(ch->name);
261         g_free(ch);
262 }
263
264 static int add_channel(const struct sr_input *in, char *name, size_t input_id)
265 {
266         struct context *inc;
267         char *perc;
268         uint8_t conv_value;
269         struct stf_channel *stf_ch;
270
271         inc = in->priv;
272         sr_dbg("Header: Adding channel, idx %zu, name %s, ID %zu.",
273                 inc->channel_count, name, input_id);
274
275         /*
276          * Use Sigma pin names in the absence of user assigned
277          * GUI labels for traces.
278          */
279         if (!name || !*name) {
280                 if (!inc->header.sigma_inputs)
281                         return SR_ERR_DATA;
282                 if (input_id >= inc->header.input_count)
283                         return SR_ERR_DATA;
284                 name = inc->header.sigma_inputs[input_id];
285                 if (!name || !*name)
286                         return SR_ERR_DATA;
287         }
288
289         /*
290          * Undo '%xx' style escapes in channel names. Failed conversion
291          * is non-fatal, the (non convertible part of the) channel name
292          * just won't get translated. No rollback is attempted. It's a
293          * mere cosmetics issue when input data is unexpected.
294          */
295         perc = name;
296         while ((perc = strchr(perc, '%')) != NULL) {
297                 if (!g_ascii_isxdigit(perc[1]) || !g_ascii_isxdigit(perc[2])) {
298                         sr_warn("Could not unescape channel name '%s'.", name);
299                         break;
300                 }
301                 conv_value = 0;
302                 conv_value <<= 4;
303                 conv_value |= g_ascii_xdigit_value(perc[1]);
304                 conv_value <<= 4;
305                 conv_value |= g_ascii_xdigit_value(perc[2]);
306                 perc[0] = conv_value;
307                 memmove(&perc[1], &perc[3], strlen(&perc[3]) + 1);
308                 perc = &perc[1];
309         }
310
311         stf_ch = g_malloc0(sizeof(*stf_ch));
312         stf_ch->name = g_strdup(name);
313         stf_ch->input_id = input_id;
314         stf_ch->src_bitpos = input_id;
315         stf_ch->src_bitmask = 1U << stf_ch->src_bitpos;
316         stf_ch->dst_bitpos = inc->channel_count;
317         stf_ch->dst_bitmask = 1U << stf_ch->dst_bitpos;
318         inc->channels = g_slist_append(inc->channels, stf_ch);
319
320         sr_channel_new(in->sdi, inc->channel_count,
321                 SR_CHANNEL_LOGIC, TRUE, name);
322         inc->channel_count++;
323
324         return SR_OK;
325 }
326
327 /* End of header was seen. Postprocess previously accumulated data. */
328 static int eval_header(const struct sr_input *in)
329 {
330         struct context *inc;
331         uint64_t scale, large_num, p, q;
332         char num_txt[24];
333         int rc;
334         size_t spec_idx, item_idx;
335         char *spec, **items, *item, *sep;
336         int scheme, period;
337         char *type, *name, *id;
338         gboolean is_input;
339
340         inc = in->priv;
341
342         /*
343          * Count the number of Sigma input pin names. This simplifies
344          * the name assignment logic in another location.
345          */
346         if (!inc->header.sigma_inputs) {
347                 sr_err("Header: 'Inputs' information missing.");
348                 return SR_ERR_DATA;
349         }
350         inc->header.input_count = g_strv_length(inc->header.sigma_inputs);
351
352         /*
353          * Derive the total sample count from the first/last timestamps,
354          * and determine the distance to an (optional) trigger location.
355          * Ignore out-of-range trigger positions (we have seen them in
356          * Sigma USB example captures).
357          */
358         inc->submit.sample_count = inc->header.length_ts + 1;
359         inc->submit.sample_count -= inc->header.first_ts;
360         sr_dbg("Header: TS first %" PRIu64 ", last %" PRIu64 ", count %" PRIu64 ".",
361                 inc->header.first_ts, inc->header.length_ts,
362                 inc->submit.sample_count);
363         if (inc->header.trigger_ts) {
364                 if (inc->header.trigger_ts < inc->header.first_ts)
365                         inc->header.trigger_ts = 0;
366                 if (inc->header.trigger_ts > inc->header.length_ts)
367                         inc->header.trigger_ts = 0;
368                 if (!inc->header.trigger_ts)
369                         sr_dbg("Header: ignoring out-of-range trigger TS.");
370         }
371         if (inc->header.trigger_ts) {
372                 inc->submit.samples_to_trigger = inc->header.trigger_ts;
373                 inc->submit.samples_to_trigger -= inc->header.first_ts;
374                 sr_dbg("Header: TS trigger %" PRIu64 ", samples to trigger %" PRIu64 ".",
375                         inc->header.trigger_ts, inc->submit.samples_to_trigger);
376         }
377
378         /*
379          * Inspect the ClockSource/ClockScheme header fields. Memory
380          * layout of sample data differs for 50/100/200MHz rates. As
381          * does the clock period calculation for some configurations.
382          * TestCLKTime specs only are applicable to externally clocked
383          * acquisition which gets tracked internally. 200/100MHz modes
384          * use fixed sample rates, as does 50MHz mode which supports
385          * an extra divider.
386          */
387         if (!inc->header.sigma_clksrc) {
388                 sr_err("Header: Failed to parse 'ClockSource' information.");
389                 return SR_ERR_DATA;
390         }
391         scheme = -1;
392         period = 1;
393         for (spec_idx = 0; inc->header.sigma_clksrc[spec_idx]; spec_idx++) {
394                 spec = inc->header.sigma_clksrc[spec_idx];
395                 sep = strchr(spec, '=');
396                 if (!sep)
397                         continue;
398                 *sep++ = '\0';
399                 if (strcmp(spec, "ClockScheme") == 0) {
400                         scheme = strtoul(sep, NULL, 0);
401                 }
402                 if (strcmp(spec, "Period") == 0) {
403                         period = strtoul(sep, NULL, 0);
404                 }
405         }
406         if (scheme < 0) {
407                 sr_err("Header: Unsupported 'ClockSource' detail.");
408                 return SR_ERR_DATA;
409         }
410         sr_dbg("Header: ClockScheme %d, Period %d.", scheme, period);
411         switch (scheme) {
412         case 0: /* 50MHz, 1x 16bits per sample, 20ns period and divider. */
413                 inc->header.clk_div = period;
414                 inc->header.clk_pu = 20 * CLK_TIME_PU_PER1NS;
415                 inc->header.clk_pu *= inc->header.clk_div;
416                 inc->submit.bits_per_sample = 16;
417                 break;
418         case 1: /* 100MHz, 2x 8bits per sample, 10ns period. */
419                 inc->header.clk_pu = 10 * CLK_TIME_PU_PER1NS;
420                 inc->submit.bits_per_sample = 8;
421                 scale = 16 / inc->submit.bits_per_sample;
422                 inc->submit.sample_count *= scale;
423                 sr_dbg("Header: 100MHz -> 2x sample count: %" PRIu64 ".",
424                         inc->submit.sample_count);
425                 inc->submit.samples_to_trigger *= scale;
426                 break;
427         case 2: /* 200MHz, 4x 4bits per sample, 5ns period. */
428                 inc->header.clk_pu = 5 * CLK_TIME_PU_PER1NS;
429                 inc->submit.bits_per_sample = 4;
430                 scale = 16 / inc->submit.bits_per_sample;
431                 inc->submit.sample_count *= scale;
432                 sr_dbg("Header: 200MHz -> 4x sample count: %" PRIu64 ".",
433                         inc->submit.sample_count);
434                 inc->submit.samples_to_trigger *= scale;
435                 break;
436         default: /* "Async", not implemented. */
437                 sr_err("Header: Unsupported 'ClockSource' detail.");
438                 return SR_ERR_NA;
439         }
440
441         /*
442          * Prefer the externally provided samplerate when specified by
443          * the user. Use the input file's samplerate otherwise (when
444          * available and plausible).
445          *
446          * Highest sample rate is 50MHz which translates to 20ns period.
447          * We don't expect "odd" numbers that are not a multiple of 1ns.
448          * Special acquisition modes can provide data at 100MHz/200MHz
449          * rates, which still results in full 5ns periods.
450          * The detour via text buffer and parse routine is rather easy
451          * to verify, and leaves complex arith in common support code.
452          */
453         do {
454                 inc->submit.sample_rate = inc->keep.sample_rate;
455                 if (inc->submit.sample_rate) {
456                         sr_dbg("Header: rate %" PRIu64 " (user).",
457                                 inc->submit.sample_rate);
458                         break;
459                 }
460                 large_num = inc->header.clk_pu;
461                 if (!large_num)
462                         break;
463                 if (large_num == CLK_TIME_PU_UNKNOWN)
464                         break;
465                 large_num /= CLK_TIME_PU_PER1NS;
466                 snprintf(num_txt, sizeof(num_txt), "%" PRIu64 "ns", large_num);
467                 rc = sr_parse_period(num_txt, &p, &q);
468                 if (rc != SR_OK)
469                         return rc;
470                 inc->submit.sample_rate = q / p;
471                 sr_dbg("Header: period %s -> rate %" PRIu64 " (calc).",
472                         num_txt, inc->submit.sample_rate);
473         } while (0);
474
475         /*
476          * Scan "Trace" specs, filter for 'Input' types, determine
477          * trace names from input ID and Sigma input names.
478          *
479          * TODO Also support 'Bus' types which involve more 'Input<n>'
480          * references.
481          */
482         if (!inc->header.trace_specs) {
483                 sr_err("Header: Failed to parse 'Trace' information.");
484                 return SR_ERR_DATA;
485         }
486         for (spec_idx = 0; inc->header.trace_specs[spec_idx]; spec_idx++) {
487                 spec = inc->header.trace_specs[spec_idx];
488                 items = g_strsplit_set(spec, ":", 0);
489                 type = name = id = NULL;
490                 for (item_idx = 0; items[item_idx]; item_idx++) {
491                         item = items[item_idx];
492                         sep = strchr(item, '=');
493                         if (!sep)
494                                 continue;
495                         *sep++ = '\0';
496                         if (strcmp(item, "Type") == 0) {
497                                 type = sep;
498                         } else if (strcmp(item, "Caption") == 0) {
499                                 name = sep;
500                         } else if (strcmp(item, "Input0") == 0) {
501                                 id = sep;
502                         }
503                 }
504                 if (!type) {
505                         g_strfreev(items);
506                         continue;
507                 }
508                 is_input = strcmp(type, "Input") == 0;
509                 is_input |= strcmp(type, "Digital") == 0;
510                 if (!is_input) {
511                         g_strfreev(items);
512                         continue;
513                 }
514                 if (!id || !*id) {
515                         g_strfreev(items);
516                         continue;
517                 }
518                 rc = add_channel(in, name, strtoul(id, NULL, 0));
519                 g_strfreev(items);
520                 if (rc != SR_OK)
521                         return rc;
522         }
523
524         if (!check_header_in_reread(in))
525                 return SR_ERR_DATA;
526
527         return SR_OK;
528 }
529
530 /* Preare datafeed submission in the DATA phase. */
531 static int data_enter(const struct sr_input *in)
532 {
533         struct context *inc;
534         GVariant *var;
535
536         /*
537          * Send the datafeed header and meta packets. Get the unit size
538          * from the channel count, and create a buffer for sample data
539          * submission to the session feed.
540          *
541          * Cope with multiple invocations, only do the header transmission
542          * once during inspection of an input file.
543          */
544         inc = in->priv;
545         if (inc->header_sent)
546                 return SR_OK;
547         sr_dbg("Data: entering data phase.");
548         std_session_send_df_header(in->sdi);
549         if (inc->submit.sample_rate) {
550                 var = g_variant_new_uint64(inc->submit.sample_rate);
551                 (void)sr_session_send_meta(in->sdi, SR_CONF_SAMPLERATE, var);
552         }
553         inc->header_sent = TRUE;
554
555         /*
556          * Arrange for buffered submission of samples to the session feed.
557          */
558         if (!inc->channel_count)
559                 return SR_ERR_DATA;
560         inc->submit.unit_size = (inc->channel_count + 8 - 1) / 8;
561         inc->submit.feed = feed_queue_logic_alloc(in->sdi,
562                 CHUNKSIZE, inc->submit.unit_size);
563         if (!inc->submit.feed)
564                 return SR_ERR_MALLOC;
565
566         return SR_OK;
567 }
568
569 /* Terminate datafeed submission of the DATA phase. */
570 static void data_leave(const struct sr_input *in)
571 {
572         struct context *inc;
573
574         inc = in->priv;
575         if (!inc->header_sent)
576                 return;
577
578         sr_dbg("Data: leaving data phase.");
579         (void)feed_queue_logic_flush(inc->submit.feed);
580         feed_queue_logic_free(inc->submit.feed);
581         inc->submit.feed = NULL;
582
583         std_session_send_df_end(in->sdi);
584
585         inc->header_sent = FALSE;
586 }
587
588 /* Forward (repetitions of) sample data, optionally mark trigger location. */
589 static void add_sample(const struct sr_input *in, uint16_t data, size_t count)
590 {
591         struct context *inc;
592         uint8_t unit_buffer[sizeof(data)];
593         size_t send_first;
594
595         inc = in->priv;
596
597         if (!count)
598                 return;
599
600         /* Also enforce the total sample count limit here. */
601         if (inc->submit.submit_count + count > inc->submit.sample_count) {
602                 sr_dbg("Samples: large app submit count %zu, capping.", count);
603                 count = inc->submit.sample_count - inc->submit.submit_count;
604                 sr_dbg("Samples: capped to %zu.", count);
605         }
606
607         /*
608          * Convert the caller's logical information (C language variable)
609          * to its byte buffer presentation. Then send the caller specified
610          * number of that value's repetitions to the session feed. Track
611          * the number of forwarded samples, to skip remaining buffer content
612          * after a previously configured amount of payload got forwarded,
613          * and to emit the trigger location within the stream of sample
614          * values. Split the transmission when needed to insert the packet
615          * for a trigger location.
616          */
617         write_u16le(unit_buffer, data);
618         send_first = 0;
619         if (!inc->submit.samples_to_trigger) {
620                 /* EMPTY */
621         } else if (count >= inc->submit.samples_to_trigger) {
622                 send_first = inc->submit.samples_to_trigger;
623                 count -= inc->submit.samples_to_trigger;
624         }
625         if (send_first) {
626                 (void)feed_queue_logic_submit(inc->submit.feed,
627                         unit_buffer, send_first);
628                 inc->submit.submit_count += send_first;
629                 inc->submit.samples_to_trigger -= send_first;
630                 feed_queue_logic_flush(inc->submit.feed);
631                 sr_dbg("Trigger: sending DF packet, at %" PRIu64 ".",
632                         inc->submit.submit_count);
633                 std_session_send_df_trigger(in->sdi);
634         }
635         if (count) {
636                 (void)feed_queue_logic_submit(inc->submit.feed,
637                         unit_buffer, count);
638                 inc->submit.submit_count += count;
639                 if (inc->submit.samples_to_trigger)
640                         inc->submit.samples_to_trigger -= count;
641         }
642 }
643
644 static int match_magic(GString *buf)
645 {
646
647         if (!buf || !buf->str)
648                 return SR_ERR;
649         if (buf->len < STF_MAGIC_LENGTH)
650                 return SR_ERR;
651         if (strncmp(buf->str, STF_MAGIC_SIGMA, STF_MAGIC_LENGTH) == 0)
652                 return SR_OK;
653         if (strncmp(buf->str, STF_MAGIC_OMEGA, STF_MAGIC_LENGTH) == 0)
654                 return SR_OK;
655         return SR_ERR;
656 }
657
658 /* Check the leading magic marker at the top of the file. */
659 static int parse_magic(struct sr_input *in)
660 {
661         struct context *inc;
662
663         /*
664          * Make sure the minimum amount of input data is available, to
665          * span the magic string literal. Check the magic and remove it
666          * from buffered receive data. Advance progress (or fail for
667          * unknown or yet unsupported formats).
668          */
669         inc = in->priv;
670         if (in->buf->len < STF_MAGIC_LENGTH)
671                 return SR_OK;
672         if (strncmp(in->buf->str, STF_MAGIC_SIGMA, STF_MAGIC_LENGTH) == 0) {
673                 inc->file_format = STF_FORMAT_SIGMA;
674                 g_string_erase(in->buf, 0, STF_MAGIC_LENGTH);
675                 sr_dbg("Magic check: Detected SIGMA file format.");
676                 inc->file_stage = STF_STAGE_HEADER;
677                 return SR_OK;
678         }
679         if (strncmp(in->buf->str, STF_MAGIC_OMEGA, STF_MAGIC_LENGTH) == 0) {
680                 inc->file_format = STF_FORMAT_OMEGA;
681                 g_string_erase(in->buf, 0, STF_MAGIC_LENGTH);
682                 sr_dbg("Magic check: Detected OMEGA file format.");
683                 sr_err("OMEGA format not supported by STF input module.");
684                 inc->file_stage = STF_STAGE_DONE;
685                 return SR_ERR_NA;
686         }
687         sr_err("Could not identify STF input format.");
688         return SR_ERR_NA;
689 }
690
691 /* Parse a single text line of the header section. */
692 static void parse_header_line(struct context *inc, char *line, size_t len)
693 {
694         char *key, *value;
695
696         /*
697          * Split keys and values. Convert the simple types. Store the
698          * more complex types here, only evaluate their content later.
699          * Some of the fields might reference each other. Check limits
700          * and apply scaling factors later as well.
701          */
702         (void)len;
703         key = line;
704         value = strchr(line, '=');
705         if (!value)
706                 return;
707         *value++ = '\0';
708
709         if (strcmp(key, "TestFirstTS") == 0) {
710                 inc->header.first_ts = strtoull(value, NULL, 0);
711         } else if (strcmp(key, "TestLengthTS") == 0) {
712                 inc->header.length_ts = strtoull(value, NULL, 0);
713         } else if (strcmp(key, "TestTriggerTS") == 0) {
714                 inc->header.trigger_ts = strtoull(value, NULL, 0);
715                 sr_dbg("Trigger: text '%s' -> num %." PRIu64,
716                         value, inc->header.trigger_ts);
717         } else if (strcmp(key, "TestCLKTime") == 0) {
718                 inc->header.clk_pu = strtoull(value, NULL, 0);
719         } else if (strcmp(key, "Sigma.ClockSource") == 0) {
720                 inc->header.sigma_clksrc = g_strsplit_set(value, ";", 0);
721         } else if (strcmp(key, "Sigma.SigmaInputs") == 0) {
722                 inc->header.sigma_inputs = g_strsplit_set(value, ";", 0);
723         } else if (strcmp(key, "Traces.Traces") == 0) {
724                 inc->header.trace_specs = g_strsplit_set(value, ";", 0);
725         } else if (strcmp(key, "DateTime") == 0) {
726                 inc->header.c_date_time = strtoull(value, NULL, 0);
727         } else if (strcmp(key, "DataClass") == 0) {
728                 inc->header.omega_data_class = g_strdup(value);
729         }
730 }
731
732 /* Parse the content of the "settings" section of the file. */
733 static int parse_header(struct sr_input *in)
734 {
735         struct context *inc;
736         int rc;
737         char *line, *eol;
738         size_t len;
739
740         /*
741          * Process those text lines which have completed (which have
742          * their line termination present). A NUL character signals the
743          * end of the header section and the start of the data section.
744          *
745          * Implementor's note: The Omega file will _not_ include the NUL
746          * termination. Instead the un-zipped configuration data will
747          * see its EOF. Either the post-processing needs to get factored
748          * out, or the caller needs to send a NUL containing buffer in
749          * the Omega case, too.
750          */
751         inc = in->priv;
752         while (in->buf->len) {
753                 if (in->buf->str[0] == '\0') {
754                         g_string_erase(in->buf, 0, 1);
755                         sr_dbg("Header: End of section seen.");
756                         rc = eval_header(in);
757                         if (rc != SR_OK)
758                                 return rc;
759                         inc->file_stage = STF_STAGE_DATA;
760                         return SR_OK;
761                 }
762
763                 line = in->buf->str;
764                 len = in->buf->len;
765                 eol = g_strstr_len(line, len, STF_HEADER_EOL);
766                 if (!eol) {
767                         sr_dbg("Header: Need more receive data.");
768                         return SR_OK;
769                 }
770                 *eol = '\0';            /* Trim off EOL. */
771                 len = eol - line;       /* Excludes EOL from parse call. */
772                 sr_spew("Header: Got a line, len %zd, text: %s.", len, line);
773
774                 parse_header_line(inc, line, len);
775                 g_string_erase(in->buf, 0, len + strlen(STF_HEADER_EOL));
776         }
777         return SR_OK;
778 }
779
780 /*
781  * Get one or several sample sets from a 16bit raw sample memory item.
782  * Ideally would be shared with the asix-sigma driver source files. But
783  * is kept private to each of them so that the compiler can optimize the
784  * hot code path to a maximum extent.
785  */
786 static uint16_t get_sample_bits_16(uint16_t indata)
787 {
788         return indata;
789 }
790
791 static uint16_t get_sample_bits_8(uint16_t indata, int idx)
792 {
793         uint16_t outdata;
794
795         indata >>= idx;
796         outdata = 0;
797         outdata |= (indata >> (0 * 2 - 0)) & (1 << 0);
798         outdata |= (indata >> (1 * 2 - 1)) & (1 << 1);
799         outdata |= (indata >> (2 * 2 - 2)) & (1 << 2);
800         outdata |= (indata >> (3 * 2 - 3)) & (1 << 3);
801         outdata |= (indata >> (4 * 2 - 4)) & (1 << 4);
802         outdata |= (indata >> (5 * 2 - 5)) & (1 << 5);
803         outdata |= (indata >> (6 * 2 - 6)) & (1 << 6);
804         outdata |= (indata >> (7 * 2 - 7)) & (1 << 7);
805         return outdata;
806 }
807
808 static uint16_t get_sample_bits_4(uint16_t indata, int idx)
809 {
810         uint16_t outdata;
811
812         indata >>= idx;
813         outdata = 0;
814         outdata |= (indata >> (0 * 4 - 0)) & (1 << 0);
815         outdata |= (indata >> (1 * 4 - 1)) & (1 << 1);
816         outdata |= (indata >> (2 * 4 - 2)) & (1 << 2);
817         outdata |= (indata >> (3 * 4 - 3)) & (1 << 3);
818         return outdata;
819 }
820
821 /* Map from Sigma file bit position to sigrok channel bit position. */
822 static uint16_t map_input_chans(struct sr_input *in, uint16_t bits)
823 {
824         struct context *inc;
825         uint16_t data;
826         GSList *l;
827         struct stf_channel *ch;
828
829         inc = in->priv;
830         data = 0;
831         for (l = inc->channels; l; l = l->next) {
832                 ch = l->data;
833                 if (bits & ch->src_bitmask)
834                         data |= ch->dst_bitmask;
835         }
836         return data;
837 }
838
839 /* Forward one 16bit entity to the session feed. */
840 static void xlat_send_sample_data(struct sr_input *in, uint16_t indata)
841 {
842         struct context *inc;
843         uint16_t bits, data;
844
845         /*
846          * Depending on the sample rate the memory layout for sample
847          * data varies. Get one, two, or four samples of 16, 8, or 4
848          * bits each from one 16bit entity. Get a "dense" mapping of
849          * the enabled channels from the "spread" input data. Forward
850          * the dense logic data for datafeed submission to the session,
851          * increment the timestamp for each submitted sample, and keep
852          * the last submitted pattern since it must be repeated when
853          * the next sample's timestamp is not adjacent to the current.
854          */
855         inc = in->priv;
856         switch (inc->submit.bits_per_sample) {
857         case 16:
858                 bits = get_sample_bits_16(indata);
859                 data = map_input_chans(in, bits);
860                 add_sample(in, data, 1);
861                 inc->submit.last_submit_ts++;
862                 inc->submit.curr_data = data;
863                 break;
864         case 8:
865                 bits = get_sample_bits_8(indata, 0);
866                 data = map_input_chans(in, bits);
867                 add_sample(in, data, 1);
868                 bits = get_sample_bits_8(indata, 1);
869                 data = map_input_chans(in, bits);
870                 add_sample(in, data, 1);
871                 inc->submit.last_submit_ts++;
872                 inc->submit.curr_data = data;
873                 break;
874         case 4:
875                 bits = get_sample_bits_4(indata, 0);
876                 data = map_input_chans(in, bits);
877                 add_sample(in, data, 1);
878                 bits = get_sample_bits_4(indata, 1);
879                 data = map_input_chans(in, bits);
880                 add_sample(in, data, 1);
881                 bits = get_sample_bits_4(indata, 2);
882                 data = map_input_chans(in, bits);
883                 add_sample(in, data, 1);
884                 bits = get_sample_bits_4(indata, 3);
885                 data = map_input_chans(in, bits);
886                 add_sample(in, data, 1);
887                 inc->submit.last_submit_ts++;
888                 inc->submit.curr_data = data;
889                 break;
890         }
891 }
892
893 /* Parse one "chunk" of a "record" of the file. */
894 static int stf_parse_data_chunk(struct sr_input *in,
895         const uint8_t *info, const uint8_t *stamps, const uint8_t *samples)
896 {
897         struct context *inc;
898         uint32_t chunk_id;
899         uint64_t first_ts, last_ts, chunk_len;
900         uint64_t ts, ts_diff;
901         size_t cluster, sample_count, sample;
902         uint16_t sample_data;
903
904         inc = in->priv;
905
906         chunk_id = read_u32le(&info[4]);
907         first_ts = read_u64le(&info[8]);
908         last_ts = read_u64le(&info[16]);
909         chunk_len = read_u64le(&info[24]);
910         sr_spew("Chunk info: id %08x, first %" PRIu64 ", last %" PRIu64 ", len %." PRIu64,
911                 chunk_id, first_ts, last_ts, chunk_len);
912
913         if (first_ts < inc->submit.last_submit_ts) {
914                 /* Leap backwards? Cannot be valid input data. */
915                 sr_dbg("Chunk: TS %" PRIu64 " before last submit TS %" PRIu64 ", stopping.",
916                         first_ts, inc->submit.last_submit_ts);
917                 return SR_ERR_DATA;
918         }
919
920         if (!inc->submit.last_submit_ts) {
921                 sr_dbg("Chunk: First seen TS %" PRIu64 ".", first_ts);
922                 inc->submit.last_submit_ts = first_ts;
923         }
924         if (inc->submit.submit_count >= inc->submit.sample_count) {
925                 sr_dbg("Chunk: Sample count reached, stopping.");
926                 return SR_OK;
927         }
928         for (cluster = 0; cluster < STF_CHUNK_CLUSTER_COUNT; cluster++) {
929                 ts = read_u64le_inc(&stamps);
930
931                 if (ts > inc->header.length_ts) {
932                         /*
933                          * This cluster is beyond the file's valid TS
934                          * range. Cease processing after submitting the
935                          * last seen sample up to the last valid TS.
936                          */
937                         sr_dbg("Data: Cluster TS %" PRIu64 " past header's last, flushing.", ts);
938                         ts_diff = inc->header.length_ts;
939                         ts_diff -= inc->submit.last_submit_ts;
940                         if (!ts_diff)
941                                 return SR_OK;
942                         ts_diff *= 16 / inc->submit.bits_per_sample;
943                         add_sample(in, inc->submit.curr_data, ts_diff);
944                         return SR_OK;
945                 }
946                 if (ts < inc->submit.last_submit_ts) {
947                         sr_dbg("Data: Cluster TS %" PRIu64 " before last submit TS, stopping.", ts);
948                         return SR_OK;
949                 }
950                 sample_count = STF_CHUNK_SAMPLE_SIZE / sizeof(uint16_t);
951                 if (ts + sample_count < inc->header.first_ts) {
952                         /*
953                          * The file may contain data which is located
954                          * _before_ the "first valid timestamp". We need
955                          * to avoid feeding these samples to the session,
956                          * yet track their most recent value.
957                          */
958                         inc->submit.last_submit_ts = ts;
959                         for (sample = 0; sample < sample_count; sample++) {
960                                 sample_data = read_u16le_inc(&samples);
961                                 inc->submit.last_submit_ts++;
962                                 inc->submit.curr_data = sample_data;
963                         }
964                         continue;
965                 }
966                 ts_diff = ts - inc->submit.last_submit_ts;
967                 if (ts_diff) {
968                         sr_spew("Cluster: TS %" PRIu64 ", need to skip %" PRIu64 ".",
969                                 ts, ts_diff);
970                         ts_diff *= 16 / inc->submit.bits_per_sample;
971                         add_sample(in, inc->submit.curr_data, ts_diff);
972                 }
973                 inc->submit.last_submit_ts = ts;
974                 for (sample = 0; sample < sample_count; sample++) {
975                         sample_data = read_u16le_inc(&samples);
976                         xlat_send_sample_data(in, sample_data);
977                 }
978                 if (inc->submit.submit_count >= inc->submit.sample_count) {
979                         sr_dbg("Cluster: Sample count reached, stopping.");
980                         return SR_OK;
981                 }
982         }
983         sr_spew("Chunk done.");
984
985         return SR_OK;
986 }
987
988 /* Parse a "record" of the file which contains several "chunks". */
989 static int stf_parse_data_record(struct sr_input *in, struct stf_record *rec)
990 {
991         size_t chunk_count, chunk_idx;
992         const uint8_t *rdpos, *info, *stamps, *samples;
993         size_t rec_len;
994         int ret;
995
996         chunk_count = rec->len / STF_CHUNK_TOTAL_SIZE;
997         if (chunk_count * STF_CHUNK_TOTAL_SIZE != rec->len) {
998                 sr_err("Unexpected record length, not a multiple of chunks.");
999                 return SR_ERR_DATA;
1000         }
1001         sr_dbg("Data: Processing record, len %zu, chunks %zu, remain %zu.",
1002                 rec->len, chunk_count, rec->len % STF_CHUNK_TOTAL_SIZE);
1003         rdpos = &rec->raw[0];
1004         info = rdpos;
1005         rdpos += chunk_count * STF_CHUNK_INFO_SIZE;
1006         stamps = rdpos;
1007         rdpos += chunk_count * STF_CHUNK_CLUSTER_COUNT * STF_CHUNK_STAMP_SIZE;
1008         samples = rdpos;
1009         rdpos += chunk_count * STF_CHUNK_CLUSTER_COUNT * STF_CHUNK_SAMPLE_SIZE;
1010         rec_len = rdpos - &rec->raw[0];
1011         if (rec_len != rec->len) {
1012                 sr_err("Unexpected record length, info/stamp/samples sizes.");
1013                 return SR_ERR_DATA;
1014         }
1015
1016         for (chunk_idx = 0; chunk_idx < chunk_count; chunk_idx++) {
1017                 ret = stf_parse_data_chunk(in, info, stamps, samples);
1018                 if (ret != SR_OK)
1019                         return ret;
1020                 info += STF_CHUNK_INFO_SIZE;
1021                 stamps += STF_CHUNK_CLUSTER_COUNT * STF_CHUNK_STAMP_SIZE;
1022                 samples += STF_CHUNK_CLUSTER_COUNT * STF_CHUNK_SAMPLE_SIZE;
1023         }
1024
1025         return SR_OK;
1026 }
1027
1028 /* Parse the "data" section of the file (sample data). */
1029 static int parse_file_data(struct sr_input *in)
1030 {
1031         struct context *inc;
1032         size_t len, final_len;
1033         uint32_t crc, crc_calc;
1034         size_t have_len, want_len;
1035         const uint8_t *read_ptr;
1036         void *compressed;
1037         lzo_uint raw_len;
1038         int rc;
1039
1040         inc = in->priv;
1041
1042         rc = data_enter(in);
1043         if (rc != SR_OK)
1044                 return rc;
1045
1046         /*
1047          * Make sure enough receive data is available for the
1048          * interpretation of the record header, and for the record's
1049          * respective payload data. Uncompress the payload data, have
1050          * the record processed, and remove its content from the
1051          * receive buffer.
1052          *
1053          * Implementator's note: Cope with the fact that receive data
1054          * is gathered in arbitrary pieces across arbitrary numbers of
1055          * routine calls. Insufficient amounts of receive data in one
1056          * or several iterations is non-fatal. Make sure to only "take"
1057          * input data when it's complete and got processed. Keep the
1058          * current read position when input data is incomplete.
1059          */
1060         final_len = (uint32_t)~0ul;
1061         while (in->buf->len) {
1062                 /*
1063                  * Wait for record data to become available. Check for
1064                  * the availability of a header, get the payload size
1065                  * from the header, check for the data's availability.
1066                  * Check the CRC of the (compressed) payload data.
1067                  */
1068                 have_len = in->buf->len;
1069                 if (have_len < STF_DATA_REC_HDRLEN) {
1070                         sr_dbg("Data: Need more receive data (header).");
1071                         return SR_OK;
1072                 }
1073                 read_ptr = (const uint8_t *)in->buf->str;
1074                 len = read_u32le_inc(&read_ptr);
1075                 crc = read_u32le_inc(&read_ptr);
1076                 if (len == final_len && !crc) {
1077                         sr_dbg("Data: Last record seen.");
1078                         g_string_erase(in->buf, 0, STF_DATA_REC_HDRLEN);
1079                         inc->file_stage = STF_STAGE_DONE;
1080                         return SR_OK;
1081                 }
1082                 sr_dbg("Data: Record header, len %zu, crc 0x%08lx.",
1083                         len, (unsigned long)crc);
1084                 if (len > STF_DATA_REC_PLMAX) {
1085                         sr_err("Data: Illegal record length %zu.", len);
1086                         return SR_ERR_DATA;
1087                 }
1088                 inc->record_data.len = len;
1089                 inc->record_data.crc = crc;
1090                 want_len = inc->record_data.len;
1091                 if (have_len < STF_DATA_REC_HDRLEN + want_len) {
1092                         sr_dbg("Data: Need more receive data (payload).");
1093                         return SR_OK;
1094                 }
1095                 crc_calc = crc32(0, read_ptr, want_len);
1096                 sr_spew("DBG: CRC32 calc comp 0x%08lx.",
1097                         (unsigned long)crc_calc);
1098                 if (crc_calc != inc->record_data.crc) {
1099                         sr_err("Data: Record payload CRC mismatch.");
1100                         return SR_ERR_DATA;
1101                 }
1102
1103                 /*
1104                  * Uncompress the payload data, have the record processed.
1105                  * Drop the compressed receive data from the input buffer.
1106                  */
1107                 compressed = (void *)read_ptr;
1108                 raw_len = sizeof(inc->record_data.raw);
1109                 memset(&inc->record_data.raw, 0, sizeof(inc->record_data.raw));
1110                 rc = lzo1x_decompress_safe(compressed, want_len,
1111                         inc->record_data.raw, &raw_len, NULL);
1112                 g_string_erase(in->buf, 0, STF_DATA_REC_HDRLEN + want_len);
1113                 if (rc) {
1114                         sr_err("Data: Decompression error %d.", rc);
1115                         return SR_ERR_DATA;
1116                 }
1117                 if (raw_len > sizeof(inc->record_data.raw)) {
1118                         sr_err("Data: Excessive decompressed size %zu.",
1119                                 (size_t)raw_len);
1120                         return SR_ERR_DATA;
1121                 }
1122                 inc->record_data.len = raw_len;
1123                 sr_spew("Data: Uncompressed record, len %zu.",
1124                         inc->record_data.len);
1125                 rc = stf_parse_data_record(in, &inc->record_data);
1126                 if (rc != SR_OK)
1127                         return rc;
1128         }
1129         return SR_OK;
1130 }
1131
1132 /* Process previously queued file content, invoked from receive() and end(). */
1133 static int process_data(struct sr_input *in)
1134 {
1135         struct context *inc;
1136         int ret;
1137
1138         /*
1139          * Have data which was received so far inspected, depending on
1140          * the current internal state of the input module. Have
1141          * information extracted, and/or internal state advanced to the
1142          * next phase when a section has completed.
1143          *
1144          * BEWARE! A switch() statement would be inappropriate, as it
1145          * would not allow for the timely processing of receive chunks
1146          * that span multiple input file sections. It's essential that
1147          * stage updates result in the continued inspection of received
1148          * but not yet processed input data. Yet it's desirable to bail
1149          * out upon errors as they are encountered.
1150          *
1151          * Note that it's essential to set sdi_ready and return from
1152          * receive() after the channels got created, and before data
1153          * gets submitted to the sigrok session.
1154          */
1155         inc = in->priv;
1156         if (inc->file_stage == STF_STAGE_MAGIC) {
1157                 ret = parse_magic(in);
1158                 if (ret != SR_OK)
1159                         return ret;
1160         }
1161         if (inc->file_stage == STF_STAGE_HEADER) {
1162                 ret = parse_header(in);
1163                 if (ret != SR_OK)
1164                         return ret;
1165                 if (inc->file_stage == STF_STAGE_DATA && !in->sdi_ready) {
1166                         in->sdi_ready = TRUE;
1167                         return SR_OK;
1168                 }
1169         }
1170         if (inc->file_stage == STF_STAGE_DATA) {
1171                 ret = parse_file_data(in);
1172                 if (ret != SR_OK)
1173                         return ret;
1174         }
1175         /* Nothing to be done for STF_STAGE_DONE. */
1176         return SR_OK;
1177 }
1178
1179 static const char *stf_extensions[] = { "stf", NULL, };
1180
1181 /* Check if filename ends in one of STF format's extensions. */
1182 static gboolean is_stf_extension(const char *fn)
1183 {
1184         size_t fn_len, ext_len, ext_idx, dot_idx;
1185         const char *ext;
1186
1187         if (!fn || !*fn)
1188                 return FALSE;
1189         fn_len = strlen(fn);
1190
1191         for (ext_idx = 0; /* EMPTY */; ext_idx++) {
1192                 ext = stf_extensions[ext_idx];
1193                 if (!ext || !*ext)
1194                         break;
1195                 ext_len = strlen(ext);
1196                 if (fn_len < 1 + ext_len)
1197                         continue;
1198                 dot_idx = fn_len - 1 - ext_len;
1199                 if (fn[dot_idx] != '.')
1200                         continue;
1201                 if (strcasecmp(&fn[dot_idx + 1], ext) != 0)
1202                         continue;
1203                 return TRUE;
1204         }
1205
1206         return FALSE;
1207 }
1208
1209 /* Try to auto-detect an input module for a given file. */
1210 static int format_match(GHashTable *metadata, unsigned int *confidence)
1211 {
1212         gboolean found;
1213         const char *fn;
1214         GString *buf;
1215
1216         found = FALSE;
1217
1218         /* Check the filename (its extension). */
1219         fn = (const char *)g_hash_table_lookup(metadata,
1220                 GINT_TO_POINTER(SR_INPUT_META_FILENAME));
1221         sr_dbg("Format Match: filename %s.", fn);
1222         if (is_stf_extension(fn)) {
1223                 *confidence = 100;
1224                 found = TRUE;
1225                 sr_dbg("Format Match: weak match found (filename).");
1226         }
1227
1228         /* Check the part of the file content (leading magic). */
1229         buf = (GString *)g_hash_table_lookup(metadata,
1230                 GINT_TO_POINTER(SR_INPUT_META_HEADER));
1231         if (match_magic(buf) == SR_OK) {
1232                 *confidence = 10;
1233                 found = TRUE;
1234                 sr_dbg("Format Match: strong match found (magic).");
1235         }
1236
1237         if (found)
1238                 return SR_OK;
1239         return SR_ERR;
1240 }
1241
1242 /* Initialize the input module. Inspect user specified options. */
1243 static int init(struct sr_input *in, GHashTable *options)
1244 {
1245         GVariant *var;
1246         struct context *inc;
1247         uint64_t sample_rate;
1248
1249         /* Allocate input module context. */
1250         inc = g_malloc0(sizeof(*inc));
1251         if (!inc)
1252                 return SR_ERR_MALLOC;
1253         in->priv = inc;
1254
1255         /* Allocate input device instance data. */
1256         in->sdi = g_malloc0(sizeof(*in->sdi));
1257         if (!in->sdi)
1258                 return SR_ERR_MALLOC;
1259
1260         /* Preset values from caller specified options. */
1261         var = g_hash_table_lookup(options, "samplerate");
1262         sample_rate = g_variant_get_uint64(var);
1263         inc->keep.sample_rate = sample_rate;
1264
1265         return SR_OK;
1266 }
1267
1268 /* Process another chunk of the input stream (file content). */
1269 static int receive(struct sr_input *in, GString *buf)
1270 {
1271
1272         /*
1273          * Unconditionally buffer the most recently received piece of
1274          * file content. Run another process() routine that is shared
1275          * with end(), to make sure pending data gets processed, even
1276          * when receive() is only invoked exactly once for short input.
1277          */
1278         g_string_append_len(in->buf, buf->str, buf->len);
1279         return process_data(in);
1280 }
1281
1282 /* Process the end of the input stream (file content). */
1283 static int end(struct sr_input *in)
1284 {
1285         int ret;
1286
1287         /*
1288          * Process any previously queued receive data. Flush any queued
1289          * sample data that wasn't submitted before. Send the datafeed
1290          * session end packet if a session start was sent before.
1291          */
1292         ret = process_data(in);
1293         if (ret != SR_OK)
1294                 return ret;
1295
1296         data_leave(in);
1297
1298         return SR_OK;
1299 }
1300
1301 /* Release previously allocated resources. */
1302 static void cleanup(struct sr_input *in)
1303 {
1304         struct context *inc;
1305
1306         /* Keep channel references between file re-imports. */
1307         keep_header_for_reread(in);
1308
1309         /* Release dynamically allocated resources. */
1310         inc = in->priv;
1311
1312         g_slist_free_full(inc->channels, free_channel);
1313         feed_queue_logic_free(inc->submit.feed);
1314         inc->submit.feed = NULL;
1315         g_strfreev(inc->header.sigma_clksrc);
1316         inc->header.sigma_clksrc = NULL;
1317         g_strfreev(inc->header.sigma_inputs);
1318         inc->header.sigma_inputs = NULL;
1319         g_strfreev(inc->header.trace_specs);
1320         inc->header.trace_specs = NULL;
1321 }
1322
1323 static int reset(struct sr_input *in)
1324 {
1325         struct context *inc;
1326         struct keep_specs keep;
1327
1328         inc = in->priv;
1329
1330         cleanup(in);
1331         keep = inc->keep;
1332         memset(inc, 0, sizeof(*inc));
1333         g_string_truncate(in->buf, 0);
1334         inc->keep = keep;
1335
1336         return SR_OK;
1337 }
1338
1339 enum option_index {
1340         OPT_SAMPLERATE,
1341         OPT_MAX,
1342 };
1343
1344 static struct sr_option options[] = {
1345         [OPT_SAMPLERATE] = {
1346                 "samplerate", "Samplerate (Hz)",
1347                 "The input data's sample rate in Hz. No default value.",
1348                 NULL, NULL,
1349         },
1350         ALL_ZERO,
1351 };
1352
1353 static const struct sr_option *get_options(void)
1354 {
1355         GVariant *var;
1356
1357         if (!options[0].def) {
1358                 var = g_variant_new_uint64(0);
1359                 options[OPT_SAMPLERATE].def = g_variant_ref_sink(var);
1360         }
1361
1362         return options;
1363 }
1364
1365 SR_PRIV struct sr_input_module input_stf = {
1366         .id = "stf",
1367         .name = "STF",
1368         .desc = "Sigma Test File (Asix Sigma/Omega)",
1369         .exts = stf_extensions,
1370         .metadata = {
1371                 SR_INPUT_META_FILENAME | SR_INPUT_META_REQUIRED,
1372                 SR_INPUT_META_HEADER | SR_INPUT_META_REQUIRED,
1373         },
1374         .options = get_options,
1375         .format_match = format_match,
1376         .init = init,
1377         .receive = receive,
1378         .end = end,
1379         .cleanup = cleanup,
1380         .reset = reset,
1381 };