4a2b5cb243e6d0b8d51977301b59b5576d6d6c7c
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
537 Rm_Inst *rmInst = (Rm_Inst *)((Rm_TransportNode *)transportHandle)->rmHandle;\r
538 Rm_Transaction *transaction;\r
539 \r
540 /* Make sure the transport handle is registered with the provided RM instance */\r
541 if (Rm_transportNodeFindTransportHandle(rmInst, transportHandle) == NULL)\r
542 {\r
543 /* Transport is not registered with the RM instance. Return an error.\r
544 * The packet cannot be freed since the transport handle is not valid. */\r
545 return (RM_TRANSPORT_ERROR_HANDLE_HAS_NOT_BEEN_REGISTERED);\r
546 }\r
547 \r
548 /* Based on packet type transfer the data to a transaction or a policy structure */\r
549 switch (pkt->pktType)\r
550 {\r
551 case Rm_pktType_RESOURCE_REQUEST:\r
552 {\r
553 Rm_ResourceRequestPkt *resourceReqPkt = (Rm_ResourceRequestPkt *)pkt->data;\r
554 \r
555 /* Create the request transaction filling in the remoteOriginatingId using\r
556 * the request packet's ID. The request packet's ID will map to the \r
557 * the request transaction that issued the request packet. */\r
558 transaction = Rm_transactionQueueAdd(rmInst);\r
559 transaction->remoteOriginatingId = resourceReqPkt->requestId;\r
560 \r
561 /* Transfer the rest of the data into the transaction */\r
562 if (resourceReqPkt->resourceReqType == Rm_resReqPktType_ALLOCATE)\r
563 {\r
564 transaction->type = Rm_service_RESOURCE_ALLOCATE;\r
565 }\r
566 else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_BLOCK_ALLOCATE)\r
567 {\r
568 transaction->type = Rm_service_RESOURCE_BLOCK_ALLOCATE;\r
569 }\r
570 else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_ALLOCATE_NAMED)\r
571 {\r
572 transaction->type = Rm_service_RESOURCE_ALLOCATE_BY_NAME;\r
573 }\r
574 else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_FREE)\r
575 {\r
576 transaction->type = Rm_service_RESOURCE_FREE;\r
577 }\r
578 else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_BLOCK_FREE)\r
579 {\r
580 transaction->type = Rm_service_RESOURCE_BLOCK_FREE;\r
581 }\r
582 else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_FREE_NAMED)\r
583 {\r
584 transaction->type = Rm_service_RESOURCE_FREE_BY_NAME;\r
585 }\r
586 \r
587 strcpy(transaction->sourceInstName, resourceReqPkt->instName);\r
588 transaction->state = RM_SERVICE_PROCESSING;\r
589 memcpy ((void *)&(transaction->resourceInfo), (void *)&(resourceReqPkt->resourceInfo),\r
590 sizeof(Rm_ResourceInfo));\r
591 \r
592 /* Process the transaction */\r
593 Rm_transactionProcessor(rmInst, transaction);\r
594 break;\r
595 }\r
596 case Rm_pktType_RESOURCE_RESPONSE:\r
597 {\r
598 Rm_ResourceResponsePkt *resourceRespPkt = (Rm_ResourceResponsePkt *)pkt->data;\r
599 \r
600 /* Find the transaction that is awaiting the response */\r
601 transaction = Rm_transactionQueueFind(rmInst,resourceRespPkt->responseId);\r
602 /* Transfer the result of the request to the transaction */\r
603 transaction->state = resourceRespPkt->requestState;\r
604 \r
605 if ((transaction->state == RM_SERVICE_APPROVED) &&\r
606 ((transaction->type == Rm_service_RESOURCE_ALLOCATE) ||\r
607 (transaction->type == Rm_service_RESOURCE_BLOCK_ALLOCATE) ||\r
608 (transaction->type == Rm_service_RESOURCE_ALLOCATE_BY_NAME)))\r
609 {\r
610 /* Copy resources from request for allocations since an allocation\r
611 * can be specified as unknown. Meaning the RM instance will specify the\r
612 * resource value obtained */\r
613 memcpy ((void *)&(transaction->resourceInfo), (void *)&(resourceRespPkt->resourceInfo),\r
614 sizeof(Rm_ResourceInfo));\r
615 }\r
616 \r
617 /* Process the transaction */\r
618 Rm_transactionProcessor(rmInst, transaction);\r
619 break;\r
620 }\r
621 case Rm_pktType_NAMESERVER_REQUEST:\r
622 {\r
623 Rm_NsRequestPkt *nsRequestPkt = (Rm_NsRequestPkt *)pkt->data;\r
624 \r
625 transaction = Rm_transactionQueueAdd(rmInst);\r
626 transaction->remoteOriginatingId = nsRequestPkt->requestId;\r
627 \r
628 if (nsRequestPkt->nsRequestType == Rm_nsReqPktType_MAP_RESOURCE)\r
629 {\r
630 transaction->type = Rm_service_RESOURCE_MAP_TO_NAME;\r
631 }\r
632 else if (nsRequestPkt->nsRequestType == Rm_nsReqPktType_UNMAP_RESOURCE)\r
633 {\r
634 transaction->type = Rm_service_RESOURCE_UNMAP_NAME;\r
635 }\r
636 \r
637 strcpy(transaction->sourceInstName, nsRequestPkt->instName);\r
638 transaction->state = Rm_transactionState_PROCESSING;\r
639 memcpy ((void *)&(transaction->resourceInfo), (void *)&(nsRequestPkt->resourceInfo),\r
640 sizeof(Rm_ResourceInfo));\r
641 \r
642 /* Process the transaction */\r
643 Rm_transactionProcessor(rmInst, transaction); \r
644 break;\r
645 }\r
646 case Rm_pktType_NAMESERVER_RESPONSE:\r
647 {\r
648 Rm_NsResponsePkt *nsResponsePkt = (Rm_NsResponsePkt *)pkt->data;\r
649 \r
650 /* Find the transaction that is awaiting the response */\r
651 transaction = Rm_transactionQueueFind(rmInst, nsResponsePkt->responseId);\r
652 /* Transfer the state of the request to the transaction */\r
653 transaction->state = nsResponsePkt->requestState; \r
654 \r
655 /* Process the transaction */\r
656 Rm_transactionProcessor(rmInst, transaction);\r
657 break;\r
658 }\r
659 case Rm_pktType_POLICY_REQUEST:\r
660 {\r
661 Rm_PolicyRequestPkt *policyRequestPkt = (Rm_PolicyRequestPkt *)pkt->data;\r
662 \r
663 /* FILL IN POLICY API INFORMATION */\r
664 break; \r
665 }\r
666 case Rm_pktType_POLICY_CHANGE:\r
667 {\r
668 Rm_PolicyChangePkt *policyChangePkt = (Rm_PolicyChangePkt *)pkt->data;\r
669 \r
670 /* FILL IN POLICY API INFORMATION */\r
671 break;\r
672 }\r
673 case Rm_pktType_RESOURCE_POOL_MODIFICATION_REQUEST:\r
674 {\r
675 Rm_ResourcePoolModRequestPkt *resPoolModReqPkt = (Rm_ResourcePoolModRequestPkt *)pkt->data;\r
676 \r
677 /* FILL IN RESOURCE POOL MODIFICATION API */\r
678 /* Rm_resourcePoolModRequestHandler(...); Server only - needs to allocate resources to\r
679 * the Client Delegate based on the policy and return those resources to the Client Delegate */\r
680 break;\r
681 }\r
682 case Rm_pktType_RESOURCE_POOL_MODIFICATION_RESPONSE:\r
683 {\r
684 Rm_ResourcePoolModResponsePkt *resPoolModRespPkt = (Rm_ResourcePoolModResponsePkt *)pkt->data;\r
685 \r
686 /* FILL IN RESOURCE POOL MODIFICAITON API */\r
687 /* Rm_resourcePoolModResponseHandler(...); Handler needs to populate allocator with\r
688 * new resources provided in the response and then handle any request transactions waiting on\r
689 * the resource pool modification */\r
690 break;\r
691 }\r
692 default:\r
693 /* Invalid packet type. Free the packet and return */\r
694 rmInst->transport.rmFreePkt(transportHandle, pkt);\r
695 return (RM_TRANSPORT_ERROR_INVALID_PACKET_TYPE);\r
696 }\r
697 \r
698 /* Free the packet after it has been processed */\r
699 rmInst->transport.rmFreePkt(transportHandle, pkt);\r
700 return (RM_TRANSPORT_SUCCESSFUL);\r
701 }\r
702 \r
703 /* Application can call this API so that RM handles reception of packets based on\r
704 * the RM handle and transport handle provided */\r
705 int32_t Rm_receivePktPolling(Rm_TransportHandle transportHandle)\r
706 {\r
707 Rm_Inst *rmInst = (Rm_Inst *)((Rm_TransportNode *)transportHandle)->rmHandle;\r
708 Rm_Packet *pkt = NULL;\r
709 int32_t retVal = RM_TRANSPORT_OK_BASE;\r
710 \r
711 /* Make sure the transport handle is registered with the provided RM instance */\r
712 if (Rm_transportNodeFindTransportHandle(rmInst, transportHandle) == NULL)\r
713 {\r
714 /* Transport is not registered with the RM instance. Return an error.\r
715 * The packet cannot be freed since the transport handle is not valid. */\r
716 return (RM_TRANSPORT_ERROR_HANDLE_HAS_NOT_BEEN_REGISTERED);\r
717 }\r
718 \r
719 /* Check to see if any RM packets are available. Process any available packets. */\r
720 while (rmInst->transport.rmNumPktsReceived(transportHandle) > 0)\r
721 {\r
722 pkt = rmInst->transport.rmReceive(transportHandle);\r
723 \r
724 if (pkt == NULL)\r
725 {\r
726 return (RM_TRANSPORT_ERROR_PACKET_RECEPTION_ERROR);\r
727 }\r
728 \r
729 /* Pass the packet to RM. The packet will be freed within the PktIsr API */\r
730 if (retVal = Rm_receivePktIsr(transportHandle, pkt) <= RM_SERVICE_ERROR_BASE)\r
731 {\r
732 /* Return if an error is encountered */\r
733 return (retVal);\r
734 }\r
735 }\r
736 return (retVal); \r
737 }\r
738 \r
739 /**\r
740 @}\r
741 */\r