3971489822613758de00f4c08b7bdd51d8ff5ea8
[keystone-rtos/rm-lld.git] / src / rmtransport.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/rmtransport.h>\r
48 \r
49 /* RM internal includes */\r
50 #include <ti/drv/rm/rmloc.h>\r
51 #include <ti/drv/rm/rmtransportloc.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_osalLocalCsEnter();\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         return;\r
76     }\r
77 \r
78     /* Populate the new entry. */\r
79     newTransportNode->remoteInstType = transportCfg->remoteInstType;\r
80     strcpy(&(newTransportNode->remoteInstName)[0], transportCfg->remoteInstName);\r
81     newTransportNode->nextNode = NULL;  /* New node will always be NULL */\r
82 \r
83     /* Check if there are any nodes in the transport routing map */\r
84     if (routeMap)\r
85     {\r
86         /* At least one node in the routing map.  Add the new node to the end of the\r
87          * routing map */\r
88         while (routeMap->nextNode != NULL)\r
89         {\r
90             /* Traverse the list until arriving at the last node */\r
91             routeMap = routeMap->nextNode;\r
92         }\r
93 \r
94         /* Add the new node to the end of the list */\r
95         routeMap->nextNode = newTransportNode;\r
96     }\r
97     else\r
98     {\r
99         /* The transport routing map does not currently exist.  The new node is the first node */\r
100         rmInst->routeMap = newTransportNode;\r
101     }\r
102    \r
103     Rm_osalLocalCsExit(key);\r
104 \r
105     return (newTransportNode);\r
106 }\r
107 \r
108 Rm_TransportNode *Rm_transportNodeFindTransportHandle(Rm_Inst *rmInst, \r
109                                                       Rm_TransportHandle transportHandle)\r
110 {\r
111     Rm_TransportNode *transportNode = (Rm_TransportNode *)rmInst->routeMap;\r
112 \r
113     /* Make sure there is at least one node in the route map */\r
114     if (transportNode != NULL)\r
115     {\r
116         /* Find the transport node with the transport handle within the RM instance's\r
117          * route map.  If the end of the route map is reached without finding the node the \r
118          * node pointer will be NULL */\r
119         while (transportNode != NULL)\r
120         {\r
121             /* The transport handle is the address of the transport node */\r
122             if (transportNode == ((Rm_TransportNode *)transportHandle)\r
123             {\r
124                 /* Match: break out of loop and return the node */\r
125                 break;             \r
126             }\r
127             transportNode = transportNode->nextNode;\r
128         }\r
129     }\r
130 \r
131     return (transportNode);\r
132 }\r
133 \r
134 Rm_TransportNode *Rm_transportNodeFindRemoteName(Rm_Inst *rmInst, char *remoteName)\r
135 {\r
136     Rm_TransportNode *transportNode = (Rm_TransportNode *)rmInst->routeMap;\r
137 \r
138     /* Make sure there is at least one node in the route map */\r
139     if (transportNode != NULL)\r
140     {\r
141         /* Find the transport node with the provided remote instance name.\r
142          * If the end of the route map is reached without finding the node the \r
143          * node pointer will be NULL */\r
144         while (transportNode != NULL)\r
145         {\r
146             /* The transport handle is the address of the transport node */\r
147             if (strcmp(&(transportNode->remoteInstName)[0], remoteName) == 0)\r
148             {\r
149                 /* Match: break out of loop and return the node */\r
150                 break;             \r
151             }\r
152             transportNode = transportNode->nextNode;\r
153         }\r
154     }\r
155 \r
156     return (transportNode);\r
157 }\r
158 \r
159 Rm_TransportNode *Rm_transportNodeFindRemoteInstType(Rm_Inst *rmInst,\r
160                                                      Rm_InstType remoteInstType)\r
161 {\r
162     Rm_TransportNode *transportNode = (Rm_TransportNode *)rmInst->routeMap;\r
163 \r
164     /* Make sure there is at least one node in the route map */\r
165     if (transportNode != NULL)\r
166     {\r
167         /* Find the transport node with the provided remote instance type.\r
168          * If the end of the route map is reached without finding the node the \r
169          * node pointer will be NULL */\r
170         while (transportNode != NULL)\r
171         {\r
172             if (transportNode->remoteInstType == remoteInstType)\r
173             {\r
174                 /* Match: break out of loop and return the node */\r
175                 break;             \r
176             }\r
177             transportNode = transportNode->nextNode;\r
178         }\r
179     }\r
180 \r
181     return (transportNode);\r
182 }\r
183 \r
184 Rm_TransportResult Rm_transportNodeDelete(Rm_Inst *rmInst, Rm_TransportHandle transportHandle)\r
185 {\r
186     Rm_TransportNode *transportNode = (Rm_TransportNode *)rmInst->routeMap;\r
187     Rm_TransportNode *prevNode = NULL;\r
188     void *key;\r
189 \r
190     /* Lock access to the RM instance's route map */\r
191     key = Rm_osalLocalCsEnter();\r
192 \r
193     /* Make sure there is at least one entry in the transaction queue */\r
194     if (transportNode == NULL)\r
195     {\r
196         Rm_osalLocalCsExit(key);\r
197         return (RM_TRANSPORT_ERROR_NO_TRANSPORTS_REGISTERED);\r
198     }\r
199 \r
200     /* Find the transport handle within the RM instance's route map. */\r
201     while (transportNode != NULL)\r
202     {\r
203         if (transportNode == (Rm_TransportNode *) transportHandle)\r
204         {\r
205             /* Match: break out of loop and delete the entry */\r
206             break;             \r
207         }\r
208 \r
209         prevNode = transportNode;\r
210         transportNode = transportNode->nextNode;\r
211     }\r
212 \r
213     /* Traversed entire queue but did not find transaction */\r
214     if (transportNode == NULL)\r
215     {\r
216         Rm_osalLocalCsExit(key);\r
217         return (RM_TRANSPORT_ERROR_HANDLE_HAS_NOT_BEEN_REGISTERED);\r
218     }\r
219     else\r
220     {\r
221         /* Delete the transport node */\r
222         if ((prevNode == NULL) && transportNode->nextNode)\r
223         {\r
224             /* Node to be deleted exists at start of route map.  Map second\r
225              * node to be start of route map as long as there are more than\r
226              * one nodes */\r
227             rmInst->routeMap = transportNode->nextNode;\r
228         }\r
229         else\r
230         {\r
231             /* Node to be deleted is in the middle or at end of the route map.  Adjust adjacent\r
232              * node pointers.  This covers the case where the node to be removed is at the\r
233              * end of the route map. */\r
234             prevNode->nextNode = transportNode->nextNode;\r
235         }\r
236 \r
237         /* Free the memory associated with the node. */\r
238         Rm_osalFree((void *) transportNode, sizeof(Rm_TransportNode), false);\r
239     }\r
240 \r
241     Rm_osalLocalCsExit(key);\r
242     return (RM_TRANSPORT_SUCCESSFUL);\r
243 }\r
244 \r
245 Rm_Packet *Rm_transportCreateResourceReqPkt(Rm_Inst *rmInst, Rm_TransportNode *dstTransportNode,\r
246                                             Rm_Transaction *transaction, Rm_TransactionReceipt *receipt)\r
247 {\r
248     Rm_Packet *rmPkt = NULL;\r
249     Rm_ResourceRequestPkt *resourceReqPkt = NULL;\r
250 \r
251     /* Make sure a buffer for the packet was allocated  */\r
252     if ((rmPkt = rmInst->transport.rmAllocPkt((Rm_TransportHandle)dstTransportNode, sizeof(Rm_Packet))) ==\r
253         NULL)\r
254     {\r
255         receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_ALLOC_PKT_ERROR;\r
256         return;\r
257     }\r
258 \r
259     /* Make sure allocated buffer is large enough to fit the request packet plus the \r
260      * rmPktLen and Rm_PktType fields */\r
261     if (rmPkt->rmPktLen < (sizeof(Rm_ResourceRequestPkt) + sizeof(uint32_t) + sizeof(Rm_pktType))\r
262     {   \r
263         receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_PKT_BUF_TOO_SMALL;\r
264         return;\r
265     }\r
266 \r
267     /* Set the Rm Packet type */    \r
268     rmPkt->pktType = Rm_pktType_RESOURCE_REQUEST;\r
269                           \r
270     /* Assign the packet's data field to be the start of the resource request packet */\r
271     resourceReqPkt = (Rm_ResourceRequestPkt *) rmPkt->data;\r
272     /* Populate the resource request packet using the transaction information */\r
273     resourceReqPkt->requestId = transaction->id;\r
274     if (transaction->type == Rm_service_RESOURCE_ALLOCATE)\r
275     {\r
276         resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE;\r
277     }\r
278     else if (transaction->type == Rm_service_RESOURCE_BLOCK_ALLOCATE)\r
279     {\r
280         resourceReqPkt->resourceReqType = Rm_resReqPktType_BLOCK_ALLOCATE;\r
281     }\r
282     else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_BY_NAME)\r
283     {\r
284         resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE_NAMED;\r
285     }\r
286     else if (transaction->type == Rm_service_RESOURCE_FREE)\r
287     {\r
288         resourceReqPkt->resourceReqType = Rm_resReqPktType_FREE;\r
289     }\r
290     else if (transaction->type == case Rm_service_RESOURCE_BLOCK_FREE)\r
291     {\r
292         resourceReqPkt->resourceReqType = Rm_resReqPktType_BLOCK_FREE;\r
293     }\r
294     else if (transaction->type == Rm_service_RESOURCE_FREE_BY_NAME)\r
295     {\r
296         resourceReqPkt->resourceReqType = Rm_resReqPktType_FREE_NAMED;\r
297     }\r
298     strcpy(&(resourceReqPkt->instName)[0], rmInst->name);\r
299     /* Copy the resource data */\r
300     memcpy ((void *)&(resourceReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),\r
301             sizeof(Rm_ResourceInfo));\r
302 \r
303     return (rmPkt);\r
304 }\r
305 \r
306 Rm_Packet *Rm_transportCreateResourceResponsePkt(Rm_Inst *rmInst, Rm_TransportNode *dstTransportNode,\r
307                                                  Rm_Transaction *transaction, Rm_TransactionReceipt *receipt)\r
308 {\r
309     Rm_Packet *rmPkt = NULL;\r
310     Rm_ResourceResponsePkt *resourceRespPkt = NULL;\r
311 \r
312     /* Make sure a buffer for the packet was allocated  */\r
313     if ((rmPkt = rmInst->transport.rmAllocPkt((Rm_TransportHandle)dstTransportNode, sizeof(Rm_Packet))) ==\r
314         NULL)\r
315     {\r
316         receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_ALLOC_PKT_ERROR;\r
317         return;\r
318     }\r
319 \r
320     /* Make sure allocated buffer is large enough to fit the request packet plus the \r
321      * rmPktLen and Rm_PktType fields */\r
322     if (rmPkt->rmPktLen < (sizeof(Rm_ResourceResponsePkt) + sizeof(uint32_t) + sizeof(Rm_pktType))\r
323     {   \r
324         receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_PKT_BUF_TOO_SMALL;\r
325         return;\r
326     }\r
327 \r
328     /* Set the Rm Packet type */    \r
329     rmPkt->pktType = Rm_pktType_RESOURCE_RESPONSE;\r
330                           \r
331     /* Assign the packet's data field to be the start of the resource response packet */\r
332     resourceRespPkt = (Rm_ResourceResponsePkt *)rmPkt->data);\r
333     /* Populate the resource response packet using the transaction information */\r
334     resourceRespPkt->responseId = transaction->id;\r
335     resourceRespPkt->requestResult = transaction->details;\r
336     /* Copy the resource data */\r
337     memcpy ((void *)&(resourceRespPkt->resourceInfo), (void *)&(transaction->resourceInfo),\r
338             sizeof(Rm_ResourceInfo));\r
339 \r
340     return (rmPkt);\r
341 }\r
342 \r
343 Rm_Packet *Rm_transportCreateNsRequestPkt(Rm_Inst *rmInst, Rm_TransportNode *dstTransportNode,\r
344                                           Rm_Transaction *transaction, Rm_TransactionReceipt *receipt)\r
345 {\r
346     Rm_Packet *rmPkt = NULL;\r
347     Rm_NsRequestPkt *nsReqPkt = NULL;\r
348 \r
349     /* Make sure a buffer for the packet was allocated  */\r
350     if ((rmPkt = rmInst->transport.rmAllocPkt((Rm_TransportHandle)dstTransportNode, sizeof(Rm_Packet))) ==\r
351         NULL)\r
352     {\r
353         receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_ALLOC_PKT_ERROR;\r
354         return;\r
355     }\r
356 \r
357     /* Make sure allocated buffer is large enough to fit the request packet plus the \r
358      * rmPktLen and Rm_PktType fields */\r
359     if (rmPkt->rmPktLen < (sizeof(Rm_NsRequestPkt) + sizeof(uint32_t) + sizeof(Rm_pktType))\r
360     {   \r
361         receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_PKT_BUF_TOO_SMALL;\r
362         return;\r
363     }\r
364 \r
365     /* Set the Rm Packet type */    \r
366     rmPkt->pktType = Rm_pktType_NAMESERVER_REQUEST;\r
367                           \r
368     /* Assign the packet's data field to be the start of the NameServer request packet */\r
369     nsReqPkt = (Rm_NsRequestPkt *)rmPkt->data;\r
370     /* Populate the NameServer request packet using the transaction information */\r
371     nsReqPkt->requestId = transaction->id;\r
372     if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME)\r
373     {\r
374         nsReqPkt->nsRequestType = Rm_nsReqPktType_MAP_RESOURCE;\r
375     }\r
376     else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME)\r
377     {\r
378         nsReqPkt->nsRequestType = Rm_nsReqPktType_UNMAP_RESOURCE;\r
379     }\r
380     strcpy(&(nsReqPkt->instName)[0], rmInst->name);\r
381     /* Copy the NameServer request data */\r
382     memcpy ((void *)&(nsReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),\r
383             sizeof(Rm_ResourceInfo));\r
384 \r
385     return (rmPkt);\r
386 }\r
387 \r
388 Rm_Packet *Rm_transportCreateNsResponsePkt(Rm_Inst *rmInst, Rm_TransportNode *dstTransportNode,\r
389                                            Rm_Transaction *transaction, Rm_TransactionReceipt *receipt)\r
390 {\r
391     Rm_Packet *rmPkt = NULL;\r
392     Rm_NsResponsePkt *nsRespPkt = NULL;\r
393 \r
394     /* Make sure a buffer for the packet was allocated  */\r
395     if ((rmPkt = rmInst->transport.rmAllocPkt((Rm_TransportHandle)dstTransportNode, sizeof(Rm_Packet))) ==\r
396         NULL)\r
397     {\r
398         receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_ALLOC_PKT_ERROR;\r
399         return;\r
400     }\r
401 \r
402     /* Make sure allocated buffer is large enough to fit the response packet plus the \r
403      * rmPktLen and Rm_PktType fields */\r
404     if (rmPkt->rmPktLen < (sizeof(Rm_NsResponsePkt) + sizeof(uint32_t) + sizeof(Rm_pktType))\r
405     {   \r
406         receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_PKT_BUF_TOO_SMALL;\r
407         return;\r
408     }\r
409 \r
410     /* Set the Rm Packet type */    \r
411     rmPkt->pktType = Rm_pktType_NAMESERVER_RESPONSE;\r
412                           \r
413     /* Assign the packet's data field to be the start of the NameServer response packet */\r
414     nsRespPkt = (Rm_NsResponsePkt *)rmPkt->data;\r
415     /* Populate the NameServer response packet using the transaction information */\r
416     nsRespPkt->responseId = transaction->id;\r
417     nsRespPkt->requestResult = transaction->details;\r
418 \r
419     return (rmPkt);\r
420 }\r
421 \r
422 /**********************************************************************\r
423  *********************** Application visible APIs ***************************\r
424  **********************************************************************/\r
425 \r
426 Rm_TransportHandle Rm_transportRegister (Rm_Handle rmHandle, Rm_TransportCfg *transportCfg)\r
427 {\r
428     Rm_Inst *rmInst = (Rm_Inst *) rmHandle;\r
429     Rm_TransportNode *transportNode = NULL;\r
430     void *key;\r
431 \r
432     /* Lock access to the RM instance */\r
433     key = Rm_osalLocalCsEnter();\r
434 \r
435     /* RM Servers cannot connect to other Servers */\r
436     if ((rmInst->instType == Rm_instType_SERVER) &&\r
437         (transportCfg->rmRemoteInstType == Rm_instType_SERVER))\r
438     {\r
439         Rm_osalLocalCsExit(key);\r
440         return (NULL); /* Error - return null */\r
441     }\r
442 \r
443     /* Verify Clients and Client Delegates are not registering with more than one \r
444      * Client Delegate or Server. Assuming a Client Delegate can register with another \r
445      * Client Delegate that can "act" as a server */\r
446     if (((rmInst->instType == Rm_instType_CLIENT) || \r
447          (rmInst->instType == Rm_instType_CLIENT_DELEGATE)) &&\r
448         ((transportCfg->rmRemoteInstType == Rm_instType_CLIENT_DELEGATE) ||\r
449          (transportCfg->rmRemoteInstType == Rm_instType_SERVER)) &&\r
450         rmInst->registeredWithDelegateOrServer)\r
451     {\r
452         Rm_osalLocalCsExit(key);\r
453         return (NULL); /* Error - return null */\r
454     }         \r
455 \r
456     /* Error checks passed - Create a new transport handle for the specified RM instance and\r
457      * create a new node in the RM instance's routing map. */\r
458     transportNode = Rm_transportNodeAdd(rmInst, transportCfg);\r
459 \r
460     /* Specify RM instance has registered with a higher level agent */\r
461     if ((transportNode->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||\r
462         (transportNode->remoteInstType == Rm_instType_SERVER))\r
463     {\r
464         rmInst->registeredWithDelegateOrServer = true;\r
465     }\r
466 \r
467     Rm_osalLocalCsExit(key);\r
468 \r
469     return ((Rm_TransportHandle) transportNode);\r
470 }\r
471 \r
472 Rm_TransportResult Rm_transportUnregister (Rm_Handle rmHandle, Rm_TransportHandle transportHandle)\r
473 {\r
474     Rm_Inst *rmInst = (Rm_Inst *) rmHandle;\r
475     Rm_TransportNode *transportNode = NULL;\r
476     Rm_TransportResult retVal = RM_TRANSPORT_SUCCESSFUL;\r
477     void *key;\r
478 \r
479     /* Lock access to the RM instance */\r
480     key = Rm_osalLocalCsEnter();    \r
481 \r
482     /* Check if the transportHandle exists in the RM instance's route map */\r
483     transportNode = Rm_transportNodeFindTransportHandle(rmInst, transportHandle);\r
484 \r
485     if (transportNode == NULL)\r
486     {\r
487         /* Error - transport node does not exist in RM instance route map */\r
488         Rm_osalLocalCsExit(key);\r
489         return (RM_TRANSPORT_ERROR_HANDLE_HAS_NOT_BEEN_REGISTERED);\r
490     }\r
491 \r
492     /* Remove specification that RM instance has been connected to an upper level agent\r
493      * if the node to be deleted has a remote instance type of Client Delegate or Server */\r
494     if ((transportNode->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||\r
495         (transportNode->remoteInstType == Rm_instType_SERVER))\r
496     {\r
497         rmInst->registeredWithDelegateOrServer = false;\r
498     }\r
499 \r
500     /* Delete the transport node */\r
501     retVal = Rm_transportNodeDelete(rmInst, transportHandle);\r
502 \r
503     Rm_osalLocalCsExit(key);\r
504 \r
505     return (retVal);\r
506 }\r
507 \r
508 \r
509 Rm_TransVerifyResult Rm_transportVerify (Rm_Handle rmHandle, uint32_t timeout, \r
510                                          Rm_TransFailData *failData)\r
511 {\r
512 \r
513 }\r
514 \r
515 \r
516 /* Used by the application to pass RM packets received from a transport to RM.\r
517  * CODE THE FUNCTION SUCH THAT IT CAN BE CALLED DIRECTLY BY APP OR BE PLUGGED\r
518  * AS PART OF AN ISR HANDLER FOR THE TRANSACTION RECEIVE */\r
519 int32_t Rm_receivePktIsr(Rm_Handle rmHandle, Rm_TransportHandle transportHandle, Rm_Packet *pkt)\r
520 {\r\r\r
521     Rm_Inst *rmInst = (Rm_Inst *)rmHandle;\r
522     Rm_TransportNode *transportNode = (Rm_TransportNode *)transportHandle;\r
523     Rm_Transaction *transaction;\r
524     Rm_TransactionReceipt receipt;\r
525     void *key;\r
526 \r
527     /* Make sure the transport handle is registered with the provided RM instance */\r
528     if (Rm_transportNodeFindTransportHandle(rmInst, transportHandle) == NULL)\r
529     {\r
530         /* Transport is not registered with the RM instance.  Return an error.\r
531          * The packet cannot be freed since the transport handle is not valid. */\r
532         return (RM_TRANSPORT_ERROR_TRANSPORT_HANDLE_NOT_REGISTERED_WITH_INSTANCE);\r
533     }\r
534 \r
535     /* Clear the transaction receipt */\r
536     memset((void *)&receipt, 0, sizeof(Rm_TransactionReceipt));\r
537 \r
538     /* Based on packet type transfer the data to a transaction or a policy structure */\r
539     switch (pkt->pktType)\r
540     {\r
541         case Rm_pktType_RESOURCE_REQUEST:\r
542             Rm_ResourceRequestPkt *resourceReqPkt = (Rm_ResourceRequestPkt *)pkt->data;\r
543 \r
544             /* The transaction ID will be the request ID.  The request ID\r
545              * will become the response packet's ID so the requesting RM instance\r
546              * can filter received resource responses */\r
547             transaction = Rm_transactionQueueAdd(rmInst, resourceReqPkt->requestId);\r
548 \r
549             /* Transfer the rest of the data into the transaction */\r
550             if (resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE)\r
551             {\r
552                 transaction->type = Rm_service_RESOURCE_ALLOCATE;\r
553             }\r
554             else if (resourceReqPkt->resourceReqType = Rm_resReqPktType_BLOCK_ALLOCATE)\r
555             {\r
556                 transaction->type = Rm_service_RESOURCE_BLOCK_ALLOCATE;\r
557             }\r
558             else if (resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE_NAMED)\r
559             {\r
560                 transaction->type = Rm_service_RESOURCE_ALLOCATE_BY_NAME;\r
561             }\r
562             else if (resourceReqPkt->resourceReqType = Rm_resReqPktType_FREE)\r
563             {\r
564                 transaction->type = Rm_service_RESOURCE_FREE;\r
565             }\r
566             else if (resourceReqPkt->resourceReqType = Rm_resReqPktType_BLOCK_FREE)\r
567             {\r
568                 transaction->type = case Rm_service_RESOURCE_BLOCK_FREE;\r
569             }\r
570             else if (resourceReqPkt->resourceReqType = Rm_resReqPktType_FREE_NAMED)\r
571             {\r
572                 transaction->type = Rm_service_RESOURCE_FREE_BY_NAME;\r
573             }\r
574 \r
575             strcpy(transaction->sourceInstName, resourceReqPkt->instName);\r
576             transaction->state = Rm_transactionState_PROCESSING;\r
577             memcpy ((void *)&(transaction->resourceInfo), (void *)&(resourceReqPkt->resourceInfo),\r
578                     sizeof(Rm_ResourceInfo));\r
579 \r
580             /* Process the transaction */\r
581             Rm_transactionProcessor(rmInst, transaction, &receipt);\r
582             break;\r
583         case Rm_pktType_RESOURCE_RESPONSE:\r
584             Rm_ResourceResponsePkt *resourceRespPkt = (Rm_ResourceResponsePkt *)pkt->data;\r
585 \r
586             /* If the packet is a response packet the transaction ID should match a queued \r
587              * request transaction's ID  */\r
588             transaction = Rm_transactionQueueAdd(rmInst, resourceRespPkt->responseId);\r
589 \r
590             /* Transfer the rest of the data into the transaction */\r
591             if (resourceRespPkt->resourceReqType = Rm_resReqPktType_ALLOCATE)\r
592             {\r
593                 transaction->type = Rm_service_RESOURCE_ALLOCATE;\r
594             }\r
595             else if (resourceRespPkt->resourceReqType = Rm_resReqPktType_BLOCK_ALLOCATE)\r
596             {\r
597                 transaction->type = Rm_service_RESOURCE_BLOCK_ALLOCATE;\r
598             }\r
599             else if (resourceRespPkt->resourceReqType = Rm_resReqPktType_ALLOCATE_NAMED)\r
600             {\r
601                 transaction->type = Rm_service_RESOURCE_ALLOCATE_BY_NAME;\r
602             }\r
603             else if (resourceRespPkt->resourceReqType = Rm_resReqPktType_FREE)\r
604             {\r
605                 transaction->type = Rm_service_RESOURCE_FREE;\r
606             }\r
607             else if (resourceRespPkt->resourceReqType = Rm_resReqPktType_BLOCK_FREE)\r
608             {\r
609                 transaction->type = case Rm_service_RESOURCE_BLOCK_FREE;\r
610             }\r
611             else if (resourceRespPkt->resourceReqType = Rm_resReqPktType_FREE_NAMED)\r
612             {\r
613                 transaction->type = Rm_service_RESOURCE_FREE_BY_NAME;\r
614             }\r
615 \r
616             strcpy(transaction->sourceInstName, resourceReqPkt->instName);\r
617 \r
618             if (resourceRespPkt->requestResult = RM_SERVICE_APPROVED)\r
619             {\r
620                 transaction->state = Rm_transactionState_RESOURCE_APPROVED;\r
621             }\r
622             else if ((resourceRespPkt->requestResult >= RM_SERVICE_DENIED_BEGIN) &&\r
623                      (resourceRespPkt->requestResult <= RM_SERVICE_DENIED_END)\r
624             {\r
625                 transaction->state - Rm_transactionState_RESOURCE_DENIED;\r
626             }            \r
627             /* The result of the request should be placed in the details field of the \r
628              * response transaction */\r
629             transaction->details = resourceRespPkt->requestResult;\r
630             memcpy ((void *)&(transaction->resourceInfo), (void *)&(resourceRespPkt->resourceInfo),\r
631                     sizeof(Rm_ResourceInfo));\r
632             \r
633             /* Process the transaction */\r
634             Rm_transactionProcessor(rmInst, transaction, &receipt);\r
635             break;\r
636         case Rm_pktType_NAMESERVER_REQUEST:\r
637             break;\r
638         case Rm_pktType_NAMESERVER_RESPONSE:\r
639             break;\r
640         case Rm_pktType_POLICY_CHANGE:\r
641             break;\r
642         case Rm_pktType_POLICY_REQUEST:\r
643             break;\r
644         default:\r
645             /* Invalid packet type.  Free the packet and return */\r
646             rmInst->transport.rmFreePkt(transportHandle, pkt);\r
647             return (RM_TRANSPORT_ERROR_INVALID_PACKET_TYPE);\r
648       }\r
649 \r
650     /* Return the receipt's service result which contains the result return code\r
651      * for the receive packet */\r
652     return (receipt->serviceResult);\r
653 }\r
654 \r
655 /* Application can call this API so that RM handles reception of packets based on\r
656  * the RM handle and transport handle provided */\r
657 Rm_Result Rm_receivePktPolling(Rm_Handle rmHandle, Rm_TransportHandle transHandle)\r
658 {\r
659     Rm_Inst *rmInst = (Rm_Inst *)rmHandle;\r
660     Rm_TransRouteMapNode *transNode = rmInst->routeMap;\r
661     Rm_Packet *rmPkt = NULL;\r
662     Rm_Result retVal = 0;\r
663     void *key;\r
664 \r
665     /* Lock access to the RM instance's transaction queue */\r
666     key = Rm_osalLocalCsEnter();    \r
667 \r
668     /* Verify the transport handle is registered with the RM handle */\r
669     while (transNode != NULL)\r
670     {\r
671         if (transNode->transHandle == transHandle)\r
672         {\r
673            /* Break out of loop if an entry in the route map has been found */\r
674            break;\r
675         }\r
676         transNode = transNode->nextNode;\r
677     }\r
678 \r
679     if (transNode == NULL)\r
680     {\r
681         Rm_osalLocalCsExit(key);\r
682         return (-1) /* ERROR: THE TRANSPORT HANDLE IS NOT REGISTERED WITH THE RM HANDLE */\r
683     }\r
684 \r
685     /* Check to see if any RM packets are available.  Process any available packets. */\r
686     while (rmInst->transport.rmNumPktsReceived(transHandle))\r
687     {\r
688         rmInst->transport.rmReceive(transHandle, rmPkt);\r
689 \r
690         if (rmPkt == NULL)\r
691         {\r
692             retVal = -1;  /* ERROR - PACKET RECEIVED FROM TRANSPORT IS NULL */\r
693         }\r
694 \r
695         /* Pass the packet to RM */\r
696         retVal = Rm_receiveRmPkt(rmHandle, transHandle, rmPkt);\r
697         /* Delete the packet */\r
698         rmInst->transport.rmFreePkt(transHandle, rmPkt);\r
699 \r
700         if (retVal)\r
701         {\r
702             /* If retVal is not 0 (Okay) there was an error so break out of loop and return */\r
703             break;\r
704         }\r
705     }\r
706     \r
707     Rm_osalLocalCsExit(key);\r
708     return (retVal); \r
709 }\r
710 \r
711 \r
712 /**\r
713 @}\r
714 */\r