srvmgr: Fix issue with memcopy
[ipc/ipcdev.git] / packages / ti / srvmgr / ServiceMgr.c
1 /*
2  * Copyright (c) 2011-2019, 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 "rpmsg_omx.h"
53 #include "ServiceMgr.h"
55 #define  MAX_NAMELEN       64
57 /* This artificially limits the number of service instances on this core: */
58 #define  MAX_TUPLES        256
59 #define  FREE_TUPLE_KEY    0xFFFFFFFF
61 #define  MAX_SERVICES      4
63 /* ServiceMgr disconnect hook function */
64 static ServiceMgr_disconnectFuncPtr ServiceMgr_disconnectUserFxn = NULL;
66 struct ServiceDef {
67     Char                   name[MAX_NAMELEN];
68     RcmServer_Params       rcmServerParams;
69     Bool                   taken;
70 };
72 struct ServiceDef serviceDefs[ServiceMgr_NUMSERVICETYPES];
74 struct Tuple {
75     UInt32   key;
76     UInt32   value;
77 };
78 struct Tuple Tuples[MAX_TUPLES];
80 typedef struct {
81     Task_FuncPtr    fxn;
82     Char            name[MAX_NAMELEN];
83     Task_Params     params;
84     UInt16          reserved;
85     Bool            taken;
86 } ServiceMgr_ServiceTask;
88 static ServiceMgr_ServiceTask serviceTasks[MAX_SERVICES];
91 Void ServiceMgr_init()
92 {
93     static Int  curInit = 0;
94     UInt        i;
96     if (curInit++ != 0) {
97         return; /* module already initialized */
98     }
100     RcmServer_init();
102     for (i = 0; i < ServiceMgr_NUMSERVICETYPES; i++) {
103        serviceDefs[i].taken = FALSE;
104     }
106     for (i = 0; i < MAX_TUPLES; i++) {
107        Tuples[i].key = FREE_TUPLE_KEY;
108     }
110     for (i = 0; i < MAX_SERVICES; i++) {
111         serviceTasks[i].taken = FALSE;
112         serviceTasks[i].fxn = NULL;
113         serviceTasks[i].reserved = (UInt16) -1;
114     }
117 UInt ServiceMgr_start(UInt16 reserved)
119     UInt        i;
120     UInt        count = 0;
121     static Bool started = FALSE;
123     if (started) {
124         return 0;
125     }
127     for (i = 0; (i < MAX_SERVICES) && (serviceTasks[i].taken); i++) {
128         Task_create(serviceTasks[i].fxn, &serviceTasks[i].params, NULL);
129         count++;
130     }
132     return (count);
135 Bool ServiceMgr_registerSrvTask(UInt16 reserved, Task_FuncPtr func,
136                                 Task_Params *taskParams)
138     UInt                    i;
139     Bool                    found = FALSE;
140     ServiceMgr_ServiceTask  *st;
141     Task_Params             *params;
143     /* Search the array for a free slot */
144     for (i = 0; (i < MAX_SERVICES) && (found == FALSE); i++) {
145         if (!serviceTasks[i].taken) {
146             st = &serviceTasks[i];
147             st->fxn = func;
148             strncpy(st->name, taskParams->instance->name, MAX_NAMELEN-1);
149             st->name[MAX_NAMELEN-1] = '\0';
151             /* Deal with the Task_Params to avoid IInstance mismatch */
152             params = &st->params;
153             Task_Params_init(params);
154             memcpy((Void *)(&params->arg0), &taskParams->arg0,
155                         sizeof(*params) - ((UArg)&taskParams->arg0-(UArg)taskParams));
156             params->instance->name = st->name;
158             st->reserved = reserved;
159             st->taken = TRUE;
160             found = TRUE;
161             break;
162         }
163     }
165     return (found);
168 Bool ServiceMgr_register(String name, RcmServer_Params *rcmServerParams)
170     UInt              i;
171     Bool              found = FALSE;
172     struct ServiceDef *sd;
174     if (strlen(name) >= MAX_NAMELEN) {
175         System_printf("ServiceMgr_register: service name longer than %d\n",
176                        MAX_NAMELEN );
177     }
178     else {
179         /* Search the array for a free slot */
180         for (i = 0; (i < ServiceMgr_NUMSERVICETYPES) && (found == FALSE); i++) {
181             if (!serviceDefs[i].taken) {
182                 sd = &serviceDefs[i];
183                 strcpy(sd->name, name);
184                 sd->rcmServerParams = *rcmServerParams;
185                 sd->taken = TRUE;
186                 found = TRUE;
187                 break;
188             }
189         }
190     }
192     return(found);
195 Void ServiceMgr_send(Service_Handle srvc, Ptr data, UInt16 len)
197     UInt32 local;
198     UInt32 remote;
199     struct omx_msg_hdr * hdr = (struct omx_msg_hdr *)data;
200     UInt16 dstProc;
202     /* Get reply endpoint and local address for sending: */
203     remote  = RcmServer_getRemoteAddress(srvc);
204     dstProc = RcmServer_getRemoteProc(srvc);
205     local   = RcmServer_getLocalAddress(srvc);
207     /* Set special rpmsg_omx header so Linux side can strip it off: */
208     hdr->type    = OMX_RAW_MSG;
209     hdr->len     = len;
211     /* Send it off (and no response expected): */
212     RPMessage_send(dstProc, remote, local, data, HDRSIZE+len);
215 Bool ServiceMgr_registerDisconnectFxn(Service_Handle srvc, Ptr data,
216                                       ServiceMgr_disconnectFuncPtr func)
218     if (func == NULL) {
219         System_printf("ServiceMgr_registerDisconnectFxn: Invalid function.\n");
220         return FALSE;
221     }
223     /* Register the user-supplied function */
224     if (!ServiceMgr_disconnectUserFxn) {
225         ServiceMgr_disconnectUserFxn = func;
226     }
227     return TRUE;
230 /* Tuple store/retrieve fxns:  */
232 static Bool storeTuple(UInt32 key, UInt32 value)
234     UInt              i;
235     Bool              stored = FALSE;
237     if (key == FREE_TUPLE_KEY) {
238         System_printf("storeTuple: reserved key %d\n", key);
239     }
240     else {
241         /* Search the array for a free slot: */
242         for (i = 0; (i < MAX_TUPLES) && (stored == FALSE); i++) {
243            if (Tuples[i].key == FREE_TUPLE_KEY) {
244                Tuples[i].key = key;
245                Tuples[i].value = value;
246                stored = TRUE;
247                break;
248            }
249         }
250     }
252     return(stored);
255 static Bool removeTuple(UInt32 key, UInt32 * value)
257     UInt              i;
258     Bool              found = FALSE;
260     /* Search the array for tuple matching key: */
261     for (i = 0; (i < MAX_TUPLES) && (found == FALSE); i++) {
262        if (Tuples[i].key == key) {
263            found = TRUE;
264            *value = Tuples[i].value;
265            /* and free it... */
266            Tuples[i].value = 0;
267            Tuples[i].key = FREE_TUPLE_KEY;
268            break;
269        }
270     }
272     return(found);
275 UInt32 ServiceMgr_createService(Char * name, UInt32 * endpt)
277     Int i;
278     Int status = 0;
279     struct ServiceDef *sd;
280     RcmServer_Handle  rcmSrvHandle;
282     for (i = 0; i < ServiceMgr_NUMSERVICETYPES; i++) {
283        if (!strcmp(name, serviceDefs[i].name)) {
284            sd = &serviceDefs[i];
285            break;
286        }
287     }
289     if (i >= ServiceMgr_NUMSERVICETYPES) {
290        System_printf("createService: unrecognized service name: %s\n", name);
291        return OMX_NOTSUPP;
292     }
294     /* Create the RcmServer instance. */
295 #if 0
296     System_printf("createService: Calling RcmServer_create with name = %s\n"
297                   "priority = %d\n"
298                   "osPriority = %d\n"
299                   "rcmServerParams.fxns.length = %d\n",
300                   sd->name, sd->rcmServerParams.priority,
301                   sd->rcmServerParams.osPriority,
302                   sd->rcmServerParams.fxns.length);
303 #endif
304     status = RcmServer_create(sd->name, &sd->rcmServerParams, &rcmSrvHandle);
306     if (status < 0) {
307         System_printf("createService: RcmServer_create() returned error %d\n",
308                        status);
309         return OMX_FAIL;
310     }
312     /* Get endpoint allowing clients to send messages to this new server: */
313     *endpt = RcmServer_getLocalAddress(rcmSrvHandle);
315     /* Store Server's endpoint with handle so we can cleanup on disconnect: */
316     if (!storeTuple(*endpt, (UInt32)rcmSrvHandle))  {
317         System_printf("createService: Limit reached on max instances!\n");
318         RcmServer_delete(&rcmSrvHandle);
319         return OMX_FAIL;
320     }
322     /* start the server */
323     RcmServer_start(rcmSrvHandle);
325     System_printf("createService: new OMX Service at endpoint: %d\n", *endpt);
327     return OMX_SUCCESS;
331 UInt32 ServiceMgr_deleteService(UInt32 addr)
333     Int status = 0;
334     RcmServer_Handle  rcmSrvHandle;
336     if (!removeTuple(addr, (UInt32 *)&rcmSrvHandle))  {
337        System_printf("deleteService: could not find service instance at"
338                      " address: 0x%x\n", addr);
339        return OMX_FAIL;
340     }
342     /* Notify a ServiceMgr client of disconnection.
343      * rcmSrvHandle is same as the ServiceMgr handle
344      */
345     if (ServiceMgr_disconnectUserFxn) {
346         /* Pass NULL data for the moment */
347         ServiceMgr_disconnectUserFxn(rcmSrvHandle, NULL);
348     }
350     /* Destroy the RcmServer instance. */
351     status = RcmServer_delete(&rcmSrvHandle);
352     if (status < 0) {
353         System_printf("deleteService: RcmServer_delete() returned error %d\n",
354                        status);
355         return OMX_FAIL;
356     }
358     System_printf("deleteService: removed RcmServer at endpoint: %d\n", addr);
360     return OMX_SUCCESS;