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-2013, 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 /* Standard includes */\r
43 #include <string.h>\r
44 #include <stdbool.h>\r
45 \r
46 /* RM external includes */\r
47 #include <ti/drv/rm/rm.h>\r
48 #include <ti/drv/rm/rm_transport.h>\r
49 \r
50 /* RM internal includes */\r
51 #include <ti/drv/rm/include/rm_loc.h>\r
52 #include <ti/drv/rm/include/rm_transportloc.h>\r
53 \r
54 /* RM OSAL layer */\r
55 #include <rm_osal.h>\r
56 \r
57 /**********************************************************************\r
58 ********************** Internal Functions ****************************\r
59 **********************************************************************/\r
60 \r
61 static Rm_Transport *transportAdd(Rm_TransportCfg *transportCfg)\r
62 {\r
63 Rm_Inst *rmInst = (Rm_Inst *) transportCfg->rmHandle;\r
64 Rm_Transport *transports = rmInst->transports;\r
65 Rm_Transport *newTransport = NULL;\r
66 \r
67 newTransport = Rm_osalMalloc (sizeof(Rm_Transport));\r
68 memset((void *)newTransport, 0, sizeof(Rm_Transport));\r
69 \r
70 if (newTransport) {\r
71 newTransport->rmHandle = transportCfg->rmHandle;\r
72 newTransport->appTransportHandle = transportCfg->appTransportHandle;\r
73 newTransport->remoteInstType = transportCfg->remoteInstType;\r
74 strncpy(newTransport->remoteInstName, transportCfg->remoteInstName, RM_NAME_MAX_CHARS);\r
75 newTransport->nextTransport = NULL;\r
76 \r
77 if (transports) {\r
78 while (transports->nextTransport) {\r
79 transports = transports->nextTransport;\r
80 }\r
81 transports->nextTransport = newTransport;\r
82 }\r
83 else {\r
84 rmInst->transports = (void *)newTransport;\r
85 }\r
86 }\r
87 return (newTransport);\r
88 }\r
89 \r
90 static bool transportIsTransportRegistered(Rm_Handle rmHandle, Rm_Transport *transport)\r
91 {\r
92 Rm_Inst *rmInst = (Rm_Inst *)rmHandle;\r
93 Rm_Transport *transportList = (Rm_Transport *)rmInst->transports;\r
94 \r
95 while (transportList) {\r
96 if (transportList == transport) {\r
97 return(true); \r
98 }\r
99 transportList = transportList->nextTransport;\r
100 }\r
101 return (false);\r
102 }\r
103 \r
104 static void transportDelete(Rm_Transport *transport)\r
105 {\r
106 Rm_Inst *rmInst = (Rm_Inst *)transport->rmHandle;\r
107 Rm_Transport *transportList = (Rm_Transport *)rmInst->transports;\r
108 Rm_Transport *prevTransport = NULL;\r
109 \r
110 /* Get previous transport in list */\r
111 while (transportList) {\r
112 if (transportList == transport) {\r
113 break; \r
114 }\r
115 prevTransport = transportList;\r
116 transportList = transportList->nextTransport;\r
117 }\r
118 \r
119 if (prevTransport == NULL) {\r
120 rmInst->transports = (void *)transport->nextTransport;\r
121 }\r
122 else {\r
123 prevTransport->nextTransport = transport->nextTransport;\r
124 }\r
125 Rm_osalFree((void *)transport, sizeof(Rm_Transport));\r
126 }\r
127 \r
128 Rm_Transport *rmTransportFindRemoteName(Rm_Transport *transports, char *remoteName)\r
129 {\r
130 while (transports) {\r
131 if (strncmp(transports->remoteInstName, remoteName, RM_NAME_MAX_CHARS) == 0) {\r
132 break; \r
133 }\r
134 transports = transports->nextTransport;\r
135 }\r
136 return (transports);\r
137 }\r
138 \r
139 Rm_Transport *rmTransportFindRemoteInstType(Rm_Transport *transports, Rm_InstType remoteInstType)\r
140 {\r
141 while (transports) {\r
142 if (transports->remoteInstType == remoteInstType) {\r
143 break; \r
144 }\r
145 transports = transports->nextTransport;\r
146 }\r
147 return (transports);\r
148 }\r
149 \r
150 Rm_PacketHandle rmTransportCreateResourceReqPkt(Rm_Inst *rmInst, Rm_AppTransportHandle appTransport,\r
151 Rm_Transaction *transaction)\r
152 {\r
153 Rm_Packet *rmPkt = NULL;\r
154 Rm_PacketHandle pktHandle = NULL;\r
155 Rm_ResourceRequestPkt *resourceReqPkt = NULL;\r
156 \r
157 if ((rmPkt = rmInst->transportCallouts.rmAllocPkt(appTransport, \r
158 sizeof(Rm_Packet),\r
159 &pktHandle)) == NULL) {\r
160 transaction->state = RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR;\r
161 return (NULL);\r
162 }\r
163 \r
164 rmPkt->pktType = Rm_pktType_RESOURCE_REQUEST;\r
165 resourceReqPkt = (Rm_ResourceRequestPkt *) rmPkt->data;\r
166 resourceReqPkt->requestId = transaction->localId;\r
167 if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {\r
168 resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE_INIT;\r
169 }\r
170 else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {\r
171 resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE_USE;\r
172 } \r
173 else if (transaction->type == Rm_service_RESOURCE_FREE) {\r
174 resourceReqPkt->resourceReqType = Rm_resReqPktType_FREE;\r
175 }\r
176 else if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {\r
177 resourceReqPkt->resourceReqType = Rm_resReqPktType_GET_NAMED;\r
178 }\r
179 strncpy(resourceReqPkt->pktSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS);\r
180 strncpy(resourceReqPkt->serviceSrcInstName, transaction->serviceSrcInstName, RM_NAME_MAX_CHARS);\r
181 memcpy ((void *)&(resourceReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),\r
182 sizeof(Rm_ResourceInfo));\r
183 \r
184 return (pktHandle);\r
185 }\r
186 \r
187 Rm_PacketHandle rmTransportCreateResourceResponsePkt(Rm_Inst *rmInst, Rm_AppTransportHandle appTransport,\r
188 Rm_Transaction *transaction)\r
189 {\r
190 Rm_Packet *rmPkt = NULL;\r
191 Rm_PacketHandle pktHandle = NULL;\r
192 Rm_ResourceResponsePkt *resourceRespPkt = NULL;\r
193 \r
194 if ((rmPkt = rmInst->transportCallouts.rmAllocPkt(appTransport, \r
195 sizeof(Rm_Packet),\r
196 &pktHandle)) == NULL) {\r
197 transaction->state = RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR;\r
198 return (NULL);\r
199 }\r
200 \r
201 rmPkt->pktType = Rm_pktType_RESOURCE_RESPONSE; \r
202 resourceRespPkt = (Rm_ResourceResponsePkt *)rmPkt->data;\r
203 resourceRespPkt->responseId = transaction->remoteOriginatingId;\r
204 resourceRespPkt->requestState = transaction->state;\r
205 memcpy ((void *)&(resourceRespPkt->resourceInfo), (void *)&(transaction->resourceInfo),\r
206 sizeof(Rm_ResourceInfo));\r
207 \r
208 return (pktHandle);\r
209 }\r
210 \r
211 Rm_PacketHandle rmTransportCreateNsRequestPkt(Rm_Inst *rmInst, Rm_AppTransportHandle appTransport,\r
212 Rm_Transaction *transaction)\r
213 {\r
214 Rm_Packet *rmPkt = NULL;\r
215 Rm_PacketHandle pktHandle = NULL; \r
216 Rm_NsRequestPkt *nsReqPkt = NULL;\r
217 \r
218 if ((rmPkt = rmInst->transportCallouts.rmAllocPkt(appTransport, \r
219 sizeof(Rm_Packet),\r
220 &pktHandle)) == NULL) {\r
221 transaction->state = RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR;\r
222 return (NULL);\r
223 }\r
224 \r
225 rmPkt->pktType = Rm_pktType_NAMESERVER_REQUEST; \r
226 nsReqPkt = (Rm_NsRequestPkt *)rmPkt->data;\r
227 nsReqPkt->requestId = transaction->localId;\r
228 if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {\r
229 nsReqPkt->nsRequestType = Rm_nsReqPktType_MAP_RESOURCE;\r
230 }\r
231 else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME) {\r
232 nsReqPkt->nsRequestType = Rm_nsReqPktType_UNMAP_RESOURCE;\r
233 }\r
234 strncpy(nsReqPkt->pktSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS);\r
235 strncpy(nsReqPkt->serviceSrcInstName, transaction->serviceSrcInstName, RM_NAME_MAX_CHARS);\r
236 memcpy ((void *)&(nsReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),\r
237 sizeof(Rm_ResourceInfo));\r
238 \r
239 return (pktHandle);\r
240 }\r
241 \r
242 Rm_PacketHandle rmTransportCreateNsResponsePkt(Rm_Inst *rmInst, Rm_AppTransportHandle appTransport,\r
243 Rm_Transaction *transaction)\r
244 {\r
245 Rm_Packet *rmPkt = NULL;\r
246 Rm_PacketHandle pktHandle = NULL;\r
247 Rm_NsResponsePkt *nsRespPkt = NULL;\r
248 \r
249 if ((rmPkt = rmInst->transportCallouts.rmAllocPkt(appTransport, \r
250 sizeof(Rm_Packet),\r
251 &pktHandle)) == NULL) {\r
252 transaction->state = RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR;\r
253 return (NULL);\r
254 }\r
255 \r
256 rmPkt->pktType = Rm_pktType_NAMESERVER_RESPONSE; \r
257 nsRespPkt = (Rm_NsResponsePkt *)rmPkt->data;\r
258 nsRespPkt->responseId = transaction->remoteOriginatingId;\r
259 nsRespPkt->requestState = transaction->state;\r
260 \r
261 return (pktHandle);\r
262 }\r
263 \r
264 /**********************************************************************\r
265 ********************* Application visible APIs ***********************\r
266 **********************************************************************/\r
267 \r
268 Rm_TransportHandle Rm_transportRegister (Rm_TransportCfg *transportCfg, int32_t *result)\r
269 {\r
270 Rm_Inst *rmInst = (Rm_Inst *) transportCfg->rmHandle;\r
271 Rm_Transport *transport = NULL;\r
272 \r
273 /* RM Servers cannot connect to other Servers. \r
274 * RM Client Delegates cannot connect to other Client Delegates.\r
275 * RM Clients cannot connect to other Clients */\r
276 if (((rmInst->instType == Rm_instType_SERVER) &&\r
277 (transportCfg->remoteInstType == Rm_instType_SERVER)) ||\r
278 ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
279 (transportCfg->remoteInstType == Rm_instType_CLIENT_DELEGATE)) ||\r
280 ((rmInst->instType == Rm_instType_CLIENT) &&\r
281 (transportCfg->remoteInstType == Rm_instType_CLIENT))) {\r
282 *result = RM_ERROR_INVALID_REMOTE_INST_TYPE;\r
283 return(NULL);\r
284 }\r
285 \r
286 /* Verify Clients are not registering with more than one Client Delegate or Server. And\r
287 * that Client Delegate is not registering with more than one Server. */\r
288 if (rmInst->registeredWithDelegateOrServer &&\r
289 (((rmInst->instType == Rm_instType_CLIENT) &&\r
290 (transportCfg->remoteInstType == Rm_instType_CLIENT_DELEGATE)) || \r
291 ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
292 (transportCfg->remoteInstType == Rm_instType_SERVER)))) {\r
293 *result = RM_ERROR_ALREADY_REGD_SERVER_OR_CD;\r
294 return(NULL);\r
295 } \r
296 \r
297 if (transportCfg->transportCalloutsValid &&\r
298 ((transportCfg->transportCallouts.rmAllocPkt == NULL) ||\r
299 (transportCfg->transportCallouts.rmSendPkt == NULL))) {\r
300 *result = RM_ERROR_NULL_CALLOUTS_WHEN_VALID;\r
301 return(NULL);\r
302 }\r
303 else {\r
304 rmInst->transportCallouts.rmAllocPkt = transportCfg->transportCallouts.rmAllocPkt;\r
305 rmInst->transportCallouts.rmSendPkt = transportCfg->transportCallouts.rmSendPkt;\r
306 }\r
307 \r
308 transport = transportAdd(transportCfg);\r
309 \r
310 if ((transport->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||\r
311 (transport->remoteInstType == Rm_instType_SERVER)) {\r
312 rmInst->registeredWithDelegateOrServer = true;\r
313 }\r
314 \r
315 *result = RM_OK;\r
316 return ((Rm_TransportHandle) transport);\r
317 }\r
318 \r
319 int32_t Rm_transportUnregister(Rm_TransportHandle transportHandle)\r
320 {\r
321 Rm_Transport *transport = (Rm_Transport *)transportHandle;\r
322 Rm_Inst *rmInst = (Rm_Inst *)transport->rmHandle;\r
323 int32_t retVal = RM_OK; \r
324 \r
325 if (transportIsTransportRegistered(transport->rmHandle, transport)) {\r
326 if ((transport->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||\r
327 (transport->remoteInstType == Rm_instType_SERVER)) {\r
328 rmInst->registeredWithDelegateOrServer = false;\r
329 }\r
330 transportDelete(transport);\r
331 }\r
332 else {\r
333 retVal = RM_ERROR_TRANSPORT_HANDLE_DOES_NOT_EXIST;\r
334 }\r
335 return (retVal);\r
336 }\r
337 \r
338 /* Used by the application to pass RM packets received from a transport to RM.\r
339 * Function can be called from polling or ISR context. */\r
340 int32_t Rm_receivePacket(Rm_TransportHandle transportHandle, Rm_Packet *pkt)\r
342 Rm_Transport *transport = (Rm_Transport *)transportHandle;\r
343 Rm_Inst *rmInst = (Rm_Inst *)transport->rmHandle;\r
344 Rm_Transaction *transaction;\r
345 \r
346 if (!transportIsTransportRegistered(transport->rmHandle, transport)) {\r
347 return (RM_ERROR_TRANSPORT_HANDLE_DOES_NOT_EXIST);\r
348 }\r
349 \r
350 switch (pkt->pktType) {\r
351 case Rm_pktType_RESOURCE_REQUEST:\r
352 {\r
353 Rm_ResourceRequestPkt *resourceReqPkt = (Rm_ResourceRequestPkt *)pkt->data;\r
354 \r
355 transaction = rmTransactionQueueAdd(rmInst);\r
356 transaction->remoteOriginatingId = resourceReqPkt->requestId;\r
357 if (resourceReqPkt->resourceReqType == Rm_resReqPktType_ALLOCATE_INIT) {\r
358 transaction->type = Rm_service_RESOURCE_ALLOCATE_INIT;\r
359 }\r
360 else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_ALLOCATE_USE) {\r
361 transaction->type = Rm_service_RESOURCE_ALLOCATE_USE;\r
362 } \r
363 else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_FREE) {\r
364 transaction->type = Rm_service_RESOURCE_FREE;\r
365 }\r
366 else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_GET_NAMED) {\r
367 transaction->type = Rm_service_RESOURCE_GET_BY_NAME;\r
368 } \r
369 strncpy(transaction->pktSrcInstName, resourceReqPkt->pktSrcInstName, RM_NAME_MAX_CHARS);\r
370 strncpy(transaction->serviceSrcInstName, resourceReqPkt->serviceSrcInstName, RM_NAME_MAX_CHARS);\r
371 transaction->state = RM_SERVICE_PROCESSING;\r
372 memcpy ((void *)&(transaction->resourceInfo), (void *)&(resourceReqPkt->resourceInfo),\r
373 sizeof(Rm_ResourceInfo));\r
374 rmTransactionProcessor(rmInst, transaction);\r
375 break;\r
376 }\r
377 case Rm_pktType_RESOURCE_RESPONSE:\r
378 {\r
379 Rm_ResourceResponsePkt *resourceRespPkt = (Rm_ResourceResponsePkt *)pkt->data;\r
380 \r
381 if (transaction = rmTransactionQueueFind(rmInst,resourceRespPkt->responseId)) {\r
382 if ((transaction->state == RM_SERVICE_APPROVED_STATIC) &&\r
383 (resourceRespPkt->requestState != RM_SERVICE_APPROVED)) {\r
384 /* Lock the RM instance since service validated against static policy failed against \r
385 * Server's global policy */\r
386 rmInst->isLocked = true;\r
387 }\r
388 transaction->state = resourceRespPkt->requestState;\r
389 \r
390 if ((transaction->state == RM_SERVICE_APPROVED) &&\r
391 ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||\r
392 (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||\r
393 (transaction->type == Rm_service_RESOURCE_GET_BY_NAME))) {\r
394 memcpy ((void *)&(transaction->resourceInfo), (void *)&(resourceRespPkt->resourceInfo),\r
395 sizeof(Rm_ResourceInfo));\r
396 }\r
397 rmTransactionProcessor(rmInst, transaction);\r
398 }\r
399 else {\r
400 return (RM_ERROR_PKT_RESP_DOES_NOT_MATCH_ANY_REQ);\r
401 }\r
402 break;\r
403 }\r
404 case Rm_pktType_NAMESERVER_REQUEST:\r
405 {\r
406 Rm_NsRequestPkt *nsRequestPkt = (Rm_NsRequestPkt *)pkt->data;\r
407 \r
408 transaction = rmTransactionQueueAdd(rmInst);\r
409 transaction->remoteOriginatingId = nsRequestPkt->requestId;\r
410 \r
411 if (nsRequestPkt->nsRequestType == Rm_nsReqPktType_MAP_RESOURCE) {\r
412 transaction->type = Rm_service_RESOURCE_MAP_TO_NAME;\r
413 }\r
414 else if (nsRequestPkt->nsRequestType == Rm_nsReqPktType_UNMAP_RESOURCE) {\r
415 transaction->type = Rm_service_RESOURCE_UNMAP_NAME;\r
416 }\r
417 \r
418 strncpy(transaction->pktSrcInstName, nsRequestPkt->pktSrcInstName, RM_NAME_MAX_CHARS);\r
419 strncpy(transaction->serviceSrcInstName, nsRequestPkt->serviceSrcInstName, RM_NAME_MAX_CHARS);\r
420 transaction->state = RM_SERVICE_PROCESSING;\r
421 memcpy ((void *)&(transaction->resourceInfo), (void *)&(nsRequestPkt->resourceInfo),\r
422 sizeof(Rm_ResourceInfo));\r
423 rmTransactionProcessor(rmInst, transaction); \r
424 break;\r
425 }\r
426 case Rm_pktType_NAMESERVER_RESPONSE:\r
427 {\r
428 Rm_NsResponsePkt *nsResponsePkt = (Rm_NsResponsePkt *)pkt->data;\r
429 \r
430 if (transaction = rmTransactionQueueFind(rmInst, nsResponsePkt->responseId)) {\r
431 if ((transaction->state == RM_SERVICE_APPROVED_STATIC) &&\r
432 (nsResponsePkt->requestState != RM_SERVICE_APPROVED)) {\r
433 /* Lock the RM instance since service validated against static policy failed against \r
434 * Server's global policy */ \r
435 rmInst->isLocked = true;\r
436 } \r
437 transaction->state = nsResponsePkt->requestState; \r
438 rmTransactionProcessor(rmInst, transaction);\r
439 }\r
440 else {\r
441 return (RM_ERROR_PKT_RESP_DOES_NOT_MATCH_ANY_REQ);\r
442 }\r
443 break;\r
444 }\r
445 default:\r
446 return (RM_ERROR_RECEIVED_INVALID_PACKET_TYPE);\r
447 }\r
448 \r
449 return (RM_OK);\r
450 }\r
451 \r