/* --------------------------------------------------------------------------- * RemoteProcedureCalls.c - v0.1 (c) 2008 Micro-key bv * --------------------------------------------------------------------------- * Micro-key bv * Industrieweg 28, 9804 TG Noordhorn * Postbus 92, 9800 AB Zuidhorn * The Netherlands * Tel: +31 594 503020 * Fax: +31 594 505825 * Email: support@microkey.nl * Web: www.microkey.nl * --------------------------------------------------------------------------- * Description: * --------------------------------------------------------------------------- * Version(s): 0.1, Jan 29, 2008, FSc * Creation. * --------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------- * System include files * --------------------------------------------------------------------------- */ #include /* --------------------------------------------------------------------------- * Application include files * --------------------------------------------------------------------------- */ #include "BpPort.h" #include "RpcResults.h" #include "BusProtocol.h" #include "mem_mod.h" /* --------------------------------------------------------------------------- * Local constant and macro definitions * --------------------------------------------------------------------------- */ #define RPCR_DISPATCH_QUEUE_SIZE (10) typedef struct t_RPCR_ENTITY { UINT8 functionId; UINT8 nrOfParams; t_bp_rpcresult_callback rpcrFunction; struct t_RPCR_ENTITY *next; struct t_RPCR_ENTITY *previous; } t_rpcr_entity; typedef struct t_RPCR_ADMIN { t_rpcr_entity *firstEntry; t_rpcr_entity *lastEntry; } t_rpcr_admin; extern memman *bpMessagePool; /* --------------------------------------------------------------------------- * Global variable definitions * --------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------- * Local variable definitions * --------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------- * Local function definitions * --------------------------------------------------------------------------- */ static t_rpcr_entity *lookupRpcrEntry( int handle, UINT8 functionId ); /** \brief Initialises a Remote Procedure Call administration * * \returns Handle to Remote Procedure Call administration (0 = failure) */ int rpcrInit() { t_rpcr_admin *newAdmin = (t_rpcr_admin *)pvPortMalloc( sizeof(t_rpcr_admin) ); if (newAdmin != NULL) { newAdmin->firstEntry = NULL; newAdmin->lastEntry = NULL; } return (int)newAdmin; } /** \brief Deinitialises the Remote Procedure Call administration * * \param handle Handle to RPC-adminstration */ void rpcrDeinit( int handle ) { t_rpcr_admin *theAdmin = (t_rpcr_admin *)handle; // Remove whole list if (theAdmin->firstEntry != NULL) { t_rpcr_entity *entry = theAdmin->firstEntry; while (entry != NULL) { t_rpcr_entity *nextEntry = entry->next; vPortFree( entry ); entry = nextEntry; } } // Remove admin vPortFree( (void *)handle ); } /** \brief Adds a Remote Procedure Call to the administration * * \param handle Handle to RPC-administration * \param functionId Identifier for RPC * \param nrOfParams Nr of parameters required by RPC-function */ void rpcrAdd( int handle, UINT8 functionId, t_bp_rpcresult_callback funcptr, UINT8 nrOfParams ) { t_rpcr_entity *newEntry = (t_rpcr_entity *)pvPortMalloc( sizeof(t_rpcr_entity) ); t_rpcr_admin *theAdmin = (t_rpcr_admin *)handle; // fill entry newEntry->functionId = functionId; newEntry->rpcrFunction = funcptr; newEntry->nrOfParams = nrOfParams; newEntry->next = NULL; newEntry->previous = NULL; // Add to linked list if (theAdmin->firstEntry != NULL) { theAdmin->lastEntry->next = newEntry; newEntry->previous = theAdmin->lastEntry; theAdmin->lastEntry = newEntry; } else { theAdmin->firstEntry = newEntry; theAdmin->lastEntry = newEntry; } } /** \brief Removes a Remote Procedure Call to the administration * * \param handle Handle to RPC-administration * \param functionId Identifier for RPC-function */ void rpcrRemove( int handle, UINT8 functionId ) { t_rpcr_entity *entry = lookupRpcrEntry(handle, functionId); t_rpcr_admin *theAdmin = (t_rpcr_admin *)handle; if (entry != NULL) { // rebuild linked list if (entry->next != NULL) { entry->next->previous = entry->previous; } else { theAdmin->lastEntry = entry->previous; } if (entry->previous != NULL) { entry->previous->next = entry->next; } else { theAdmin->firstEntry = entry->next; } // remove entry vPortFree( entry ); } } /** \brief Looks up a Remote Procedure Call to the administration * * \param handle Handle to RPC-administration * \param functionId Identifier for RPC-function * \retval Pointer to RPC-function (NULL when not found) */ t_bp_rpcresult_callback rpcrLookup( int handle, UINT8 functionId ) { t_bp_rpcresult_callback result = NULL; t_rpcr_entity *entry = lookupRpcrEntry(handle, functionId); if (entry != NULL) { result = entry->rpcrFunction; } return result; } t_rpcr_entity *lookupRpcrEntry( int handle, UINT8 functionId ) { t_rpcr_admin *theAdmin = (t_rpcr_admin *)handle; t_rpcr_entity *result = NULL; t_rpcr_entity *iterator; iterator = theAdmin->firstEntry; while ((result == NULL) && (iterator != NULL)) { if (iterator->functionId == functionId) { result = iterator; } else { iterator = iterator->next; } } return result; } void rpcrRequestHandler(t_bpmsg_message *msg, int ownHandler) { UINT8 index = 0; UINT8 count; UINT8 targetId, senderId, requestNr, functionId, nrOfResults; UINT32 *results; t_rpcr_entity *rpcrEntry; BP_DEBUG_OUT( '!'); // Decode message targetId = msg->targetId; senderId = msg->senderId; requestNr = bpmsgGet8bit( msg->payload, &index); functionId = bpmsgGet8bit( msg->payload, &index); nrOfResults = bpmsgGet8bit( msg->payload, &index); // Allocate an array for the params if (nrOfResults > 0) { results = (UINT32 *)Memmod_Alloc( bpMessagePool ); if (results != NULL) { for (count = 0; count < nrOfResults; count++) { results[count] = bpmsgGet32bit(msg->payload, &index); } } else { /// \todo Error handling return; } } else { results = NULL; } // Call RPC-function rpcrEntry = lookupRpcrEntry(ownHandler, functionId); if (rpcrEntry != NULL) { // execute function BP_DEBUG_OUT('#'); rpcrEntry->rpcrFunction( requestNr, nrOfResults, results ); } if (results != NULL) { Memmod_Free( bpMessagePool, results ); } }