]> sigrok.org Git - libsigrok.git/blob - src/input/stf.c
ddef5de6ee8bc2b72ef92f054329f194485e4c18
[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_one(inc->submit.feed,
627                         unit_buffer, send_first);
628                 inc->submit.submit_count += send_first;
629                 inc->submit.samples_to_trigger -= send_first;
630                 sr_dbg("Trigger: sending DF packet, at %" PRIu64 ".",
631                         inc->submit.submit_count);
632                 feed_queue_logic_send_trigger(inc->submit.feed);
633         }
634         if (count) {
635                 (void)feed_queue_logic_submit_one(inc->submit.feed,
636                         unit_buffer, count);
637                 inc->submit.submit_count += count;
638                 if (inc->submit.samples_to_trigger)
639                         inc->submit.samples_to_trigger -= count;
640         }
641 }
642
643 static int match_magic(GString *buf)
644 {
645
646         if (!buf || !buf->str)
647                 return SR_ERR;
648         if (buf->len < STF_MAGIC_LENGTH)
649                 return SR_ERR;
650         if (strncmp(buf->str, STF_MAGIC_SIGMA, STF_MAGIC_LENGTH) == 0)
651                 return SR_OK;
652         if (strncmp(buf->str, STF_MAGIC_OMEGA, STF_MAGIC_LENGTH) == 0)
653                 return SR_OK;
654         return SR_ERR;
655 }
656
657 /* Check the leading magic marker at the top of the file. */
658 static int parse_magic(struct sr_input *in)
659 {
660         struct context *inc;
661
662         /*
663          * Make sure the minimum amount of input data is available, to
664          * span the magic string literal. Check the magic and remove it
665          * from buffered receive data. Advance progress (or fail for
666          * unknown or yet unsupported formats).
667          */
668         inc = in->priv;
669         if (in->buf->len < STF_MAGIC_LENGTH)
670                 return SR_OK;
671         if (strncmp(in->buf->str, STF_MAGIC_SIGMA, STF_MAGIC_LENGTH) == 0) {
672                 inc->file_format = STF_FORMAT_SIGMA;
673                 g_string_erase(in->buf, 0, STF_MAGIC_LENGTH);
674                 sr_dbg("Magic check: Detected SIGMA file format.");
675                 inc->file_stage = STF_STAGE_HEADER;
676                 return SR_OK;
677         }
678         if (strncmp(in->buf->str, STF_MAGIC_OMEGA, STF_MAGIC_LENGTH) == 0) {
679                 inc->file_format = STF_FORMAT_OMEGA;
680                 g_string_erase(in->buf, 0, STF_MAGIC_LENGTH);
681                 sr_dbg("Magic check: Detected OMEGA file format.");
682                 sr_err("OMEGA format not supported by STF input module.");
683                 inc->file_stage = STF_STAGE_DONE;
684                 return SR_ERR_NA;
685         }
686         sr_err("Could not identify STF input format.");
687         return SR_ERR_NA;
688 }
689
690 /* Parse a single text line of the header section. */
691 static void parse_header_line(struct context *inc, char *line, size_t len)
692 {
693         char *key, *value;
694
695         /*
696          * Split keys and values. Convert the simple types. Store the
697          * more complex types here, only evaluate their content later.
698          * Some of the fields might reference each other. Check limits
699          * and apply scaling factors later as well.
700          */
701         (void)len;
702         key = line;
703         value = strchr(line, '=');
704         if (!value)
705                 return;
706         *value++ = '\0';
707
708         if (strcmp(key, "TestFirstTS") == 0) {
709                 inc->header.first_ts = strtoull(value, NULL, 0);
710         } else if (strcmp(key, "TestLengthTS") == 0) {
711                 inc->header.length_ts = strtoull(value, NULL, 0);
712         } else if (strcmp(key, "TestTriggerTS") == 0) {
713                 inc->header.trigger_ts = strtoull(value, NULL, 0);
714                 sr_dbg("Trigger: text '%s' -> num %." PRIu64,
715                         value, inc->header.trigger_ts);
716         } else if (strcmp(key, "TestCLKTime") == 0) {
717                 inc->header.clk_pu = strtoull(value, NULL, 0);
718         } else if (strcmp(key, "Sigma.ClockSource") == 0) {
719                 inc->header.sigma_clksrc = g_strsplit_set(value, ";", 0);
720         } else if (strcmp(key, "Sigma.SigmaInputs") == 0) {
721                 inc->header.sigma_inputs = g_strsplit_set(value, ";", 0);
722         } else if (strcmp(key, "Traces.Traces") == 0) {
723                 inc->header.trace_specs = g_strsplit_set(value, ";", 0);
724         } else if (strcmp(key, "DateTime") == 0) {
725                 inc->header.c_date_time = strtoull(value, NULL, 0);
726         } else if (strcmp(key, "DataClass") == 0) {
727                 inc->header.omega_data_class = g_strdup(value);
728         }
729 }
730
731 /* Parse the content of the "settings" section of the file. */
732 static int parse_header(struct sr_input *in)
733 {
734         struct context *inc;
735         int rc;
736         char *line, *eol;
737         size_t len;
738
739         /*
740          * Process those text lines which have completed (which have
741          * their line termination present). A NUL character signals the
742          * end of the header section and the start of the data section.
743          *
744          * Implementor's note: The Omega file will _not_ include the NUL
745          * termination. Instead the un-zipped configuration data will
746          * see its EOF. Either the post-processing needs to get factored
747          * out, or the caller needs to send a NUL containing buffer in
748          * the Omega case, too.
749          */
750         inc = in->priv;
751         while (in->buf->len) {
752                 if (in->buf->str[0] == '\0') {
753                         g_string_erase(in->buf, 0, 1);
754                         sr_dbg("Header: End of section seen.");
755                         rc = eval_header(in);
756                         if (rc != SR_OK)
757                                 return rc;
758                         inc->file_stage = STF_STAGE_DATA;
759                         return SR_OK;
760                 }
761
762                 line = in->buf->str;
763                 len = in->buf->len;
764                 eol = g_strstr_len(line, len, STF_HEADER_EOL);
765                 if (!eol) {
766                         sr_dbg("Header: Need more receive data.");
767                         return SR_OK;
768                 }
769                 *eol = '\0';            /* Trim off EOL. */
770                 len = eol - line;       /* Excludes EOL from parse call. */
771                 sr_spew("Header: Got a line, len %zd, text: %s.", len, line);
772
773                 parse_header_line(inc, line, len);
774                 g_string_erase(in->buf, 0, len + strlen(STF_HEADER_EOL));
775         }
776         return SR_OK;
777 }
778
779 /*
780  * Get one or several sample sets from a 16bit raw sample memory item.
781  * Ideally would be shared with the asix-sigma driver source files. But
782  * is kept private to each of them so that the compiler can optimize the
783  * hot code path to a maximum extent.
784  */
785 static uint16_t get_sample_bits_16(uint16_t indata)
786 {
787         return indata;
788 }
789
790 static uint16_t get_sample_bits_8(uint16_t indata, int idx)
791 {
792         uint16_t outdata;
793
794         indata >>= idx;
795         outdata = 0;
796         outdata |= (indata >> (0 * 2 - 0)) & (1 << 0);
797         outdata |= (indata >> (1 * 2 - 1)) & (1 << 1);
798         outdata |= (indata >> (2 * 2 - 2)) & (1 << 2);
799         outdata |= (indata >> (3 * 2 - 3)) & (1 << 3);
800         outdata |= (indata >> (4 * 2 - 4)) & (1 << 4);
801         outdata |= (indata >> (5 * 2 - 5)) & (1 << 5);
802         outdata |= (indata >> (6 * 2 - 6)) & (1 << 6);
803         outdata |= (indata >> (7 * 2 - 7)) & (1 << 7);
804         return outdata;
805 }
806
807 static uint16_t get_sample_bits_4(uint16_t indata, int idx)
808 {
809         uint16_t outdata;
810
811         indata >>= idx;
812         outdata = 0;
813         outdata |= (indata >> (0 * 4 - 0)) & (1 << 0);
814         outdata |= (indata >> (1 * 4 - 1)) & (1 << 1);
815         outdata |= (indata >> (2 * 4 - 2)) & (1 << 2);
816         outdata |= (indata >> (3 * 4 - 3)) & (1 << 3);
817         return outdata;
818 }
819
820 /* Map from Sigma file bit position to sigrok channel bit position. */
821 static uint16_t map_input_chans(struct sr_input *in, uint16_t bits)
822 {
823         struct context *inc;
824         uint16_t data;
825         GSList *l;
826         struct stf_channel *ch;
827
828         inc = in->priv;
829         data = 0;
830         for (l = inc->channels; l; l = l->next) {
831                 ch = l->data;
832                 if (bits & ch->src_bitmask)
833                         data |= ch->dst_bitmask;
834         }
835         return data;
836 }
837
838 /* Forward one 16bit entity to the session feed. */
839 static void xlat_send_sample_data(struct sr_input *in, uint16_t indata)
840 {
841         struct context *inc;
842         uint16_t bits, data;
843
844         /*
845          * Depending on the sample rate the memory layout for sample
846          * data varies. Get one, two, or four samples of 16, 8, or 4
847          * bits each from one 16bit entity. Get a "dense" mapping of
848          * the enabled channels from the "spread" input data. Forward
849          * the dense logic data for datafeed submission to the session,
850          * increment the timestamp for each submitted sample, and keep
851          * the last submitted pattern since it must be repeated when
852          * the next sample's timestamp is not adjacent to the current.
853          */
854         inc = in->priv;
855         switch (inc->submit.bits_per_sample) {
856         case 16:
857                 bits = get_sample_bits_16(indata);
858                 data = map_input_chans(in, bits);
859                 add_sample(in, data, 1);
860                 inc->submit.last_submit_ts++;
861                 inc->submit.curr_data = data;
862                 break;
863         case 8:
864                 bits = get_sample_bits_8(indata, 0);
865                 data = map_input_chans(in, bits);
866                 add_sample(in, data, 1);
867                 bits = get_sample_bits_8(indata, 1);
868                 data = map_input_chans(in, bits);
869                 add_sample(in, data, 1);
870                 inc->submit.last_submit_ts++;
871                 inc->submit.curr_data = data;
872                 break;
873         case 4:
874                 bits = get_sample_bits_4(indata, 0);
875                 data = map_input_chans(in, bits);
876                 add_sample(in, data, 1);
877                 bits = get_sample_bits_4(indata, 1);
878                 data = map_input_chans(in, bits);
879                 add_sample(in, data, 1);
880                 bits = get_sample_bits_4(indata, 2);
881                 data = map_input_chans(in, bits);
882                 add_sample(in, data, 1);
883                 bits = get_sample_bits_4(indata, 3);
884                 data = map_input_chans(in, bits);
885                 add_sample(in, data, 1);
886                 inc->submit.last_submit_ts++;
887                 inc->submit.curr_data = data;
888                 break;
889         }
890 }
891
892 /* Parse one "chunk" of a "record" of the file. */
893 static int stf_parse_data_chunk(struct sr_input *in,
894         const uint8_t *info, const uint8_t *stamps, const uint8_t *samples)
895 {
896         struct context *inc;
897         uint32_t chunk_id;
898         uint64_t first_ts, last_ts, chunk_len;
899         uint64_t ts, ts_diff;
900         size_t cluster, sample_count, sample;
901         uint16_t sample_data;
902
903         inc = in->priv;
904
905         chunk_id = read_u32le(&info[4]);
906         first_ts = read_u64le(&info[8]);
907         last_ts = read_u64le(&info[16]);
908         chunk_len = read_u64le(&info[24]);
909         sr_spew("Chunk info: id %08x, first %" PRIu64 ", last %" PRIu64 ", len %." PRIu64,
910                 chunk_id, first_ts, last_ts, chunk_len);
911
912         if (first_ts < inc->submit.last_submit_ts) {
913                 /* Leap backwards? Cannot be valid input data. */
914                 sr_dbg("Chunk: TS %" PRIu64 " before last submit TS %" PRIu64 ", stopping.",
915                         first_ts, inc->submit.last_submit_ts);
916                 return SR_ERR_DATA;
917         }
918
919         if (!inc->submit.last_submit_ts) {
920                 sr_dbg("Chunk: First seen TS %" PRIu64 ".", first_ts);
921                 inc->submit.last_submit_ts = first_ts;
922         }
923         if (inc->submit.submit_count >= inc->submit.sample_count) {
924                 sr_dbg("Chunk: Sample count reached, stopping.");
925                 return SR_OK;
926         }
927         for (cluster = 0; cluster < STF_CHUNK_CLUSTER_COUNT; cluster++) {
928                 ts = read_u64le_inc(&stamps);
929
930                 if (ts > inc->header.length_ts) {
931                         /*
932                          * This cluster is beyond the file's valid TS
933                          * range. Cease processing after submitting the
934                          * last seen sample up to the last valid TS.
935                          */
936                         sr_dbg("Data: Cluster TS %" PRIu64 " past header's last, flushing.", ts);
937                         ts_diff = inc->header.length_ts;
938                         ts_diff -= inc->submit.last_submit_ts;
939                         if (!ts_diff)
940                                 return SR_OK;
941                         ts_diff *= 16 / inc->submit.bits_per_sample;
942                         add_sample(in, inc->submit.curr_data, ts_diff);
943                         return SR_OK;
944                 }
945                 if (ts < inc->submit.last_submit_ts) {
946                         sr_dbg("Data: Cluster TS %" PRIu64 " before last submit TS, stopping.", ts);
947                         return SR_OK;
948                 }
949                 sample_count = STF_CHUNK_SAMPLE_SIZE / sizeof(uint16_t);
950                 if (ts + sample_count < inc->header.first_ts) {
951                         /*
952                          * The file may contain data which is located
953                          * _before_ the "first valid timestamp". We need
954                          * to avoid feeding these samples to the session,
955                          * yet track their most recent value.
956                          */
957                         inc->submit.last_submit_ts = ts;
958                         for (sample = 0; sample < sample_count; sample++) {
959                                 sample_data = read_u16le_inc(&samples);
960                                 inc->submit.last_submit_ts++;
961                                 inc->submit.curr_data = sample_data;
962                         }
963                         continue;
964                 }
965                 ts_diff = ts - inc->submit.last_submit_ts;
966                 if (ts_diff) {
967                         sr_spew("Cluster: TS %" PRIu64 ", need to skip %" PRIu64 ".",
968                                 ts, ts_diff);
969                         ts_diff *= 16 / inc->submit.bits_per_sample;
970                         add_sample(in, inc->submit.curr_data, ts_diff);
971                 }
972                 inc->submit.last_submit_ts = ts;
973                 for (sample = 0; sample < sample_count; sample++) {
974                         sample_data = read_u16le_inc(&samples);
975                         xlat_send_sample_data(in, sample_data);
976                 }
977                 if (inc->submit.submit_count >= inc->submit.sample_count) {
978                         sr_dbg("Cluster: Sample count reached, stopping.");
979                         return SR_OK;
980                 }
981         }
982         sr_spew("Chunk done.");
983
984         return SR_OK;
985 }
986
987 /* Parse a "record" of the file which contains several "chunks". */
988 static int stf_parse_data_record(struct sr_input *in, struct stf_record *rec)
989 {
990         size_t chunk_count, chunk_idx;
991         const uint8_t *rdpos, *info, *stamps, *samples;
992         size_t rec_len;
993         int ret;
994
995         chunk_count = rec->len / STF_CHUNK_TOTAL_SIZE;
996         if (chunk_count * STF_CHUNK_TOTAL_SIZE != rec->len) {
997                 sr_err("Unexpected record length, not a multiple of chunks.");
998                 return SR_ERR_DATA;
999         }
1000         sr_dbg("Data: Processing record, len %zu, chunks %zu, remain %zu.",
1001                 rec->len, chunk_count, rec->len % STF_CHUNK_TOTAL_SIZE);
1002         rdpos = &rec->raw[0];
1003         info = rdpos;
1004         rdpos += chunk_count * STF_CHUNK_INFO_SIZE;
1005         stamps = rdpos;
1006         rdpos += chunk_count * STF_CHUNK_CLUSTER_COUNT * STF_CHUNK_STAMP_SIZE;
1007         samples = rdpos;
1008         rdpos += chunk_count * STF_CHUNK_CLUSTER_COUNT * STF_CHUNK_SAMPLE_SIZE;
1009         rec_len = rdpos - &rec->raw[0];
1010         if (rec_len != rec->len) {
1011                 sr_err("Unexpected record length, info/stamp/samples sizes.");
1012                 return SR_ERR_DATA;
1013         }
1014
1015         for (chunk_idx = 0; chunk_idx < chunk_count; chunk_idx++) {
1016                 ret = stf_parse_data_chunk(in, info, stamps, samples);
1017                 if (ret != SR_OK)
1018                         return ret;
1019                 info += STF_CHUNK_INFO_SIZE;
1020                 stamps += STF_CHUNK_CLUSTER_COUNT * STF_CHUNK_STAMP_SIZE;
1021                 samples += STF_CHUNK_CLUSTER_COUNT * STF_CHUNK_SAMPLE_SIZE;
1022         }
1023
1024         return SR_OK;
1025 }
1026
1027 /* Parse the "data" section of the file (sample data). */
1028 static int parse_file_data(struct sr_input *in)
1029 {
1030         struct context *inc;
1031         size_t len, final_len;
1032         uint32_t crc, crc_calc;
1033         size_t have_len, want_len;
1034         const uint8_t *read_ptr;
1035         void *compressed;
1036         lzo_uint raw_len;
1037         int rc;
1038
1039         inc = in->priv;
1040
1041         rc = data_enter(in);
1042         if (rc != SR_OK)
1043                 return rc;
1044
1045         /*
1046          * Make sure enough receive data is available for the
1047          * interpretation of the record header, and for the record's
1048          * respective payload data. Uncompress the payload data, have
1049          * the record processed, and remove its content from the
1050          * receive buffer.
1051          *
1052          * Implementator's note: Cope with the fact that receive data
1053          * is gathered in arbitrary pieces across arbitrary numbers of
1054          * routine calls. Insufficient amounts of receive data in one
1055          * or several iterations is non-fatal. Make sure to only "take"
1056          * input data when it's complete and got processed. Keep the
1057          * current read position when input data is incomplete.
1058          */
1059         final_len = (uint32_t)~0ul;
1060         while (in->buf->len) {
1061                 /*
1062                  * Wait for record data to become available. Check for
1063                  * the availability of a header, get the payload size
1064                  * from the header, check for the data's availability.
1065                  * Check the CRC of the (compressed) payload data.
1066                  */
1067                 have_len = in->buf->len;
1068                 if (have_len < STF_DATA_REC_HDRLEN) {
1069                         sr_dbg("Data: Need more receive data (header).");
1070                         return SR_OK;
1071                 }
1072                 read_ptr = (const uint8_t *)in->buf->str;
1073                 len = read_u32le_inc(&read_ptr);
1074                 crc = read_u32le_inc(&read_ptr);
1075                 if (len == final_len && !crc) {
1076                         sr_dbg("Data: Last record seen.");
1077                         g_string_erase(in->buf, 0, STF_DATA_REC_HDRLEN);
1078                         inc->file_stage = STF_STAGE_DONE;
1079                         return SR_OK;
1080                 }
1081                 sr_dbg("Data: Record header, len %zu, crc 0x%08lx.",
1082                         len, (unsigned long)crc);
1083                 if (len > STF_DATA_REC_PLMAX) {
1084                         sr_err("Data: Illegal record length %zu.", len);
1085                         return SR_ERR_DATA;
1086                 }
1087                 inc->record_data.len = len;
1088                 inc->record_data.crc = crc;
1089                 want_len = inc->record_data.len;
1090                 if (have_len < STF_DATA_REC_HDRLEN + want_len) {
1091                         sr_dbg("Data: Need more receive data (payload).");
1092                         return SR_OK;
1093                 }
1094                 crc_calc = crc32(0, read_ptr, want_len);
1095                 sr_spew("DBG: CRC32 calc comp 0x%08lx.",
1096                         (unsigned long)crc_calc);
1097                 if (crc_calc != inc->record_data.crc) {
1098                         sr_err("Data: Record payload CRC mismatch.");
1099                         return SR_ERR_DATA;
1100                 }
1101
1102                 /*
1103                  * Uncompress the payload data, have the record processed.
1104                  * Drop the compressed receive data from the input buffer.
1105                  */
1106                 compressed = (void *)read_ptr;
1107                 raw_len = sizeof(inc->record_data.raw);
1108                 memset(&inc->record_data.raw, 0, sizeof(inc->record_data.raw));
1109                 rc = lzo1x_decompress_safe(compressed, want_len,
1110                         inc->record_data.raw, &raw_len, NULL);
1111                 g_string_erase(in->buf, 0, STF_DATA_REC_HDRLEN + want_len);
1112                 if (rc) {
1113                         sr_err("Data: Decompression error %d.", rc);
1114                         return SR_ERR_DATA;
1115                 }
1116                 if (raw_len > sizeof(inc->record_data.raw)) {
1117                         sr_err("Data: Excessive decompressed size %zu.",
1118                                 (size_t)raw_len);
1119                         return SR_ERR_DATA;
1120                 }
1121                 inc->record_data.len = raw_len;
1122                 sr_spew("Data: Uncompressed record, len %zu.",
1123                         inc->record_data.len);
1124                 rc = stf_parse_data_record(in, &inc->record_data);
1125                 if (rc != SR_OK)
1126                         return rc;
1127         }
1128         return SR_OK;
1129 }
1130
1131 /* Process previously queued file content, invoked from receive() and end(). */
1132 static int process_data(struct sr_input *in)
1133 {
1134         struct context *inc;
1135         int ret;
1136
1137         /*
1138          * Have data which was received so far inspected, depending on
1139          * the current internal state of the input module. Have
1140          * information extracted, and/or internal state advanced to the
1141          * next phase when a section has completed.
1142          *
1143          * BEWARE! A switch() statement would be inappropriate, as it
1144          * would not allow for the timely processing of receive chunks
1145          * that span multiple input file sections. It's essential that
1146          * stage updates result in the continued inspection of received
1147          * but not yet processed input data. Yet it's desirable to bail
1148          * out upon errors as they are encountered.
1149          *
1150          * Note that it's essential to set sdi_ready and return from
1151          * receive() after the channels got created, and before data
1152          * gets submitted to the sigrok session.
1153          */
1154         inc = in->priv;
1155         if (inc->file_stage == STF_STAGE_MAGIC) {
1156                 ret = parse_magic(in);
1157                 if (ret != SR_OK)
1158                         return ret;
1159         }
1160         if (inc->file_stage == STF_STAGE_HEADER) {
1161                 ret = parse_header(in);
1162                 if (ret != SR_OK)
1163                         return ret;
1164                 if (inc->file_stage == STF_STAGE_DATA && !in->sdi_ready) {
1165                         in->sdi_ready = TRUE;
1166                         return SR_OK;
1167                 }
1168         }
1169         if (inc->file_stage == STF_STAGE_DATA) {
1170                 ret = parse_file_data(in);
1171                 if (ret != SR_OK)
1172                         return ret;
1173         }
1174         /* Nothing to be done for STF_STAGE_DONE. */
1175         return SR_OK;
1176 }
1177
1178 static const char *stf_extensions[] = { "stf", NULL, };
1179
1180 /* Check if filename ends in one of STF format's extensions. */
1181 static gboolean is_stf_extension(const char *fn)
1182 {
1183         size_t fn_len, ext_len, ext_idx, dot_idx;
1184         const char *ext;
1185
1186         if (!fn || !*fn)
1187                 return FALSE;
1188         fn_len = strlen(fn);
1189
1190         for (ext_idx = 0; /* EMPTY */; ext_idx++) {
1191                 ext = stf_extensions[ext_idx];
1192                 if (!ext || !*ext)
1193                         break;
1194                 ext_len = strlen(ext);
1195                 if (fn_len < 1 + ext_len)
1196                         continue;
1197                 dot_idx = fn_len - 1 - ext_len;
1198                 if (fn[dot_idx] != '.')
1199                         continue;
1200                 if (strcasecmp(&fn[dot_idx + 1], ext) != 0)
1201                         continue;
1202                 return TRUE;
1203         }
1204
1205         return FALSE;
1206 }
1207
1208 /* Try to auto-detect an input module for a given file. */
1209 static int format_match(GHashTable *metadata, unsigned int *confidence)
1210 {
1211         gboolean found;
1212         const char *fn;
1213         GString *buf;
1214
1215         found = FALSE;
1216
1217         /* Check the filename (its extension). */
1218         fn = (const char *)g_hash_table_lookup(metadata,
1219                 GINT_TO_POINTER(SR_INPUT_META_FILENAME));
1220         sr_dbg("Format Match: filename %s.", fn);
1221         if (is_stf_extension(fn)) {
1222                 *confidence = 100;
1223                 found = TRUE;
1224                 sr_dbg("Format Match: weak match found (filename).");
1225         }
1226
1227         /* Check the part of the file content (leading magic). */
1228         buf = (GString *)g_hash_table_lookup(metadata,
1229                 GINT_TO_POINTER(SR_INPUT_META_HEADER));
1230         if (match_magic(buf) == SR_OK) {
1231                 *confidence = 10;
1232                 found = TRUE;
1233                 sr_dbg("Format Match: strong match found (magic).");
1234         }
1235
1236         if (found)
1237                 return SR_OK;
1238         return SR_ERR;
1239 }
1240
1241 /* Initialize the input module. Inspect user specified options. */
1242 static int init(struct sr_input *in, GHashTable *options)
1243 {
1244         GVariant *var;
1245         struct context *inc;
1246         uint64_t sample_rate;
1247
1248         /* Allocate input module context. */
1249         inc = g_malloc0(sizeof(*inc));
1250         if (!inc)
1251                 return SR_ERR_MALLOC;
1252         in->priv = inc;
1253
1254         /* Allocate input device instance data. */
1255         in->sdi = g_malloc0(sizeof(*in->sdi));
1256         if (!in->sdi)
1257                 return SR_ERR_MALLOC;
1258
1259         /* Preset values from caller specified options. */
1260         var = g_hash_table_lookup(options, "samplerate");
1261         sample_rate = g_variant_get_uint64(var);
1262         inc->keep.sample_rate = sample_rate;
1263
1264         return SR_OK;
1265 }
1266
1267 /* Process another chunk of the input stream (file content). */
1268 static int receive(struct sr_input *in, GString *buf)
1269 {
1270
1271         /*
1272          * Unconditionally buffer the most recently received piece of
1273          * file content. Run another process() routine that is shared
1274          * with end(), to make sure pending data gets processed, even
1275          * when receive() is only invoked exactly once for short input.
1276          */
1277         g_string_append_len(in->buf, buf->str, buf->len);
1278         return process_data(in);
1279 }
1280
1281 /* Process the end of the input stream (file content). */
1282 static int end(struct sr_input *in)
1283 {
1284         int ret;
1285
1286         /*
1287          * Process any previously queued receive data. Flush any queued
1288          * sample data that wasn't submitted before. Send the datafeed
1289          * session end packet if a session start was sent before.
1290          */
1291         ret = process_data(in);
1292         if (ret != SR_OK)
1293                 return ret;
1294
1295         data_leave(in);
1296
1297         return SR_OK;
1298 }
1299
1300 /* Release previously allocated resources. */
1301 static void cleanup(struct sr_input *in)
1302 {
1303         struct context *inc;
1304
1305         /* Keep channel references between file re-imports. */
1306         keep_header_for_reread(in);
1307
1308         /* Release dynamically allocated resources. */
1309         inc = in->priv;
1310
1311         g_slist_free_full(inc->channels, free_channel);
1312         feed_queue_logic_free(inc->submit.feed);
1313         inc->submit.feed = NULL;
1314         g_strfreev(inc->header.sigma_clksrc);
1315         inc->header.sigma_clksrc = NULL;
1316         g_strfreev(inc->header.sigma_inputs);
1317         inc->header.sigma_inputs = NULL;
1318         g_strfreev(inc->header.trace_specs);
1319         inc->header.trace_specs = NULL;
1320 }
1321
1322 static int reset(struct sr_input *in)
1323 {
1324         struct context *inc;
1325         struct keep_specs keep;
1326
1327         inc = in->priv;
1328
1329         cleanup(in);
1330         keep = inc->keep;
1331         memset(inc, 0, sizeof(*inc));
1332         g_string_truncate(in->buf, 0);
1333         inc->keep = keep;
1334
1335         return SR_OK;
1336 }
1337
1338 enum option_index {
1339         OPT_SAMPLERATE,
1340         OPT_MAX,
1341 };
1342
1343 static struct sr_option options[] = {
1344         [OPT_SAMPLERATE] = {
1345                 "samplerate", "Samplerate (Hz)",
1346                 "The input data's sample rate in Hz. No default value.",
1347                 NULL, NULL,
1348         },
1349         ALL_ZERO,
1350 };
1351
1352 static const struct sr_option *get_options(void)
1353 {
1354         GVariant *var;
1355
1356         if (!options[0].def) {
1357                 var = g_variant_new_uint64(0);
1358                 options[OPT_SAMPLERATE].def = g_variant_ref_sink(var);
1359         }
1360
1361         return options;
1362 }
1363
1364 SR_PRIV struct sr_input_module input_stf = {
1365         .id = "stf",
1366         .name = "STF",
1367         .desc = "Sigma Test File (Asix Sigma/Omega)",
1368         .exts = stf_extensions,
1369         .metadata = {
1370                 SR_INPUT_META_FILENAME | SR_INPUT_META_REQUIRED,
1371                 SR_INPUT_META_HEADER | SR_INPUT_META_REQUIRED,
1372         },
1373         .options = get_options,
1374         .format_match = format_match,
1375         .init = init,
1376         .receive = receive,
1377         .end = end,
1378         .cleanup = cleanup,
1379         .reset = reset,
1380 };