IPC app failing to build

Hello all,

I’m having some trouble building my app that uses IPC bindings. I’ve read the docs and tried my best to follow open examples such as the battery service example (https://github.com/mangOH/BatteryService), but I’m still having issues.

It seems there is some type issue between my code and the generated interface as indicated by this error message:

/home/nick/Documents/BRNKL_MangOH/apps/digitalInputs/inputHandler/inputHandler.c:118:13: error: conflicting types for 'brnkl_digital_read'
 le_result_t brnkl_digital_read (DigitalInputs *read) {
             ^
In file included from /home/nick/Documents/BRNKL_MangOH/_build_mangOH_Red/wp85/component/30aadd6f99b59795df3676f1abb1e178/src/interfaces.h:19:0,
                 from /home/nick/Documents/BRNKL_MangOH/apps/digitalInputs/inputHandler/inputHandler.c:2:
./_build_mangOH_Red/wp85/api/4ddcc9014d2799d2f2e67fb8048325e6/server/brnkl_digital_server.h:63:13: note: previous declaration of 'brnkl_digital_read' was here
 le_result_t brnkl_digital_read
             ^

I dug into the generated files a bit but I wasn’t really sure what I was reading.

My app is defined as follows:

inputHandler.h

/**
 * A single digital reading
 */
typedef struct {
  bool value;
  uint64_t timestamp;
} DigitalChange;

/**
 * A single digital input
 *
 * Stores a pointer to a dynamically
 * allocated array of DigitalChange
 */
typedef struct {
  int nBytesAllocated;
  int nValues;
  DigitalChange *values;
} DigitalInput;

/**
 * Collection of all readings
 *
 * Please note that the the PIR
 * and bilge inputs are unlikely to
 * change and are therefore
 * not generalized like other digital inputs
 */
typedef struct {
  DigitalInput pir;
  DigitalInput bilgeActivity;
  DigitalInput digital1; // likely door switch
  DigitalInput digital2; // likely high water float switch
  DigitalInput digital3; // generic
} DigitalInputs;

inputHandler.c

DigitalInputs digital_readings;

le_result_t brnkl_digital_read (DigitalInputs *read) {
  *read = digital_readings;
  // TODO return a meaningful result
  return LE_OK;
}

brnkl_digital.api

REFERENCE DigitalInputs;

FUNCTION le_result_t read (DigitalInputs read OUT);

Component.cdef (for inputHandler)

cflags:
{
  -std=c99
}

requires:
{
  api:
  {
    le_digital1 = ${LEGATO_ROOT}/interfaces/le_gpio.api
    le_digital2 = ${LEGATO_ROOT}/interfaces/le_gpio.api
    le_digital3 = ${LEGATO_ROOT}/interfaces/le_gpio.api
    le_pir = ${LEGATO_ROOT}/interfaces/le_gpio.api
    le_bilge = ${LEGATO_ROOT}/interfaces/le_gpio.api
  }
}

provides:
{
	api:
	{
		$CURDIR/../brnkl_digital.api
	}
}

sources:
{
  inputHandler.c
}

digitalInputs.adef

sandboxed: true
version: 1.0.0
start: auto

executables:
{
  digitalInputs = ( inputHandler )
}

processes:
{
  envVars:
  {
    LE_LOG_LEVEL = DEBUG
  }
  run:
  {
     ( digitalInputs )
  }
  faultAction: restart
}

bindings:
{
  digitalInputs.inputHandler.le_digital1 -> gpioExpanderServiceRed.mangoh_gpioExpPin4 // door switch
  digitalInputs.inputHandler.le_digital2 -> gpioExpanderServiceRed.mangoh_gpioExpPin3 // high water float switch
  digitalInputs.inputHandler.le_digital3 -> <root>.le_gpioPin8 // generic digital input
  digitalInputs.inputHandler.le_pir -> gpioService.le_gpioPin36 // (WP_GPIO_5) pir
  digitalInputs.inputHandler.le_bilge -> <root>.le_gpioPin42 // bilge activity
}

extern:
{
  digitalInputs.inputHandler.brnkl_digital
}

Really hoping I didn’t miss something obvious here. I can post a link to the complete app in GitHub if that’s helpful.

Thanks in advance, any help is greatly appreciated.

Hi Nick,

The basic problem is that you can’t use REFERENCE the way you are trying to. REFERENCE creates an opaque reference to an object. So you can pass it over IPC, but you can’t dereference it on the other side. Say you had some sort of account database stored in one service in memory. You could expose a LookupByName() function that returns a REFERENCE to the use that is found and then you could have other functions GetName(), GetBirthday(), etc. that take a reference as a parameter to specify the user to look at.

For your use case, I think you will need to define a number of OUT parameters for every data element you would like to return. Another option is to use the file descriptor support and stream the data across, but that’s a bit more complicated.

Hey @dfrey ,

I was trying to avoid this but I’ll give it a try and report back.

Thanks

Hey @dfrey,

That did the trick, thanks for the help.

One last question: how do I configure arguments to be an IN and OUT? I’ve seen tons of IPC function bindings (e.g spiService) that accept a single pointer used for input and output (usually to read a length and then overwrite it with a new length). In the case of spiService, it looks like the input and output argument is omitted from the function definition in the .api file (see https://github.com/legatoproject/legato-af/blob/master/interfaces/le_spi.api)?