Syntax

Legato API files support defining functions, events, handlers (callback functions) and user-defined types.

Functions are similar to C functions. They can take input and output parameters, and can return a result.

A handler is a callback function, which can be passed as a parameter to a function and can be registered to be called when events occur.

The API file currently supports:

  • a limited number of pre-defined types
  • a number of different user-defined types.

Type Support

The API file currently supports a limited number of pre-defined types. These are:

uint8
uint16
uint32
uint64

int8
int16
int32
int64

string
file
handler

The unsigned and signed integer types are self-explanatory. See Specifying a Function for details on the string type. The file type is used to pass an open file descriptor (fd) as a parameter. This is used for passing an fd between a client and server. The handler type is used for passing a handler as a parameter.

The following user-defined types are supported:

  • DEFINE
  • ENUM
  • BITMAP
  • REFERENCE

Type definitions can also be shared between API files with USETYPES.

Also, all C types defined in the legato.h file are available. The most commonly used of these is the le_result_t type. Support for directly using these C types is a temporary measure and will be removed in a future release.

DEFINE

A DEFINE is specified as:

DEFINE <name> = <value>;

The value can be a string or an expression evaluated to a numeric value (when the definition is read).

ENUM

An ENUM is specified as:

ENUM <name>
{
    [<elementList>]
};

The elementList is a comma separated list of elements. The elements should all be uppper-case. Element values assigned are internally generated and can't be explicitly given.

BITMASK

A BITMASK is a special type of ENUM. It is specified the same way as an ENUM, but the internally generated element values are bit positions, i.e. 0x1, 0x2, 0x4, etc.

REFERENCE

A REFERENCE is specified as:

REFERENCE <name>;

The REFERENCE is used to define a reference to an object. The object reference is mapped to an opaque reference in C and an object instance or similar in other languages.

USETYPES

You can share type definitions between .api files with USETYPES. This is commonly referred to as importing, although only the type definitions are imported or used. Any code related definitions in a .api file, e.g. FUNCTION, are ignored. These USETYPES can even be nested.

Note
It is not necessary to include the .api extension when importing. I.e.
USETYPES defn; 
is equivalent to
USETYPES defn.api; 

As an example of usage, suppose the files defn.api, common.api and example.api are defined as follows:

defn.api

DEFINE FIVE = 5;

common.api

USETYPES defn.api;

DEFINE TEN = defn.FIVE + 5;

example.api

USETYPES common.api;

DEFINE twenty = common.TEN + defn.FIVE + 5;

This example illustrates that nesting causes an implicit USETYPES. Thus, any definitions from defn.api, can be used in example.api, in the same way as if it had explicitly imported defn.api.

Specifying a Function

A function is specified as:

FUNCTION [<returnType>] <name>
(
    [<parameterList>]
);

The parameterList can contain one or more parameters separated by commas, or can be empty if there are no parameters. These parameters types are supported:

<type> <name> [ ( "IN" | "OUT" ) ]
  • scalar type
  • defaults to IN if a direction is not specified
<type> <name> "[" [ <minSize> ".." ] <maxSize> "]" "IN"
  • an IN array
  • maxSize specifies the maximum number of elements allowed for the array
  • optional minSize specifies the minimum number of elements required for the array
<type> <name> "[" <minSize> "]" "OUT"
  • an OUT array
  • array should be large enough to store minSize elements; if supported by the function implemention, a shorter OUT array can be used.
"string" <name> "[" [ <minSize> ".." ] <maxSize> "]" "IN"
  • an IN string
  • maxSize specifies the maximum string length allowed,
  • optional minSize specifies the minimum string length required
  • string length is given as number of characters, excluding any terminating characters
"string" <name> "[" <minSize> "]" "OUT"
  • an OUT string
  • string should be large enough to store minSize characters; if supported by the function implemention, a shorter OUT string can be used.
  • string length is given as number of characters, excluding any terminating characters

"handler" <name> "

The returnType is optional, and if specified, can be any type that's not an array, string, or handler.

Specifying an Event

Do this to specify an event:

EVENT <eventType>
(
    <parameterList>
);

The parameterList can contain one or more parameters separated by commas. It can contain anything that's valid for a function, but it must contain one handler parameter. The parameters are used when registering a handler for the specified event.

See Events in C for details on the C code generated from the above event definition.

Specifying a Handler

Do this to specify a handler:

HANDLER <handlerType>
(
    [<parameterList>]
);

The parameterList can contain one or more parameters separated by commas, or can be empty if there are no parameters. It can only contain scalar types or string types, as described above for Specifying a Function. All the parameters should be IN parameters.

See Handlers in C for details on the C code generated from the above handler definition.

Comments

The API file supports both C and C++ comment styles. Comments that use the doxygen formats

/** 

to start a multi-line comment or

///< 

to start a one line comment receive special processing. Multi-line comments at the start of the API file will be copied directly to the start of the appropriate generated files.

Comments given in the function definition will be copied to the appropriate generated files under the following conditions:

  • Multi-line comments must start with
    /** 
  • Single-line comments must start with
    ///< 
  • In a block of single-line comments, each line must start with
    ///< 
    rather than just the first line. This is different from typical doxygen usage.
  • If the function definition is preceded by a multi-line comment then this comment will be copied to the appropriate generated files.
  • If any parameter is followed by a multi-line comment or one or more single line comments, then all these comments will be copied to the appropriate generated files.

If an event or handler definition is preceded by a multi-line comment, then this comment will be copied to the appropriate generated files, under the same conditions as function definitions.

Any comments provided after an element in an ENUM or BITMASK, will be copied to the appropriate generated files, under the same conditions as function parameter comments.

Sample API

Here's the defn.api file containing just type defintions

/**
 * Example of nested .api file
 */

DEFINE SIX = 6;

Here's the common.api file containing just type defintions, and using the types defined in defn.api

/**
 * Common definitions potentially used across multiple .api files
 */

USETYPES defn;


/**
 * Definition example
 */
DEFINE FOUR = 4;

/**
 * Example of using previously DEFINEd symbol within an imported file.
 */
DEFINE TEN = FOUR + defn.SIX;

/**
 * Reference example
 */
REFERENCE OpaqueReference;

/**
 * ENUM example
 */
ENUM EnumExample
{
    ZERO,     ///< first enum
    ONE,      ///< second enum
    TWO,      ///< third enum
    THREE     ///< fourth enum
};

/**
 * BITMASK example
 */
BITMASK BitMaskExample
{
    BIT0,     ///< first
    BIT1,     ///< second
    BIT2,     ///< third
};


Here's the example.api file containing various definitions, and using the types defined in defn.api and common.api

/**
 * Example API file
 */

// The .api suffix is optional
USETYPES defn;
USETYPES common.api;


DEFINE TEN = common.FOUR + defn.SIX;
DEFINE TWENTY = TEN + common.TEN;
DEFINE SOME_STRING = "some string";


/**
 * Handler definition
 */
HANDLER TestAHandler
(
    int32 x   ///< First parameter for the handler
              ///< Second comment line
);


/**
 * This event provides an example of an EVENT definition
 */
EVENT TestA
(
    uint32 data,          ///< Used when registering the handler i.e. it is
                          ///< passed into the generated ADD_HANDLER function.
    handler TestAHandler
);


/**
 * Function takes all the possible kinds of parameters, but returns nothing
 */
FUNCTION AllParameters
(
    common.EnumExample a,  ///< first one-line comment
                           ///< second one-line comment
    uint32 b OUT,
    uint32 data[common.TEN] IN,

    uint32 output[TEN] OUT,   ///< some more comments here
    ///< and some comments here as well

    string label [common.TEN..20] IN,
    string response [TWENTY] OUT
    ///< comments on final parameter, first line
    ///< and more comments
);


/**
 * Test file descriptors as IN and OUT parameters
 */
FUNCTION FileTest
(
    file dataFile IN,   ///< file descriptor as IN parameter
    file dataOut OUT    ///< file descriptor as OUT parameter
);

/**
 * Function that takes a handler parameter
 */
FUNCTION int32 UseCallback
(
    uint32 someParm IN,
    handler TestAHandler
);