Support in QNX MmRpc/MmServiceMgr to identify deleted instance during cleanup
[ipc/ipcdev.git] / packages / ti / srvmgr / omaprpc / OmapRpc.c
1 /*
2  * Copyright (c) 2012-2014, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
33 #include <xdc/std.h>
34 #include <xdc/cfg/global.h>
35 #include <xdc/runtime/System.h>
36 #include <xdc/runtime/Memory.h>
38 #include <ti/sysbios/BIOS.h>
39 #include <ti/sysbios/knl/Semaphore.h>
40 #include <ti/sysbios/knl/Task.h>
42 #include <ti/grcm/RcmTypes.h>
43 #include <ti/grcm/RcmServer.h>
45 #include <string.h>
46 #include <stdlib.h>
48 #include <ti/ipc/mm/MmType.h>
49 #include <ti/ipc/rpmsg/RPMessage.h>
50 #include <ti/ipc/rpmsg/NameMap.h>
51 #include <ti/srvmgr/ServiceMgr.h>
53 #include "OmapRpc.h"
55 typedef struct OmapRpc_Object {
56     Char                     channelName[OMAPRPC_MAX_CHANNEL_NAMELEN];
57     UInt16                   dstProc;
58     UInt32                   port;
59     RPMessage_Handle         msgq;
60     UInt32                   localEndPt;
61     Task_Handle              taskHandle;
62     Bool                     shutdown;
63     Semaphore_Handle         exitSem;
64     OmapRpc_SrvDelNotifyFxn  srvDelCB;
65     OmapRpc_SrvDelNotifyFxn2 srvDelCB2;
66     RcmServer_Params         rcmParams;
67     UInt32                   numFuncs;
68     OmapRpc_FuncSignature   *funcSigs;
69 } OmapRpc_Object;
71 static OmapRpc_Handle _OmapRpc_createChannel(String channelName, UInt16 dstProc,
72         UInt32 port, RcmServer_Params *rcmParams, MmType_FxnSigTab *fxnSigTab);
74 Int32 OmapRpc_GetSvrMgrHandle(Void *srvc, Int32 num, Int32 *params)
75 {
76     System_printf("OMAPRPC: Calling RCM Service Manager Create Function!\n");
77     return 0;
78 }
80 static Void omapRpcTask(UArg arg0, UArg arg1)
81 {
82     OmapRpc_Object *obj = (OmapRpc_Object *)arg0;
83     UInt32 local;
84     UInt32 remote;
85     Int status;
86     UInt16 len;
87     Char  * msg = NULL;
88     OmapRpc_MsgHeader *hdr = NULL;
90     msg = Memory_alloc(NULL, 512, 0, NULL); /* maximum rpmsg size is probably
91                                              * smaller, but we need to
92                                              * be cautious */
93     if (msg == NULL) {
94         System_printf("OMAPRPC: Failed to allocate msg!\n");
95         return;
96     }
98     hdr = (OmapRpc_MsgHeader *)&msg[0];
100     if (obj == NULL) {
101         System_printf("OMAPRPC: Failed to start task as arguments are NULL!\n");
102         return;
103     }
105     if (obj->msgq == NULL) {
106         System_printf("OMAPRPC: Failed to start task as MessageQ was NULL!\n");
107         return;
108     }
110     /* get the local endpoint we are to use */
111     local = obj->localEndPt;
112     System_printf("OMAPRPC: connecting from local endpoint %u to port %u\n",
113                         obj->localEndPt, obj->port);
115     NameMap_register("rpmsg-rpc", obj->channelName, obj->port);
117     System_printf("OMAPRPC: started channel on port: %d\n", obj->port);
119     while (!obj->shutdown) {
121         /* clear out the message and our message vars */
122         _memset(msg, 0, sizeof(msg));
123         len = 0;
124         remote = 0;
126         /* receive the message */
127         status = RPMessage_recv(obj->msgq, (Ptr)msg, &len, &remote,
128                                         RPMessage_FOREVER);
130         if (status == RPMessage_E_UNBLOCKED) {
131             System_printf("OMAPRPC: unblocked while waiting for messages\n");
132             continue;
133         }
135         System_printf("OMAPRPC: received msg type: %d len: %d from addr: %d\n",
136                              hdr->msgType, len, remote);
137         switch (hdr->msgType) {
138             case OmapRpc_MsgType_CREATE_INSTANCE:
139             {
140                 /* temp pointer to payload */
141                 OmapRpc_CreateInstance *create =
142                                 OmapRpc_PAYLOAD(msg, OmapRpc_CreateInstance);
143                 /* local copy of name */
144                 Char name[sizeof(create->name)];
145                 /* return structure */
146                 OmapRpc_InstanceHandle *handle =
147                                 OmapRpc_PAYLOAD(msg, OmapRpc_InstanceHandle);
148                 /* save a copy of the input structure data */
149                 _strcpy(name, create->name);
150                 /* clear out the old data */
151                 _memset(msg, 0, sizeof(msg));
153                 /* create a new instance of the service */
154                 handle->status = ServiceMgr_createService(name,
155                                                 &handle->endpointAddress);
157                 System_printf("OMAPRPC: created service instance named: %s "
158                               "(status=%d) addr: %d\n", name, handle->status,
159                                 handle->endpointAddress);
161                 hdr->msgType = OmapRpc_MsgType_INSTANCE_CREATED;
162                 hdr->msgLen  = sizeof(OmapRpc_InstanceHandle);
163                 break;
164             }
165             case OmapRpc_MsgType_DESTROY_INSTANCE:
166             {
167                 /* temp pointer to payload */
168                 OmapRpc_InstanceHandle *handle =
169                                 OmapRpc_PAYLOAD(msg, OmapRpc_InstanceHandle);
171                 if (obj->srvDelCB != NULL) {
172                     obj->srvDelCB();
173                 }
174                 else if (obj->srvDelCB2 != NULL) {
175                     obj->srvDelCB2(handle->endpointAddress);
176                 }
178                 /* don't clear out the old data... */
179                 System_printf("OMAPRPC: destroying instance addr: %d\n",
180                                                     handle->endpointAddress);
181                 handle->status = ServiceMgr_deleteService(
182                                                     handle->endpointAddress);
183                 hdr->msgType = OmapRpc_MsgType_INSTANCE_DESTROYED;
184                 hdr->msgLen = sizeof(OmapRpc_InstanceHandle);
185                 /* leave the endpoint address alone. */
186                 break;
187             }
188             case OmapRpc_MsgType_QUERY_CHAN_INFO:
189             {
190                 OmapRpc_ChannelInfo *chanInfo =
191                                       OmapRpc_PAYLOAD(msg, OmapRpc_ChannelInfo);
193                 chanInfo->numFuncs = obj->numFuncs;
194                 System_printf("OMAPRPC: channel info query - name %s fxns %u\n",
195                                             obj->channelName, chanInfo->numFuncs);
196                 hdr->msgType = OmapRpc_MsgType_CHAN_INFO;
197                 hdr->msgLen = sizeof(OmapRpc_ChannelInfo);
198                 break;
199             }
200             case OmapRpc_MsgType_QUERY_FUNCTION:
201             {
202                 OmapRpc_QueryFunction *fxnInfo = OmapRpc_PAYLOAD(msg,
203                                                          OmapRpc_QueryFunction);
204                 System_printf("OMAPRPC: function query of type %u\n",
205                               fxnInfo->infoType);
207                 switch (fxnInfo->infoType)
208                 {
209                     case OmapRpc_InfoType_FUNC_SIGNATURE:
210                         if (fxnInfo->funcIndex < obj->numFuncs)
211                             memcpy(&fxnInfo->info.signature,
212                                    &obj->funcSigs[fxnInfo->funcIndex],
213                                    sizeof(OmapRpc_FuncSignature));
214                         break;
215                     case OmapRpc_InfoType_FUNC_PERFORMANCE:
216                         break;
217                     case OmapRpc_InfoType_NUM_CALLS:
218                         break;
219                     default:
220                         System_printf("OMAPRPC: Invalid info type!\n");
221                         break;
222                 }
223                 hdr->msgType = OmapRpc_MsgType_FUNCTION_INFO;
224                 hdr->msgLen = sizeof(OmapRpc_QueryFunction);
225                 break;
226             }
227             default:
228             {
229                 /* temp pointer to payload */
230                 OmapRpc_Error *err = OmapRpc_PAYLOAD(msg, OmapRpc_Error);
232                 /* the debugging message before we clear */
233                 System_printf("OMAPRPC: unexpected msg type: %d\n",
234                               hdr->msgType);
236                 /* clear out the old data */
237                 _memset(msg, 0, sizeof(msg));
239                 hdr->msgType = OmapRpc_MsgType_ERROR;
240                 err->endpointAddress = local;
241                 err->status = OmapRpc_ErrorType_NOT_SUPPORTED;
242                 break;
243             }
244        }
246        /* compute the length of the return message. */
247        len = sizeof(struct OmapRpc_MsgHeader) + hdr->msgLen;
249        System_printf("OMAPRPC: Replying with msg type: %d to addr: %d "
250                       " from: %d len: %u\n", hdr->msgType, remote, local, len);
252        /* send the response. All messages get responses! */
253        RPMessage_send(obj->dstProc, remote, local, msg, len);
254     }
256     System_printf("OMAPRPC: destroying channel on port: %d\n", obj->port);
257     NameMap_unregister("rpmsg-rpc", obj->channelName, obj->port);
258     if (msg != NULL) {
259        Memory_free(NULL, msg, 512);
260     }
261     /* @TODO delete any outstanding ServiceMgr instances if no disconnect
262      * was issued? */
264     Semaphore_post(obj->exitSem);
267 /*
268  *  ======== OmapRpc_createChannel ========
269  */
270 OmapRpc_Handle OmapRpc_createChannel(String channelName, UInt16 dstProc,
271         UInt32 port, RcmServer_Params *rcmParams, MmType_FxnSigTab *fxnSigTab,
272         OmapRpc_SrvDelNotifyFxn srvDelCBFunc)
274     OmapRpc_Object * obj;
276     obj = _OmapRpc_createChannel(channelName, dstProc, port, rcmParams,
277         fxnSigTab);
278     if (obj != NULL) {
279         obj->srvDelCB = srvDelCBFunc;
280     }
282     return (obj);
285 /*
286  *  ======== OmapRpc_createChannel2 ========
287  */
288 OmapRpc_Handle OmapRpc_createChannel2(String channelName, UInt16 dstProc,
289         UInt32 port, RcmServer_Params *rcmParams, MmType_FxnSigTab *fxnSigTab,
290         OmapRpc_SrvDelNotifyFxn2 srvDelCBFunc2)
292     OmapRpc_Object * obj;
294     obj = _OmapRpc_createChannel(channelName, dstProc, port, rcmParams,
295         fxnSigTab);
296     if (obj != NULL) {
297         obj->srvDelCB2 = srvDelCBFunc2;
298     }
300     return (obj);
304 /*
305  *  ======== _OmapRpc_createChannel ========
306  */
307 static OmapRpc_Handle _OmapRpc_createChannel(String channelName, UInt16 dstProc,
308         UInt32 port, RcmServer_Params *rcmParams, MmType_FxnSigTab *fxnSigTab)
310     Task_Params taskParams;
311     UInt32      func;
313     OmapRpc_Object *obj = Memory_alloc(NULL, sizeof(OmapRpc_Object), 0, NULL);
315     if (obj == NULL) {
316         System_printf("OMAPRPC: Failed to allocate memory for object!\n");
317         goto unload;
318     }
319     _memset(obj, 0, sizeof(OmapRpc_Object));
320     obj->numFuncs = fxnSigTab->count + 1;
321 #if 0
322     RcmServer_Params_init(&obj->rcmParams);
323     obj->rcmParams.priority = Thread_Priority_ABOVE_NORMAL;
324     obj->rcmParams.stackSize = 0x1000;
325     obj->rcmParams.fxns.length = obj->numFuncs;
326     obj->rcmParams.fxns.elem = Memory_alloc(NULL,
327             sizeof(RcmServer_FxnDesc) * obj->numFuncs, 0, NULL);
329     if (obj->rcmParams.fxns.elem == NULL) {
330         System_printf("OMAPRPC: Failed to allocate RCM function list!\n");
331         goto unload;
332     }
333 #else
334     memcpy(&obj->rcmParams, rcmParams, sizeof(RcmServer_Params));
335     obj->rcmParams.fxns.length = obj->numFuncs;
336     obj->rcmParams.fxns.elem = Memory_calloc(NULL, obj->numFuncs *
337             sizeof(RcmServer_FxnDesc), 0, NULL);
339     if (obj->rcmParams.fxns.elem == NULL) {
340         System_printf("OMAPRPC: Failed to allocate RCM function list!\n");
341         goto unload;
342     }
343 #endif
345     /* setup other variables... */
346     obj->shutdown = FALSE;
347     obj->dstProc = dstProc;
348     obj->port = port;
349     strncpy(obj->channelName, channelName, OMAPRPC_MAX_CHANNEL_NAMELEN-1);
350     obj->channelName[OMAPRPC_MAX_CHANNEL_NAMELEN-1]='\0';
351     obj->funcSigs = Memory_alloc(NULL, obj->numFuncs *
352             sizeof(OmapRpc_FuncSignature), 0, NULL);
354     if (obj->funcSigs == NULL) {
355         System_printf("OMAPRPC: Failed to allocate signtures list!\n");
356         goto unload;
357     }
359     /* setup the RCM functions and Signatures */
360     for (func = 0; func < obj->numFuncs; func++) {
361         if (func == 0) {
362             /* assign the "first function" */
363             obj->rcmParams.fxns.elem[func].name =
364                     OmapRpc_Stringerize(OmapRpc_GetSvrMgrHandle);
365             obj->rcmParams.fxns.elem[func].addr.createFxn =
366                     (RcmServer_MsgCreateFxn)OmapRpc_GetSvrMgrHandle;
368             strncpy(obj->funcSigs[func].name, obj->rcmParams.fxns.elem[0].name,
369                     OMAPRPC_MAX_CHANNEL_NAMELEN);
370             obj->funcSigs[func].numParam = 0;
371         }
372         else {
373             /* assign the other functions */
374 /*          obj->rcmParams.fxns.elem[func].name = fxns[func-1].signature.name; */
375             obj->rcmParams.fxns.elem[func].name =
376                     rcmParams->fxns.elem[func-1].name;
377 /*          obj->rcmParams.fxns.elem[func].addr.fxn =
378                     (RcmServer_MsgFxn)fxns[func-1].function; */
379             obj->rcmParams.fxns.elem[func].addr.fxn =
380                     rcmParams->fxns.elem[func-1].addr.fxn;
382             /* copy the signature */
383 /*          memcpy(&obj->funcSigs[func], &fxns[func-1].signature,
384                     sizeof(OmapRpc_FuncSignature)); */
385             memcpy(&obj->funcSigs[func], &fxnSigTab->table[func - 1],
386                     sizeof(MmType_FxnSig));
387         }
388     }
390     ServiceMgr_init();
392     if (ServiceMgr_register(channelName, &obj->rcmParams) == TRUE) {
393         System_printf("OMAPRPC: registered channel: %s\n", obj->channelName);
395         obj->msgq = RPMessage_create(obj->port, NULL, NULL,&obj->localEndPt);
397         if (obj->msgq == NULL) {
398             goto unload;
399         }
401         Task_Params_init(&taskParams);
402         taskParams.instance->name = channelName;
403         taskParams.stackSize = 0x2000; /* must cover all proxy stack usage */
404         taskParams.priority = 1;   /* lowest priority thread */
405         taskParams.arg0 = (UArg)obj;
407         obj->exitSem = Semaphore_create(0, NULL, NULL);
409         if (obj->exitSem == NULL) {
410             goto unload;
411         }
413         obj->taskHandle = Task_create(omapRpcTask, &taskParams, NULL);
415         if (obj->taskHandle == NULL) {
416             goto unload;
417         }
418     }
419     else {
420         System_printf("OMAPRPC: FAILED to register channel: %s\n",
421                 obj->channelName);
422     }
424     System_printf("OMAPRPC: Returning Object %p\n", obj);
425     return(obj);
427 unload:
428     OmapRpc_deleteChannel(obj);
429     return(NULL);
432 Int OmapRpc_deleteChannel(OmapRpc_Handle handle)
434     OmapRpc_Object *obj = (OmapRpc_Object *)handle;
436     if (obj == NULL) {
437         return OmapRpc_E_FAIL;
438     }
440     System_printf("OMAPRPC: deleting channel %s\n", obj->channelName);
441     obj->shutdown = TRUE;
442     if (obj->msgq) {
443         RPMessage_unblock(obj->msgq);
444         if (obj->exitSem) {
445             Semaphore_pend(obj->exitSem, BIOS_WAIT_FOREVER);
446             RPMessage_delete(&obj->msgq);
447             Semaphore_delete(&obj->exitSem);
448         }
449         if (obj->taskHandle) {
450             Task_delete(&obj->taskHandle);
451         }
452     }
453     if (obj->funcSigs)
454         Memory_free(NULL, obj->funcSigs, sizeof(*obj->funcSigs)*(obj->numFuncs-1));
455     if (obj->rcmParams.fxns.elem)
456         Memory_free(NULL, obj->rcmParams.fxns.elem,
457                     sizeof(obj->rcmParams.fxns.elem[0])*obj->numFuncs);
459     Memory_free(NULL, obj, sizeof(*obj));
460     return OmapRpc_S_SUCCESS;
463 #if 0
464 /*
465  *  ======== OmapRpc_start ========
466  */
467 Int OmapRpc_start(const String name, Int port, Int aryLen,
468         OmapRpc_FuncSignature *sigAry)
470     Int status = OmapRpc_S_SUCCESS;
471     Task_Params taskParams;
472     OmapRpc_Object *obj;
474     /* create an instance */
475     obj = Memory_calloc(NULL, sizeof(OmapRpc_Object), 0, NULL);
477     if (obj == NULL) {
478         System_printf("OMAPRPC: Failed to allocate memory for object!\n");
479         status = OmapRpc_E_FAIL;
480         goto leave;
481     }
483     obj->numFuncs = aryLen + 1;
484     obj->shutdown = FALSE;
485     obj->dstProc = MultiProc_getId("HOST");
486     obj->port = port;
487     strncpy(obj->channelName, name, OMAPRPC_MAX_CHANNEL_NAMELEN-1);
488     obj->channelName[OMAPRPC_MAX_CHANNEL_NAMELEN-1]='\0';
489     obj->srvDelCB = srvDelCBFunc;
490     obj->funcSigs = Memory_alloc(NULL,
491             sizeof(OmapRpc_FuncSignature) * obj->numFuncs, 0, NULL);
493     if (obj->funcSigs == NULL) {
494         System_printf("OMAPRPC: Failed to allocate signtures list!\n");
495         goto unload;
496     }
498     /* setup the functions and signatures */
499     for (func = 0; func < obj->numFuncs; func++) {
500         if (func == 0) {
501             /* assign the "first function" */
502 /*          strncpy(obj->funcSigs[func].name, obj->rcmParams.fxns.elem[0].name,
503                     OMAPRPC_MAX_CHANNEL_NAMELEN); */
504             strncpy(obj->funcSigs[func].name,
505                     OmapRpc_Stringerize(OmapRpc_GetSvrMgrHandle),
506                     OMAPRPC_MAX_CHANNEL_NAMELEN);
507             obj->funcSigs[func].numParam = 0;
508         }
509         else {
510             /* copy the signature */
511             memcpy(&obj->funcSigs[func], &fxns[func-1].signature,
512                     sizeof(OmapRpc_FuncSignature));
513         }
514     }
516     obj->msgq = RPMessage_create(obj->port, NULL, NULL,&obj->localEndPt);
518     if (obj->msgq == NULL) {
519         goto unload;
520     }
522     Task_Params_init(&taskParams);
523     taskParams.instance->name = channelName;
524     taskParams.priority = 1;   /* Lowest priority thread */
525     taskParams.arg0 = (UArg)obj;
527     obj->exitSem = Semaphore_create(0, NULL, NULL);
529     if (obj->exitSem == NULL) {
530         goto unload;
531     }
533     obj->taskHandle = Task_create(omapRpcTask, &taskParams, NULL);
535     if (obj->taskHandle == NULL) {
536         goto unload;
537     }
539     System_printf("OMAPRPC: Returning Object %p\n", obj);
540     return(obj);
542 leave:
543     if (status < 0) {
544         OmapRpc_deleteChannel(obj);
545     }
546     return(status);
548 #endif