SrvMgr: Pulled in ServiceMgr (and OmxSrvMgr) from omapzoom sysbios-rpmsg.
[ipc/ipcdev.git] / packages / ti / srvmgr / ServiceMgr.c
1 /*
2  * Copyright (c) 2011-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  */
32 /*
33  *  ======== ServiceMgr.c ========
34  *  Simple server that handles requests to create threads (services) by name
35  *  and provide an endpoint to the new thread.
36  *
37  */
39 #include <xdc/std.h>
40 #include <xdc/cfg/global.h>
41 #include <xdc/runtime/System.h>
43 #include <ti/sysbios/knl/Task.h>
45 #include <ti/grcm/RcmTypes.h>
46 #include <ti/grcm/RcmServer.h>
48 #include <stdio.h>
49 #include <string.h>
50 #include <stdlib.h>
52 #include <ti/ipc/rpmsg/MessageQCopy.h>
53 #include <ti/ipc/rpmsg/NameMap.h>
54 #include "rpmsg_omx.h"
55 #include "ServiceMgr.h"
57 #define  MAX_NAMELEN       64
59 /* This artificially limits the number of service instances on this core: */
60 #define  MAX_TUPLES        256
61 #define  FREE_TUPLE_KEY    0xFFFFFFFF
63 #define  MAX_SERVICES      4
65 /* ServiceMgr disconnect hook function */
66 static ServiceMgr_disconnectFuncPtr ServiceMgr_disconnectUserFxn = NULL;
68 struct ServiceDef {
69     Char                   name[MAX_NAMELEN];
70     RcmServer_Params       rcmServerParams;
71     Bool                   taken;
72 };
74 struct ServiceDef serviceDefs[ServiceMgr_NUMSERVICETYPES];
76 struct Tuple {
77     UInt32   key;
78     UInt32   value;
79 };
80 struct Tuple Tuples[MAX_TUPLES];
82 typedef struct {
83     Task_FuncPtr    fxn;
84     Char            name[MAX_NAMELEN];
85     Task_Params     params;
86     UInt16          reserved;
87     Bool            taken;
88 } ServiceMgr_ServiceTask;
90 static ServiceMgr_ServiceTask serviceTasks[MAX_SERVICES];
93 Void ServiceMgr_init()
94 {
95     static Int  curInit = 0;
96     UInt        i;
98     if (curInit++ != 0) {
99         return; /* module already initialized */
100     }
102     RcmServer_init();
104     for (i = 0; i < ServiceMgr_NUMSERVICETYPES; i++) {
105        serviceDefs[i].taken = FALSE;
106     }
108     for (i = 0; i < MAX_TUPLES; i++) {
109        Tuples[i].key = FREE_TUPLE_KEY;
110     }
112     for (i = 0; i < MAX_SERVICES; i++) {
113         serviceTasks[i].taken = FALSE;
114         serviceTasks[i].fxn = NULL;
115         serviceTasks[i].reserved = (UInt16) -1;
116     }
119 UInt ServiceMgr_start(UInt16 reserved)
121     UInt        i;
122     UInt        count = 0;
123     static Bool started = FALSE;
125     if (started) {
126         return 0;
127     }
129     for (i = 0; (i < MAX_SERVICES) && (serviceTasks[i].taken); i++) {
130         Task_create(serviceTasks[i].fxn, &serviceTasks[i].params, NULL);
131         count++;
132     }
134     return (count);
137 Bool ServiceMgr_registerSrvTask(UInt16 reserved, Task_FuncPtr func,
138                                 Task_Params *taskParams)
140     UInt                    i;
141     Bool                    found = FALSE;
142     ServiceMgr_ServiceTask  *st;
143     Task_Params             *params;
145     /* Search the array for a free slot */
146     for (i = 0; (i < MAX_SERVICES) && (found == FALSE); i++) {
147         if (!serviceTasks[i].taken) {
148             st = &serviceTasks[i];
149             st->fxn = func;
150             strcpy(st->name, taskParams->instance->name);
152             /* Deal with the Task_Params to avoid IInstance mismatch */
153             params = &st->params;
154             Task_Params_init(params);
155             memcpy((Void *)(&params->arg0), &taskParams->arg0,
156                         sizeof(*params) - sizeof(Void *));
157             params->instance->name = st->name;
159             st->reserved = reserved;
160             st->taken = TRUE;
161             found = TRUE;
162             break;
163         }
164     }
166     return (found);
169 Bool ServiceMgr_register(String name, RcmServer_Params  *rcmServerParams)
171     UInt              i;
172     Bool              found = FALSE;
173     struct ServiceDef *sd;
175     if (strlen(name) >= MAX_NAMELEN) {
176         System_printf("ServiceMgr_register: service name longer than %d\n",
177                        MAX_NAMELEN );
178     }
179     else {
180         /* Search the array for a free slot */
181         for (i = 0; (i < ServiceMgr_NUMSERVICETYPES) && (found == FALSE); i++) {
182             if (!serviceDefs[i].taken) {
183                 sd = &serviceDefs[i];
184                 strcpy(sd->name, name);
185                 sd->rcmServerParams = *rcmServerParams;
186                 sd->taken = TRUE;
187                 found = TRUE;
188                 break;
189             }
190         }
191     }
193     return(found);
196 Void ServiceMgr_send(Service_Handle srvc, Ptr data, UInt16 len)
198     UInt32 local;
199     UInt32 remote;
200     struct omx_msg_hdr * hdr = (struct omx_msg_hdr *)data;
201     UInt16 dstProc;
203     /* Get reply endpoint and local address for sending: */
204     remote  = RcmServer_getRemoteAddress(srvc);
205     dstProc = RcmServer_getRemoteProc(srvc);
206     local   = RcmServer_getLocalAddress(srvc);
208     /* Set special rpmsg_omx header so Linux side can strip it off: */
209     hdr->type    = OMX_RAW_MSG;
210     hdr->len     = len;
211     hdr->flags   = 0;
213     /* Send it off (and no response expected): */
214     MessageQCopy_send(dstProc, remote, local, data, HDRSIZE+len);
217 Bool ServiceMgr_registerDisconnectFxn(Service_Handle srvc, Ptr data,
218                                       ServiceMgr_disconnectFuncPtr func)
220     if (func == NULL) {
221         System_printf("ServiceMgr_registerDisconnectFxn: Invalid function.\n");
222         return FALSE;
223     }
225     /* Register the user-supplied function */
226     if (!ServiceMgr_disconnectUserFxn) {
227         ServiceMgr_disconnectUserFxn = func;
228     }
229     return TRUE;
232 /* Tuple store/retrieve fxns:  */
234 static Bool storeTuple(UInt32 key, UInt32 value)
236     UInt              i;
237     Bool              stored = FALSE;
239     if (key == FREE_TUPLE_KEY) {
240         System_printf("storeTuple: reserved key %d\n", key);
241     }
242     else {
243         /* Search the array for a free slot: */
244         for (i = 0; (i < MAX_TUPLES) && (stored == FALSE); i++) {
245            if (Tuples[i].key == FREE_TUPLE_KEY) {
246                Tuples[i].key = key;
247                Tuples[i].value = value;
248                stored = TRUE;
249                break;
250            }
251         }
252     }
254     return(stored);
257 static Bool removeTuple(UInt32 key, UInt32 * value)
259     UInt              i;
260     Bool              found = FALSE;
262     /* Search the array for tuple matching key: */
263     for (i = 0; (i < MAX_TUPLES) && (found == FALSE); i++) {
264        if (Tuples[i].key == key) {
265            found = TRUE;
266            *value = Tuples[i].value;
267            /* and free it... */
268            Tuples[i].value = 0;
269            Tuples[i].key = FREE_TUPLE_KEY;
270            break;
271        }
272     }
274     return(found);
277 UInt32 ServiceMgr_createService(Char * name, UInt32 * endpt)
279     Int i;
280     Int status = 0;
281     struct ServiceDef *sd;
282     RcmServer_Handle  rcmSrvHandle;
284     for (i = 0; i < ServiceMgr_NUMSERVICETYPES; i++) {
285        if (!strcmp(name, serviceDefs[i].name)) {
286            sd = &serviceDefs[i];
287            break;
288        }
289     }
291     if (i >= ServiceMgr_NUMSERVICETYPES) {
292        System_printf("createService: unrecognized service name: %s\n", name);
293        return OMX_NOTSUPP;
294     }
296     /* Create the RcmServer instance. */
297 #if 0
298     System_printf("createService: Calling RcmServer_create with name = %s\n"
299                   "priority = %d\n"
300                   "osPriority = %d\n"
301                   "rcmServerParams.fxns.length = %d\n",
302                   sd->name, sd->rcmServerParams.priority,
303                   sd->rcmServerParams.osPriority,
304                   sd->rcmServerParams.fxns.length);
305 #endif
306     status = RcmServer_create(sd->name, &sd->rcmServerParams, &rcmSrvHandle);
308     if (status < 0) {
309         System_printf("createService: RcmServer_create() returned error %d\n",
310                        status);
311         return OMX_FAIL;
312     }
314     /* Get endpoint allowing clients to send messages to this new server: */
315     *endpt = RcmServer_getLocalAddress(rcmSrvHandle);
317     /* Store Server's endpoint with handle so we can cleanup on disconnect: */
318     if (!storeTuple(*endpt, (UInt32)rcmSrvHandle))  {
319         System_printf("createService: Limit reached on max instances!\n");
320         RcmServer_delete(&rcmSrvHandle);
321         return OMX_FAIL;
322     }
324     /* start the server */
325     RcmServer_start(rcmSrvHandle);
327     System_printf("createService: new OMX Service at endpoint: %d\n", *endpt);
329     return OMX_SUCCESS;
333 UInt32 ServiceMgr_deleteService(UInt32 addr)
335     Int status = 0;
336     RcmServer_Handle  rcmSrvHandle;
338     if (!removeTuple(addr, (UInt32 *)&rcmSrvHandle))  {
339        System_printf("deleteService: could not find service instance at"
340                      " address: 0x%x\n", addr);
341        return OMX_FAIL;
342     }
344     /* Notify a ServiceMgr client of disconnection.
345      * rcmSrvHandle is same as the ServiceMgr handle
346      */
347     if (ServiceMgr_disconnectUserFxn) {
348         /* Pass NULL data for the moment */
349         ServiceMgr_disconnectUserFxn(rcmSrvHandle, NULL);
350     }
352     /* Destroy the RcmServer instance. */
353     status = RcmServer_delete(&rcmSrvHandle);
354     if (status < 0) {
355         System_printf("deleteService: RcmServer_delete() returned error %d\n",
356                        status);
357         return OMX_FAIL;
358     }
360     System_printf("deleteService: removed RcmServer at endpoint: %d\n", addr);
362     return OMX_SUCCESS;