Output API

From Sigrok

Jump to: navigation, search

Sigrok supports several output formats. In order to separate the generation of these various formats from the frontends that use them, the sigrok library provides an output API that frontends use. New formats can thus be implemented without having to change the frontends at all.

All output modules are fed data in a stream. Devices that can stream data into sigrok live, instead of storing and then transferring the whole buffer, can thus generate output live.

Output modules are responsible for allocating enough memory to store their own output, and passing a pointer to that memory (and length) of the allocated memory back to the caller. The caller is then expected to free this memory when finished with it.

Contents

Creating a new module

  • create the source file in the backend/output directory. You can use output_skeleton.c as a handy template.
  • reference your source file in the file backend/output.c twice: once to pull in the extern, and once in the output_module_list[] array.

Make sure to declare the three callbacks static; they're referenced and used from their output_format entry, so there's no need to export the symbols from your source file.


Structures

struct output_format

struct output_format {
	char *extension;
	char *description;
	void (*init) (struct output *o);
	int (*data) (struct output *o,
		char *data_in, uint64_t length_in,
		char **data_out, uint64_t *length_out);
	int (*event) (struct output *o, int event_type,
		char **data_out, uint64_t *length_out);
};

extension

This is the default file extension for this format, when it's saved to a file. It is also used by the sigrok CLI, to select this format for use. For example, calling the CLI with -f hex will select the hexadecimal text output format, but when saved to a file with no extension in the filename, will be added to it.

description

A short description of the format in freeform text. This will be displayed by the sigrok GUI, when selecting the output format for saving a file.

init, data and event

These are function references to your module's callbacks. See below for more information on each callback.


struct output

struct output {
	struct output_format *format;
	struct device *device;
	char *param;
	void *internal;
};

format

This is a pointer to this format's output_format struct. The frontend can use this to call the module's callbacks.

device

The device for which this output module is creating output. This can be used by the module to find out probe names and numbers.

param

An optional parameter which the frontend can pass in to the output module. How the string is interpreted is entirely up to the module. The bin/hex text module uses this to pass the maximum number of bits to show on a single output line. From the CLI frontend, when passing in an argument like bin64, the output module providing the "bin" extension will be used, and a pointer to the string "64" will be passed as the param field.

internal

This is a generic pointer, which can be used by the module to keep internal state between calls into its callback functions. For example, the module might store a pointer to a chunk of output there, and only flush it when it reaches a certain size. The text output module defines an internal struct to keep track of various internal variables; a pointer to it is kept in the internal field.


Global functions

struct output_format *output_list(void)

Returns a NULL-terminated list of pointers to struct output_format, defining which formats are available for use.


Per-module callback functions

All callbacks return SIGROK_OK if all went well, or another SIGROK_ERR_* code in case of error.

int init(struct output *o)

This function is called once, at the beginning of an output stream, The device struct will be available in the output struct passed in, as well as the param field -- which may be NULL or an empty string, if no parameter was passed.

The module can use this to initialize itself, create a struct for keeping state and storing it in the internal field.


int data(struct output *o, char *data_in, uint64_t length_in, char **data_out, uint64_t *length_out)

Whenever a chunk of data comes in, it will be passed to the output module via this function. The data_in and length_in values refers to this data; the module must not alter or free() this buffer.

The function must allocate a buffer for storing its output, and pass along a pointer to this buffer in the data_out parameter, as well as storing the length of the buffer in length_out. The calling frontend will free() this buffer when it's done with it.

If there is no output, this function MUST store NULL in the data_out parameter, so the caller knows not to try and free() it.


int event(struct output *o, int event_type, char **data_out, uint64_t *length_out)

This function is called when an event occurs in the datafeed which the output module may need to be aware of. No data is passed in, only the fact that the event occurs. The following events can currently be passed in:

  • DF_TRIGGER: at this point in the datafeed, the trigger matched. The output module may mark this in same way, e.g. by plotting a red line on a graph.
  • DF_END: this marks the end of the datafeed. No more calls into the output module will be done, so this is a good time to free up any memory used to keep state, for example.

Any output generated by this function must have a reference to it stored in the data_out and length_out parameters, just as in the data() callback above, or NULL if no output was generated.