Completed transaction forwarder
authorJustin Sobota <jsobota@ti.com>
Fri, 2 Nov 2012 20:44:39 +0000 (16:44 -0400)
committerJustin Sobota <jsobota@ti.com>
Fri, 2 Nov 2012 20:44:39 +0000 (16:44 -0400)
include/rm_pvt.h
rm_services.h
src/rm.c

index bbb1016f513ccad7b24665b3cf9df6dffdcf5f83..190bf41ca1636a1d0667f7bf258a3e1a855c746f 100644 (file)
@@ -127,10 +127,11 @@ typedef struct
 #define RM_MAX_POLICY_SIZE_BYTES (64)  // Placeholder: This will change 
                                        // during development
 
-/* Pointer to RM instance's transport routing map */
+/** Pointer to RM instance's transport routing map */
 typedef void *Rm_TransRouteMap;
 
-typedef Rm_ServiceResult Rm_TransactionResult;
+/** Pointer to RM instance's transaction queue */
+typedef void *Rm_TransactionQueue;
 
 /**
  * @brief RM transport routing map linked list node
@@ -144,6 +145,19 @@ typedef struct {
     Rm_TransRouteMapNode *nextNode;
 } Rm_TransRouteMapNode;
 
+/**
+ * @brief RM transaction queue linked list node
+ */
+typedef struct {
+    /** The transaction ID for the transaction awaiting a response */
+    uint32_t transactionId;
+    /** The callback function associated with the transaction ID.  Will
+     *  be called when a response is received matching the transaction ID. */
+    void *transactionCallback;
+    /** Link to the next transaction queue entry */
+    Rm_TransactionQueueEntry *nextEntry;
+} Rm_TransactionQueueEntry;
+
 /**
  * @brief RM protocol commands.  The first N commands should be synchronized with
  *        the Rm_ServiceType enum in rm_service.h
@@ -173,6 +187,21 @@ typedef enum {
     Rm_command_POLICY_RESPONSE
 } Rm_Command;
 
+
+/* REMOVE BELOW??? */
+/**
+ * @brief RM transaction states.  The transaction state describes what processes have
+ *        been executed on the transaction thus far
+ */
+typedef enum {
+    /** Transaction is being processed */
+    Rm_transactionState_PROCESSING = 0,
+    /** Transaction has been approved */
+    Rm_transactionState_APPROVED = 1,
+    /** Transaction has been denied */
+    Rm_transactionState_DENIED = 2    
+} Rm_TransactionState;
+
 /**
  * @brief RM protocol packet resource information
  */
@@ -195,13 +224,19 @@ typedef struct {
  *        from components and RM commands received from other RM instances.
  */
 typedef struct {
-    /* Transaction type */
-    Rm_Command transType;
-    /* Transaction details */
+    /** Transaction type */
+    Rm_Command transCommand;
+    /** Packet ID of packet that transaction originated from.  This field will be
+     *  NULL if transaction originated from a component */
+    uint32_t transPktId;
+    /** Transaction's associated callback function is the transaction originated
+     *  from a registered component */
+    void *transCallback;
+    /** Transaction details */
     union {
         /** If the command has to do with resources these fields
          *  will contain the resource information */
-        Rm_ResourceInfo transInfo;
+        Rm_ResourceInfo resourceInfo;
         /** Pointer to policy data if the command has to do with policies */
         char *policyData;
     } u;
@@ -213,6 +248,7 @@ typedef struct {
  *        a component that requested a service or a RM instance that sent a command.
  */
 typedef struct {
+    int32_t transactionResult;
     uint32_t transactionId;
     uint32_t resBase;
     uint32_t resNum;
@@ -269,6 +305,8 @@ typedef struct {
 
     /* RM instance transport parameters */
     Rm_TransRouteMap routeMap;
+    /* RM transaction queue */
+    Rm_TransactionQueue transactionQueue;
     /* Transport API function pointers - not global in case application wants to
       * hook up different transports to RM */
     Rm_TransportCallouts transport;
index c4b915737be39a1aee0f6a8e145a7b33ab33df54..501a77ee0c7c20d14227ab62d88a104836c1c335 100644 (file)
@@ -59,51 +59,95 @@ extern "C" {
  */
 #define RM_SERVICE_INDEX_NOT_SPECIFIED (-1)
 
-/** 
- * @brief Result of requested RM service
- */
-typedef enum {
-    /** RM Service was okay */
-    RM_service_OKAY = 0,
-    /** RM Service request not recognized */
-    RM_service_INVALID_SERVICE_TYPE = 1
-} Rm_ServiceResult;
+/** RM Service Request (serviceResult) Action Codes and Errors */
+/** RM Service Request Action Code Base */
+#define RM_SERVICE_ACTION_BASE (0)
+/** RM service was approved.  The resource data in the response is valid if
+ *  the service has been approved. */
+#define RM_SERVICE_APPROVED (RM_SERVICE_ACTION_BASE)
+/** RM service was denied. The resource data in the response is not valid */
+#define RM_SERVICE_DENIED (RM_SERVICE_APPROVED+1)
+/** RM service is being processed.  Typically this means the service is
+ *  being sent to a higher level RM agent for processing */
+#define RM_SERVICE_PROCESSING (RM_SERVICE_DENIED+2)
+
+/** RM Service Request Error Code Base */
+#define RM_SERVICE_ERROR_BASE (-64)
+/** RM service request type not recognized */
+#define RM_SERVICE_ERROR_INVALID_SERVICE_TYPE (RM_SERVICE_ERROR_BASE)
+/** RM Service request was not provided a component callback
+ *  function.  Service requests may result in blocking operations.  A callback
+ *  function must always be provided with a service request since
+ *  blocked or non-blocked operations cannot be promised.  */
+#define RM_SERVICE_ERROR_CALLBACK_NOT_PROVIDED (RM_SERVICE_ERROR_BASE-1)
+/** RM service request needs to be forwarded to another RM agent but no transports
+ *  have been registered */
+#define RM_SERVICE_ERROR_NO_TRANSPORT_REGISTERED (RM_SERVICE_ERROR_BASE-2)
+/** RM service request needs to be forwarded but no client delegate or server has 
+ *  been registered with the RM instance */
+#define RM_SERVICE_ERROR_NOT_REGISTERED_WITH_DEL_OR_SERVER (RM_SERVICE_ERROR_BASE-3)
+/** RM service request needs to be forwarded but the transport packet alloc API
+ *  has not been provided */
+#define RM_SERVICE_ERROR_TRANSPORT_PKT_ALLOC_API_NULL (RM_SERVICE_ERROR_BASE-4)
+/** RM service request needs to be forwarded but the transport packet alloc returned
+ *  NULL for the packet buffer */
+#define RM_SERVICE_ERROR_TRANSPORT_NULL_PKT_BUF (RM_SERVICE_ERROR_BASE-5)
+/** RM service request needs to be forwarded but the buffer allocated by transport
+ *  is not large enough to fit the RM transport packet */
+#define RM_SERVICE_ERROR_TRANSPORT_PKT_BUF_TOO_SMALL (RM_SERVICE_ERROR_BASE-6)
+/** RM service request needs to be forwarded but the transport returned an error
+ *  when trying to send the RM packet to the higher level agent */
+#define RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR (RM_SERVICE_ERROR_BASE-7)
+/** RM service request needs to be forwarded but the transport packet send API
+ *  has not been provided */
+#define RM_SERVICE_ERROR_TRANSPORT_PKT_SEND_API_NULL (RM_SERVICE_ERROR_BASE-8)
 
 /** 
  * @brief RM service types
  */
 typedef enum {
+    /** First service type.  Used by RM for bounds checking.  Should
+     *  not be used by component. */
+    Rm_service_FIRST = 0,
     /** RM resource allocate service */
     Rm_service_RESOURCE_ALLOCATE = 0,
     /** RM resource block allocate service */
-    Rm_service_RESOURCE_BLOCK_ALLOCATE,
+    Rm_service_RESOURCE_BLOCK_ALLOCATE = 1,
     /** RM resource allocate by name service */
-    Rm_service_RESOURCE_ALLOCATE_BY_NAME,    
+    Rm_service_RESOURCE_ALLOCATE_BY_NAME = 2,    
     /** RM resource free service */
-    Rm_service_RESOURCE_FREE,
+    Rm_service_RESOURCE_FREE = 3,
     /** RM resource block free service */
-    Rm_service_RESOURCE_BLOCK_FREE,
+    Rm_service_RESOURCE_BLOCK_FREE = 4,
     /** RM resource free by name service */
-    Rm_service_RESOURCE_FREE_BY_NAME,
+    Rm_service_RESOURCE_FREE_BY_NAME = 5,
     /** RM resource mapping to name service */
-    Rm_service_RESOURCE_MAP_TO_NAME,
+    Rm_service_RESOURCE_MAP_TO_NAME = 6,
     /** RM resource name unmapping service */
-    Rm_service_RESOURCE_UNMAP_NAME,
+    Rm_service_RESOURCE_UNMAP_NAME = 7,
     /** RM resource status service */
-    Rm_service_RESOURCE_STATUS
+    Rm_service_RESOURCE_STATUS = 8,
+    /** Last service type.  Used by RM for bounds checking.  Should
+     *  not be used by component. */
+    Rm_service_LAST = 8
 } Rm_ServiceType;
 
 /** 
- * @brief RM service response information provided by RM back to the requesting component
+ * @brief RM service response information provided by RM back to the 
+ *        requesting component
  */
 typedef struct {
+    /** Result of the service request
+     *  Non-negative result: RM has taken an action based on the request
+     *  Negative result: RM has encountered an error handling the request */
+    int32_t serviceResult;
     /** A request ID will be returned to the component if the requested service cannot
-     * be completed immediately.  The request ID can be used by the component to identify
-     * service responses received via the component callback function.  A request ID will not
-     * be returned if the service request is satisfied immediately */
+     *  be completed immediately.  The request ID can be used by the component to identify
+     *  service responses received via the component callback function.  A request ID will not
+     *  be returned if the service request is satisfied immediately */
     uint32_t requestId;
-    /** The value of the returned resource.  In the case of a block resource allocation response
-     * this field will contain the base value of the block. */
+    /** The base value of the returned resource.  In the case of a block resource allocation 
+     *  response this field will contain the base value of the block. */
     int32_t resBase;
     /** The number of resources allocated in block requests */
     uint32_t resNum;
@@ -122,21 +166,19 @@ typedef struct {
     /** The resource base value. */
     int32_t resBase;
     /** The number of the specified resources.  Will be greater than one only
-     * for block allocate and free service requests. */
+     *  for block allocate and free service requests. */
     uint32_t resNum;
     /** Resource alignment in block allocation requests */
     uint32_t resAlign;    
     /** The name server name associated with the resource.  Used only for 
-     * allocate and free by name service requests */
+     *  allocate and free by name service requests */
     char *resNsName;
     /** Component callback function.  RM will call this function when the 
      *  resource service request is completed. The callback function supplied
      *  for this parameter must match this function pointer prototype. */
-    void (*serviceCallback) (Rm_ServiceResult rmResult, char *resourceName,
-                             uint32_t resourceIndex);
+    void (*serviceCallback) (Rm_ServiceRespInfo *responseInfo);
 } Rm_ServiceReqInfo;
 
-
 /** 
  * @brief RM Service Handle provided to software components that 
  *        request RM services for the resources they control
@@ -161,14 +203,9 @@ typedef struct {
      *  @param[in]  responseInfo
      *      Service response structure that provides details of RM's response to the
      *      service request
-     *
-     *  @retval
-     *      Success - 0 - Service request was handled okay.
-     *  @retval
-     *      Failure - non-zero - Service request error.
      */
-    Rm_ServiceResult  (*rmService)(void *rmHandle, Rm_ServiceReqInfo *requestInfo,
-                                                      Rm_ServiceRespInfo *responseInfo);
+    void (*rmService)(void *rmHandle, Rm_ServiceReqInfo *requestInfo,
+                      Rm_ServiceRespInfo *responseInfo);
 } Rm_ServicesPort;
 
 /** 
index 8f54b2ef90baf6e45a0182c10062bdd3418fb417..f4f134dde2a101f74eeb23f621d7bf0c1ca11f53 100644 (file)
--- a/src/rm.c
+++ b/src/rm.c
@@ -66,32 +66,176 @@ Rm_Perms rmQmssPdspFirmwarePerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_QMSS_FIRMWARE_PDS
 const char   rmVersionStr[] = RM_VERSION_STR ":" __DATE__  ":" __TIME__;
 
 /**********************************************************************
- ********************** Internal Functions *********************************
+ ********************** Internal Functions ****************************
  **********************************************************************/
 
-Rm_TransactionResult rmTransactionForwarder (void *rmHandle, Rm_Transaction *transInfo,
-                                                         Rm_TransactionReceipt *transReceipt)
+void Rm_transactionQueueAdd(void *rmHandle, uint32_t transactionId, void *callbackFunc)
+{
+    Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
+    Rm_TransactionQueueEntry *transactionQueue = (Rm_TransactionQueueEntry *) rmInst->transactionQueue;
+    Rm_TransactionQueueEntry *newEntry;
+    void *key;
+
+    /* Lock access to the RM instance's transaction queue */
+    key = Rm_osalLocalCsEnter();
+
+    /* Get memory for a new transaction queue entry from local memory */
+    newEntry = Rm_osalMalloc (sizeof(Rm_TransactionQueueNode), false);
+
+    /* Populate the new entry. */
+    newEntry->transactionId = transactionId;
+    newEntry->transactionCallback = callbackFunc;
+    newEntry->nextEntry = NULL;  /* New entry's nextEntry pointer will always be NULL */
+
+    /* Check if there are any entries in the transaction queue */
+    if (transactionQueue)
+    {
+        /* At least one entry in the transaction queue.  Add the new entry to the end of the
+         * transaction queue */
+        while (transactionQueue->nextEntry != NULL)
+        {
+            /* Traverse the list until arriving at the last entry */
+            transactionQueue = transactionQueue->nextEntry;
+        }
+
+        /* Add the new entry to the end of the queue */
+        transactionQueue->nextEntry = newEntry;
+    }
+    else
+    {
+        /* The transaction queue does not currently exist.  The new entry is the first entry */
+        rmInst->routeMap = newEntry;
+    }
+
+    Rm_osalLocalCsExit(key);
+}
+
+Rm_TransactionQueueEntry *Rm_transactionQueueFind(void *rmHandle, uint32_t transactionId)
+{
+    Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
+    Rm_TransactionQueueEntry *entry = (Rm_TransactionQueueEntry *) rmInst->transactionQueue;
+    void *key;
+
+    /* Lock access to the RM instance's transaction queue */
+    key = Rm_osalLocalCsEnter();
+
+    /* Make sure there is at least one entry in the transaction queue */
+    if (entry != NULL)
+    {
+        /* Find the transaction ID within the specified RM instance's transaction queue.
+         * If the end of the transaction queue is reached without finding the entry the 
+         * entry pointer will be NULL */
+        while (entry != NULL)
+        {
+            if (entry->transactionId == transactionId)
+            {
+                /* Match: break out of loop and return the entry */
+                break;             
+            }
+            entry = entry->nextEntry;
+        }
+    }
+    
+    Rm_osalLocalCsExit(key);
+    return (entry);
+}
+
+uint32_t Rm_transactionQueueDelete(void *rmHandle, uint32_t transactionId)
+{
+    Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
+    Rm_TransactionQueueEntry *currentEntry = (Rm_TransactionQueueEntry *) rmInst->transactionQueue;
+    Rm_TransactionQueueEntry *prevEntry = NULL;
+    void *key;
+
+    /* Lock access to the RM instance's transaction queue */
+    key = Rm_osalLocalCsEnter();
+
+    /* Make sure there is at least one entry in the transaction queue */
+    if (currentEntry == NULL)
+    {
+        Rm_osalLocalCsExit(key);
+        return (-1); /* TEMP ERROR RETURN */
+    }
+
+    /* Find the transaction ID within the specified RM instance's transaction queue. */
+    while (currentEntry != NULL)
+    {
+        if (currentEntry->transactionId == transactionId)
+        {
+            /* Match: break out of loop and delete the entry */
+            break;             
+        }
+
+        prevEntry = currentEntry;
+        currentEntry = currentEntry->nextEntry;
+    }
+
+    /* Traversed entire queue but did not find transaction */
+    if (currentEntry == NULL)
+    {
+        Rm_osalLocalCsExit(key);
+        return (-2); /* TEMP ERROR RETURN */
+    }
+    else
+    {
+        /* Delete the transaction queue entry */
+        if ((prevEntry == NULL) && currentEntry->nextEntry)
+        {
+            /* Entry to be deleted exists at start of transaction queue.  Map second
+             * entry to be start of transaction queue as long as there are more than
+             * one entries */
+            rmInst->transactionQueue = currentEntry->nextNode;
+        }
+        else
+        {
+            /* Entry to be deleted is in the middle or at end of the queue.  Adjust adjacent
+             * entry pointers.  This covers the case where the entry to be removed is at the
+             * end of the queue. */
+            prevEntry->nextNode = currentEntry->nextNode;
+        }
+
+        /* Delete the node, free the memory associated with the node. */
+        Rm_osalFree((void *) currentEntry, sizeof(Rm_TransactionQueueEntry), false);
+    }
+
+    Rm_osalLocalCsExit(key);
+    return (0); /* RETURN OKAY - FIX MAGIC NUMBER */
+}
+
+/* Used in Client Delegate case where it forwarded requests from Client to Server
+ * callback will direct to internal function that forwards response from server back
+ * to client */
+void Rm_internalCallback (Rm_ServiceRespInfo *responseInfo)
+{
+
+}
+
+void Rm_transactionForwarder (void *rmHandle, Rm_Transaction *transInfo,
+                              Rm_TransactionReceipt *transReceipt)
 {
     Rm_Inst *rmInst = (Rm_Inst *) rmHandle;
     Rm_TransRouteMapNode *routeMap = (Rm_TransRouteMapNode *) rmInst->routeMap;
-    Rm_ProtocolPkt *rmPkt = NULL;
+    uint32_t transactionId;
+    Rm_Packet *rmPkt = NULL;
+    Rm_ProtocolPkt *rmProtPkt = NULL;
 
-    /* Error if no transports have been registered and a service has been requested that
-     * must be forwarded to another RM agent */
+    /* Make sure at least one transport has been registered */
     if (routeMap == NULL)
     {
-        return (-1); /* temp error */
+        transReceipt->transactionResult = RM_SERVICE_ERROR_NO_TRANSPORT_REGISTERED;
+        return;
     }
     
     /* Make sure the RM instance has a transport registered with a higher level agent */
     if (!rmInst->registeredWithDelegateOrServer)
     {
-        return (-1); /* temp error - can't handle request because client delegate or server not registered */
+        transReceipt->transactionResult = RM_SERVICE_ERROR_NOT_REGISTERED_WITH_DEL_OR_SERVER;
+        return;
     }
 
     /* Parse the RM instance's routing map to find the higher level agent for forwarding */
     while ((routeMap->remoteInstType != Rm_instType_CLIENT_DELEGATE) || 
-              (routeMap->remoteInstType != Rm_instType_SERVER))
+           (routeMap->remoteInstType != Rm_instType_SERVER))
     {
         /* Traverse the list until arriving at the upper level agent node */
         routeMap = routeMap->nextNode;
@@ -100,82 +244,187 @@ Rm_TransactionResult rmTransactionForwarder (void *rmHandle, Rm_Transaction *tra
     /* Create a RM packet using the service information */
     if (rmInst->transport.rmAllocPkt)
     {
-        rmPkt = rmInst->transport.rmAllocPkt (routeMap->transHandle, sizeof(Rm_ProtocolPkt));
+        rmPkt = rmInst->transport.rmAllocPkt(routeMap->transHandle, sizeof(Rm_Packet));
+    }
+    else
+    {
+        /* The transport packet alloc API is not plugged */
+        transReceipt->transactionResult = RM_SERVICE_ERROR_TRANSPORT_PKT_ALLOC_API_NULL;
+        return;
     }
 
-    /* Return error if the packet allocation API is not plugged or if a NULL packet pointer
-     * was returned */
-    if (!rmPkt)
+    /* Make sure a buffer for the packet was allocated  */
+    if (rmPkt == NULL)
     {
-        return (-1); /* temp error */
+        transReceipt->transactionResult = RM_SERVICE_ERROR_TRANSPORT_NULL_PKT_BUF;
+        return;
+    }
+
+    /* Make sure allocated buffer is large enough to fit the protocol packet plus the 
+     * rmPktLen field */
+    if (rmPkt->rmPktLen < (sizeof(Rm_ProtocolPkt) + sizeof(uint32_t))
+    {   
+        transReceipt->transactionResult = RM_SERVICE_ERROR_TRANSPORT_PKT_BUF_TOO_SMALL;
+        return;
     }
 
+    /* Create an ID for this transaction.  The ID will be used for two purposes:
+     * 1) Matching the response from the higher level RM agent to the request
+     * 2) Provided to the service requesting component so that it can match the
+     *    service request with the response it receives via its callback function */
+    transactionId = ...; /* NEED SCHEME FOR CREATING A MUTUALLY EXCLUSIVE PKT ID.  CAN'T
+                          * CONFLICT WITH PCKT IDS CREATED ON OTHER RM INSTANCES */
+    /* Initialize the rmPkt.  Do not assume the transport code will do it */                            
+    memset((void *)rmPkt, 0, sizeof(Rm_Packet));
+                          
+    /* Assign the rmData field to be the rmProtPkt */
+    rmProtPkt = &(rmPkt->rmData[0]);
     /* Populate the RM packet using the service information */
+    rmProtPkt->rmPktId = transactionId;
+    strcpy((void *)rmProtPkt->rmInstName,(void *)rmInst->name);
+    rmProtPkt->rmCmd = (uint32_t) transInfo->transType;
+    if ((transInfo->transCommand == Rm_command_POLICY_REQUEST) ||
+        (transInfo->transCommand == Rm_command_POLICY_RESPONSE)
+    {
+        /* Copy the policy data if the transaction is policy based */
+        memcpy ((void *)rmProtPkt->u.rmPolicyData, (void *)transInfo->u.policyData,
+                RM_MAX_POLICY_SIZE_BYTES);
+    }
+    else
+    {
+        /* Otherwise copy the resource data */
+        memcpy ((void *)&(rmProtPkt->u.resInfo), (void *) &(transInfo->u.resourceInfo),
+                sizeof(Rm_ResourceInfo));
+    }
 
+    /* Create an entry in the transaction queue */
+    Rm_transactionQueueAdd(rmHandle, transactionId, transInfo->transCallback);
 
+    /* Send the RM packet to the application transport */
+    if (rmInst->transport.rmSend)
+    {
+        if (!(rmInst->transport.rmSend(routeMap->transHandle, rmPkt))
+        {
+            /* Transport returned an error */
 
-    /* Inform component that requested the service that the resource is being requested
-     * from the higher level RM agent.  The component must assume the resource service
-     * result will be returned using the specified callback function */
-    return (RM_REQUESTING_RESOURCE);
+            /* SHOULD TRANSPORT ERROR SOMEHOW BE OR'D WITH THE SERVICE ERROR ??? */
+            transReceipt->transactionResult = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;
+            return;
+        }
+    }
+    else
+    {
+        /* The transport packet send API is not plugged */
+        transReceipt->transactionResult = RM_SERVICE_ERROR_TRANSPORT_PKT_SEND_API_NULL;
+        return;
+    }    
+
+    /* Inform requesting component that the service is being forwarded to a higher lever
+     * RM agent for processing.  The result of the service will be provided to the 
+     * component via the specified callback function */
+    transReceipt->transactionResult = RM_SERVICE_PROCESSING;
+    transReceipt->transactionId = transactionId;
+    return;
 }
 
-Rm_TransactionResult rmTransactionProcessor (rmHandle, Rm_Transaction *newTransaction, 
-                                                               Rm_TransactionReceipt *newTransactionReceipt)
+void Rm_transactionProcessor (void *rmHandle, Rm_Transaction *transaction, 
+                                 Rm_TransactionReceipt *transactionReceipt)
 {
+    Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
+
+    /* All service requests on Clients are forwarded to the higher level RM agent
+     * either a Client Delegate or Server, based on the RM system architecture */
+    if (rmInst->instType == Rm_instType_CLIENT)
+    {
+        Rm_transactionForwarder(rmHandle, transaction, transactionReceipt);
+
+        if (requestInfo->serviceCallback == NULL)
+        {
+            /* RM Client's always use a blocking RM transport to consult with a high-level
+             * RM agent prior to providing a response to the component.  It is assumed the 
+             * component's cannot block.  Therefore, all responses must go through the 
+             * callback function provided by the component.  Return an error if the 
+             * component does not provide a callback function */
+        }
+
+        /* Provide a transaction ID back to the component so that it can map service requests
+         * to the responses received via the component's callback function */
+        responseInfo->requestId = transactionReceipt.transactionId;
+    }
+    else
+    {
+
+
+    }
 
 }
 
-Rm_ServiceResult rmServiceHandler (void *rmHandle, Rm_ServiceReqInfo *requestInfo,
-                                                               Rm_ServiceRespInfo *responseInfo)
+void Rm_serviceHandler (void *rmHandle, Rm_ServiceReqInfo *requestInfo,
+                        Rm_ServiceRespInfo *responseInfo)
 {
     Rm_Inst *rmInst = (Rm_Inst *) rmHandle;
-    Rm_Transaction newTransaction;
-    Rm_TransactionReceipt newTransactionReceipt;
-    Rm_ServiceResult retVal = RM_service_OKAY;
+    Rm_Transaction transaction;
+    Rm_TransactionReceipt transactionReceipt;
     void *key;
 
     /* Prevent another component using the same instance from wiping out the current
      * service request */
     key = Rm_osalLocalCsEnter();
 
+    /* Make sure serviceType is valid and that a callback function has been provided */
+    if ((requestInfo->serviceType < Rm_service_FIRST) || 
+        (requestInfo->serviceType > Rm_service_LAST))
+    {
+        responseInfo->serviceResult = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;
+        Rm_osalLocalCsExit(key);
+        return;
+    }
+    else if (requestInfo->serviceCallback == NULL)
+    {
+        responseInfo->serviceResult = RM_SERVICE_ERROR_CALLBACK_NOT_PROVIDED;
+        Rm_osalLocalCsExit(key);
+        return;
+    }
+
+    /* Clear the transaction and receipt prior to using them */
+    memset((void *) &transaction, 0, sizeof(Rm_Transaction));
+    memset((void *) &transactionReceipt, 0, sizeof(Rm_TransactionReceipt));
+
     /* Transfer request information into the internal transaction format */
-    newTransaction.transType = (Rm_Command) requestInfo->serviceType;
+    transaction.transCommand = (Rm_Command) requestInfo->serviceType;
+    transaction.transCallback = requestInfo->serviceCallback;
     /* Policy modifications will never originate from components */
-    strcpy ((void *) &(newTransaction.u.transInfo.resName)[0], (void *)requestInfo->resName);
-    newTransaction.u.transInfo.resBase = requestInfo->resourceAlign;
-    newTransaction.u.transInfo.resNum = requestInfo->resourceNum;
-    newTransaction.u.transInfo.resAlign = requestInfo->resourceAlign;
-    strcpy ((void *) &(newTransaction.u.transInfo.resNsName)[0], (void *)requestInfo->resNsName);
-
-    /* All service requests on Clients are forwarded to the higher level RM agent
-     * either a Client Delegate or Server, based on the RM system architecture */
-    if (rmInst->instType == Rm_instType_CLIENT)
+    strcpy ((void *) &(transaction.u.resourceInfo.resName)[0], (void *)requestInfo->resName);
+    transaction.u.resourceInfo.resBase = requestInfo->resourceBase;
+    transaction.u.resourceInfo.resNum = requestInfo->resourceNum;
+    transaction.u.resourceInfo.resAlign = requestInfo->resourceAlign;
+    strcpy ((void *) &(transaction.u.resourceInfo.resNsName)[0], (void *)requestInfo->resNsName);
+
+    /* Pass the new transaction to the transaction processor */
+    Rm_transactionProcessor (rmHandle, &transaction, &transactionReceipt);
+
+    /* Copy transaction receipt information into the response info fields for the 
+     * component based on the result of the transaction.  Denied service requests
+     * will have only a valid serviceResult field */
+    responseInfo->serviceResult = transactionReceipt->transactionResult;
+    if (responseInfo->serviceResult == RM_SERVICE_APPROVED)
     {
-        retVal = (Rm_ServiceResult) rmTransactionForwarder (rmHandle, &newTransaction, &newTransactionReceipt);
-
-        /* Copy internal transaction receipt information into the response info fields for the 
-         * component */
-        responseInfo->requestId = newTransactionReceipt.transactionId;
-        responseInfo->resBase = newTransactionReceipt.resBase;
-        responseInfo->resNum = newTransactionReceipt.resNum;
+        /* Service was approved.  The resource data should be passed back
+         * to the component */
+        responseInfo->resBase = transactionReceipt.resBase;
+        responseInfo->resNum = transactionReceipt.resNum;
     }
-    else
+    else if (responseInfo->serviceResult == RM_SERVICE_PROCESSING)
     {
-        /* Directly handle the request if on a Client Delegate or Server.  On Client Delegates, if
-         * the request cannot be serviced it will be forwarded to the higher level RM instance. */
-        retVal = (Rm_ServiceResult) rmTransactionProcessor (rmHandle, &newTransaction, &newTransactionReceipt);
-
-        /* Copy internal transaction receipt information into the response info fields for the 
-         * component */
-        responseInfo->requestId = newTransactionReceipt.transactionId;
-        responseInfo->resBase = newTransactionReceipt.resBase;
-        responseInfo->resNum = newTransactionReceipt.resNum;
+        /* The service is still being processed.  Provide the transaction ID
+         * back to the component so that it can sort service responses received
+         * via the provided callback function */
+        responseInfo->requestId = transactionReceipt.transactionId;
     }
 
     Rm_osalLocalCsExit(key);
     
-    return (retVal);
+    return;
 }
 
 /**********************************************************************
@@ -210,13 +459,18 @@ Rm_Handle Rm_init(Rm_InitCfg *initCfg)
     rmInst->transport.rmNumPktsReceived = initCfg->rmNumPktsReceivedFuncPtr;
 
     /* Initialize the transport routing map linked list pointer to NULL.  The linked list
-      * nodes will be created when the application registers transports */
+     * nodes will be created when the application registers transports */
     rmInst->routeMap = NULL;
 
+    /* Initialize the transaction queue linked list pointer to NULL.  The linked list
+     * nodes will be created when the transactions are forwarded to higher level RM
+     * agents. */
+    rmInst->transactionQueue= NULL;
+
     /* RM Server specific actions */
     if (rmInst->instType == Rm_instType_SERVER)
     {
-
+       /* parse DTB, etc */
     }
 
     /* Instance startup policies are only used for Servers and Client Delegates */
@@ -253,8 +507,14 @@ Rm_ServiceHandle Rm_getServiceHandle(Rm_Handle rmHandle)
     return ((Rm_ServiceHandle) newServicePort);
 }
 
-Rm_TransportHandle Rm_registerTransport (Rm_Handle rmHandle, 
-                                     Rm_TransCfg *transCfg)
+/* Resource requests that come directly from application go through this API */
+void Rm_requestService (void *rmHandle, Rm_ServiceReqInfo *requestInfo,
+                        Rm_ServiceRespInfo *responseInfo)
+{
+    Rm_serviceHandler(rmHandle, requestInfo, responseInfo);
+}
+
+Rm_TransportHandle Rm_registerTransport (Rm_Handle rmHandle, Rm_TransCfg *transCfg)
 {
     Rm_Inst *rmInst = (Rm_Inst *) rmHandle;
     Rm_TransRouteMapNode *existingRouteMap = (Rm_TransRouteMapNode *) rmInst->routeMap;
@@ -267,12 +527,14 @@ Rm_TransportHandle Rm_registerTransport (Rm_Handle rmHandle,
         return (NULL); /* Error -return null */
     }
 
-    /* Verify Clients and Client Delegates are not registering with more than one Client Delegate or Server.
-     * Assuming a Client Delegate can register with another Client Delegate that can "act" as a server */
-    if (((rmInst->instType == Rm_instType_CLIENT) || (rmInst->instType == Rm_instType_CLIENT_DELEGATE)) &&
-         ((transCfg->rmRemoteInstType == Rm_instType_CLIENT_DELEGATE) ||
-           (transCfg->rmRemoteInstType == Rm_instType_SERVER)) &&
-          rmInst->registeredWithDelegateOrServer)
+    /* Verify Clients and Client Delegates are not registering with more than one 
+     * Client Delegate or Server. Assuming a Client Delegate can register with another 
+     * Client Delegate that can "act" as a server */
+    if (((rmInst->instType == Rm_instType_CLIENT) || 
+         (rmInst->instType == Rm_instType_CLIENT_DELEGATE)) &&
+        ((transCfg->rmRemoteInstType == Rm_instType_CLIENT_DELEGATE) ||
+         (transCfg->rmRemoteInstType == Rm_instType_SERVER)) &&
+        rmInst->registeredWithDelegateOrServer)
     {
         return (NULL); /* Error -return null */
     }         
@@ -310,7 +572,7 @@ Rm_TransportHandle Rm_registerTransport (Rm_Handle rmHandle,
 
     /* Specify RM instance has registered with a higher level agent */
     if ((newRouteMapNode->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||
-         (newRouteMapNode->remoteInstType == Rm_instType_SERVER))
+        (newRouteMapNode->remoteInstType == Rm_instType_SERVER))
     {
         rmInst->registeredWithDelegateOrServer = true;
     }
@@ -325,7 +587,7 @@ Rm_Result Rm_unregisterTransport (Rm_Handle rmHandle, Rm_TransportHandle transHa
     Rm_TransRouteMapNode *prevNode = NULL;
 
     /* Make sure a routing map exists for the RM instance */
-    if (!routeMapNode)
+    if (routeMapNode == NULL)
     {
         return (-1); /* TEMP ERROR RETURN */
     }
@@ -333,18 +595,18 @@ Rm_Result Rm_unregisterTransport (Rm_Handle rmHandle, Rm_TransportHandle transHa
     /* Find the transport handle within the specified RM instance's routing map. */
     while (1)
     {
-         if (routeMapNode->transHandle == transHandle)
-         {
-             /* Match: break out of loop and delete the node */
-             break;             
-         }
-         else if (routeMapNode->nextNode == NULL)
-         {
-             return (-1); /* TEMP ERROR: transhandle does not exist for RM instance */
-         }
+        if (routeMapNode->transHandle == transHandle)
+        {
+            /* Match: break out of loop and delete the node */
+            break;             
+        }
+        else if (routeMapNode->nextNode == NULL)
+        {
+            return (-1); /* TEMP ERROR: transhandle does not exist for RM instance */
+        }
 
-         prevNode = routeMapNode;
-         routeMapNode = routeMapNode->nextNode;
+        prevNode = routeMapNode;
+        routeMapNode = routeMapNode->nextNode;
     }
     
     /* Delete the routing map node */
@@ -365,7 +627,7 @@ Rm_Result Rm_unregisterTransport (Rm_Handle rmHandle, Rm_TransportHandle transHa
     /* Remove specification in RM instance that it has been connected to an upper level agent
      * if the node to be deleted has a remote instance type of Client Delegate or Server */
     if ((routeMapNode->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||
-         (routeMapNode->remoteInstType == Rm_instType_SERVER))
+        (routeMapNode->remoteInstType == Rm_instType_SERVER))
     {
         rmInst->registeredWithDelegateOrServer = false;
     }