diff --git a/src/rm_transport.c b/src/rm_transport.c
index e0b09f7b14d03453af46d4cc31a4a99aaad0dcdb..470a6d19e6f57a2ab36954b3bbbc564c44c52d14 100644 (file)
--- a/src/rm_transport.c
+++ b/src/rm_transport.c
/**\r
- * @file rm.c\r
+ * @file rm_transport.c\r
*\r
* @brief \r
- * This is the Resource Manager source.\r
+ * This is the Resource Manager transport source.\r
*\r
* \par\r
* ============================================================================\r
- * @n (C) Copyright 2012, Texas Instruments, Inc.\r
+ * @n (C) Copyright 2012-2013, Texas Instruments, Inc.\r
* \r
* Redistribution and use in source and binary forms, with or without \r
* modification, are permitted provided that the following conditions \r
* \par\r
*/\r
\r
-/* RM Types */\r
-#include <ti/drv/rm/rm_types.h>\r
+/* Standard includes */\r
+#include <string.h>\r
\r
/* RM external includes */\r
#include <ti/drv/rm/rm.h>\r
#include <rm_osal.h>\r
\r
/**********************************************************************\r
- ********************** Internal Functions ****************************\r
+ ************************ Local Functions *****************************\r
**********************************************************************/\r
\r
-Rm_TransportNode *Rm_transportNodeAdd(Rm_Inst *rmInst, Rm_TransportCfg *transportCfg)\r
+/* FUNCTION PURPOSE: Adds a transport\r
+ ***********************************************************************\r
+ * DESCRIPTION: Returns a pointer to a transport structure that\r
+ * was created, initialized, and added to the \r
+ * instance transport list.\r
+ */\r
+static Rm_Transport *transportAdd(const Rm_TransportCfg *transportCfg)\r
{\r
- Rm_TransportNode *routeMap = (Rm_TransportNode *)rmInst->routeMap;\r
- Rm_TransportNode *newTransportNode = NULL;\r
- void *key;\r
-\r
- /* Lock access to the RM instance's route map */\r
- key = Rm_osalLocalCsEnter();\r
-\r
- /* Get memory for a new transport node from local memory */\r
- newTransportNode = Rm_osalMalloc (sizeof(Rm_TransportNode), false);\r
-\r
- /* Return if the memory allocated for the transport node is NULL */\r
- if (newTransportNode != NULL)\r
- {\r
- /* Populate the new entry. */\r
- newTransportNode->remoteInstType = transportCfg->remoteInstType;\r
- strcpy(&(newTransportNode->remoteInstName)[0], transportCfg->remoteInstName);\r
- newTransportNode->nextNode = NULL; /* New node will always be NULL */\r
-\r
- /* Check if there are any nodes in the transport routing map */\r
- if (routeMap)\r
- {\r
- /* At least one node in the routing map. Add the new node to the end of the\r
- * routing map */\r
- while (routeMap->nextNode != NULL)\r
- {\r
- /* Traverse the list until arriving at the last node */\r
- routeMap = (Rm_TransportNode *)routeMap->nextNode;\r
+ Rm_Inst *rmInst = (Rm_Inst *) transportCfg->rmHandle;\r
+ Rm_Transport *transports = rmInst->transports;\r
+ Rm_Transport *newTransport = NULL;\r
+\r
+ newTransport = Rm_osalMalloc (sizeof(Rm_Transport));\r
+ memset((void *)newTransport, 0, sizeof(Rm_Transport));\r
+\r
+ if (newTransport) {\r
+ newTransport->rmHandle = transportCfg->rmHandle;\r
+ newTransport->appTransportHandle = transportCfg->appTransportHandle;\r
+ newTransport->remoteInstType = transportCfg->remoteInstType;\r
+ newTransport->callouts.rmAllocPkt = transportCfg->transportCallouts.rmAllocPkt;\r
+ newTransport->callouts.rmSendPkt = transportCfg->transportCallouts.rmSendPkt;\r
+ newTransport->nextTransport = NULL;\r
+\r
+ if (transports) {\r
+ while (transports->nextTransport) {\r
+ transports = transports->nextTransport;\r
}\r
-\r
- /* Add the new node to the end of the list */\r
- routeMap->nextNode = (void *)newTransportNode;\r
- }\r
- else\r
- {\r
- /* The transport routing map does not currently exist. The new node is the first node */\r
- rmInst->routeMap = (void *)newTransportNode;\r
+ transports->nextTransport = newTransport;\r
}\r
- }\r
- \r
- Rm_osalLocalCsExit(key);\r
-\r
- return (newTransportNode);\r
-}\r
-\r
-Rm_TransportNode *Rm_transportNodeFindTransportHandle(Rm_Inst *rmInst, \r
- Rm_TransportHandle transportHandle)\r
-{\r
- Rm_TransportNode *transportNode = (Rm_TransportNode *)rmInst->routeMap;\r
-\r
- /* Make sure there is at least one node in the route map */\r
- if (transportNode != NULL)\r
- {\r
- /* Find the transport node with the transport handle within the RM instance's\r
- * route map. If the end of the route map is reached without finding the node the \r
- * node pointer will be NULL */\r
- while (transportNode != NULL)\r
- {\r
- /* The transport handle is the address of the transport node */\r
- if (transportNode == ((Rm_TransportNode *)transportHandle))\r
- {\r
- /* Match: break out of loop and return the node */\r
- break; \r
- }\r
- transportNode = (Rm_TransportNode *)transportNode->nextNode;\r
- }\r
- }\r
-\r
- return (transportNode);\r
-}\r
-\r
-Rm_TransportNode *Rm_transportNodeFindRemoteName(Rm_Inst *rmInst, char *remoteName)\r
-{\r
- Rm_TransportNode *transportNode = (Rm_TransportNode *)rmInst->routeMap;\r
-\r
- /* Make sure there is at least one node in the route map */\r
- if (transportNode != NULL)\r
- {\r
- /* Find the transport node with the provided remote instance name.\r
- * If the end of the route map is reached without finding the node the \r
- * node pointer will be NULL */\r
- while (transportNode != NULL)\r
- {\r
- /* The transport handle is the address of the transport node */\r
- if (strcmp(&(transportNode->remoteInstName)[0], remoteName) == 0)\r
- {\r
- /* Match: break out of loop and return the node */\r
- break; \r
- }\r
- transportNode = (Rm_TransportNode *)transportNode->nextNode;\r
+ else {\r
+ rmInst->transports = newTransport;\r
}\r
}\r
-\r
- return (transportNode);\r
+ return (newTransport);\r
}\r
\r
-Rm_TransportNode *Rm_transportNodeFindRemoteInstType(Rm_Inst *rmInst,\r
- Rm_InstType remoteInstType)\r
+/* FUNCTION PURPOSE: Tests if a transport is registered to an instance\r
+ ***********************************************************************\r
+ * DESCRIPTION: Returns TRUE if the supplied transport is found in\r
+ * the instance transport list. Otherwise, returns FALSE\r
+ */\r
+static int transportIsRegistered(Rm_Handle rmHandle, Rm_Transport *transport)\r
{\r
- Rm_TransportNode *transportNode = (Rm_TransportNode *)rmInst->routeMap;\r
-\r
- /* Make sure there is at least one node in the route map */\r
- if (transportNode != NULL)\r
- {\r
- /* Find the transport node with the provided remote instance type.\r
- * If the end of the route map is reached without finding the node the \r
- * node pointer will be NULL */\r
- while (transportNode != NULL)\r
- {\r
- if (transportNode->remoteInstType == remoteInstType)\r
- {\r
- /* Match: break out of loop and return the node */\r
- break; \r
- }\r
- transportNode = (Rm_TransportNode *)transportNode->nextNode;\r
+ Rm_Inst *rmInst = (Rm_Inst *)rmHandle;\r
+ Rm_Transport *transportList = (Rm_Transport *)rmInst->transports;\r
+ \r
+ while (transportList) {\r
+ if (transportList == transport) {\r
+ return(RM_TRUE); \r
}\r
+ transportList = transportList->nextTransport;\r
}\r
-\r
- return (transportNode);\r
+ return (RM_FALSE);\r
}\r
\r
-Rm_TransportResult Rm_transportNodeDelete(Rm_Inst *rmInst, Rm_TransportHandle transportHandle)\r
+/* FUNCTION PURPOSE: Deletes a transport\r
+ ***********************************************************************\r
+ * DESCRIPTION: Removes a transport from an instance transport list\r
+ * and then frees the memory associated with the transport\r
+ * data structure\r
+ */\r
+static void transportDelete(Rm_Transport *transport)\r
{\r
- Rm_TransportNode *transportNode = (Rm_TransportNode *)rmInst->routeMap;\r
- Rm_TransportNode *prevNode = NULL;\r
- void *key;\r
-\r
- /* Lock access to the RM instance's route map */\r
- key = Rm_osalLocalCsEnter();\r
-\r
- /* Make sure there is at least one entry in the transaction queue */\r
- if (transportNode == NULL)\r
- {\r
- Rm_osalLocalCsExit(key);\r
- return (RM_TRANSPORT_ERROR_NO_TRANSPORTS_REGISTERED);\r
- }\r
+ Rm_Inst *rmInst = (Rm_Inst *)transport->rmHandle;\r
+ Rm_Transport *transportList = (Rm_Transport *)rmInst->transports;\r
+ Rm_Transport *prevTransport = NULL;\r
\r
- /* Find the transport handle within the RM instance's route map. */\r
- while (transportNode != NULL)\r
- {\r
- if (transportNode == (Rm_TransportNode *) transportHandle)\r
- {\r
- /* Match: break out of loop and delete the entry */\r
+ /* Get previous transport in list */\r
+ while (transportList) {\r
+ if (transportList == transport) {\r
break; \r
}\r
-\r
- prevNode = transportNode;\r
- transportNode = (Rm_TransportNode *)transportNode->nextNode;\r
+ prevTransport = transportList;\r
+ transportList = transportList->nextTransport;\r
}\r
\r
- /* Traversed entire queue but did not find transaction */\r
- if (transportNode == NULL)\r
- {\r
- Rm_osalLocalCsExit(key);\r
- return (RM_TRANSPORT_ERROR_HANDLE_HAS_NOT_BEEN_REGISTERED);\r
+ if (prevTransport == NULL) {\r
+ rmInst->transports = transport->nextTransport;\r
}\r
- else\r
- {\r
- /* Delete the transport node */\r
- if ((prevNode == NULL) && transportNode->nextNode)\r
- {\r
- /* Node to be deleted exists at start of route map. Map second\r
- * node to be start of route map as long as there are more than\r
- * one nodes */\r
- rmInst->routeMap = transportNode->nextNode;\r
- }\r
- else\r
- {\r
- /* Node to be deleted is in the middle or at end of the route map. Adjust adjacent\r
- * node pointers. This covers the case where the node to be removed is at the\r
- * end of the route map. */\r
- prevNode->nextNode = transportNode->nextNode;\r
- }\r
-\r
- /* Free the memory associated with the node. */\r
- Rm_osalFree((void *) transportNode, sizeof(Rm_TransportNode), false);\r
+ else {\r
+ prevTransport->nextTransport = transport->nextTransport;\r
}\r
-\r
- Rm_osalLocalCsExit(key);\r
- return (RM_TRANSPORT_SUCCESSFUL);\r
+ Rm_osalFree((void *)transport, sizeof(Rm_Transport));\r
}\r
\r
-Rm_Packet *Rm_transportCreateResourceReqPkt(Rm_Inst *rmInst, Rm_TransportNode *dstTransportNode,\r
- Rm_Transaction *transaction, Rm_TransactionReceipt *receipt)\r
-{\r
- Rm_Packet *rmPkt = NULL;\r
- Rm_ResourceRequestPkt *resourceReqPkt = NULL;\r
-\r
- /* Make sure a buffer for the packet was allocated */\r
- if ((rmPkt = rmInst->transport.rmAllocPkt((Rm_TransportHandle)dstTransportNode, sizeof(Rm_Packet))) ==\r
- NULL)\r
- {\r
- receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_ALLOC_PKT_ERROR;\r
- return (NULL);\r
- }\r
-\r
- /* Make sure allocated buffer is large enough to fit the request packet plus the \r
- * rmPktLen and Rm_PktType fields */\r
- if (rmPkt->pktLenBytes < (sizeof(Rm_ResourceRequestPkt) + sizeof(uint32_t) + sizeof(Rm_pktType)))\r
- { \r
- receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_PKT_BUF_TOO_SMALL;\r
- return (NULL);\r
- }\r
+/**********************************************************************\r
+ ********************** Internal Functions ****************************\r
+ **********************************************************************/\r
\r
- /* Set the Rm Packet type */ \r
- rmPkt->pktType = Rm_pktType_RESOURCE_REQUEST;\r
- \r
- /* Assign the packet's data field to be the start of the resource request packet */\r
- resourceReqPkt = (Rm_ResourceRequestPkt *) rmPkt->data;\r
- /* Populate the resource request packet using the transaction information */\r
- resourceReqPkt->requestId = transaction->id;\r
- if (transaction->type == Rm_service_RESOURCE_ALLOCATE)\r
- {\r
- resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE;\r
- }\r
- else if (transaction->type == Rm_service_RESOURCE_BLOCK_ALLOCATE)\r
- {\r
- resourceReqPkt->resourceReqType = Rm_resReqPktType_BLOCK_ALLOCATE;\r
- }\r
- else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_BY_NAME)\r
- {\r
- resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE_NAMED;\r
- }\r
- else if (transaction->type == Rm_service_RESOURCE_FREE)\r
- {\r
- resourceReqPkt->resourceReqType = Rm_resReqPktType_FREE;\r
- }\r
- else if (transaction->type == Rm_service_RESOURCE_BLOCK_FREE)\r
- {\r
- resourceReqPkt->resourceReqType = Rm_resReqPktType_BLOCK_FREE;\r
- }\r
- else if (transaction->type == Rm_service_RESOURCE_FREE_BY_NAME)\r
- {\r
- resourceReqPkt->resourceReqType = Rm_resReqPktType_FREE_NAMED;\r
+/* FUNCTION PURPOSE: Finds a transport based on remote inst type\r
+ ***********************************************************************\r
+ * DESCRIPTION: Returns a pointer to the transport within an instance's\r
+ * transport list that matches the provided remote\r
+ * instance type. NULL is returned if no transports in \r
+ * the list match the remote instance type.\r
+ */\r
+Rm_Transport *rmTransportFindRemoteInstType(Rm_Transport *transports, Rm_InstType remoteInstType)\r
+{\r
+ while (transports) {\r
+ if (transports->remoteInstType == remoteInstType) {\r
+ break; \r
+ }\r
+ transports = transports->nextTransport;\r
}\r
- strcpy(&(resourceReqPkt->instName)[0], rmInst->name);\r
- /* Copy the resource data */\r
- memcpy ((void *)&(resourceReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),\r
- sizeof(Rm_ResourceInfo));\r
-\r
- return (rmPkt);\r
+ return (transports);\r
}\r
\r
-Rm_Packet *Rm_transportCreateResourceResponsePkt(Rm_Inst *rmInst, Rm_TransportNode *dstTransportNode,\r
- Rm_Transaction *transaction, Rm_TransactionReceipt *receipt)\r
-{\r
- Rm_Packet *rmPkt = NULL;\r
- Rm_ResourceResponsePkt *resourceRespPkt = NULL;\r
-\r
- /* Make sure a buffer for the packet was allocated */\r
- if ((rmPkt = rmInst->transport.rmAllocPkt((Rm_TransportHandle)dstTransportNode, sizeof(Rm_Packet))) ==\r
- NULL)\r
- {\r
- receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_ALLOC_PKT_ERROR;\r
- return (NULL);\r
- }\r
+/**********************************************************************\r
+ ********************* Application visible APIs ***********************\r
+ **********************************************************************/\r
\r
- /* Make sure allocated buffer is large enough to fit the request packet plus the \r
- * rmPktLen and Rm_PktType fields */\r
- if (rmPkt->pktLenBytes < (sizeof(Rm_ResourceResponsePkt) + sizeof(uint32_t) + sizeof(Rm_pktType)))\r
- { \r
- receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_PKT_BUF_TOO_SMALL;\r
- return (NULL);\r
- }\r
+/* FUNCTION PURPOSE: Registers an app transport with a RM instance\r
+ ***********************************************************************\r
+ * DESCRIPTION: Returns a transport handle to the application that\r
+ * has been registered with an RM instance. The handle\r
+ * is used by the application to route packets to the\r
+ * proper RM instance's based on the application\r
+ * transport receive code. The handle is also used\r
+ * internally by RM to route request and response \r
+ * packets to the correct application transports. NULL\r
+ * is returned for the transport handle if any errors\r
+ * are encountered.\r
+ */\r
+Rm_TransportHandle Rm_transportRegister (const Rm_TransportCfg *transportCfg, int32_t *result)\r
+{\r
+ Rm_Inst *rmInst = (Rm_Inst *) transportCfg->rmHandle;\r
+ Rm_Transport *transport = NULL;\r
+ void *key;\r
\r
- /* Set the Rm Packet type */ \r
- rmPkt->pktType = Rm_pktType_RESOURCE_RESPONSE;\r
- \r
- /* Assign the packet's data field to be the start of the resource response packet */\r
- resourceRespPkt = (Rm_ResourceResponsePkt *)rmPkt->data;\r
- /* Populate the resource response packet using the transaction information */\r
- resourceRespPkt->responseId = transaction->id;\r
- resourceRespPkt->requestResult = transaction->details;\r
- /* Copy the resource data */\r
- memcpy ((void *)&(resourceRespPkt->resourceInfo), (void *)&(transaction->resourceInfo),\r
- sizeof(Rm_ResourceInfo));\r
-\r
- return (rmPkt);\r
-}\r
+ *result = RM_OK;\r
\r
-Rm_Packet *Rm_transportCreateNsRequestPkt(Rm_Inst *rmInst, Rm_TransportNode *dstTransportNode,\r
- Rm_Transaction *transaction, Rm_TransactionReceipt *receipt)\r
-{\r
- Rm_Packet *rmPkt = NULL;\r
- Rm_NsRequestPkt *nsReqPkt = NULL;\r
-\r
- /* Make sure a buffer for the packet was allocated */\r
- if ((rmPkt = rmInst->transport.rmAllocPkt((Rm_TransportHandle)dstTransportNode, sizeof(Rm_Packet))) ==\r
- NULL)\r
- {\r
- receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_ALLOC_PKT_ERROR;\r
- return (NULL);\r
- }\r
+ RM_SS_INST_INV_ENTER_CS(key);\r
\r
- /* Make sure allocated buffer is large enough to fit the request packet plus the \r
- * rmPktLen and Rm_PktType fields */\r
- if (rmPkt->pktLenBytes < (sizeof(Rm_NsRequestPkt) + sizeof(uint32_t) + sizeof(Rm_pktType)))\r
- { \r
- receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_PKT_BUF_TOO_SMALL;\r
- return (NULL);\r
+ /* Shared servers and clients cannot connect to anyone */\r
+ if ((rmInst->instType == Rm_instType_SHARED_SERVER) ||\r
+ (rmInst->instType == Rm_instType_SHARED_CLIENT)){\r
+ *result = RM_ERROR_SHARED_INSTANCE_CANNOT_REG_TRANS;\r
+ goto errorExit;\r
}\r
\r
- /* Set the Rm Packet type */ \r
- rmPkt->pktType = Rm_pktType_NAMESERVER_REQUEST;\r
- \r
- /* Assign the packet's data field to be the start of the NameServer request packet */\r
- nsReqPkt = (Rm_NsRequestPkt *)rmPkt->data;\r
- /* Populate the NameServer request packet using the transaction information */\r
- nsReqPkt->requestId = transaction->id;\r
- if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME)\r
- {\r
- nsReqPkt->nsRequestType = Rm_nsReqPktType_MAP_RESOURCE;\r
- }\r
- else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME)\r
- {\r
- nsReqPkt->nsRequestType = Rm_nsReqPktType_UNMAP_RESOURCE;\r
+ /* No one can connect to a shared server\r
+ * RM Servers cannot connect to other Servers. \r
+ * RM Client Delegates cannot connect to other Client Delegates.\r
+ * RM Clients cannot connect to other Clients */\r
+ if ((transportCfg->remoteInstType == Rm_instType_SHARED_SERVER) ||\r
+ ((rmInst->instType == Rm_instType_SERVER) &&\r
+ (transportCfg->remoteInstType == Rm_instType_SERVER)) ||\r
+ ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
+ (transportCfg->remoteInstType == Rm_instType_CLIENT_DELEGATE)) ||\r
+ ((rmInst->instType == Rm_instType_CLIENT) &&\r
+ (transportCfg->remoteInstType == Rm_instType_CLIENT))) {\r
+ *result = RM_ERROR_INVALID_REMOTE_INST_TYPE;\r
+ goto errorExit;\r
+ }\r
+\r
+ /* Verify Clients are not registering with more than one Client Delegate or Server. And\r
+ * that Client Delegate is not registering with more than one Server. */\r
+ if (rmInst->registeredWithDelegateOrServer &&\r
+ (((rmInst->instType == Rm_instType_CLIENT) &&\r
+ (transportCfg->remoteInstType == Rm_instType_CLIENT_DELEGATE)) || \r
+ ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
+ (transportCfg->remoteInstType == Rm_instType_SERVER)))) {\r
+ *result = RM_ERROR_ALREADY_REGD_SERVER_OR_CD;\r
+ goto errorExit;\r
+ } \r
+ \r
+ if (!transportCfg->transportCallouts.rmAllocPkt) {\r
+ *result = RM_ERROR_TRANSPORT_ALLOC_PKT_NOT_REGD;\r
+ goto errorExit;\r
}\r
- strcpy(&(nsReqPkt->instName)[0], rmInst->name);\r
- /* Copy the NameServer request data */\r
- memcpy ((void *)&(nsReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),\r
- sizeof(Rm_ResourceInfo));\r
-\r
- return (rmPkt);\r
-}\r
-\r
-Rm_Packet *Rm_transportCreateNsResponsePkt(Rm_Inst *rmInst, Rm_TransportNode *dstTransportNode,\r
- Rm_Transaction *transaction, Rm_TransactionReceipt *receipt)\r
-{\r
- Rm_Packet *rmPkt = NULL;\r
- Rm_NsResponsePkt *nsRespPkt = NULL;\r
-\r
- /* Make sure a buffer for the packet was allocated */\r
- if ((rmPkt = rmInst->transport.rmAllocPkt((Rm_TransportHandle)dstTransportNode, sizeof(Rm_Packet))) ==\r
- NULL)\r
- {\r
- receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_ALLOC_PKT_ERROR;\r
- return (NULL);\r
+ else if (!transportCfg->transportCallouts.rmSendPkt) {\r
+ *result = RM_ERROR_TRANSPORT_SEND_NOT_REGD;\r
+ goto errorExit;\r
}\r
\r
- /* Make sure allocated buffer is large enough to fit the response packet plus the \r
- * rmPktLen and Rm_PktType fields */\r
- if (rmPkt->pktLenBytes < (sizeof(Rm_NsResponsePkt) + sizeof(uint32_t) + sizeof(Rm_pktType)))\r
- { \r
- receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_PKT_BUF_TOO_SMALL;\r
- return (NULL);\r
+ transport = transportAdd(transportCfg);\r
+ if ((transport->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||\r
+ (transport->remoteInstType == Rm_instType_SERVER)) {\r
+ rmInst->registeredWithDelegateOrServer = RM_TRUE;\r
}\r
-\r
- /* Set the Rm Packet type */ \r
- rmPkt->pktType = Rm_pktType_NAMESERVER_RESPONSE;\r
- \r
- /* Assign the packet's data field to be the start of the NameServer response packet */\r
- nsRespPkt = (Rm_NsResponsePkt *)rmPkt->data;\r
- /* Populate the NameServer response packet using the transaction information */\r
- nsRespPkt->responseId = transaction->id;\r
- nsRespPkt->requestResult = transaction->details;\r
-\r
- return (rmPkt);\r
+errorExit:\r
+ RM_SS_INST_WB_EXIT_CS(key); \r
+ return ((Rm_TransportHandle) transport);\r
}\r
\r
-/**********************************************************************\r
- ********************* Application visible APIs ***********************\r
- **********************************************************************/\r
-\r
-Rm_TransportHandle Rm_transportRegister (Rm_Handle rmHandle, Rm_TransportCfg *transportCfg)\r
+/* FUNCTION PURPOSE: Reconfigures an instance's transport handle\r
+ ***********************************************************************\r
+ * DESCRIPTION: Reconfigures a transport handle based on the provided\r
+ * configuration parameters if it exists within the \r
+ * instance.\r
+ */\r
+int32_t Rm_transportReconfig (Rm_TransportHandle transportHandle, const Rm_TransportReCfg *reCfg)\r
{\r
- Rm_Inst *rmInst = (Rm_Inst *) rmHandle;\r
- Rm_TransportNode *transportNode = NULL;\r
- void *key;\r
+ Rm_Transport *transport = (Rm_Transport *)transportHandle;\r
+ Rm_Inst *rmInst = (Rm_Inst *)transport->rmHandle;\r
+ void *key;\r
+ int32_t retVal = RM_OK;\r
\r
- /* Lock access to the RM instance */\r
- key = Rm_osalLocalCsEnter();\r
+ RM_SS_INST_INV_ENTER_CS(key);\r
\r
- /* RM Servers cannot connect to other Servers. RM Client Delegates cannot\r
- * connect to other Client Delegates. */\r
- if (((rmInst->instType == Rm_instType_SERVER) &&\r
- (transportCfg->remoteInstType == Rm_instType_SERVER)) ||\r
- ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
- (transportCfg->remoteInstType == Rm_instType_CLIENT_DELEGATE)))\r
- {\r
- Rm_osalLocalCsExit(key);\r
- return (NULL); /* Error - return null */\r
- }\r
+ if (transportIsRegistered(transport->rmHandle, transport)) {\r
+ /* Reconfigure existing transport's appTransportHandle. Used in cases where instances\r
+ * running on same core connected by function call. */\r
+ transport->appTransportHandle = reCfg->appTransportHandle;\r
\r
- /* Verify Clients and Client Delegates are not registering with more than one \r
- * Client Delegate or Server. Assuming a Client Delegate can register with another \r
- * Client Delegate that can "act" as a server */\r
- if (((rmInst->instType == Rm_instType_CLIENT) &&\r
- (transportCfg->remoteInstType == Rm_instType_CLIENT_DELEGATE)) || \r
- ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
- (transportCfg->remoteInstType == Rm_instType_SERVER)) &&\r
- rmInst->registeredWithDelegateOrServer)\r
- {\r
- Rm_osalLocalCsExit(key);\r
- return (NULL); /* Error - return null */\r
- } \r
-\r
- /* Copy the transport callout function pointers into the RM instance as long as they're\r
- * valid or not NULL */\r
- if (transportCfg->transportCalloutsValid)\r
- {\r
- /* The transport APIs must not be NULL */\r
- if ((transportCfg->transportCallouts.rmAllocPkt == NULL) ||\r
- (transportCfg->transportCallouts.rmFreePkt == NULL) ||\r
- (transportCfg->transportCallouts.rmSend == NULL) ||\r
- (transportCfg->transportCallouts.rmReceive == NULL) ||\r
- (transportCfg->transportCallouts.rmNumPktsReceived == NULL))\r
- {\r
- Rm_osalLocalCsExit(key);\r
- return (NULL); /* Error - return null */\r
+ if (reCfg->transportCallouts.rmAllocPkt) {\r
+ transport->callouts.rmAllocPkt = reCfg->transportCallouts.rmAllocPkt;\r
+ }\r
+ if (reCfg->transportCallouts.rmSendPkt) {\r
+ transport->callouts.rmSendPkt = reCfg->transportCallouts.rmSendPkt;\r
}\r
- \r
- /* Populate the instance transport callouts */\r
- rmInst->transport.rmAllocPkt = transportCfg->transportCallouts.rmAllocPkt;\r
- rmInst->transport.rmFreePkt = transportCfg->transportCallouts.rmFreePkt;\r
- rmInst->transport.rmSend = transportCfg->transportCallouts.rmSend;\r
- rmInst->transport.rmReceive = transportCfg->transportCallouts.rmReceive;\r
- rmInst->transport.rmNumPktsReceived = transportCfg->transportCallouts.rmNumPktsReceived;\r
- }\r
-\r
- /* Error checks passed - Create a new transport handle for the specified RM instance and\r
- * create a new node in the RM instance's routing map. */\r
- transportNode = Rm_transportNodeAdd(rmInst, transportCfg);\r
-\r
- /* Specify RM instance has registered with a higher level agent */\r
- if ((transportNode->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||\r
- (transportNode->remoteInstType == Rm_instType_SERVER))\r
- {\r
- rmInst->registeredWithDelegateOrServer = true;\r
}\r
+ else {\r
+ retVal = RM_ERROR_TRANSPORT_HANDLE_DOES_NOT_EXIST;\r
+ } \r
\r
- Rm_osalLocalCsExit(key);\r
- return ((Rm_TransportHandle) transportNode);\r
+ RM_SS_INST_WB_EXIT_CS(key); \r
+ return (retVal);\r
}\r
\r
-Rm_TransportResult Rm_transportUnregister (Rm_Handle rmHandle, Rm_TransportHandle transportHandle)\r
+/* FUNCTION PURPOSE: Unregisters an app transport from a RM instance\r
+ ***********************************************************************\r
+ * DESCRIPTION: Deletes a registered transport from the transport\r
+ * list and cleans up the memory associated with the\r
+ * transport data structure.\r
+ */\r
+int32_t Rm_transportUnregister(Rm_TransportHandle transportHandle)\r
{\r
- Rm_Inst *rmInst = (Rm_Inst *) rmHandle;\r
- Rm_TransportNode *transportNode = NULL;\r
- Rm_TransportResult retVal = RM_TRANSPORT_SUCCESSFUL;\r
- void *key;\r
-\r
- /* Lock access to the RM instance */\r
- key = Rm_osalLocalCsEnter(); \r
-\r
- /* Check if the transportHandle exists in the RM instance's route map */\r
- transportNode = Rm_transportNodeFindTransportHandle(rmInst, transportHandle);\r
-\r
- if (transportNode == NULL)\r
- {\r
- /* Error - transport node does not exist in RM instance route map */\r
- Rm_osalLocalCsExit(key);\r
- return (RM_TRANSPORT_ERROR_HANDLE_HAS_NOT_BEEN_REGISTERED);\r
+ Rm_Transport *transport = (Rm_Transport *)transportHandle;\r
+ Rm_Inst *rmInst = (Rm_Inst *)transport->rmHandle;\r
+ int32_t retVal = RM_OK;\r
+\r
+ if (transportIsRegistered(transport->rmHandle, transport)) {\r
+ if ((transport->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||\r
+ (transport->remoteInstType == Rm_instType_SERVER)) {\r
+ rmInst->registeredWithDelegateOrServer = RM_FALSE;\r
+ }\r
+ transportDelete(transport);\r
}\r
-\r
- /* Remove specification that RM instance has been connected to an upper level agent\r
- * if the node to be deleted has a remote instance type of Client Delegate or Server */\r
- if ((transportNode->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||\r
- (transportNode->remoteInstType == Rm_instType_SERVER))\r
- {\r
- rmInst->registeredWithDelegateOrServer = false;\r
+ else {\r
+ retVal = RM_ERROR_TRANSPORT_HANDLE_DOES_NOT_EXIST;\r
}\r
-\r
- /* Delete the transport node */\r
- retVal = Rm_transportNodeDelete(rmInst, transportHandle);\r
-\r
- Rm_osalLocalCsExit(key);\r
-\r
return (retVal);\r
}\r
\r
-/* Used by the application to pass RM packets received from a transport to RM.\r
- * CODE THE FUNCTION SUCH THAT IT CAN BE CALLED DIRECTLY BY APP OR BE PLUGGED\r
- * AS PART OF AN ISR HANDLER FOR THE TRANSACTION RECEIVE */\r
-int32_t Rm_receivePktIsr(Rm_Handle rmHandle, Rm_TransportHandle transportHandle, Rm_Packet *pkt)\r
+/* FUNCTION PURPOSE: Receives RM packets\r
+ ***********************************************************************\r
+ * DESCRIPTION: The application provides RM packets received on the\r
+ * application transports to RM via this API. Function\r
+ * can be called from polling or ISR contexts. Assume \r
+ * invoking application will free packet after this\r
+ * function returns.\r
+ */\r
+int32_t Rm_receivePacket(Rm_TransportHandle transportHandle, const Rm_Packet *pkt)\r
{\r\r\r
- Rm_Inst *rmInst = (Rm_Inst *)rmHandle;\r
+ Rm_Transport *transport = (Rm_Transport *)transportHandle;\r
+ Rm_Inst *rmInst = (Rm_Inst *)transport->rmHandle;\r
Rm_Transaction *transaction;\r
- Rm_TransactionReceipt receipt;\r
-\r
- /* Make sure the transport handle is registered with the provided RM instance */\r
- if (Rm_transportNodeFindTransportHandle(rmInst, transportHandle) == NULL)\r
- {\r
- /* Transport is not registered with the RM instance. Return an error.\r
- * The packet cannot be freed since the transport handle is not valid. */\r
- return (RM_TRANSPORT_ERROR_HANDLE_HAS_NOT_BEEN_REGISTERED);\r
- }\r
+ int32_t retVal = RM_OK;\r
\r
- /* Clear the transaction receipt */\r
- memset((void *)&receipt, 0, sizeof(Rm_TransactionReceipt));\r
+ if (!transportIsRegistered(transport->rmHandle, transport)) {\r
+ retVal = RM_ERROR_TRANSPORT_HANDLE_DOES_NOT_EXIST;\r
+ goto errorExit;\r
+ }\r
\r
- /* Based on packet type transfer the data to a transaction or a policy structure */\r
- switch (pkt->pktType)\r
- {\r
+ switch (pkt->pktType) {\r
case Rm_pktType_RESOURCE_REQUEST:\r
{\r
Rm_ResourceRequestPkt *resourceReqPkt = (Rm_ResourceRequestPkt *)pkt->data;\r
\r
- /* The transaction ID will be the request ID. The request ID\r
- * will become the response packet's ID so the requesting RM instance\r
- * can filter received resource responses */\r
- transaction = Rm_transactionQueueAdd(rmInst, resourceReqPkt->requestId);\r
-\r
- /* Transfer the rest of the data into the transaction */\r
- if (resourceReqPkt->resourceReqType == Rm_resReqPktType_ALLOCATE)\r
- {\r
- transaction->type = Rm_service_RESOURCE_ALLOCATE;\r
+ transaction = rmTransactionQueueAdd(rmInst);\r
+ transaction->remoteOriginatingId = resourceReqPkt->requestId;\r
+ transaction->u.respTrans = transport;\r
+ if (resourceReqPkt->resourceReqType == Rm_resReqPktType_ALLOCATE_INIT) {\r
+ transaction->type = Rm_service_RESOURCE_ALLOCATE_INIT;\r
}\r
- else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_BLOCK_ALLOCATE)\r
- {\r
- transaction->type = Rm_service_RESOURCE_BLOCK_ALLOCATE;\r
+ else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_ALLOCATE_USE) {\r
+ transaction->type = Rm_service_RESOURCE_ALLOCATE_USE;\r
}\r
- else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_ALLOCATE_NAMED)\r
- {\r
- transaction->type = Rm_service_RESOURCE_ALLOCATE_BY_NAME;\r
+ else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_GET_STATUS) {\r
+ transaction->type = Rm_service_RESOURCE_STATUS;\r
}\r
- else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_FREE)\r
- {\r
+ else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_FREE) {\r
transaction->type = Rm_service_RESOURCE_FREE;\r
}\r
- else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_BLOCK_FREE)\r
- {\r
- transaction->type = Rm_service_RESOURCE_BLOCK_FREE;\r
- }\r
- else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_FREE_NAMED)\r
- {\r
- transaction->type = Rm_service_RESOURCE_FREE_BY_NAME;\r
- }\r
-\r
- strcpy(transaction->sourceInstName, resourceReqPkt->instName);\r
- transaction->state = Rm_transactionState_PROCESSING;\r
+ else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_GET_NAMED) {\r
+ transaction->type = Rm_service_RESOURCE_GET_BY_NAME;\r
+ } \r
+ strncpy(transaction->serviceSrcInstName, resourceReqPkt->serviceSrcInstName, RM_NAME_MAX_CHARS);\r
+ transaction->state = RM_SERVICE_PROCESSING;\r
memcpy ((void *)&(transaction->resourceInfo), (void *)&(resourceReqPkt->resourceInfo),\r
sizeof(Rm_ResourceInfo));\r
-\r
- /* Process the transaction */\r
- Rm_transactionProcessor(rmInst, transaction, &receipt);\r
break;\r
}\r
case Rm_pktType_RESOURCE_RESPONSE:\r
{\r
Rm_ResourceResponsePkt *resourceRespPkt = (Rm_ResourceResponsePkt *)pkt->data;\r
\r
- /* If the packet is a response packet the transaction ID should match a queued \r
- * request transaction's ID */\r
- transaction = Rm_transactionQueueAdd(rmInst, resourceRespPkt->responseId);\r
-\r
- if (resourceRespPkt->requestResult == RM_SERVICE_APPROVED)\r
- {\r
- transaction->state = Rm_transactionState_RESOURCE_APPROVED;\r
+ if (transaction = rmTransactionQueueFind(rmInst,resourceRespPkt->responseId)) {\r
+ if ((transaction->state == RM_SERVICE_APPROVED_STATIC) &&\r
+ (resourceRespPkt->requestState != RM_SERVICE_APPROVED)) {\r
+ /* Lock the RM instance since service validated against static policy failed against \r
+ * Server's global policy */\r
+ rmInst->isLocked = RM_TRUE;\r
+ }\r
+ transaction->state = resourceRespPkt->requestState;\r
+\r
+ if ((transaction->state == RM_SERVICE_APPROVED) &&\r
+ ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||\r
+ (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||\r
+ (transaction->type == Rm_service_RESOURCE_STATUS) ||\r
+ (transaction->type == Rm_service_RESOURCE_GET_BY_NAME))) {\r
+ memcpy ((void *)&(transaction->resourceInfo), (void *)&(resourceRespPkt->resourceInfo),\r
+ sizeof(Rm_ResourceInfo));\r
+ }\r
+ else {\r
+ /* Always copy owner count and instance allocation count */\r
+ transaction->resourceInfo.ownerCount = resourceRespPkt->resourceInfo.ownerCount;\r
+ transaction->resourceInfo.instAllocCount = resourceRespPkt->resourceInfo.instAllocCount;\r
+ }\r
+ }\r
+ else {\r
+ retVal = RM_ERROR_PKT_RESP_DOES_NOT_MATCH_ANY_REQ;\r
+ goto errorExit;\r
}\r
- else if ((resourceRespPkt->requestResult >= RM_SERVICE_DENIED_BEGIN) &&\r
- (resourceRespPkt->requestResult <= RM_SERVICE_DENIED_END))\r
- {\r
- transaction->state = Rm_transactionState_RESOURCE_DENIED;\r
- } \r
- /* The result of the request should be placed in the details field of the \r
- * response transaction */\r
- transaction->details = resourceRespPkt->requestResult;\r
- memcpy ((void *)&(transaction->resourceInfo), (void *)&(resourceRespPkt->resourceInfo),\r
- sizeof(Rm_ResourceInfo));\r
- \r
- /* Process the transaction */\r
- Rm_transactionProcessor(rmInst, transaction, &receipt);\r
break;\r
}\r
case Rm_pktType_NAMESERVER_REQUEST:\r
{\r
Rm_NsRequestPkt *nsRequestPkt = (Rm_NsRequestPkt *)pkt->data;\r
\r
- transaction = Rm_transactionQueueAdd(rmInst, nsRequestPkt->requestId);\r
+ transaction = rmTransactionQueueAdd(rmInst);\r
+ transaction->remoteOriginatingId = nsRequestPkt->requestId;\r
+ transaction->u.respTrans = transport;\r
\r
- if (nsRequestPkt->nsRequestType == Rm_nsReqPktType_MAP_RESOURCE)\r
- {\r
+ if (nsRequestPkt->nsRequestType == Rm_nsReqPktType_MAP_RESOURCE) {\r
transaction->type = Rm_service_RESOURCE_MAP_TO_NAME;\r
}\r
- else if (nsRequestPkt->nsRequestType == Rm_nsReqPktType_UNMAP_RESOURCE)\r
- {\r
+ else if (nsRequestPkt->nsRequestType == Rm_nsReqPktType_UNMAP_RESOURCE) {\r
transaction->type = Rm_service_RESOURCE_UNMAP_NAME;\r
}\r
\r
- strcpy(transaction->sourceInstName, nsRequestPkt->instName);\r
- transaction->state = Rm_transactionState_PROCESSING;\r
+ strncpy(transaction->serviceSrcInstName, nsRequestPkt->serviceSrcInstName, RM_NAME_MAX_CHARS);\r
+ transaction->state = RM_SERVICE_PROCESSING;\r
memcpy ((void *)&(transaction->resourceInfo), (void *)&(nsRequestPkt->resourceInfo),\r
- sizeof(Rm_ResourceInfo));\r
-\r
- /* Process the transaction */\r
- Rm_transactionProcessor(rmInst, transaction, &receipt); \r
+ sizeof(Rm_ResourceInfo)); \r
break;\r
}\r
case Rm_pktType_NAMESERVER_RESPONSE:\r
{\r
Rm_NsResponsePkt *nsResponsePkt = (Rm_NsResponsePkt *)pkt->data;\r
\r
- transaction = Rm_transactionQueueAdd(rmInst, nsResponsePkt->responseId);\r
- transaction->details = nsResponsePkt->requestResult;\r
-\r
- if (nsResponsePkt->requestResult == RM_SERVICE_APPROVED)\r
- {\r
- transaction->state = Rm_transactionState_RESOURCE_APPROVED;\r
+ if (transaction = rmTransactionQueueFind(rmInst, nsResponsePkt->responseId)) {\r
+ if ((transaction->state == RM_SERVICE_APPROVED_STATIC) &&\r
+ (nsResponsePkt->requestState != RM_SERVICE_APPROVED)) {\r
+ /* Lock the RM instance since service validated against static policy failed against \r
+ * Server's global policy */ \r
+ rmInst->isLocked = RM_TRUE;\r
+ } \r
+ transaction->state = nsResponsePkt->requestState; \r
}\r
- else if ((nsResponsePkt->requestResult >= RM_SERVICE_DENIED_BEGIN) &&\r
- (nsResponsePkt->requestResult <= RM_SERVICE_DENIED_END))\r
- {\r
- transaction->state = Rm_transactionState_RESOURCE_DENIED;\r
+ else {\r
+ retVal = RM_ERROR_PKT_RESP_DOES_NOT_MATCH_ANY_REQ;\r
+ goto errorExit;\r
}\r
-\r
- /* Process the transaction */\r
- Rm_transactionProcessor(rmInst, transaction, &receipt);\r
- break;\r
- }\r
- case Rm_pktType_POLICY_REQUEST:\r
- {\r
- Rm_PolicyRequestPkt *policyRequestPkt = (Rm_PolicyRequestPkt *)pkt->data;\r
-\r
- /* FILL IN POLICY API INFORMATION */\r
- break; \r
- }\r
- case Rm_pktType_POLICY_CHANGE:\r
- {\r
- Rm_PolicyChangePkt *policyChangePkt = (Rm_PolicyChangePkt *)pkt->data;\r
-\r
- /* FILL IN POLICY API INFORMATION */\r
- break;\r
- }\r
- case Rm_pktType_RESOURCE_POOL_MODIFICATION_REQUEST:\r
- {\r
- Rm_ResourcePoolModRequestPkt *resPoolModReqPkt = (Rm_ResourcePoolModRequestPkt *)pkt->data;\r
-\r
- /* FILL IN RESOURCE POOL MODIFICATION API */\r
- /* Rm_resourcePoolModRequestHandler(...); Server only - needs to allocate resources to\r
- * the Client Delegate based on the policy and return those resources to the Client Delegate */\r
- break;\r
- }\r
- case Rm_pktType_RESOURCE_POOL_MODIFICATION_RESPONSE:\r
- {\r
- Rm_ResourcePoolModResponsePkt *resPoolModRespPkt = (Rm_ResourcePoolModResponsePkt *)pkt->data;\r
-\r
- /* FILL IN RESOURCE POOL MODIFICAITON API */\r
- /* Rm_resourcePoolModResponseHandler(...); Handler needs to populate allocator with\r
- * new resources provided in the response and then handle any request transactions waiting on\r
- * the resource pool modification */\r
break;\r
}\r
default:\r
- /* Invalid packet type. Free the packet and return */\r
- rmInst->transport.rmFreePkt(transportHandle, pkt);\r
- return (RM_TRANSPORT_ERROR_INVALID_PACKET_TYPE);\r
- }\r
-\r
- /* Free the packet after it has been processed */\r
- rmInst->transport.rmFreePkt(transportHandle, pkt);\r
-\r
- /* Return the receipt's service result which contains the result return code\r
- * for the receive packet */\r
- return (receipt.serviceResult);\r
-}\r
-\r
-/* Application can call this API so that RM handles reception of packets based on\r
- * the RM handle and transport handle provided */\r
-int32_t Rm_receivePktPolling(Rm_Handle rmHandle, Rm_TransportHandle transportHandle)\r
-{\r
- Rm_Inst *rmInst = (Rm_Inst *)rmHandle;\r
- Rm_Packet *pkt = NULL;\r
- int32_t retVal = RM_SERVICE_ACTION_BASE;\r
-\r
- /* Make sure the transport handle is registered with the provided RM instance */\r
- if (Rm_transportNodeFindTransportHandle(rmInst, transportHandle) == NULL)\r
- {\r
- /* Transport is not registered with the RM instance. Return an error.\r
- * The packet cannot be freed since the transport handle is not valid. */\r
- return (RM_TRANSPORT_ERROR_HANDLE_HAS_NOT_BEEN_REGISTERED);\r
+ retVal = RM_ERROR_RECEIVED_INVALID_PACKET_TYPE;\r
+ goto errorExit;\r
}\r
\r
- /* Check to see if any RM packets are available. Process any available packets. */\r
- while (rmInst->transport.rmNumPktsReceived(transportHandle))\r
- {\r
- pkt = rmInst->transport.rmReceive(transportHandle);\r
-\r
- if (pkt == NULL)\r
- {\r
- return (RM_TRANSPORT_ERROR_PACKET_RECEPTION_ERROR);\r
- }\r
-\r
- /* Pass the packet to RM. The packet will be freed within the PktIsr API */\r
- if (retVal = Rm_receivePktIsr(rmHandle, transportHandle, pkt) <= RM_SERVICE_ERROR_BASE)\r
- {\r
- /* Return if an error is encountered */\r
- return (retVal);\r
- }\r
- }\r
- return (retVal); \r
+ /* Process received transaction */\r
+ rmProcessRouter(rmInst, transaction); \r
+errorExit:\r
+ return(retVal);\r
}\r
\r
-/**\r
-@}\r
-*/\r