e7b1ab0029a5098369d4dc48cfe4209e46d0da49
[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 <stdio.h>
46 #include <string.h>
47 #include <stdlib.h>
49 #include <ti/ipc/mm/MmType.h>
50 #include <ti/ipc/rpmsg/RPMessage.h>
51 #include <ti/ipc/rpmsg/NameMap.h>
52 #include <ti/srvmgr/ServiceMgr.h>
54 #include "OmapRpc.h"
56 typedef struct OmapRpc_Object {
57     Char                    channelName[OMAPRPC_MAX_CHANNEL_NAMELEN];
58     UInt16                  dstProc;
59     UInt32                  port;
60     RPMessage_Handle        msgq;
61     UInt32                  localEndPt;
62     Task_Handle             taskHandle;
63     Bool                    shutdown;
64     Semaphore_Handle        exitSem;
65     OmapRpc_SrvDelNotifyFxn srvDelCB;
66     RcmServer_Params        rcmParams;
67     UInt32                  numFuncs;
68     OmapRpc_FuncSignature  *funcSigs;
69 } OmapRpc_Object;
71 Int32 OmapRpc_GetSvrMgrHandle(Void *srvc, Int32 num, Int32 *params)
72 {
73     System_printf("OMAPRPC: Calling RCM Service Manager Create Function!\n");
74     return 0;
75 }
77 static Void omapRpcTask(UArg arg0, UArg arg1)
78 {
79     OmapRpc_Object *obj = (OmapRpc_Object *)arg0;
80     UInt32 local;
81     UInt32 remote;
82     Int status;
83     UInt16 len;
84     Char  * msg = NULL;
85     OmapRpc_MsgHeader *hdr = NULL;
87     msg = Memory_alloc(NULL, 512, 0, NULL); /* maximum rpmsg size is probably
88                                              * smaller, but we need to
89                                              * be cautious */
90     if (msg == NULL) {
91         System_printf("OMAPRPC: Failed to allocate msg!\n");
92         return;
93     }
95     hdr = (OmapRpc_MsgHeader *)&msg[0];
97     if (obj == NULL) {
98         System_printf("OMAPRPC: Failed to start task as arguments are NULL!\n");
99         return;
100     }
102     if (obj->msgq == NULL) {
103         System_printf("OMAPRPC: Failed to start task as MessageQ was NULL!\n");
104         return;
105     }
107     /* get the local endpoint we are to use */
108     local = obj->localEndPt;
109     System_printf("OMAPRPC: connecting from local endpoint %u to port %u\n",
110                         obj->localEndPt, obj->port);
112     NameMap_register("rpmsg-rpc", obj->channelName, obj->port);
114     System_printf("OMAPRPC: started channel on port: %d\n", obj->port);
116     while (!obj->shutdown) {
118         /* clear out the message and our message vars */
119         _memset(msg, 0, sizeof(msg));
120         len = 0;
121         remote = 0;
123         /* receive the message */
124         status = RPMessage_recv(obj->msgq, (Ptr)msg, &len, &remote,
125                                         RPMessage_FOREVER);
127         if (status == RPMessage_E_UNBLOCKED) {
128             System_printf("OMAPRPC: unblocked while waiting for messages\n");
129             continue;
130         }
132         System_printf("OMAPRPC: received msg type: %d len: %d from addr: %d\n",
133                              hdr->msgType, len, remote);
134         switch (hdr->msgType) {
135             case OmapRpc_MsgType_CREATE_INSTANCE:
136             {
137                 /* temp pointer to payload */
138                 OmapRpc_CreateInstance *create =
139                                 OmapRpc_PAYLOAD(msg, OmapRpc_CreateInstance);
140                 /* local copy of name */
141                 Char name[sizeof(create->name)];
142                 /* return structure */
143                 OmapRpc_InstanceHandle *handle =
144                                 OmapRpc_PAYLOAD(msg, OmapRpc_InstanceHandle);
145                 /* save a copy of the input structure data */
146                 _strcpy(name, create->name);
147                 /* clear out the old data */
148                 _memset(msg, 0, sizeof(msg));
150                 /* create a new instance of the service */
151                 handle->status = ServiceMgr_createService(name,
152                                                 &handle->endpointAddress);
154                 System_printf("OMAPRPC: created service instance named: %s "
155                               "(status=%d) addr: %d\n", name, handle->status,
156                                 handle->endpointAddress);
158                 hdr->msgType = OmapRpc_MsgType_INSTANCE_CREATED;
159                 hdr->msgLen  = sizeof(OmapRpc_InstanceHandle);
160                 break;
161             }
162             case OmapRpc_MsgType_DESTROY_INSTANCE:
163             {
164                 /* temp pointer to payload */
165                 OmapRpc_InstanceHandle *handle =
166                                 OmapRpc_PAYLOAD(msg, OmapRpc_InstanceHandle);
168                 if (obj->srvDelCB != NULL) {
169                     obj->srvDelCB();
170                 }
172                 /* don't clear out the old data... */
173                 System_printf("OMAPRPC: destroying instance addr: %d\n",
174                                                     handle->endpointAddress);
175                 handle->status = ServiceMgr_deleteService(
176                                                     handle->endpointAddress);
177                 hdr->msgType = OmapRpc_MsgType_INSTANCE_DESTROYED;
178                 hdr->msgLen = sizeof(OmapRpc_InstanceHandle);
179                 /* leave the endpoint address alone. */
180                 break;
181             }
182             case OmapRpc_MsgType_QUERY_CHAN_INFO:
183             {
184                 OmapRpc_ChannelInfo *chanInfo =
185                                       OmapRpc_PAYLOAD(msg, OmapRpc_ChannelInfo);
187                 chanInfo->numFuncs = obj->numFuncs;
188                 System_printf("OMAPRPC: channel info query - name %s fxns %u\n",
189                                             obj->channelName, chanInfo->numFuncs);
190                 hdr->msgType = OmapRpc_MsgType_CHAN_INFO;
191                 hdr->msgLen = sizeof(OmapRpc_ChannelInfo);
192                 break;
193             }
194             case OmapRpc_MsgType_QUERY_FUNCTION:
195             {
196                 OmapRpc_QueryFunction *fxnInfo = OmapRpc_PAYLOAD(msg,
197                                                          OmapRpc_QueryFunction);
198                 System_printf("OMAPRPC: function query of type %u\n",
199                               fxnInfo->infoType);
201                 switch (fxnInfo->infoType)
202                 {
203                     case OmapRpc_InfoType_FUNC_SIGNATURE:
204                         if (fxnInfo->funcIndex < obj->numFuncs)
205                             memcpy(&fxnInfo->info.signature,
206                                    &obj->funcSigs[fxnInfo->funcIndex],
207                                    sizeof(OmapRpc_FuncSignature));
208                         break;
209                     case OmapRpc_InfoType_FUNC_PERFORMANCE:
210                         break;
211                     case OmapRpc_InfoType_NUM_CALLS:
212                         break;
213                     default:
214                         System_printf("OMAPRPC: Invalid info type!\n");
215                         break;
216                 }
217                 hdr->msgType = OmapRpc_MsgType_FUNCTION_INFO;
218                 hdr->msgLen = sizeof(OmapRpc_QueryFunction);
219                 break;
220             }
221             default:
222             {
223                 /* temp pointer to payload */
224                 OmapRpc_Error *err = OmapRpc_PAYLOAD(msg, OmapRpc_Error);
226                 /* the debugging message before we clear */
227                 System_printf("OMAPRPC: unexpected msg type: %d\n",
228                               hdr->msgType);
230                 /* clear out the old data */
231                 _memset(msg, 0, sizeof(msg));
233                 hdr->msgType = OmapRpc_MsgType_ERROR;
234                 err->endpointAddress = local;
235                 err->status = OmapRpc_ErrorType_NOT_SUPPORTED;
236                 break;
237             }
238        }
240        /* compute the length of the return message. */
241        len = sizeof(struct OmapRpc_MsgHeader) + hdr->msgLen;
243        System_printf("OMAPRPC: Replying with msg type: %d to addr: %d "
244                       " from: %d len: %u\n", hdr->msgType, remote, local, len);
246        /* send the response. All messages get responses! */
247        RPMessage_send(obj->dstProc, remote, local, msg, len);
248     }
250     System_printf("OMAPRPC: destroying channel on port: %d\n", obj->port);
251     NameMap_unregister("rpmsg-rpc", obj->channelName, obj->port);
252     if (msg != NULL) {
253        Memory_free(NULL, msg, 512);
254     }
255     /* @TODO delete any outstanding ServiceMgr instances if no disconnect
256      * was issued? */
258     Semaphore_post(obj->exitSem);
261 /*
262  *  ======== OmapRpc_createChannel ========
263  */
264 #if 0
265 OmapRpc_Handle OmapRpc_createChannel(String channelName, UInt16 dstProc,
266         UInt32 port, UInt32 numFuncs, OmapRpc_FuncDeclaration *fxns,
267         OmapRpc_SrvDelNotifyFxn srvDelCBFunc)
268 #else
269 OmapRpc_Handle OmapRpc_createChannel(String channelName, UInt16 dstProc,
270         UInt32 port, RcmServer_Params *rcmParams, MmType_FxnSigTab *fxnSigTab,
271         OmapRpc_SrvDelNotifyFxn srvDelCBFunc)
272 #endif
274     Task_Params taskParams;
275     UInt32      func;
277     OmapRpc_Object *obj = Memory_alloc(NULL, sizeof(OmapRpc_Object), 0, NULL);
279     if (obj == NULL) {
280         System_printf("OMAPRPC: Failed to allocate memory for object!\n");
281         goto unload;
282     }
283     _memset(obj, 0, sizeof(OmapRpc_Object));
284     obj->numFuncs = fxnSigTab->count + 1;
285 #if 0
286     RcmServer_Params_init(&obj->rcmParams);
287     obj->rcmParams.priority = Thread_Priority_ABOVE_NORMAL;
288     obj->rcmParams.stackSize = 0x1000;
289     obj->rcmParams.fxns.length = obj->numFuncs;
290     obj->rcmParams.fxns.elem = Memory_alloc(NULL,
291             sizeof(RcmServer_FxnDesc) * obj->numFuncs, 0, NULL);
293     if (obj->rcmParams.fxns.elem == NULL) {
294         System_printf("OMAPRPC: Failed to allocate RCM function list!\n");
295         goto unload;
296     }
297 #else
298     memcpy(&obj->rcmParams, rcmParams, sizeof(RcmServer_Params));
299     obj->rcmParams.fxns.length = obj->numFuncs;
300     obj->rcmParams.fxns.elem = Memory_calloc(NULL, obj->numFuncs *
301             sizeof(RcmServer_FxnDesc), 0, NULL);
303     if (obj->rcmParams.fxns.elem == NULL) {
304         System_printf("OMAPRPC: Failed to allocate RCM function list!\n");
305         goto unload;
306     }
307 #endif
309     /* setup other variables... */
310     obj->shutdown = FALSE;
311     obj->dstProc = dstProc;
312     obj->port = port;
313     strncpy(obj->channelName, channelName, OMAPRPC_MAX_CHANNEL_NAMELEN-1);
314     obj->channelName[OMAPRPC_MAX_CHANNEL_NAMELEN-1]='\0';
315     obj->srvDelCB = srvDelCBFunc;
316     obj->funcSigs = Memory_alloc(NULL, obj->numFuncs *
317             sizeof(OmapRpc_FuncSignature), 0, NULL);
319     if (obj->funcSigs == NULL) {
320         System_printf("OMAPRPC: Failed to allocate signtures list!\n");
321         goto unload;
322     }
324     /* setup the RCM functions and Signatures */
325     for (func = 0; func < obj->numFuncs; func++) {
326         if (func == 0) {
327             /* assign the "first function" */
328             obj->rcmParams.fxns.elem[func].name =
329                     OmapRpc_Stringerize(OmapRpc_GetSvrMgrHandle);
330             obj->rcmParams.fxns.elem[func].addr.createFxn =
331                     (RcmServer_MsgCreateFxn)OmapRpc_GetSvrMgrHandle;
333             strncpy(obj->funcSigs[func].name, obj->rcmParams.fxns.elem[0].name,
334                     OMAPRPC_MAX_CHANNEL_NAMELEN);
335             obj->funcSigs[func].numParam = 0;
336         }
337         else {
338             /* assign the other functions */
339 /*          obj->rcmParams.fxns.elem[func].name = fxns[func-1].signature.name; */
340             obj->rcmParams.fxns.elem[func].name =
341                     rcmParams->fxns.elem[func-1].name;
342 /*          obj->rcmParams.fxns.elem[func].addr.fxn =
343                     (RcmServer_MsgFxn)fxns[func-1].function; */
344             obj->rcmParams.fxns.elem[func].addr.fxn =
345                     rcmParams->fxns.elem[func-1].addr.fxn;
347             /* copy the signature */
348 /*          memcpy(&obj->funcSigs[func], &fxns[func-1].signature,
349                     sizeof(OmapRpc_FuncSignature)); */
350             memcpy(&obj->funcSigs[func], &fxnSigTab->table[func - 1],
351                     sizeof(MmType_FxnSig));
352         }
353     }
355     ServiceMgr_init();
357     if (ServiceMgr_register(channelName, &obj->rcmParams) == TRUE) {
358         System_printf("OMAPRPC: registered channel: %s\n", obj->channelName);
360         obj->msgq = RPMessage_create(obj->port, NULL, NULL,&obj->localEndPt);
362         if (obj->msgq == NULL) {
363             goto unload;
364         }
366         Task_Params_init(&taskParams);
367         taskParams.instance->name = channelName;
368         taskParams.stackSize = 0x2000; /* must cover all proxy stack usage */
369         taskParams.priority = 1;   /* lowest priority thread */
370         taskParams.arg0 = (UArg)obj;
372         obj->exitSem = Semaphore_create(0, NULL, NULL);
374         if (obj->exitSem == NULL) {
375             goto unload;
376         }
378         obj->taskHandle = Task_create(omapRpcTask, &taskParams, NULL);
380         if (obj->taskHandle == NULL) {
381             goto unload;
382         }
383     }
384     else {
385         System_printf("OMAPRPC: FAILED to register channel: %s\n",
386                 obj->channelName);
387     }
389     System_printf("OMAPRPC: Returning Object %p\n", obj);
390     return(obj);
392 unload:
393     OmapRpc_deleteChannel(obj);
394     return(NULL);
397 Int OmapRpc_deleteChannel(OmapRpc_Handle handle)
399     OmapRpc_Object *obj = (OmapRpc_Object *)handle;
401     if (obj == NULL) {
402         return OmapRpc_E_FAIL;
403     }
405     System_printf("OMAPRPC: deleting channel %s\n", obj->channelName);
406     obj->shutdown = TRUE;
407     if (obj->msgq) {
408         RPMessage_unblock(obj->msgq);
409         if (obj->exitSem) {
410             Semaphore_pend(obj->exitSem, BIOS_WAIT_FOREVER);
411             RPMessage_delete(&obj->msgq);
412             Semaphore_delete(&obj->exitSem);
413         }
414         if (obj->taskHandle) {
415             Task_delete(&obj->taskHandle);
416         }
417     }
418     if (obj->funcSigs)
419         Memory_free(NULL, obj->funcSigs, sizeof(*obj->funcSigs)*(obj->numFuncs-1));
420     if (obj->rcmParams.fxns.elem)
421         Memory_free(NULL, obj->rcmParams.fxns.elem,
422                     sizeof(obj->rcmParams.fxns.elem[0])*obj->numFuncs);
424     Memory_free(NULL, obj, sizeof(*obj));
425     return OmapRpc_S_SUCCESS;
428 #if 0
429 /*
430  *  ======== OmapRpc_start ========
431  */
432 Int OmapRpc_start(const String name, Int port, Int aryLen,
433         OmapRpc_FuncSignature *sigAry)
435     Int status = OmapRpc_S_SUCCESS;
436     Task_Params taskParams;
437     OmapRpc_Object *obj;
439     /* create an instance */
440     obj = Memory_calloc(NULL, sizeof(OmapRpc_Object), 0, NULL);
442     if (obj == NULL) {
443         System_printf("OMAPRPC: Failed to allocate memory for object!\n");
444         status = OmapRpc_E_FAIL;
445         goto leave;
446     }
448     obj->numFuncs = aryLen + 1;
449     obj->shutdown = FALSE;
450     obj->dstProc = MultiProc_getId("HOST");
451     obj->port = port;
452     strncpy(obj->channelName, name, OMAPRPC_MAX_CHANNEL_NAMELEN-1);
453     obj->channelName[OMAPRPC_MAX_CHANNEL_NAMELEN-1]='\0';
454     obj->srvDelCB = srvDelCBFunc;
455     obj->funcSigs = Memory_alloc(NULL,
456             sizeof(OmapRpc_FuncSignature) * obj->numFuncs, 0, NULL);
458     if (obj->funcSigs == NULL) {
459         System_printf("OMAPRPC: Failed to allocate signtures list!\n");
460         goto unload;
461     }
463     /* setup the functions and signatures */
464     for (func = 0; func < obj->numFuncs; func++) {
465         if (func == 0) {
466             /* assign the "first function" */
467 /*          strncpy(obj->funcSigs[func].name, obj->rcmParams.fxns.elem[0].name,
468                     OMAPRPC_MAX_CHANNEL_NAMELEN); */
469             strncpy(obj->funcSigs[func].name,
470                     OmapRpc_Stringerize(OmapRpc_GetSvrMgrHandle),
471                     OMAPRPC_MAX_CHANNEL_NAMELEN);
472             obj->funcSigs[func].numParam = 0;
473         }
474         else {
475             /* copy the signature */
476             memcpy(&obj->funcSigs[func], &fxns[func-1].signature,
477                     sizeof(OmapRpc_FuncSignature));
478         }
479     }
481     obj->msgq = RPMessage_create(obj->port, NULL, NULL,&obj->localEndPt);
483     if (obj->msgq == NULL) {
484         goto unload;
485     }
487     Task_Params_init(&taskParams);
488     taskParams.instance->name = channelName;
489     taskParams.priority = 1;   /* Lowest priority thread */
490     taskParams.arg0 = (UArg)obj;
492     obj->exitSem = Semaphore_create(0, NULL, NULL);
494     if (obj->exitSem == NULL) {
495         goto unload;
496     }
498     obj->taskHandle = Task_create(omapRpcTask, &taskParams, NULL);
500     if (obj->taskHandle == NULL) {
501         goto unload;
502     }
504     System_printf("OMAPRPC: Returning Object %p\n", obj);
505     return(obj);
507 leave:
508     if (status < 0) {
509         OmapRpc_deleteChannel(obj);
510     }
511     return(status);
513 #endif