Coded basic unit test to test RM infrastructure
[keystone-rtos/rm-lld.git] / src / rm_transport.c
1 /**\r
2  *   @file  rm.c\r
3  *\r
4  *   @brief   \r
5  *      This is the Resource Manager source.\r
6  *\r
7  *  \par\r
8  *  ============================================================================\r
9  *  @n   (C) Copyright 2012, Texas Instruments, Inc.\r
10  * \r
11  *  Redistribution and use in source and binary forms, with or without \r
12  *  modification, are permitted provided that the following conditions \r
13  *  are met:\r
14  *\r
15  *    Redistributions of source code must retain the above copyright \r
16  *    notice, this list of conditions and the following disclaimer.\r
17  *\r
18  *    Redistributions in binary form must reproduce the above copyright\r
19  *    notice, this list of conditions and the following disclaimer in the \r
20  *    documentation and/or other materials provided with the   \r
21  *    distribution.\r
22  *\r
23  *    Neither the name of Texas Instruments Incorporated nor the names of\r
24  *    its contributors may be used to endorse or promote products derived\r
25  *    from this software without specific prior written permission.\r
26  *\r
27  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
28  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
29  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
30  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT \r
31  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \r
32  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \r
33  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
34  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
35  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
36  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE \r
37  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
38  *\r
39  *  \par\r
40 */\r
41 \r
42 /* RM Types */\r
43 #include <ti/drv/rm/rm_types.h>\r
44 \r
45 /* RM external includes */\r
46 #include <ti/drv/rm/rm.h>\r
47 #include <ti/drv/rm/rm_transport.h>\r
48 \r
49 /* RM internal includes */\r
50 #include <ti/drv/rm/include/rm_loc.h>\r
51 #include <ti/drv/rm/include/rm_transportloc.h>\r
52 \r
53 /* RM OSAL layer */\r
54 #include <rm_osal.h>\r
55 \r
56 /**********************************************************************\r
57  ********************** Internal Functions ****************************\r
58  **********************************************************************/\r
59 \r
60 Rm_TransportNode *Rm_transportNodeAdd(Rm_Inst *rmInst, Rm_TransportCfg *transportCfg)\r
61 {\r
62     Rm_TransportNode *routeMap = (Rm_TransportNode *)rmInst->routeMap;\r
63     Rm_TransportNode *newTransportNode = NULL;\r
64     void *key;\r
65 \r
66     /* Lock access to the RM instance's route map */\r
67     key = Rm_osalCsEnter();\r
68 \r
69     /* Get memory for a new transport node from local memory */\r
70     newTransportNode = Rm_osalMalloc (sizeof(Rm_TransportNode), false);\r
71 \r
72     /* Return if the memory allocated for the transport node is NULL */\r
73     if (newTransportNode != NULL)\r
74     {\r
75         /* Populate the new entry */\r
76         newTransportNode->rmHandle = (Rm_Handle) rmInst;\r
77         newTransportNode->remoteInstType = transportCfg->remoteInstType;\r
78         strcpy(&(newTransportNode->remoteInstName)[0], transportCfg->remoteInstName);\r
79         newTransportNode->nextNode = NULL;  /* New node will always be NULL */\r
80 \r
81         /* Check if there are any nodes in the transport routing map */\r
82         if (routeMap)\r
83         {\r
84             /* At least one node in the routing map.  Add the new node to the end of the\r
85              * routing map */\r
86             while (routeMap->nextNode != NULL)\r
87             {\r
88                 /* Traverse the list until arriving at the last node */\r
89                 routeMap = (Rm_TransportNode *)routeMap->nextNode;\r
90             }\r
91 \r
92             /* Add the new node to the end of the list */\r
93             routeMap->nextNode = (void *)newTransportNode;\r
94         }\r
95         else\r
96         {\r
97             /* The transport routing map does not currently exist.  The new node is the first node */\r
98             rmInst->routeMap = (void *)newTransportNode;\r
99         }\r
100     }\r
101    \r
102     Rm_osalCsExit(key);\r
103 \r
104     return (newTransportNode);\r
105 }\r
106 \r
107 Rm_TransportNode *Rm_transportNodeFindTransportHandle(Rm_Inst *rmInst, \r
108                                                       Rm_TransportHandle transportHandle)\r
109 {\r
110     Rm_TransportNode *transportNode = (Rm_TransportNode *)rmInst->routeMap;\r
111 \r
112     /* Make sure there is at least one node in the route map */\r
113     if (transportNode != NULL)\r
114     {\r
115         /* Find the transport node with the transport handle within the RM instance's\r
116          * route map.  If the end of the route map is reached without finding the node the \r
117          * node pointer will be NULL */\r
118         while (transportNode != NULL)\r
119         {\r
120             /* The transport handle is the address of the transport node */\r
121             if (transportNode == ((Rm_TransportNode *)transportHandle))\r
122             {\r
123                 /* Match: break out of loop and return the node */\r
124                 break;             \r
125             }\r
126             transportNode = (Rm_TransportNode *)transportNode->nextNode;\r
127         }\r
128     }\r
129 \r
130     return (transportNode);\r
131 }\r
132 \r
133 Rm_TransportNode *Rm_transportNodeFindRemoteName(Rm_Inst *rmInst, char *remoteName)\r
134 {\r
135     Rm_TransportNode *transportNode = (Rm_TransportNode *)rmInst->routeMap;\r
136 \r
137     /* Make sure there is at least one node in the route map */\r
138     if (transportNode != NULL)\r
139     {\r
140         /* Find the transport node with the provided remote instance name.\r
141          * If the end of the route map is reached without finding the node the \r
142          * node pointer will be NULL */\r
143         while (transportNode != NULL)\r
144         {\r
145             /* The transport handle is the address of the transport node */\r
146             if (strcmp(&(transportNode->remoteInstName)[0], remoteName) == 0)\r
147             {\r
148                 /* Match: break out of loop and return the node */\r
149                 break;             \r
150             }\r
151             transportNode = (Rm_TransportNode *)transportNode->nextNode;\r
152         }\r
153     }\r
154 \r
155     return (transportNode);\r
156 }\r
157 \r
158 Rm_TransportNode *Rm_transportNodeFindRemoteInstType(Rm_Inst *rmInst,\r
159                                                      Rm_InstType remoteInstType)\r
160 {\r
161     Rm_TransportNode *transportNode = (Rm_TransportNode *)rmInst->routeMap;\r
162 \r
163     /* Make sure there is at least one node in the route map */\r
164     if (transportNode != NULL)\r
165     {\r
166         /* Find the transport node with the provided remote instance type.\r
167          * If the end of the route map is reached without finding the node the \r
168          * node pointer will be NULL */\r
169         while (transportNode != NULL)\r
170         {\r
171             if (transportNode->remoteInstType == remoteInstType)\r
172             {\r
173                 /* Match: break out of loop and return the node */\r
174                 break;             \r
175             }\r
176             transportNode = (Rm_TransportNode *)transportNode->nextNode;\r
177         }\r
178     }\r
179 \r
180     return (transportNode);\r
181 }\r
182 \r
183 Rm_TransportResult Rm_transportNodeDelete(Rm_Inst *rmInst, Rm_TransportHandle transportHandle)\r
184 {\r
185     Rm_TransportNode *transportNode = (Rm_TransportNode *)rmInst->routeMap;\r
186     Rm_TransportNode *prevNode = NULL;\r
187     void *key;\r
188 \r
189     /* Lock access to the RM instance's route map */\r
190     key = Rm_osalCsEnter();\r
191 \r
192     /* Make sure there is at least one entry in the transaction queue */\r
193     if (transportNode == NULL)\r
194     {\r
195         Rm_osalCsExit(key);\r
196         return (RM_TRANSPORT_ERROR_NO_TRANSPORTS_REGISTERED);\r
197     }\r
198 \r
199     /* Find the transport handle within the RM instance's route map. */\r
200     while (transportNode != NULL)\r
201     {\r
202         if (transportNode == (Rm_TransportNode *) transportHandle)\r
203         {\r
204             /* Match: break out of loop and delete the entry */\r
205             break;             \r
206         }\r
207 \r
208         prevNode = transportNode;\r
209         transportNode = (Rm_TransportNode *)transportNode->nextNode;\r
210     }\r
211 \r
212     /* Traversed entire queue but did not find transaction */\r
213     if (transportNode == NULL)\r
214     {\r
215         Rm_osalCsExit(key);\r
216         return (RM_TRANSPORT_ERROR_HANDLE_HAS_NOT_BEEN_REGISTERED);\r
217     }\r
218     else\r
219     {\r
220         /* Delete the transport node */\r
221         if ((prevNode == NULL) && transportNode->nextNode)\r
222         {\r
223             /* Node to be deleted exists at start of route map.  Map second\r
224              * node to be start of route map as long as there are more than\r
225              * one nodes */\r
226             rmInst->routeMap = transportNode->nextNode;\r
227         }\r
228         else\r
229         {\r
230             /* Node to be deleted is in the middle or at end of the route map.  Adjust adjacent\r
231              * node pointers.  This covers the case where the node to be removed is at the\r
232              * end of the route map. */\r
233             prevNode->nextNode = transportNode->nextNode;\r
234         }\r
235 \r
236         /* Free the memory associated with the node. */\r
237         Rm_osalFree((void *) transportNode, sizeof(Rm_TransportNode), false);\r
238     }\r
239 \r
240     Rm_osalCsExit(key);\r
241     return (RM_TRANSPORT_SUCCESSFUL);\r
242 }\r
243 \r
244 Rm_Packet *Rm_transportCreateResourceReqPkt(Rm_Inst *rmInst, Rm_TransportNode *dstTransportNode,\r
245                                             Rm_Transaction *transaction, Rm_TransactionReceipt *receipt)\r
246 {\r
247     Rm_Packet *rmPkt = NULL;\r
248     Rm_ResourceRequestPkt *resourceReqPkt = NULL;\r
249 \r
250     /* Make sure a buffer for the packet was allocated  */\r
251     if ((rmPkt = rmInst->transport.rmAllocPkt((Rm_TransportHandle)dstTransportNode, sizeof(Rm_Packet))) ==\r
252         NULL)\r
253     {\r
254         receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_ALLOC_PKT_ERROR;\r
255         return (NULL);\r
256     }\r
257 \r
258     /* Make sure allocated buffer is large enough to fit the request packet plus the \r
259      * rmPktLen and Rm_PktType fields */\r
260     if (rmPkt->pktLenBytes < (sizeof(Rm_ResourceRequestPkt) + sizeof(uint32_t) + sizeof(Rm_pktType)))\r
261     {   \r
262         receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_PKT_BUF_TOO_SMALL;\r
263         return (NULL);\r
264     }\r
265 \r
266     /* Set the Rm Packet type */    \r
267     rmPkt->pktType = Rm_pktType_RESOURCE_REQUEST;\r
268                           \r
269     /* Assign the packet's data field to be the start of the resource request packet */\r
270     resourceReqPkt = (Rm_ResourceRequestPkt *) rmPkt->data;\r
271     /* Populate the resource request packet using the transaction information */\r
272     resourceReqPkt->requestId = transaction->id;\r
273     if (transaction->type == Rm_service_RESOURCE_ALLOCATE)\r
274     {\r
275         resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE;\r
276     }\r
277     else if (transaction->type == Rm_service_RESOURCE_BLOCK_ALLOCATE)\r
278     {\r
279         resourceReqPkt->resourceReqType = Rm_resReqPktType_BLOCK_ALLOCATE;\r
280     }\r
281     else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_BY_NAME)\r
282     {\r
283         resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE_NAMED;\r
284     }\r
285     else if (transaction->type == Rm_service_RESOURCE_FREE)\r
286     {\r
287         resourceReqPkt->resourceReqType = Rm_resReqPktType_FREE;\r
288     }\r
289     else if (transaction->type == Rm_service_RESOURCE_BLOCK_FREE)\r
290     {\r
291         resourceReqPkt->resourceReqType = Rm_resReqPktType_BLOCK_FREE;\r
292     }\r
293     else if (transaction->type == Rm_service_RESOURCE_FREE_BY_NAME)\r
294     {\r
295         resourceReqPkt->resourceReqType = Rm_resReqPktType_FREE_NAMED;\r
296     }\r
297     strcpy(&(resourceReqPkt->instName)[0], rmInst->name);\r
298     /* Copy the resource data */\r
299     memcpy ((void *)&(resourceReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),\r
300             sizeof(Rm_ResourceInfo));\r
301 \r
302     return (rmPkt);\r
303 }\r
304 \r
305 Rm_Packet *Rm_transportCreateResourceResponsePkt(Rm_Inst *rmInst, Rm_TransportNode *dstTransportNode,\r
306                                                  Rm_Transaction *transaction, Rm_TransactionReceipt *receipt)\r
307 {\r
308     Rm_Packet *rmPkt = NULL;\r
309     Rm_ResourceResponsePkt *resourceRespPkt = NULL;\r
310 \r
311     /* Make sure a buffer for the packet was allocated  */\r
312     if ((rmPkt = rmInst->transport.rmAllocPkt((Rm_TransportHandle)dstTransportNode, sizeof(Rm_Packet))) ==\r
313         NULL)\r
314     {\r
315         receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_ALLOC_PKT_ERROR;\r
316         return (NULL);\r
317     }\r
318 \r
319     /* Make sure allocated buffer is large enough to fit the request packet plus the \r
320      * rmPktLen and Rm_PktType fields */\r
321     if (rmPkt->pktLenBytes < (sizeof(Rm_ResourceResponsePkt) + sizeof(uint32_t) + sizeof(Rm_pktType)))\r
322     {   \r
323         receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_PKT_BUF_TOO_SMALL;\r
324         return (NULL);\r
325     }\r
326 \r
327     /* Set the Rm Packet type */    \r
328     rmPkt->pktType = Rm_pktType_RESOURCE_RESPONSE;\r
329                           \r
330     /* Assign the packet's data field to be the start of the resource response packet */\r
331     resourceRespPkt = (Rm_ResourceResponsePkt *)rmPkt->data;\r
332     /* Populate the resource response packet using the transaction information */\r
333     resourceRespPkt->responseId = transaction->id;\r
334     resourceRespPkt->requestResult = transaction->details;\r
335     /* Copy the resource data */\r
336     memcpy ((void *)&(resourceRespPkt->resourceInfo), (void *)&(transaction->resourceInfo),\r
337             sizeof(Rm_ResourceInfo));\r
338 \r
339     return (rmPkt);\r
340 }\r
341 \r
342 Rm_Packet *Rm_transportCreateNsRequestPkt(Rm_Inst *rmInst, Rm_TransportNode *dstTransportNode,\r
343                                           Rm_Transaction *transaction, Rm_TransactionReceipt *receipt)\r
344 {\r
345     Rm_Packet *rmPkt = NULL;\r
346     Rm_NsRequestPkt *nsReqPkt = NULL;\r
347 \r
348     /* Make sure a buffer for the packet was allocated  */\r
349     if ((rmPkt = rmInst->transport.rmAllocPkt((Rm_TransportHandle)dstTransportNode, sizeof(Rm_Packet))) ==\r
350         NULL)\r
351     {\r
352         receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_ALLOC_PKT_ERROR;\r
353         return (NULL);\r
354     }\r
355 \r
356     /* Make sure allocated buffer is large enough to fit the request packet plus the \r
357      * rmPktLen and Rm_PktType fields */\r
358     if (rmPkt->pktLenBytes < (sizeof(Rm_NsRequestPkt) + sizeof(uint32_t) + sizeof(Rm_pktType)))\r
359     {   \r
360         receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_PKT_BUF_TOO_SMALL;\r
361         return (NULL);\r
362     }\r
363 \r
364     /* Set the Rm Packet type */    \r
365     rmPkt->pktType = Rm_pktType_NAMESERVER_REQUEST;\r
366                           \r
367     /* Assign the packet's data field to be the start of the NameServer request packet */\r
368     nsReqPkt = (Rm_NsRequestPkt *)rmPkt->data;\r
369     /* Populate the NameServer request packet using the transaction information */\r
370     nsReqPkt->requestId = transaction->id;\r
371     if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME)\r
372     {\r
373         nsReqPkt->nsRequestType = Rm_nsReqPktType_MAP_RESOURCE;\r
374     }\r
375     else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME)\r
376     {\r
377         nsReqPkt->nsRequestType = Rm_nsReqPktType_UNMAP_RESOURCE;\r
378     }\r
379     strcpy(&(nsReqPkt->instName)[0], rmInst->name);\r
380     /* Copy the NameServer request data */\r
381     memcpy ((void *)&(nsReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),\r
382             sizeof(Rm_ResourceInfo));\r
383 \r
384     return (rmPkt);\r
385 }\r
386 \r
387 Rm_Packet *Rm_transportCreateNsResponsePkt(Rm_Inst *rmInst, Rm_TransportNode *dstTransportNode,\r
388                                            Rm_Transaction *transaction, Rm_TransactionReceipt *receipt)\r
389 {\r
390     Rm_Packet *rmPkt = NULL;\r
391     Rm_NsResponsePkt *nsRespPkt = NULL;\r
392 \r
393     /* Make sure a buffer for the packet was allocated  */\r
394     if ((rmPkt = rmInst->transport.rmAllocPkt((Rm_TransportHandle)dstTransportNode, sizeof(Rm_Packet))) ==\r
395         NULL)\r
396     {\r
397         receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_ALLOC_PKT_ERROR;\r
398         return (NULL);\r
399     }\r
400 \r
401     /* Make sure allocated buffer is large enough to fit the response packet plus the \r
402      * rmPktLen and Rm_PktType fields */\r
403     if (rmPkt->pktLenBytes < (sizeof(Rm_NsResponsePkt) + sizeof(uint32_t) + sizeof(Rm_pktType)))\r
404     {   \r
405         receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_PKT_BUF_TOO_SMALL;\r
406         return (NULL);\r
407     }\r
408 \r
409     /* Set the Rm Packet type */    \r
410     rmPkt->pktType = Rm_pktType_NAMESERVER_RESPONSE;\r
411                           \r
412     /* Assign the packet's data field to be the start of the NameServer response packet */\r
413     nsRespPkt = (Rm_NsResponsePkt *)rmPkt->data;\r
414     /* Populate the NameServer response packet using the transaction information */\r
415     nsRespPkt->responseId = transaction->id;\r
416     nsRespPkt->requestResult = transaction->details;\r
417 \r
418     return (rmPkt);\r
419 }\r
420 \r
421 /**********************************************************************\r
422  ********************* Application visible APIs ***********************\r
423  **********************************************************************/\r
424 \r
425 Rm_TransportHandle Rm_transportRegister (Rm_Handle rmHandle, Rm_TransportCfg *transportCfg)\r
426 {\r
427     Rm_Inst *rmInst = (Rm_Inst *) rmHandle;\r
428     Rm_TransportNode *transportNode = NULL;\r
429     void *key;\r
430 \r
431     /* Lock access to the RM instance */\r
432     key = Rm_osalCsEnter();\r
433 \r
434     /* RM Servers cannot connect to other Servers.  RM Client Delegates cannot\r
435      * connect to other Client Delegates. */\r
436     if (((rmInst->instType == Rm_instType_SERVER) &&\r
437          (transportCfg->remoteInstType == Rm_instType_SERVER)) ||\r
438         ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
439          (transportCfg->remoteInstType == Rm_instType_CLIENT_DELEGATE)))\r
440     {\r
441         Rm_osalCsExit(key);\r
442         return (NULL); /* Error - return null */\r
443     }\r
444 \r
445     /* Verify Clients and Client Delegates are not registering with more than one \r
446      * Client Delegate or Server. Assuming a Client Delegate can register with another \r
447      * Client Delegate that can "act" as a server */\r
448     if (((rmInst->instType == Rm_instType_CLIENT) &&\r
449          (transportCfg->remoteInstType == Rm_instType_CLIENT_DELEGATE)) || \r
450         ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
451          (transportCfg->remoteInstType == Rm_instType_SERVER)) &&\r
452         rmInst->registeredWithDelegateOrServer)\r
453     {\r
454         Rm_osalCsExit(key);\r
455         return (NULL); /* Error - return null */\r
456     }         \r
457 \r
458     /* Copy the transport callout function pointers into the RM instance as long as they're\r
459      * valid or not NULL */\r
460     if (transportCfg->transportCalloutsValid)\r
461     {\r
462         /* The transport APIs must not be NULL */\r
463         if ((transportCfg->transportCallouts.rmAllocPkt == NULL) ||\r
464             (transportCfg->transportCallouts.rmFreePkt == NULL) ||\r
465             (transportCfg->transportCallouts.rmSend == NULL) ||\r
466             (transportCfg->transportCallouts.rmReceive == NULL) ||\r
467             (transportCfg->transportCallouts.rmNumPktsReceived == NULL))\r
468         {\r
469             Rm_osalCsExit(key);\r
470             return (NULL); /* Error - return null */\r
471         }\r
472             \r
473         /* Populate the instance transport callouts */\r
474         rmInst->transport.rmAllocPkt = transportCfg->transportCallouts.rmAllocPkt;\r
475         rmInst->transport.rmFreePkt = transportCfg->transportCallouts.rmFreePkt;\r
476         rmInst->transport.rmSend = transportCfg->transportCallouts.rmSend;\r
477         rmInst->transport.rmReceive = transportCfg->transportCallouts.rmReceive;\r
478         rmInst->transport.rmNumPktsReceived = transportCfg->transportCallouts.rmNumPktsReceived;\r
479     }\r
480 \r
481     /* Error checks passed - Create a new transport handle for the specified RM instance and\r
482      * create a new node in the RM instance's routing map. */\r
483     transportNode = Rm_transportNodeAdd(rmInst, transportCfg);\r
484 \r
485     /* Specify RM instance has registered with a higher level agent */\r
486     if ((transportNode->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||\r
487         (transportNode->remoteInstType == Rm_instType_SERVER))\r
488     {\r
489         rmInst->registeredWithDelegateOrServer = true;\r
490     }\r
491 \r
492     Rm_osalCsExit(key);\r
493     return ((Rm_TransportHandle) transportNode);\r
494 }\r
495 \r
496 Rm_TransportResult Rm_transportUnregister (Rm_Handle rmHandle, Rm_TransportHandle transportHandle)\r
497 {\r
498     Rm_Inst *rmInst = (Rm_Inst *) rmHandle;\r
499     Rm_TransportNode *transportNode = NULL;\r
500     Rm_TransportResult retVal = RM_TRANSPORT_SUCCESSFUL;\r
501     void *key;\r
502 \r
503     /* Lock access to the RM instance */\r
504     key = Rm_osalCsEnter();    \r
505 \r
506     /* Check if the transportHandle exists in the RM instance's route map */\r
507     transportNode = Rm_transportNodeFindTransportHandle(rmInst, transportHandle);\r
508 \r
509     if (transportNode == NULL)\r
510     {\r
511         /* Error - transport node does not exist in RM instance route map */\r
512         Rm_osalCsExit(key);\r
513         return (RM_TRANSPORT_ERROR_HANDLE_HAS_NOT_BEEN_REGISTERED);\r
514     }\r
515 \r
516     /* Remove specification that RM instance has been connected to an upper level agent\r
517      * if the node to be deleted has a remote instance type of Client Delegate or Server */\r
518     if ((transportNode->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||\r
519         (transportNode->remoteInstType == Rm_instType_SERVER))\r
520     {\r
521         rmInst->registeredWithDelegateOrServer = false;\r
522     }\r
523 \r
524     /* Delete the transport node */\r
525     retVal = Rm_transportNodeDelete(rmInst, transportHandle);\r
526 \r
527     Rm_osalCsExit(key);\r
528 \r
529     return (retVal);\r
530 }\r
531 \r
532 /* Used by the application to pass RM packets received from a transport to RM.\r
533  * CODE THE FUNCTION SUCH THAT IT CAN BE CALLED DIRECTLY BY APP OR BE PLUGGED\r
534  * AS PART OF AN ISR HANDLER FOR THE TRANSACTION RECEIVE */\r
535 int32_t Rm_receivePktIsr(Rm_TransportHandle transportHandle, Rm_Packet *pkt)\r
536 {\r\r\r
537     Rm_Inst *rmInst = (Rm_Inst *)((Rm_TransportNode *)transportHandle)->rmHandle;\r
538     Rm_Transaction *transaction;\r
539     Rm_TransactionReceipt receipt;\r
540 \r
541     /* Make sure the transport handle is registered with the provided RM instance */\r
542     if (Rm_transportNodeFindTransportHandle(rmInst, transportHandle) == NULL)\r
543     {\r
544         /* Transport is not registered with the RM instance.  Return an error.\r
545          * The packet cannot be freed since the transport handle is not valid. */\r
546         return (RM_TRANSPORT_ERROR_HANDLE_HAS_NOT_BEEN_REGISTERED);\r
547     }\r
548 \r
549     /* Clear the transaction receipt */\r
550     memset((void *)&receipt, 0, sizeof(Rm_TransactionReceipt));\r
551 \r
552     /* Based on packet type transfer the data to a transaction or a policy structure */\r
553     switch (pkt->pktType)\r
554     {\r
555         case Rm_pktType_RESOURCE_REQUEST:\r
556         {\r
557             Rm_ResourceRequestPkt *resourceReqPkt = (Rm_ResourceRequestPkt *)pkt->data;\r
558 \r
559             /* The transaction ID will be the request ID.  The request ID\r
560              * will become the response packet's ID so the requesting RM instance\r
561              * can filter received resource responses */\r
562             transaction = Rm_transactionQueueAdd(rmInst, resourceReqPkt->requestId);\r
563 \r
564             /* Transfer the rest of the data into the transaction */\r
565             if (resourceReqPkt->resourceReqType == Rm_resReqPktType_ALLOCATE)\r
566             {\r
567                 transaction->type = Rm_service_RESOURCE_ALLOCATE;\r
568             }\r
569             else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_BLOCK_ALLOCATE)\r
570             {\r
571                 transaction->type = Rm_service_RESOURCE_BLOCK_ALLOCATE;\r
572             }\r
573             else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_ALLOCATE_NAMED)\r
574             {\r
575                 transaction->type = Rm_service_RESOURCE_ALLOCATE_BY_NAME;\r
576             }\r
577             else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_FREE)\r
578             {\r
579                 transaction->type = Rm_service_RESOURCE_FREE;\r
580             }\r
581             else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_BLOCK_FREE)\r
582             {\r
583                 transaction->type = Rm_service_RESOURCE_BLOCK_FREE;\r
584             }\r
585             else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_FREE_NAMED)\r
586             {\r
587                 transaction->type = Rm_service_RESOURCE_FREE_BY_NAME;\r
588             }\r
589 \r
590             strcpy(transaction->sourceInstName, resourceReqPkt->instName);\r
591             transaction->state = Rm_transactionState_PROCESSING;\r
592             memcpy ((void *)&(transaction->resourceInfo), (void *)&(resourceReqPkt->resourceInfo),\r
593                     sizeof(Rm_ResourceInfo));\r
594 \r
595             /* Process the transaction */\r
596             Rm_transactionProcessor(rmInst, transaction, &receipt);\r
597             break;\r
598         }\r
599         case Rm_pktType_RESOURCE_RESPONSE:\r
600         {\r
601             Rm_ResourceResponsePkt *resourceRespPkt = (Rm_ResourceResponsePkt *)pkt->data;\r
602 \r
603             /* If the packet is a response packet the transaction ID should match a queued \r
604              * request transaction's ID  */\r
605             transaction = Rm_transactionQueueAdd(rmInst, resourceRespPkt->responseId);\r
606 \r
607             if (resourceRespPkt->requestResult == RM_SERVICE_APPROVED)\r
608             {\r
609                 transaction->state = Rm_transactionState_RESOURCE_APPROVED;\r
610             }\r
611             else if ((resourceRespPkt->requestResult >= RM_SERVICE_DENIED_BEGIN) &&\r
612                      (resourceRespPkt->requestResult <= RM_SERVICE_DENIED_END))\r
613             {\r
614                 transaction->state = Rm_transactionState_RESOURCE_DENIED;\r
615             }            \r
616             /* The result of the request should be placed in the details field of the \r
617              * response transaction */\r
618             transaction->details = resourceRespPkt->requestResult;\r
619             memcpy ((void *)&(transaction->resourceInfo), (void *)&(resourceRespPkt->resourceInfo),\r
620                     sizeof(Rm_ResourceInfo));\r
621             \r
622             /* Process the transaction */\r
623             Rm_transactionProcessor(rmInst, transaction, &receipt);\r
624             break;\r
625         }\r
626         case Rm_pktType_NAMESERVER_REQUEST:\r
627         {\r
628             Rm_NsRequestPkt *nsRequestPkt = (Rm_NsRequestPkt *)pkt->data;\r
629 \r
630             transaction = Rm_transactionQueueAdd(rmInst, nsRequestPkt->requestId);\r
631 \r
632             if (nsRequestPkt->nsRequestType == Rm_nsReqPktType_MAP_RESOURCE)\r
633             {\r
634                 transaction->type = Rm_service_RESOURCE_MAP_TO_NAME;\r
635             }\r
636             else if (nsRequestPkt->nsRequestType == Rm_nsReqPktType_UNMAP_RESOURCE)\r
637             {\r
638                 transaction->type = Rm_service_RESOURCE_UNMAP_NAME;\r
639             }\r
640 \r
641             strcpy(transaction->sourceInstName, nsRequestPkt->instName);\r
642             transaction->state = Rm_transactionState_PROCESSING;\r
643             memcpy ((void *)&(transaction->resourceInfo), (void *)&(nsRequestPkt->resourceInfo),\r
644                     sizeof(Rm_ResourceInfo));\r
645 \r
646             /* Process the transaction */\r
647             Rm_transactionProcessor(rmInst, transaction, &receipt);            \r
648             break;\r
649         }\r
650         case Rm_pktType_NAMESERVER_RESPONSE:\r
651         {\r
652             Rm_NsResponsePkt *nsResponsePkt = (Rm_NsResponsePkt *)pkt->data;\r
653 \r
654             transaction = Rm_transactionQueueAdd(rmInst, nsResponsePkt->responseId);\r
655             transaction->details = nsResponsePkt->requestResult;\r
656 \r
657             if (nsResponsePkt->requestResult == RM_SERVICE_APPROVED)\r
658             {\r
659                 transaction->state = Rm_transactionState_RESOURCE_APPROVED;\r
660             }\r
661             else if ((nsResponsePkt->requestResult >= RM_SERVICE_DENIED_BEGIN) &&\r
662                      (nsResponsePkt->requestResult <= RM_SERVICE_DENIED_END))\r
663             {\r
664                 transaction->state = Rm_transactionState_RESOURCE_DENIED;\r
665             }\r
666 \r
667             /* Process the transaction */\r
668             Rm_transactionProcessor(rmInst, transaction, &receipt);\r
669             break;\r
670         }\r
671         case Rm_pktType_POLICY_REQUEST:\r
672         {\r
673             Rm_PolicyRequestPkt *policyRequestPkt = (Rm_PolicyRequestPkt *)pkt->data;\r
674 \r
675             /* FILL IN POLICY API INFORMATION */\r
676             break;  \r
677         }\r
678         case Rm_pktType_POLICY_CHANGE:\r
679         {\r
680             Rm_PolicyChangePkt *policyChangePkt = (Rm_PolicyChangePkt *)pkt->data;\r
681 \r
682             /* FILL IN POLICY API INFORMATION */\r
683             break;\r
684         }\r
685         case Rm_pktType_RESOURCE_POOL_MODIFICATION_REQUEST:\r
686         {\r
687             Rm_ResourcePoolModRequestPkt *resPoolModReqPkt = (Rm_ResourcePoolModRequestPkt *)pkt->data;\r
688 \r
689             /* FILL IN RESOURCE POOL MODIFICATION API */\r
690             /* Rm_resourcePoolModRequestHandler(...); Server only - needs to allocate resources to\r
691              * the Client Delegate based on the policy and return those resources to the Client Delegate */\r
692             break;\r
693         }\r
694         case Rm_pktType_RESOURCE_POOL_MODIFICATION_RESPONSE:\r
695         {\r
696             Rm_ResourcePoolModResponsePkt *resPoolModRespPkt = (Rm_ResourcePoolModResponsePkt *)pkt->data;\r
697 \r
698             /* FILL IN RESOURCE POOL MODIFICAITON API */\r
699             /* Rm_resourcePoolModResponseHandler(...);  Handler needs to populate allocator with\r
700              * new resources provided in the response and then handle any request transactions waiting on\r
701              * the resource pool modification */\r
702             break;\r
703         }\r
704         default:\r
705             /* Invalid packet type.  Free the packet and return */\r
706             rmInst->transport.rmFreePkt(transportHandle, pkt);\r
707             return (RM_TRANSPORT_ERROR_INVALID_PACKET_TYPE);\r
708       }\r
709 \r
710     /* Free the packet after it has been processed */\r
711     rmInst->transport.rmFreePkt(transportHandle, pkt);\r
712 \r
713     /* Return the receipt's service result which contains the result return code\r
714      * for the receive packet */\r
715     return (receipt.serviceResult);\r
716 }\r
717 \r
718 /* Application can call this API so that RM handles reception of packets based on\r
719  * the RM handle and transport handle provided */\r
720 int32_t Rm_receivePktPolling(Rm_TransportHandle transportHandle)\r
721 {\r
722     Rm_Inst *rmInst = (Rm_Inst *)((Rm_TransportNode *)transportHandle)->rmHandle;\r
723     Rm_Packet *pkt = NULL;\r
724     int32_t retVal = RM_SERVICE_ACTION_BASE;\r
725 \r
726     /* Make sure the transport handle is registered with the provided RM instance */\r
727     if (Rm_transportNodeFindTransportHandle(rmInst, transportHandle) == NULL)\r
728     {\r
729         /* Transport is not registered with the RM instance.  Return an error.\r
730          * The packet cannot be freed since the transport handle is not valid. */\r
731         return (RM_TRANSPORT_ERROR_HANDLE_HAS_NOT_BEEN_REGISTERED);\r
732     }\r
733 \r
734     /* Check to see if any RM packets are available.  Process any available packets. */\r
735     while (rmInst->transport.rmNumPktsReceived(transportHandle) > 0)\r
736     {\r
737         pkt = rmInst->transport.rmReceive(transportHandle);\r
738 \r
739         if (pkt == NULL)\r
740         {\r
741             return (RM_TRANSPORT_ERROR_PACKET_RECEPTION_ERROR);\r
742         }\r
743 \r
744         /* Pass the packet to RM.  The packet will be freed within the PktIsr API */\r
745         if (retVal = Rm_receivePktIsr(transportHandle, pkt) <= RM_SERVICE_ERROR_BASE)\r
746         {\r
747             /* Return if an error is encountered */\r
748             return (retVal);\r
749         }\r
750     }\r
751     return (retVal); \r
752 }\r
753 \r
754 /**\r
755 @}\r
756 */\r