b81f276791eb508d0e3fcd1c9c82d3b55651bca6
[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 <string.h>
49 #include <stdlib.h>
51 #include <ti/ipc/rpmsg/RPMessage.h>
52 #include <ti/ipc/rpmsg/NameMap.h>
53 #include "rpmsg_omx.h"
54 #include "ServiceMgr.h"
56 #define  MAX_NAMELEN       64
58 /* This artificially limits the number of service instances on this core: */
59 #define  MAX_TUPLES        256
60 #define  FREE_TUPLE_KEY    0xFFFFFFFF
62 #define  MAX_SERVICES      4
64 /* ServiceMgr disconnect hook function */
65 static ServiceMgr_disconnectFuncPtr ServiceMgr_disconnectUserFxn = NULL;
67 struct ServiceDef {
68     Char                   name[MAX_NAMELEN];
69     RcmServer_Params       rcmServerParams;
70     Bool                   taken;
71 };
73 struct ServiceDef serviceDefs[ServiceMgr_NUMSERVICETYPES];
75 struct Tuple {
76     UInt32   key;
77     UInt32   value;
78 };
79 struct Tuple Tuples[MAX_TUPLES];
81 typedef struct {
82     Task_FuncPtr    fxn;
83     Char            name[MAX_NAMELEN];
84     Task_Params     params;
85     UInt16          reserved;
86     Bool            taken;
87 } ServiceMgr_ServiceTask;
89 static ServiceMgr_ServiceTask serviceTasks[MAX_SERVICES];
92 Void ServiceMgr_init()
93 {
94     static Int  curInit = 0;
95     UInt        i;
97     if (curInit++ != 0) {
98         return; /* module already initialized */
99     }
101     RcmServer_init();
103     for (i = 0; i < ServiceMgr_NUMSERVICETYPES; i++) {
104        serviceDefs[i].taken = FALSE;
105     }
107     for (i = 0; i < MAX_TUPLES; i++) {
108        Tuples[i].key = FREE_TUPLE_KEY;
109     }
111     for (i = 0; i < MAX_SERVICES; i++) {
112         serviceTasks[i].taken = FALSE;
113         serviceTasks[i].fxn = NULL;
114         serviceTasks[i].reserved = (UInt16) -1;
115     }
118 UInt ServiceMgr_start(UInt16 reserved)
120     UInt        i;
121     UInt        count = 0;
122     static Bool started = FALSE;
124     if (started) {
125         return 0;
126     }
128     for (i = 0; (i < MAX_SERVICES) && (serviceTasks[i].taken); i++) {
129         Task_create(serviceTasks[i].fxn, &serviceTasks[i].params, NULL);
130         count++;
131     }
133     return (count);
136 Bool ServiceMgr_registerSrvTask(UInt16 reserved, Task_FuncPtr func,
137                                 Task_Params *taskParams)
139     UInt                    i;
140     Bool                    found = FALSE;
141     ServiceMgr_ServiceTask  *st;
142     Task_Params             *params;
144     /* Search the array for a free slot */
145     for (i = 0; (i < MAX_SERVICES) && (found == FALSE); i++) {
146         if (!serviceTasks[i].taken) {
147             st = &serviceTasks[i];
148             st->fxn = func;
149             strncpy(st->name, taskParams->instance->name, MAX_NAMELEN-1);
150             st->name[MAX_NAMELEN-1] = '\0';
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;
212     /* Send it off (and no response expected): */
213     RPMessage_send(dstProc, remote, local, data, HDRSIZE+len);
216 Bool ServiceMgr_registerDisconnectFxn(Service_Handle srvc, Ptr data,
217                                       ServiceMgr_disconnectFuncPtr func)
219     if (func == NULL) {
220         System_printf("ServiceMgr_registerDisconnectFxn: Invalid function.\n");
221         return FALSE;
222     }
224     /* Register the user-supplied function */
225     if (!ServiceMgr_disconnectUserFxn) {
226         ServiceMgr_disconnectUserFxn = func;
227     }
228     return TRUE;
231 /* Tuple store/retrieve fxns:  */
233 static Bool storeTuple(UInt32 key, UInt32 value)
235     UInt              i;
236     Bool              stored = FALSE;
238     if (key == FREE_TUPLE_KEY) {
239         System_printf("storeTuple: reserved key %d\n", key);
240     }
241     else {
242         /* Search the array for a free slot: */
243         for (i = 0; (i < MAX_TUPLES) && (stored == FALSE); i++) {
244            if (Tuples[i].key == FREE_TUPLE_KEY) {
245                Tuples[i].key = key;
246                Tuples[i].value = value;
247                stored = TRUE;
248                break;
249            }
250         }
251     }
253     return(stored);
256 static Bool removeTuple(UInt32 key, UInt32 * value)
258     UInt              i;
259     Bool              found = FALSE;
261     /* Search the array for tuple matching key: */
262     for (i = 0; (i < MAX_TUPLES) && (found == FALSE); i++) {
263        if (Tuples[i].key == key) {
264            found = TRUE;
265            *value = Tuples[i].value;
266            /* and free it... */
267            Tuples[i].value = 0;
268            Tuples[i].key = FREE_TUPLE_KEY;
269            break;
270        }
271     }
273     return(found);
276 UInt32 ServiceMgr_createService(Char * name, UInt32 * endpt)
278     Int i;
279     Int status = 0;
280     struct ServiceDef *sd;
281     RcmServer_Handle  rcmSrvHandle;
283     for (i = 0; i < ServiceMgr_NUMSERVICETYPES; i++) {
284        if (!strcmp(name, serviceDefs[i].name)) {
285            sd = &serviceDefs[i];
286            break;
287        }
288     }
290     if (i >= ServiceMgr_NUMSERVICETYPES) {
291        System_printf("createService: unrecognized service name: %s\n", name);
292        return OMX_NOTSUPP;
293     }
295     /* Create the RcmServer instance. */
296 #if 0
297     System_printf("createService: Calling RcmServer_create with name = %s\n"
298                   "priority = %d\n"
299                   "osPriority = %d\n"
300                   "rcmServerParams.fxns.length = %d\n",
301                   sd->name, sd->rcmServerParams.priority,
302                   sd->rcmServerParams.osPriority,
303                   sd->rcmServerParams.fxns.length);
304 #endif
305     status = RcmServer_create(sd->name, &sd->rcmServerParams, &rcmSrvHandle);
307     if (status < 0) {
308         System_printf("createService: RcmServer_create() returned error %d\n",
309                        status);
310         return OMX_FAIL;
311     }
313     /* Get endpoint allowing clients to send messages to this new server: */
314     *endpt = RcmServer_getLocalAddress(rcmSrvHandle);
316     /* Store Server's endpoint with handle so we can cleanup on disconnect: */
317     if (!storeTuple(*endpt, (UInt32)rcmSrvHandle))  {
318         System_printf("createService: Limit reached on max instances!\n");
319         RcmServer_delete(&rcmSrvHandle);
320         return OMX_FAIL;
321     }
323     /* start the server */
324     RcmServer_start(rcmSrvHandle);
326     System_printf("createService: new OMX Service at endpoint: %d\n", *endpt);
328     return OMX_SUCCESS;
332 UInt32 ServiceMgr_deleteService(UInt32 addr)
334     Int status = 0;
335     RcmServer_Handle  rcmSrvHandle;
337     if (!removeTuple(addr, (UInt32 *)&rcmSrvHandle))  {
338        System_printf("deleteService: could not find service instance at"
339                      " address: 0x%x\n", addr);
340        return OMX_FAIL;
341     }
343     /* Notify a ServiceMgr client of disconnection.
344      * rcmSrvHandle is same as the ServiceMgr handle
345      */
346     if (ServiceMgr_disconnectUserFxn) {
347         /* Pass NULL data for the moment */
348         ServiceMgr_disconnectUserFxn(rcmSrvHandle, NULL);
349     }
351     /* Destroy the RcmServer instance. */
352     status = RcmServer_delete(&rcmSrvHandle);
353     if (status < 0) {
354         System_printf("deleteService: RcmServer_delete() returned error %d\n",
355                        status);
356         return OMX_FAIL;
357     }
359     System_printf("deleteService: removed RcmServer at endpoint: %d\n", addr);
361     return OMX_SUCCESS;