Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Considering the application's well-name as a namespace name, an Event ID is used to uniquely identify the Event within the namespace. The Event IDs must be declared in the application's public header file, using C Enumerations and must start with value 0.

...

Code Block
typedef enum _EventId_t {

...


     IARM_BUS_IRMGR_EVENT_IRKEY = 0,

...


     IARM_BUS_IRMGR_EVENT_MAX

...


 } 
 
 Naming Convention: IARM_BUS_<Manager>EVENT<Event Name>

_EVENT_MAX must have the value of (Number Of Events Published + 1). This MAX value is used when registering all events to the IARM –Bus. 
An event may or may not have Event Data. If an event has event data, the data types must be declared so that the listeners of the events can process the data properly. The data structure should a union of event data for all events that the application would send. For example, IR Manager's IR Event Data contains a keyType and KeyCode field.

Code Block
typedef struct _IRMgr_EventData_t {

...


    union {

...


       struct _IRKEY_DATA{

...


           int keyType;

...


 	   int keyCode;

...


       } irkey, fpkey;

...


   } data; 

...


}IARM_Bus_IRMgr_EventData_t; 
 Naming Convention: IARM_Bus_<Manager>_EventData_t 

...


 To send an IARM_BUS_IRMGR_EVENT_IRKEY an IR whenever

Code Block

...

IARM_Bus_BroadcastEvent(

...


     IARM_BUS_IRMGR_NAME,	 	/* Owner of the Event */

...


     IARM_BUS_IRMGR_EVENT_IRKEY,	/* Event ID from this owner */

...


     (void ) &eventData, 		/* IARM_Bus_IRMgr_EventData_t */

...


     sizeof(eventData) 			/* Length of the eventData */

...


 )

Receive Event from IARM-Bus

Any application can listen for events from sent by other applications on the IARM-Bus. In our example, an application interested in receiving Remote Keys can register for IR Manager's IARM_BUS_IRMGR_EVENT_IRKEY event. When receiving events, a handler must be supplied to process the event. This handler will be called from IARM's internal thread context.

Code Block

...

IARM_Bus_RegisterEventHandler(

...


     IARM_BUS_IRMGR_NAME, 		/* Owner of the Event */

...


     IARM_BUS_IRMGR_EVENT_IRKEY,	/* Event ID from this owner*/

...


     _My_Event_Handler, 		/* IARM_EventHandler_t */

...


 )

...

 An An application can listen for different event with different event handlers. If a same event handler is used to listen for different events from different applications, a simple switch block can be used to further dispatch the events to their target processing.

...

 The event handler in our example would contain the following block to dispatch IR key events:

Code Block

...

_My_Event_Handler(const char *owner, IARM_EventId_t eventId, void *data, size_t len)

...


 {

...


...


     /* Dispatch By Owner first */

...


     if(strcmp(owner, IARM_BUS_IRMGR_NAME) == 0) {

...


         /* Then Dispatch by Event ID */

...


         switch(eventID) {

...


             case IARM_BUS_IRMGR_EVENT_IRKEY:

...


                 /*Cast data to its target type */

...


 		 IARM_Bus_IRMgr_EventData_t * = (IARM_Bus_IRMgr_EventData_t *) data;

...


 		/* Processing of Data */

...


...


 	}

...


     }

...


     else if(strcmp(owner, /some other application/) == 0) {

...


     }

...


     else {

...


     }

...


 }

Summary Of Events

 If an application wants to Send events, it needs to

...

 In our example, IR Manager declares this data structure as argument type for the SetRepeatInterval method.

...

Code Block
typedef struct _IARM_Bus_IRMgr_SetRepeatInterval_Param_t {

...


     unsigned int timeoutNewValue; 	/* Used when invoking RPC */

...


     unsigned int timeoutOldValue; 	/* Used to hold return value */

...


 } IARM_Bus_IRMgr_SetRepeatInterval_Param_t;

...

 Naming Convention: IARM_BUS_<Manager>_<Method>_Param_t 

 This This method has an input parameter and an output parameter. It is equivalent to a non-RPC function with signature:
SetRepeatInterval (uint timeoutNewValue, uint *{}timeoutOldValue);

 The The RPC implementation will place the old value into the storage allocated for timeoutOldValue prior to function return.

...

A RPC Method must be Registered with IARM-Bus first before it can be invoked. The application that registers the RPC method is considered the Owner of the method. During initialization, the application can register all the RPC methods it implements

...

Code Block
IARM_Result_t IARM_Bus_RegisterCall(

...


     _BUS_IRMGR_API_SetRepeatInterval, 	/* RPC Method Name */

...


     _SetRepeatInterval			/* RPC Method Implementation*/* 

...


)  

 Here Here _SetRepeatInterval () is the actual implementation of the RPC method. All RPC methods takes the signature of IARM_BusCall_t:

 typedeftypedef IARM_Result_t (*IARM_BusCall_t) (void *arg); 

 The The owner of the RPC Method provides its implementation. In irMgr.c, the implementation takes the following form:

Code Block

...

static IARM_Result_t _SetRepeatInterval(void *arg)

...


{

...


     /* First cast the argument to its target type */

...


     IARM_Bus_IRMgr_SetRepeatInterval_Param_t 

...


     *param = (IARM_Bus_IRMgr_SetRepeatInterval_Param_t *)arg;

...


     /* do something */

...


     /* populate the output fileds of param */ 

...


 }

Invoke RPC Method

Once an RPC is registered, other application can invoke the method synchronously. For example, this invocation sets the key repeat interval to 200ms.

Code Block

...

IARM_Bus_IRMgr_SetRepeatInterval_Param_t param;

...


     param. timeoutNewValue = 200;

...


     IARM_Bus_Call (

...


         IARM_BUS_IRMGR_NAME, /* Owner of the Method */

...


         IARM_BUS_IRMGR_API_SetRepeatInterval,/* Name of Method */

...


         (void )&param, / Parameter of Method */

...


         sizeof(param)); /* Length of the Parameter */ 

...


)

Summary of RPC Methods

In summary, if an application wants to publish RPC Methods, it needs to

...

        IARM_Result_t IARM_Bus_Call(const char *ownerName, const char *methodName, void *arg, size_t argLen);

 Decouples Decouples Applications from IARM


The RPC methods exposed via IARM can be called by multiple applications, so they are also named Multiple-App APIs. In contract, the regular C functions that can only be invoked from within the same Linux process that implements the C functions are named Single-App APIs. Sometimes, it is desirable that the application is decoupled from such API difference. In this case, the developer should provide a generic API that can be linked to either a local C method or a RPC method at build time.
In our example, IR Manager exports RPC API "SetRepeatInterval". To invoke this method, the application executes:

Code Block

...

IARM_Bus_Call (

...


     IARM_BUS_IRMGR_NAME, 			/* Owner of the Method */

...


     IARM_BUS_IRMGR_API_SetRepeatInterval,	/* Name of Method */

...


     (void )&param, 				/ Parameter of Method */

...


     sizeof(param)); 				/* Length of the Parameter */ 

...


)

...

 This This invocation injects the IARM dependency into the application. An alternative is to provide the application a generic API IRMgr_SetRepeatInterval(), whose implementation internally invokes the RPC method.

...

Code Block
IRMgr_SetRepeatInterval(int newInterval) 

...


 {

...


     IARM_Bus_IRMgr_SetRepeatInterval_Param_t param;

...


     param.timeoutNewValue = 200;

...


     IARM_Bus_Call (

...


         IARM_BUS_IRMGR_NAME, /* Owner of the Method */

...


         IARM_BUS_IRMGR_API_SetRepeatInterval,/* Name of Method */

...


         (void )&param, / Parameter of Method */

...


         sizeof(param)); /* Length of the Parameter */ 

...


     )

...


 }

Short-Term Approach

To invoke the same API, application now calls IRMgr_SetRepeatInterval().
A quick approach to decouple application from IARM is to define the generic API IRMgr_SetRepeatInterval() as inline function. In our example, we would include this in the irMgr.h.

Code Block

...

#define IRMgr_SetRepeatInterval(newInterval) \ 

...


 do {

...


     IARM_Bus_IRMgr_SetRepeatInterval_Param_t param;

...


     param. timeoutNewValue = 200;\

...


     IARM_Bus_Call (

...


         IARM_BUS_IRMGR_NAME,\ /* Owner of the Method */

...


         IARM_BUS_IRMGR_API_SetRepeatInterval,\/* Name of Method */

...


         (void )&param,\/ Parameter of Method */

...


         sizeof(param));\/* Length of the Parameter */ 

...


     )

...


 }while(0)

...

;

 In this approach, the application is decoupled from IARM. However, application cannot use the same API for Single-App version. This may be enough for most applications who at this point does not need a single-app version of the same API.

...

If an application may use the same API's single-app version, the following changes are needed.
To invoke the same API, application now calls IRMgr_SetRepeatInterval(), which must be implemented as an actual function that has external linkage.

Code Block

...

IRMgr_SetRepeatInterval(int newInterval) 

...


 {

...


     IARM_Bus_IRMgr_SetRepeatInterval_Param_t param;

...


     param. timeoutNewValue = 200;

...


     IARM_Bus_Call (

...


         IARM_BUS_IRMGR_NAME, /* Owner of the Method */

...


         IARM_BUS_IRMGR_API_SetRepeatInterval,/* Name of Method */

...


         (void )&param, / Parameter of Method */

...


         sizeof(param)); /* Length of the Parameter */ 

...


     )

...


 }

...


In the IR Manager's implementation of RPC Method, we have already learned from previous sections that this RPC method is registered with
 
Code Block

...

IARM_Result_t IARM_Bus_RegisterCall(

...


     _BUS_IRMGR_API_SetRepeatInterval,  /* RPC Method Name */

...


     _SetRepeatInterval			/* RPC Method Implementation*/ 

...


 )

...


Where _SetRepeatInterval changes the actual settings.

...


 static IARM_Result_t _SetRepeatInterval(void *arg)

...


 {

...


     /* First cast the argument to its target type */

...


     IARM_Bus_IRMgr_SetRepeatInterval_Param_t 

...


     *param = (IARM_Bus_IRMgr_SetRepeatInterval_Param_t *)arg;

...


     /* changes actual settings here */

...


 } 


 With generic API IRMgr_SetRepeatInterval(), we can change the _SetRepeatInterval implementation to:

Code Block

...

 static IARM_Result_t _SetRepeatInterval(void *arg)

...


 {

...


     /* First cast the argument to its target type */

...


     IARM_Bus_IRMgr_SetRepeatInterval_Param_t 

...


     *param = (IARM_Bus_IRMgr_SetRepeatInterval_Param_t *)arg; 

...


     IRMgr_SetRepeatInterval(parma->newInterval);

...


 } 

Where IRMgr_SetRepeatInterval()changes the actual settings. 
Now, we have at our hands two implementations of a same generic API IRMgr_SetRepeatInterval:


The RPC Client / Multi App Version:

Code Block
IRMgr_SetRepeatInterval(int newInterval) 

...


 {

...


     IARM_Bus_IRMgr_SetRepeatInterval_Param_t param;

...


     param. timeoutNewValue = 200;

...


     IARM_Bus_Call (

...


         IARM_BUS_IRMGR_NAME, 			/* Owner of the Method */

...


         IARM_BUS_IRMGR_API_SetRepeatInterval,	/* Name of Method */

...


         (void )&param, 			/* Parameter of Method */

...


         sizeof(param)); 			/* Length of the Parameter */ 

...


     )

...


 } 

 This function is linked into library libirMgrCli.so


 The Manager Version/Single-App version:

Code Block

...

 IRMgr_SetRepeatInterval(int newInterval) 

...


 {

...


     /* Change the Actual Settings */

...


 }

 This This function is linked into library libirMgr.so

 The The application can then choose which implementation to link to at build time based on its needs. To use the multi-app version of API, the application links to libirMgrCli.so. To use the single-app version of the API, the application links to libirMgr.so. In either choice, the application is no longer coupled to IARM. The following diagrams demonstrate the linkage relationship between applications and the generic API.

...