1 /*
2  * Copyright (c) 2010, 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 /*
34 *   @file  timm_osal_pipes.c
35 *   This file contains methods that provides the functionality
36 *   for creating/using Nucleus pipes.
37 *
38 *  @path \
39 *
40 */
41 /* -------------------------------------------------------------------------- */
42 /* =========================================================================
43  *!
44  *! Revision History
45  *! ===================================
46  *! 07-Nov-2008 Maiya ShreeHarsha: Linux specific changes
47  *! 0.1: Created the first draft version, ksrini@ti.com
48  * ========================================================================= */
49 
50 /******************************************************************************
51 * Includes
52 ******************************************************************************/
53 
54 #include "timm_osal_types.h"
55 #include "timm_osal_error.h"
56 #include "timm_osal_memory.h"
57 #include "timm_osal_trace.h"
58 
59 #include <unistd.h>
60 #include <stdio.h>
61 #include <unistd.h>
62 #include <errno.h>
63 
64 /**
65 * TIMM_OSAL_PIPE structure define the OSAL pipe
66 */
67 typedef struct TIMM_OSAL_PIPE
68 {
69 	int pfd[2];
70 	TIMM_OSAL_U32 pipeSize;
71 	TIMM_OSAL_U32 messageSize;
72 	TIMM_OSAL_U8 isFixedMessage;
73 	int messageCount;
74 	int totalBytesInPipe;
75 } TIMM_OSAL_PIPE;
76 
77 
78 /******************************************************************************
79 * Function Prototypes
80 ******************************************************************************/
81 
82 /* ========================================================================== */
83 /**
84 * @fn TIMM_OSAL_CreatePipe function
85 *
86 *
87 */
88 /* ========================================================================== */
89 
TIMM_OSAL_CreatePipe(TIMM_OSAL_PTR * pPipe,TIMM_OSAL_U32 pipeSize,TIMM_OSAL_U32 messageSize,TIMM_OSAL_U8 isFixedMessage)90 TIMM_OSAL_ERRORTYPE TIMM_OSAL_CreatePipe(TIMM_OSAL_PTR * pPipe,
91     TIMM_OSAL_U32 pipeSize,
92     TIMM_OSAL_U32 messageSize, TIMM_OSAL_U8 isFixedMessage)
93 {
94 	TIMM_OSAL_ERRORTYPE bReturnStatus = TIMM_OSAL_ERR_UNKNOWN;
95 	TIMM_OSAL_PIPE *pHandle = TIMM_OSAL_NULL;
96 
97 	pHandle =
98 	    (TIMM_OSAL_PIPE *) TIMM_OSAL_Malloc(sizeof(TIMM_OSAL_PIPE), 0, 0,
99 	    0);
100 
101 	if (TIMM_OSAL_NULL == pHandle)
102 	{
103 		bReturnStatus = TIMM_OSAL_ERR_ALLOC;
104 		goto EXIT;
105 	}
106 	TIMM_OSAL_Memset(pHandle, 0x0, sizeof(TIMM_OSAL_PIPE));
107 
108 	pHandle->pfd[0] = -1;
109 	pHandle->pfd[1] = -1;
110 	if (SUCCESS != pipe(pHandle->pfd))
111 	{
112 		TIMM_OSAL_Error("Pipe failed: %s!!!", strerror(errno));
113 		goto EXIT;
114 	}
115 
116 	pHandle->pipeSize = pipeSize;
117 	pHandle->messageSize = messageSize;
118 	pHandle->isFixedMessage = isFixedMessage;
119 	pHandle->messageCount = 0;
120 	pHandle->totalBytesInPipe = 0;
121 
122 	*pPipe = (TIMM_OSAL_PTR) pHandle;
123 
124 	bReturnStatus = TIMM_OSAL_ERR_NONE;
125 
126 
127 	return bReturnStatus;
128 EXIT:
129 	TIMM_OSAL_Free(pHandle);
130 	return bReturnStatus;
131 }
132 
133 
134 
135 /* ========================================================================== */
136 /**
137 * @fn TIMM_OSAL_DeletePipe function
138 *
139 *
140 */
141 /* ========================================================================== */
142 
TIMM_OSAL_DeletePipe(TIMM_OSAL_PTR pPipe)143 TIMM_OSAL_ERRORTYPE TIMM_OSAL_DeletePipe(TIMM_OSAL_PTR pPipe)
144 {
145 	TIMM_OSAL_ERRORTYPE bReturnStatus = TIMM_OSAL_ERR_NONE;
146 
147 	TIMM_OSAL_PIPE *pHandle = (TIMM_OSAL_PIPE *) pPipe;
148 
149 	if (TIMM_OSAL_NULL == pHandle)
150 	{
151 		bReturnStatus = TIMM_OSAL_ERR_PARAMETER;
152 		goto EXIT;
153 	}
154 
155 	if (SUCCESS != close(pHandle->pfd[0]))
156 	{
157 		TIMM_OSAL_Error("Delete_Pipe Read fd failed!!!");
158 		bReturnStatus = TIMM_OSAL_ERR_UNKNOWN;
159 	}
160 	if (SUCCESS != close(pHandle->pfd[1]))
161 	{
162 		TIMM_OSAL_Error("Delete_Pipe Write fd failed!!!");
163 		bReturnStatus = TIMM_OSAL_ERR_UNKNOWN;
164 	}
165 
166 	TIMM_OSAL_Free(pHandle);
167 EXIT:
168 	return bReturnStatus;
169 }
170 
171 
172 
173 /* ========================================================================== */
174 /**
175 * @fn TIMM_OSAL_WriteToPipe function
176 *
177 *
178 */
179 /* ========================================================================== */
180 
TIMM_OSAL_WriteToPipe(TIMM_OSAL_PTR pPipe,void * pMessage,TIMM_OSAL_U32 size,TIMM_OSAL_S32 timeout)181 TIMM_OSAL_ERRORTYPE TIMM_OSAL_WriteToPipe(TIMM_OSAL_PTR pPipe,
182     void *pMessage, TIMM_OSAL_U32 size, TIMM_OSAL_S32 timeout)
183 {
184 	TIMM_OSAL_ERRORTYPE bReturnStatus = TIMM_OSAL_ERR_UNKNOWN;
185 	TIMM_OSAL_U32 lSizeWritten = -1;
186 
187 	TIMM_OSAL_PIPE *pHandle = (TIMM_OSAL_PIPE *) pPipe;
188 
189 	if (size == 0)
190 	{
191 		TIMM_OSAL_Error("0 size!!!");
192 		bReturnStatus = TIMM_OSAL_ERR_PARAMETER;
193 		goto EXIT;
194 	}
195 	lSizeWritten = write(pHandle->pfd[1], pMessage, size);
196 
197 	if (lSizeWritten != size)
198 	{
199 		TIMM_OSAL_Error("Write of pipe failed!!!");
200 		bReturnStatus = TIMM_OSAL_ERR_PARAMETER;
201 		goto EXIT;
202 	}
203 
204 	/*Update message count and size */
205 	pHandle->messageCount++;
206 	pHandle->totalBytesInPipe += size;
207 
208 	bReturnStatus = TIMM_OSAL_ERR_NONE;
209 
210       EXIT:
211 	return bReturnStatus;
212 }
213 
214 
215 
216 /* ========================================================================== */
217 /**
218 * @fn TIMM_OSAL_WriteToFrontOfPipe function
219 *
220 *
221 */
222 /* ========================================================================== */
223 
TIMM_OSAL_WriteToFrontOfPipe(TIMM_OSAL_PTR pPipe,void * pMessage,TIMM_OSAL_U32 size,TIMM_OSAL_S32 timeout)224 TIMM_OSAL_ERRORTYPE TIMM_OSAL_WriteToFrontOfPipe(TIMM_OSAL_PTR pPipe,
225     void *pMessage, TIMM_OSAL_U32 size, TIMM_OSAL_S32 timeout)
226 {
227 
228 	TIMM_OSAL_ERRORTYPE bReturnStatus = TIMM_OSAL_ERR_UNKNOWN;
229 	TIMM_OSAL_U32 lSizeWritten = -1;
230 	TIMM_OSAL_U32 lSizeRead = -1;
231 	TIMM_OSAL_PIPE *pHandle = (TIMM_OSAL_PIPE *) pPipe;
232 	TIMM_OSAL_U8 *tempPtr = NULL;
233 
234 
235 	/*First write to this pipe */
236 	if (size == 0)
237 	{
238 		bReturnStatus = TIMM_OSAL_ERR_PARAMETER;
239 		goto EXIT;
240 	}
241 
242 	lSizeWritten = write(pHandle->pfd[1], pMessage, size);
243 
244 	if (lSizeWritten != size)
245 	{
246 		bReturnStatus = TIMM_OSAL_ERR_PARAMETER;
247 		goto EXIT;
248 	}
249 
250 	/*Update number of messages */
251 	pHandle->messageCount++;
252 
253 
254 	if (pHandle->messageCount > 1)
255 	{
256 		/*First allocate memory */
257 		tempPtr =
258 		    (TIMM_OSAL_U8 *) TIMM_OSAL_Malloc(pHandle->
259 		    totalBytesInPipe, 0, 0, 0);
260 
261 		if (tempPtr == NULL)
262 		{
263 			bReturnStatus = TIMM_OSAL_ERR_PARAMETER;
264 			goto EXIT;
265 		}
266 
267 		/*Read out of pipe */
268 		lSizeRead =
269 		    read(pHandle->pfd[0], tempPtr, pHandle->totalBytesInPipe);
270 
271 		/*Write back to pipe */
272 		lSizeWritten =
273 		    write(pHandle->pfd[1], tempPtr,
274 		    pHandle->totalBytesInPipe);
275 
276 		if (lSizeWritten != size)
277 		{
278 			bReturnStatus = TIMM_OSAL_ERR_PARAMETER;
279 			goto EXIT;
280 		}
281 
282 		/*Update Total bytes in pipe */
283 		pHandle->totalBytesInPipe += size;
284 	}
285 
286 
287       EXIT:
288 	TIMM_OSAL_Free(tempPtr);
289 
290 	return bReturnStatus;
291 
292 }
293 
294 
295 
296 /* ========================================================================== */
297 /**
298 * @fn TIMM_OSAL_ReadFromPipe function
299 *
300 *
301 */
302 /* ========================================================================== */
303 
TIMM_OSAL_ReadFromPipe(TIMM_OSAL_PTR pPipe,void * pMessage,TIMM_OSAL_U32 size,TIMM_OSAL_U32 * actualSize,TIMM_OSAL_S32 timeout)304 TIMM_OSAL_ERRORTYPE TIMM_OSAL_ReadFromPipe(TIMM_OSAL_PTR pPipe,
305     void *pMessage,
306     TIMM_OSAL_U32 size, TIMM_OSAL_U32 * actualSize, TIMM_OSAL_S32 timeout)
307 {
308 	TIMM_OSAL_ERRORTYPE bReturnStatus = TIMM_OSAL_ERR_UNKNOWN;
309 	TIMM_OSAL_U32 lSizeRead = -1;
310 	TIMM_OSAL_PIPE *pHandle = (TIMM_OSAL_PIPE *) pPipe;
311 
312 	if (size == 0)
313 	{
314 		TIMM_OSAL_Error("nRead size has error!!!");
315 		bReturnStatus = TIMM_OSAL_ERR_PARAMETER;
316 		goto EXIT;
317 	}
318 	if ((pHandle->messageCount == 0) && (timeout == TIMM_OSAL_NO_SUSPEND))
319 	{
320 		/*If timeout is 0 and pipe is empty, return error */
321 		TIMM_OSAL_Error("Pipe is empty!!!");
322 		bReturnStatus = TIMM_OSAL_ERR_PIPE_EMPTY;
323 		goto EXIT;
324 	}
325 	if ((timeout != TIMM_OSAL_NO_SUSPEND) &&
326 	    (timeout != TIMM_OSAL_SUSPEND))
327 	{
328 		TIMM_OSAL_Warning("Only infinite or no timeouts \
329 			supported. Going to read with infinite timeout now");
330 	}
331 	/*read blocks infinitely until message is available */
332 	*actualSize = lSizeRead = read(pHandle->pfd[0], pMessage, size);
333 	if (0 == lSizeRead)
334 	{
335 		TIMM_OSAL_Error("EOF reached or no data in pipe!!!");
336 		bReturnStatus = TIMM_OSAL_ERR_PARAMETER;
337 		goto EXIT;
338 	}
339 
340 	bReturnStatus = TIMM_OSAL_ERR_NONE;
341 
342 	pHandle->messageCount--;
343 	pHandle->totalBytesInPipe -= size;
344 
345       EXIT:
346 	return bReturnStatus;
347 
348 }
349 
350 
351 
352 /* ========================================================================== */
353 /**
354 * @fn TIMM_OSAL_ClearPipe function
355 *
356 *
357 */
358 /* ========================================================================== */
359 
TIMM_OSAL_ClearPipe(TIMM_OSAL_PTR pPipe)360 TIMM_OSAL_ERRORTYPE TIMM_OSAL_ClearPipe(TIMM_OSAL_PTR pPipe)
361 {
362 	TIMM_OSAL_ERRORTYPE bReturnStatus = TIMM_OSAL_ERR;
363 
364 #if 0
365 	TIMM_OSAL_ERRORTYPE bReturnStatus = TIMM_OSAL_ERR_NONE;
366 	STATUS status = NU_SUCCESS;
367 
368 	TIMM_OSAL_PIPE *pHandle = (TIMM_OSAL_PIPE *) pPipe;
369 
370 	status = NU_Reset_Pipe(&(pHandle->pipe));
371 
372 	if (NU_SUCCESS != status)
373 	{
374 		TIMM_OSAL_Error("NU_Reset_Pipe failed!!!");
375 		bReturnStatus =
376 		    TIMM_OSAL_ERR_CREATE(TIMM_OSAL_ERR, TIMM_OSAL_COMP_PIPES,
377 		    status);
378 	}
379 #endif
380 	return bReturnStatus;
381 }
382 
383 
384 
385 /* ========================================================================== */
386 /**
387 * @fn TIMM_OSAL_IsPipeReady function
388 *
389 *
390 */
391 /* ========================================================================== */
392 
TIMM_OSAL_IsPipeReady(TIMM_OSAL_PTR pPipe)393 TIMM_OSAL_ERRORTYPE TIMM_OSAL_IsPipeReady(TIMM_OSAL_PTR pPipe)
394 {
395 	TIMM_OSAL_ERRORTYPE bReturnStatus = TIMM_OSAL_ERR;
396 	TIMM_OSAL_PIPE *pHandle = (TIMM_OSAL_PIPE *) pPipe;
397 
398 #if 0
399 	TIMM_OSAL_PIPE *pHandle = (TIMM_OSAL_PIPE *) pPipe;
400 	PI_PCB *pipe = (PI_PCB *) & (pHandle->pipe);
401 
402 	if (0 != pipe->pi_messages)
403 	{
404 		return TIMM_OSAL_ERR_NONE;
405 	} else
406 	{
407 		return TIMM_OSAL_ERR_NOT_READY;
408 	}
409 #endif
410 
411 	if (pHandle->messageCount <= 0)
412 	{
413 		bReturnStatus = TIMM_OSAL_ERR_NOT_READY;
414 	} else
415 	{
416 		bReturnStatus = TIMM_OSAL_ERR_NONE;
417 	}
418 
419 	return bReturnStatus;
420 
421 }
422 
423 
424 
425 /* ========================================================================== */
426 /**
427 * @fn TIMM_OSAL_GetPipeReadyMessageCount function
428 *
429 *
430 */
431 /* ========================================================================== */
432 
TIMM_OSAL_GetPipeReadyMessageCount(TIMM_OSAL_PTR pPipe,TIMM_OSAL_U32 * count)433 TIMM_OSAL_ERRORTYPE TIMM_OSAL_GetPipeReadyMessageCount(TIMM_OSAL_PTR pPipe,
434     TIMM_OSAL_U32 * count)
435 {
436 	TIMM_OSAL_ERRORTYPE bReturnStatus = TIMM_OSAL_ERR_NONE;
437 	TIMM_OSAL_PIPE *pHandle = (TIMM_OSAL_PIPE *) pPipe;
438 #if 0
439 
440 	TIMM_OSAL_PIPE *pHandle = (TIMM_OSAL_PIPE *) pPipe;
441 	PI_PCB *pipe = (PI_PCB *) & (pHandle->pipe);
442 
443 	*count = pipe->pi_messages;
444 
445 #endif
446 
447 	*count = pHandle->messageCount;
448 	return bReturnStatus;
449 
450 }
451