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);
258 }
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
272 {
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);
394 }
396 Int OmapRpc_deleteChannel(OmapRpc_Handle handle)
397 {
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;
425 }
427 #if 0
428 /*
429 * ======== OmapRpc_start ========
430 */
431 Int OmapRpc_start(const String name, Int port, Int aryLen,
432 OmapRpc_FuncSignature *sigAry)
433 {
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);
511 }
512 #endif