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 UInt8 msg[512]; /* maximum rpmsg size is probably smaller, but we need to
85 * be cautious */
86 OmapRpc_MsgHeader *hdr = (OmapRpc_MsgHeader *)&msg[0];
88 if (obj == NULL) {
89 System_printf("OMAPRPC: Failed to start task as arguments are NULL!\n");
90 return;
91 }
93 if (obj->msgq == NULL) {
94 System_printf("OMAPRPC: Failed to start task as MessageQ was NULL!\n");
95 return;
96 }
98 /* get the local endpoint we are to use */
99 local = obj->localEndPt;
100 System_printf("OMAPRPC: connecting from local endpoint %u to port %u\n",
101 obj->localEndPt, obj->port);
103 NameMap_register("rpmsg-rpc", obj->channelName, obj->port);
105 System_printf("OMAPRPC: started channel on port: %d\n", obj->port);
107 while (!obj->shutdown) {
109 /* clear out the message and our message vars */
110 _memset(msg, 0, sizeof(msg));
111 len = 0;
112 remote = 0;
114 /* receive the message */
115 status = RPMessage_recv(obj->msgq, (Ptr)msg, &len, &remote,
116 RPMessage_FOREVER);
118 if (status == RPMessage_E_UNBLOCKED) {
119 System_printf("OMAPRPC: unblocked while waiting for messages\n");
120 continue;
121 }
123 System_printf("OMAPRPC: received msg type: %d len: %d from addr: %d\n",
124 hdr->msgType, len, remote);
125 switch (hdr->msgType) {
126 case OmapRpc_MsgType_CREATE_INSTANCE:
127 {
128 /* temp pointer to payload */
129 OmapRpc_CreateInstance *create =
130 OmapRpc_PAYLOAD(msg, OmapRpc_CreateInstance);
131 /* local copy of name */
132 Char name[sizeof(create->name)];
133 /* return structure */
134 OmapRpc_InstanceHandle *handle =
135 OmapRpc_PAYLOAD(msg, OmapRpc_InstanceHandle);
136 /* save a copy of the input structure data */
137 _strcpy(name, create->name);
138 /* clear out the old data */
139 _memset(msg, 0, sizeof(msg));
141 /* create a new instance of the service */
142 handle->status = ServiceMgr_createService(name,
143 &handle->endpointAddress);
145 System_printf("OMAPRPC: created service instance named: %s "
146 "(status=%d) addr: %d\n", name, handle->status,
147 handle->endpointAddress);
149 hdr->msgType = OmapRpc_MsgType_INSTANCE_CREATED;
150 hdr->msgLen = sizeof(OmapRpc_InstanceHandle);
151 break;
152 }
153 case OmapRpc_MsgType_DESTROY_INSTANCE:
154 {
155 /* temp pointer to payload */
156 OmapRpc_InstanceHandle *handle =
157 OmapRpc_PAYLOAD(msg, OmapRpc_InstanceHandle);
159 if (obj->srvDelCB != NULL) {
160 obj->srvDelCB();
161 }
163 /* don't clear out the old data... */
164 System_printf("OMAPRPC: destroying instance addr: %d\n",
165 handle->endpointAddress);
166 handle->status = ServiceMgr_deleteService(
167 handle->endpointAddress);
168 hdr->msgType = OmapRpc_MsgType_INSTANCE_DESTROYED;
169 hdr->msgLen = sizeof(OmapRpc_InstanceHandle);
170 /* leave the endpoint address alone. */
171 break;
172 }
173 case OmapRpc_MsgType_QUERY_CHAN_INFO:
174 {
175 OmapRpc_ChannelInfo *chanInfo =
176 OmapRpc_PAYLOAD(msg, OmapRpc_ChannelInfo);
178 chanInfo->numFuncs = obj->numFuncs;
179 System_printf("OMAPRPC: channel info query - name %s fxns %u\n",
180 obj->channelName, chanInfo->numFuncs);
181 hdr->msgType = OmapRpc_MsgType_CHAN_INFO;
182 hdr->msgLen = sizeof(OmapRpc_ChannelInfo);
183 break;
184 }
185 case OmapRpc_MsgType_QUERY_FUNCTION:
186 {
187 OmapRpc_QueryFunction *fxnInfo = OmapRpc_PAYLOAD(msg,
188 OmapRpc_QueryFunction);
189 System_printf("OMAPRPC: function query of type %u\n",
190 fxnInfo->infoType);
192 switch (fxnInfo->infoType)
193 {
194 case OmapRpc_InfoType_FUNC_SIGNATURE:
195 if (fxnInfo->funcIndex < obj->numFuncs)
196 memcpy(&fxnInfo->info.signature,
197 &obj->funcSigs[fxnInfo->funcIndex],
198 sizeof(OmapRpc_FuncSignature));
199 break;
200 case OmapRpc_InfoType_FUNC_PERFORMANCE:
201 break;
202 case OmapRpc_InfoType_NUM_CALLS:
203 break;
204 default:
205 System_printf("OMAPRPC: Invalid info type!\n");
206 break;
207 }
208 hdr->msgType = OmapRpc_MsgType_FUNCTION_INFO;
209 hdr->msgLen = sizeof(OmapRpc_QueryFunction);
210 break;
211 }
212 default:
213 {
214 /* temp pointer to payload */
215 OmapRpc_Error *err = OmapRpc_PAYLOAD(msg, OmapRpc_Error);
217 /* the debugging message before we clear */
218 System_printf("OMAPRPC: unexpected msg type: %d\n",
219 hdr->msgType);
221 /* clear out the old data */
222 _memset(msg, 0, sizeof(msg));
224 hdr->msgType = OmapRpc_MsgType_ERROR;
225 err->endpointAddress = local;
226 err->status = OmapRpc_ErrorType_NOT_SUPPORTED;
227 break;
228 }
229 }
231 /* compute the length of the return message. */
232 len = sizeof(struct OmapRpc_MsgHeader) + hdr->msgLen;
234 System_printf("OMAPRPC: Replying with msg type: %d to addr: %d "
235 " from: %d len: %u\n", hdr->msgType, remote, local, len);
237 /* send the response. All messages get responses! */
238 RPMessage_send(obj->dstProc, remote, local, msg, len);
239 }
241 System_printf("OMAPRPC: destroying channel on port: %d\n", obj->port);
242 NameMap_unregister("rpmsg-rpc", obj->channelName, obj->port);
243 /* @TODO delete any outstanding ServiceMgr instances if no disconnect
244 * was issued? */
246 Semaphore_post(obj->exitSem);
247 }
249 /*
250 * ======== OmapRpc_createChannel ========
251 */
252 #if 0
253 OmapRpc_Handle OmapRpc_createChannel(String channelName, UInt16 dstProc,
254 UInt32 port, UInt32 numFuncs, OmapRpc_FuncDeclaration *fxns,
255 OmapRpc_SrvDelNotifyFxn srvDelCBFunc)
256 #else
257 OmapRpc_Handle OmapRpc_createChannel(String channelName, UInt16 dstProc,
258 UInt32 port, RcmServer_Params *rcmParams, MmType_FxnSigTab *fxnSigTab,
259 OmapRpc_SrvDelNotifyFxn srvDelCBFunc)
260 #endif
261 {
262 Task_Params taskParams;
263 UInt32 func;
265 OmapRpc_Object *obj = Memory_alloc(NULL, sizeof(OmapRpc_Object), 0, NULL);
267 if (obj == NULL) {
268 System_printf("OMAPRPC: Failed to allocate memory for object!\n");
269 goto unload;
270 }
271 _memset(obj, 0, sizeof(OmapRpc_Object));
272 obj->numFuncs = fxnSigTab->count + 1;
273 #if 0
274 RcmServer_Params_init(&obj->rcmParams);
275 obj->rcmParams.priority = Thread_Priority_ABOVE_NORMAL;
276 obj->rcmParams.stackSize = 0x1000;
277 obj->rcmParams.fxns.length = obj->numFuncs;
278 obj->rcmParams.fxns.elem = Memory_alloc(NULL,
279 sizeof(RcmServer_FxnDesc) * obj->numFuncs, 0, NULL);
281 if (obj->rcmParams.fxns.elem == NULL) {
282 System_printf("OMAPRPC: Failed to allocate RCM function list!\n");
283 goto unload;
284 }
285 #else
286 memcpy(&obj->rcmParams, rcmParams, sizeof(RcmServer_Params));
287 obj->rcmParams.fxns.length = obj->numFuncs;
288 obj->rcmParams.fxns.elem = Memory_calloc(NULL, obj->numFuncs *
289 sizeof(RcmServer_FxnDesc), 0, NULL);
291 if (obj->rcmParams.fxns.elem == NULL) {
292 System_printf("OMAPRPC: Failed to allocate RCM function list!\n");
293 goto unload;
294 }
295 #endif
297 // setup other variables...
298 obj->shutdown = FALSE;
299 obj->dstProc = dstProc;
300 obj->port = port;
301 strncpy(obj->channelName, channelName, OMAPRPC_MAX_CHANNEL_NAMELEN-1);
302 obj->channelName[OMAPRPC_MAX_CHANNEL_NAMELEN-1]='\0';
303 obj->srvDelCB = srvDelCBFunc;
304 obj->funcSigs = Memory_alloc(NULL, obj->numFuncs *
305 sizeof(OmapRpc_FuncSignature), 0, NULL);
307 if (obj->funcSigs == NULL) {
308 System_printf("OMAPRPC: Failed to allocate signtures list!\n");
309 goto unload;
310 }
312 /* setup the RCM functions and Signatures */
313 for (func = 0; func < obj->numFuncs; func++) {
314 if (func == 0) {
315 // assign the "first function"
316 obj->rcmParams.fxns.elem[func].name =
317 OmapRpc_Stringerize(OmapRpc_GetSvrMgrHandle);
318 obj->rcmParams.fxns.elem[func].addr.createFxn =
319 (RcmServer_MsgCreateFxn)OmapRpc_GetSvrMgrHandle;
321 strncpy(obj->funcSigs[func].name, obj->rcmParams.fxns.elem[0].name,
322 OMAPRPC_MAX_CHANNEL_NAMELEN);
323 obj->funcSigs[func].numParam = 0;
324 }
325 else {
326 // assign the other functions
327 // obj->rcmParams.fxns.elem[func].name = fxns[func-1].signature.name;
328 obj->rcmParams.fxns.elem[func].name =
329 rcmParams->fxns.elem[func-1].name;
330 // obj->rcmParams.fxns.elem[func].addr.fxn =
331 // (RcmServer_MsgFxn)fxns[func-1].function;
332 obj->rcmParams.fxns.elem[func].addr.fxn =
333 rcmParams->fxns.elem[func-1].addr.fxn;
335 // copy the signature
336 // memcpy(&obj->funcSigs[func], &fxns[func-1].signature,
337 // sizeof(OmapRpc_FuncSignature));
338 memcpy(&obj->funcSigs[func], &fxnSigTab->table[func - 1],
339 sizeof(MmType_FxnSig));
340 }
341 }
343 ServiceMgr_init();
345 if (ServiceMgr_register(channelName, &obj->rcmParams) == TRUE) {
346 System_printf("OMAPRPC: registered channel: %s\n", obj->channelName);
348 obj->msgq = RPMessage_create(obj->port, NULL, NULL,&obj->localEndPt);
350 if (obj->msgq == NULL) {
351 goto unload;
352 }
354 Task_Params_init(&taskParams);
355 taskParams.instance->name = channelName;
356 taskParams.priority = 1; /* Lowest priority thread */
357 taskParams.arg0 = (UArg)obj;
359 obj->exitSem = Semaphore_create(0, NULL, NULL);
361 if (obj->exitSem == NULL) {
362 goto unload;
363 }
365 obj->taskHandle = Task_create(omapRpcTask, &taskParams, NULL);
367 if (obj->taskHandle == NULL) {
368 goto unload;
369 }
370 }
371 else {
372 System_printf("OMAPRPC: FAILED to register channel: %s\n",
373 obj->channelName);
374 }
376 System_printf("OMAPRPC: Returning Object %p\n", obj);
377 return(obj);
379 unload:
380 OmapRpc_deleteChannel(obj);
381 return(NULL);
382 }
384 Int OmapRpc_deleteChannel(OmapRpc_Handle handle)
385 {
386 OmapRpc_Object *obj = (OmapRpc_Object *)handle;
388 if (obj == NULL) {
389 return OmapRpc_E_FAIL;
390 }
392 System_printf("OMAPRPC: deleting channel %s\n", obj->channelName);
393 obj->shutdown = TRUE;
394 if (obj->msgq) {
395 RPMessage_unblock(obj->msgq);
396 if (obj->exitSem) {
397 Semaphore_pend(obj->exitSem, BIOS_WAIT_FOREVER);
398 RPMessage_delete(&obj->msgq);
399 Semaphore_delete(&obj->exitSem);
400 }
401 if (obj->taskHandle) {
402 Task_delete(&obj->taskHandle);
403 }
404 }
405 if (obj->funcSigs)
406 Memory_free(NULL, obj->funcSigs, sizeof(*obj->funcSigs)*(obj->numFuncs-1));
407 if (obj->rcmParams.fxns.elem)
408 Memory_free(NULL, obj->rcmParams.fxns.elem,
409 sizeof(obj->rcmParams.fxns.elem[0])*obj->numFuncs);
411 Memory_free(NULL, obj, sizeof(*obj));
412 return OmapRpc_S_SUCCESS;
413 }
415 #if 0
416 /*
417 * ======== OmapRpc_start ========
418 */
419 Int OmapRpc_start(const String name, Int port, Int aryLen,
420 OmapRpc_FuncSignature *sigAry)
421 {
422 Int status = OmapRpc_S_SUCCESS;
423 Task_Params taskParams;
424 OmapRpc_Object *obj;
426 /* create an instance */
427 obj = Memory_calloc(NULL, sizeof(OmapRpc_Object), 0, NULL);
429 if (obj == NULL) {
430 System_printf("OMAPRPC: Failed to allocate memory for object!\n");
431 status = OmapRpc_E_FAIL;
432 goto leave;
433 }
435 obj->numFuncs = aryLen + 1;
436 obj->shutdown = FALSE;
437 obj->dstProc = MultiProc_getId("HOST");
438 obj->port = port;
439 strncpy(obj->channelName, name, OMAPRPC_MAX_CHANNEL_NAMELEN-1);
440 obj->channelName[OMAPRPC_MAX_CHANNEL_NAMELEN-1]='\0';
441 obj->srvDelCB = srvDelCBFunc;
442 obj->funcSigs = Memory_alloc(NULL,
443 sizeof(OmapRpc_FuncSignature) * obj->numFuncs, 0, NULL);
445 if (obj->funcSigs == NULL) {
446 System_printf("OMAPRPC: Failed to allocate signtures list!\n");
447 goto unload;
448 }
450 /* setup the functions and signatures */
451 for (func = 0; func < obj->numFuncs; func++) {
452 if (func == 0) {
453 // assign the "first function"
454 // strncpy(obj->funcSigs[func].name, obj->rcmParams.fxns.elem[0].name,
455 // OMAPRPC_MAX_CHANNEL_NAMELEN);
456 strncpy(obj->funcSigs[func].name,
457 OmapRpc_Stringerize(OmapRpc_GetSvrMgrHandle),
458 OMAPRPC_MAX_CHANNEL_NAMELEN);
459 obj->funcSigs[func].numParam = 0;
460 }
461 else {
462 // copy the signature
463 memcpy(&obj->funcSigs[func], &fxns[func-1].signature,
464 sizeof(OmapRpc_FuncSignature));
465 }
466 }
468 obj->msgq = RPMessage_create(obj->port, NULL, NULL,&obj->localEndPt);
470 if (obj->msgq == NULL) {
471 goto unload;
472 }
474 Task_Params_init(&taskParams);
475 taskParams.instance->name = channelName;
476 taskParams.priority = 1; /* Lowest priority thread */
477 taskParams.arg0 = (UArg)obj;
479 obj->exitSem = Semaphore_create(0, NULL, NULL);
481 if (obj->exitSem == NULL) {
482 goto unload;
483 }
485 obj->taskHandle = Task_create(omapRpcTask, &taskParams, NULL);
487 if (obj->taskHandle == NULL) {
488 goto unload;
489 }
491 System_printf("OMAPRPC: Returning Object %p\n", obj);
492 return(obj);
494 leave:
495 if (status < 0) {
496 OmapRpc_deleteChannel(obj);
497 }
498 return(status);
499 }
500 #endif