41e1fa7d8362067445313330c1332ba22f95e327
[ipc/ipcdev.git] / packages / ti / srvmgr / omaprpc / OmapRpc.c
1 /*
2  * Copyright (c) 2012-2013, 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     RcmServer_Params        rcmParams;
66     UInt32                  numFuncs;
67     OmapRpc_FuncSignature  *funcSigs;
68 } OmapRpc_Object;
70 Int32 OmapRpc_GetSvrMgrHandle(Void *srvc, Int32 num, Int32 *params)
71 {
72     System_printf("OMAPRPC: Calling RCM Service Manager Create Function!\n");
73     return 0;
74 }
76 static Void omapRpcTask(UArg arg0, UArg arg1)
77 {
78     OmapRpc_Object *obj = (OmapRpc_Object *)arg0;
79     UInt32 local;
80     UInt32 remote;
81     Int status;
82     UInt16 len;
83     Char  * msg = NULL;
84     OmapRpc_MsgHeader *hdr = NULL;
86     msg = Memory_alloc(NULL, 512, 0, NULL); /* maximum rpmsg size is probably
87                                              * smaller, but we need to
88                                              * be cautious */
89     if (msg == NULL) {
90         System_printf("OMAPRPC: Failed to allocate msg!\n");
91         return;
92     }
94     hdr = (OmapRpc_MsgHeader *)&msg[0];
96     if (obj == NULL) {
97         System_printf("OMAPRPC: Failed to start task as arguments are NULL!\n");
98         return;
99     }
101     if (obj->msgq == NULL) {
102         System_printf("OMAPRPC: Failed to start task as MessageQ was NULL!\n");
103         return;
104     }
106     /* get the local endpoint we are to use */
107     local = obj->localEndPt;
108     System_printf("OMAPRPC: connecting from local endpoint %u to port %u\n",
109                         obj->localEndPt, obj->port);
111     NameMap_register("rpmsg-rpc", obj->channelName, obj->port);
113     System_printf("OMAPRPC: started channel on port: %d\n", obj->port);
115     while (!obj->shutdown) {
117         /* clear out the message and our message vars */
118         _memset(msg, 0, sizeof(msg));
119         len = 0;
120         remote = 0;
122         /* receive the message */
123         status = RPMessage_recv(obj->msgq, (Ptr)msg, &len, &remote,
124                                         RPMessage_FOREVER);
126         if (status == RPMessage_E_UNBLOCKED) {
127             System_printf("OMAPRPC: unblocked while waiting for messages\n");
128             continue;
129         }
131         System_printf("OMAPRPC: received msg type: %d len: %d from addr: %d\n",
132                              hdr->msgType, len, remote);
133         switch (hdr->msgType) {
134             case OmapRpc_MsgType_CREATE_INSTANCE:
135             {
136                 /* temp pointer to payload */
137                 OmapRpc_CreateInstance *create =
138                                 OmapRpc_PAYLOAD(msg, OmapRpc_CreateInstance);
139                 /* local copy of name */
140                 Char name[sizeof(create->name)];
141                 /* return structure */
142                 OmapRpc_InstanceHandle *handle =
143                                 OmapRpc_PAYLOAD(msg, OmapRpc_InstanceHandle);
144                 /* save a copy of the input structure data */
145                 _strcpy(name, create->name);
146                 /* clear out the old data */
147                 _memset(msg, 0, sizeof(msg));
149                 /* create a new instance of the service */
150                 handle->status = ServiceMgr_createService(name,
151                                                 &handle->endpointAddress);
153                 System_printf("OMAPRPC: created service instance named: %s "
154                               "(status=%d) addr: %d\n", name, handle->status,
155                                 handle->endpointAddress);
157                 hdr->msgType = OmapRpc_MsgType_INSTANCE_CREATED;
158                 hdr->msgLen  = sizeof(OmapRpc_InstanceHandle);
159                 break;
160             }
161             case OmapRpc_MsgType_DESTROY_INSTANCE:
162             {
163                 /* temp pointer to payload */
164                 OmapRpc_InstanceHandle *handle =
165                                 OmapRpc_PAYLOAD(msg, OmapRpc_InstanceHandle);
167                 if (obj->srvDelCB != NULL) {
168                     obj->srvDelCB();
169                 }
171                 /* don't clear out the old data... */
172                 System_printf("OMAPRPC: destroying instance addr: %d\n",
173                                                     handle->endpointAddress);
174                 handle->status = ServiceMgr_deleteService(
175                                                     handle->endpointAddress);
176                 hdr->msgType = OmapRpc_MsgType_INSTANCE_DESTROYED;
177                 hdr->msgLen = sizeof(OmapRpc_InstanceHandle);
178                 /* leave the endpoint address alone. */
179                 break;
180             }
181             case OmapRpc_MsgType_QUERY_CHAN_INFO:
182             {
183                 OmapRpc_ChannelInfo *chanInfo =
184                                       OmapRpc_PAYLOAD(msg, OmapRpc_ChannelInfo);
186                 chanInfo->numFuncs = obj->numFuncs;
187                 System_printf("OMAPRPC: channel info query - name %s fxns %u\n",
188                                             obj->channelName, chanInfo->numFuncs);
189                 hdr->msgType = OmapRpc_MsgType_CHAN_INFO;
190                 hdr->msgLen = sizeof(OmapRpc_ChannelInfo);
191                 break;
192             }
193             case OmapRpc_MsgType_QUERY_FUNCTION:
194             {
195                 OmapRpc_QueryFunction *fxnInfo = OmapRpc_PAYLOAD(msg,
196                                                          OmapRpc_QueryFunction);
197                 System_printf("OMAPRPC: function query of type %u\n",
198                               fxnInfo->infoType);
200                 switch (fxnInfo->infoType)
201                 {
202                     case OmapRpc_InfoType_FUNC_SIGNATURE:
203                         if (fxnInfo->funcIndex < obj->numFuncs)
204                             memcpy(&fxnInfo->info.signature,
205                                    &obj->funcSigs[fxnInfo->funcIndex],
206                                    sizeof(OmapRpc_FuncSignature));
207                         break;
208                     case OmapRpc_InfoType_FUNC_PERFORMANCE:
209                         break;
210                     case OmapRpc_InfoType_NUM_CALLS:
211                         break;
212                     default:
213                         System_printf("OMAPRPC: Invalid info type!\n");
214                         break;
215                 }
216                 hdr->msgType = OmapRpc_MsgType_FUNCTION_INFO;
217                 hdr->msgLen = sizeof(OmapRpc_QueryFunction);
218                 break;
219             }
220             default:
221             {
222                 /* temp pointer to payload */
223                 OmapRpc_Error *err = OmapRpc_PAYLOAD(msg, OmapRpc_Error);
225                 /* the debugging message before we clear */
226                 System_printf("OMAPRPC: unexpected msg type: %d\n",
227                               hdr->msgType);
229                 /* clear out the old data */
230                 _memset(msg, 0, sizeof(msg));
232                 hdr->msgType = OmapRpc_MsgType_ERROR;
233                 err->endpointAddress = local;
234                 err->status = OmapRpc_ErrorType_NOT_SUPPORTED;
235                 break;
236             }
237        }
239        /* compute the length of the return message. */
240        len = sizeof(struct OmapRpc_MsgHeader) + hdr->msgLen;
242        System_printf("OMAPRPC: Replying with msg type: %d to addr: %d "
243                       " from: %d len: %u\n", hdr->msgType, remote, local, len);
245        /* send the response. All messages get responses! */
246        RPMessage_send(obj->dstProc, remote, local, msg, len);
247     }
249     System_printf("OMAPRPC: destroying channel on port: %d\n", obj->port);
250     NameMap_unregister("rpmsg-rpc", obj->channelName, obj->port);
251     if (msg != NULL) {
252        Memory_free(NULL, msg, 512);
253     }
254     /* @TODO delete any outstanding ServiceMgr instances if no disconnect
255      * was issued? */
257     Semaphore_post(obj->exitSem);
260 /*
261  *  ======== OmapRpc_createChannel ========
262  */
263 #if 0
264 OmapRpc_Handle OmapRpc_createChannel(String channelName, UInt16 dstProc,
265         UInt32 port, UInt32 numFuncs, OmapRpc_FuncDeclaration *fxns,
266         OmapRpc_SrvDelNotifyFxn srvDelCBFunc)
267 #else
268 OmapRpc_Handle OmapRpc_createChannel(String channelName, UInt16 dstProc,
269         UInt32 port, RcmServer_Params *rcmParams, MmType_FxnSigTab *fxnSigTab,
270         OmapRpc_SrvDelNotifyFxn srvDelCBFunc)
271 #endif
273     Task_Params taskParams;
274     UInt32      func;
276     OmapRpc_Object *obj = Memory_alloc(NULL, sizeof(OmapRpc_Object), 0, NULL);
278     if (obj == NULL) {
279         System_printf("OMAPRPC: Failed to allocate memory for object!\n");
280         goto unload;
281     }
282     _memset(obj, 0, sizeof(OmapRpc_Object));
283     obj->numFuncs = fxnSigTab->count + 1;
284 #if 0
285     RcmServer_Params_init(&obj->rcmParams);
286     obj->rcmParams.priority = Thread_Priority_ABOVE_NORMAL;
287     obj->rcmParams.stackSize = 0x1000;
288     obj->rcmParams.fxns.length = obj->numFuncs;
289     obj->rcmParams.fxns.elem = Memory_alloc(NULL,
290             sizeof(RcmServer_FxnDesc) * obj->numFuncs, 0, NULL);
292     if (obj->rcmParams.fxns.elem == NULL) {
293         System_printf("OMAPRPC: Failed to allocate RCM function list!\n");
294         goto unload;
295     }
296 #else
297     memcpy(&obj->rcmParams, rcmParams, sizeof(RcmServer_Params));
298     obj->rcmParams.fxns.length = obj->numFuncs;
299     obj->rcmParams.fxns.elem = Memory_calloc(NULL, obj->numFuncs *
300             sizeof(RcmServer_FxnDesc), 0, NULL);
302     if (obj->rcmParams.fxns.elem == NULL) {
303         System_printf("OMAPRPC: Failed to allocate RCM function list!\n");
304         goto unload;
305     }
306 #endif
308     /* setup other variables... */
309     obj->shutdown = FALSE;
310     obj->dstProc = dstProc;
311     obj->port = port;
312     strncpy(obj->channelName, channelName, OMAPRPC_MAX_CHANNEL_NAMELEN-1);
313     obj->channelName[OMAPRPC_MAX_CHANNEL_NAMELEN-1]='\0';
314     obj->srvDelCB = srvDelCBFunc;
315     obj->funcSigs = Memory_alloc(NULL, obj->numFuncs *
316             sizeof(OmapRpc_FuncSignature), 0, NULL);
318     if (obj->funcSigs == NULL) {
319         System_printf("OMAPRPC: Failed to allocate signtures list!\n");
320         goto unload;
321     }
323     /* setup the RCM functions and Signatures */
324     for (func = 0; func < obj->numFuncs; func++) {
325         if (func == 0) {
326             /* assign the "first function" */
327             obj->rcmParams.fxns.elem[func].name =
328                     OmapRpc_Stringerize(OmapRpc_GetSvrMgrHandle);
329             obj->rcmParams.fxns.elem[func].addr.createFxn =
330                     (RcmServer_MsgCreateFxn)OmapRpc_GetSvrMgrHandle;
332             strncpy(obj->funcSigs[func].name, obj->rcmParams.fxns.elem[0].name,
333                     OMAPRPC_MAX_CHANNEL_NAMELEN);
334             obj->funcSigs[func].numParam = 0;
335         }
336         else {
337             /* assign the other functions */
338 /*          obj->rcmParams.fxns.elem[func].name = fxns[func-1].signature.name; */
339             obj->rcmParams.fxns.elem[func].name =
340                     rcmParams->fxns.elem[func-1].name;
341 /*          obj->rcmParams.fxns.elem[func].addr.fxn =
342                     (RcmServer_MsgFxn)fxns[func-1].function; */
343             obj->rcmParams.fxns.elem[func].addr.fxn =
344                     rcmParams->fxns.elem[func-1].addr.fxn;
346             /* copy the signature */
347 /*          memcpy(&obj->funcSigs[func], &fxns[func-1].signature,
348                     sizeof(OmapRpc_FuncSignature)); */
349             memcpy(&obj->funcSigs[func], &fxnSigTab->table[func - 1],
350                     sizeof(MmType_FxnSig));
351         }
352     }
354     ServiceMgr_init();
356     if (ServiceMgr_register(channelName, &obj->rcmParams) == TRUE) {
357         System_printf("OMAPRPC: registered channel: %s\n", obj->channelName);
359         obj->msgq = RPMessage_create(obj->port, NULL, NULL,&obj->localEndPt);
361         if (obj->msgq == NULL) {
362             goto unload;
363         }
365         Task_Params_init(&taskParams);
366         taskParams.instance->name = channelName;
367         taskParams.stackSize = 0x2000; /* must cover all proxy stack usage */
368         taskParams.priority = 1;   /* lowest priority thread */
369         taskParams.arg0 = (UArg)obj;
371         obj->exitSem = Semaphore_create(0, NULL, NULL);
373         if (obj->exitSem == NULL) {
374             goto unload;
375         }
377         obj->taskHandle = Task_create(omapRpcTask, &taskParams, NULL);
379         if (obj->taskHandle == NULL) {
380             goto unload;
381         }
382     }
383     else {
384         System_printf("OMAPRPC: FAILED to register channel: %s\n",
385                 obj->channelName);
386     }
388     System_printf("OMAPRPC: Returning Object %p\n", obj);
389     return(obj);
391 unload:
392     OmapRpc_deleteChannel(obj);
393     return(NULL);
396 Int OmapRpc_deleteChannel(OmapRpc_Handle handle)
398     OmapRpc_Object *obj = (OmapRpc_Object *)handle;
400     if (obj == NULL) {
401         return OmapRpc_E_FAIL;
402     }
404     System_printf("OMAPRPC: deleting channel %s\n", obj->channelName);
405     obj->shutdown = TRUE;
406     if (obj->msgq) {
407         RPMessage_unblock(obj->msgq);
408         if (obj->exitSem) {
409             Semaphore_pend(obj->exitSem, BIOS_WAIT_FOREVER);
410             RPMessage_delete(&obj->msgq);
411             Semaphore_delete(&obj->exitSem);
412         }
413         if (obj->taskHandle) {
414             Task_delete(&obj->taskHandle);
415         }
416     }
417     if (obj->funcSigs)
418         Memory_free(NULL, obj->funcSigs, sizeof(*obj->funcSigs)*(obj->numFuncs-1));
419     if (obj->rcmParams.fxns.elem)
420         Memory_free(NULL, obj->rcmParams.fxns.elem,
421                     sizeof(obj->rcmParams.fxns.elem[0])*obj->numFuncs);
423     Memory_free(NULL, obj, sizeof(*obj));
424     return OmapRpc_S_SUCCESS;
427 #if 0
428 /*
429  *  ======== OmapRpc_start ========
430  */
431 Int OmapRpc_start(const String name, Int port, Int aryLen,
432         OmapRpc_FuncSignature *sigAry)
434     Int status = OmapRpc_S_SUCCESS;
435     Task_Params taskParams;
436     OmapRpc_Object *obj;
438     /* create an instance */
439     obj = Memory_calloc(NULL, sizeof(OmapRpc_Object), 0, NULL);
441     if (obj == NULL) {
442         System_printf("OMAPRPC: Failed to allocate memory for object!\n");
443         status = OmapRpc_E_FAIL;
444         goto leave;
445     }
447     obj->numFuncs = aryLen + 1;
448     obj->shutdown = FALSE;
449     obj->dstProc = MultiProc_getId("HOST");
450     obj->port = port;
451     strncpy(obj->channelName, name, OMAPRPC_MAX_CHANNEL_NAMELEN-1);
452     obj->channelName[OMAPRPC_MAX_CHANNEL_NAMELEN-1]='\0';
453     obj->srvDelCB = srvDelCBFunc;
454     obj->funcSigs = Memory_alloc(NULL,
455             sizeof(OmapRpc_FuncSignature) * obj->numFuncs, 0, NULL);
457     if (obj->funcSigs == NULL) {
458         System_printf("OMAPRPC: Failed to allocate signtures list!\n");
459         goto unload;
460     }
462     /* setup the functions and signatures */
463     for (func = 0; func < obj->numFuncs; func++) {
464         if (func == 0) {
465             /* assign the "first function" */
466 /*          strncpy(obj->funcSigs[func].name, obj->rcmParams.fxns.elem[0].name,
467                     OMAPRPC_MAX_CHANNEL_NAMELEN); */
468             strncpy(obj->funcSigs[func].name,
469                     OmapRpc_Stringerize(OmapRpc_GetSvrMgrHandle),
470                     OMAPRPC_MAX_CHANNEL_NAMELEN);
471             obj->funcSigs[func].numParam = 0;
472         }
473         else {
474             /* copy the signature */
475             memcpy(&obj->funcSigs[func], &fxns[func-1].signature,
476                     sizeof(OmapRpc_FuncSignature));
477         }
478     }
480     obj->msgq = RPMessage_create(obj->port, NULL, NULL,&obj->localEndPt);
482     if (obj->msgq == NULL) {
483         goto unload;
484     }
486     Task_Params_init(&taskParams);
487     taskParams.instance->name = channelName;
488     taskParams.priority = 1;   /* Lowest priority thread */
489     taskParams.arg0 = (UArg)obj;
491     obj->exitSem = Semaphore_create(0, NULL, NULL);
493     if (obj->exitSem == NULL) {
494         goto unload;
495     }
497     obj->taskHandle = Task_create(omapRpcTask, &taskParams, NULL);
499     if (obj->taskHandle == NULL) {
500         goto unload;
501     }
503     System_printf("OMAPRPC: Returning Object %p\n", obj);
504     return(obj);
506 leave:
507     if (status < 0) {
508         OmapRpc_deleteChannel(obj);
509     }
510     return(status);
512 #endif