]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - apps/tidep0084.git/blob - components/common/src/stream_common.c
Updated TI Linux Sensor To Cloud to the latest TI 15.4-Stack v2.4, now with CC13x2...
[apps/tidep0084.git] / components / common / src / stream_common.c
1 /******************************************************************************
2  @file stream_common.c
4  @brief TIMAC 2.0 API Common/shared code for all stream types
6  Group: WCS LPC
7  $Target Devices: Linux: AM335x, Embedded Devices: CC1310, CC1350, CC1352$
9  ******************************************************************************
10  $License: BSD3 2016 $
11   
12    Copyright (c) 2015, Texas Instruments Incorporated
13    All rights reserved.
14   
15    Redistribution and use in source and binary forms, with or without
16    modification, are permitted provided that the following conditions
17    are met:
18   
19    *  Redistributions of source code must retain the above copyright
20       notice, this list of conditions and the following disclaimer.
21   
22    *  Redistributions in binary form must reproduce the above copyright
23       notice, this list of conditions and the following disclaimer in the
24       documentation and/or other materials provided with the distribution.
25   
26    *  Neither the name of Texas Instruments Incorporated nor the names of
27       its contributors may be used to endorse or promote products derived
28       from this software without specific prior written permission.
29   
30    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
31    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
32    THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
33    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
34    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
35    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
36    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
37    OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
38    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
39    OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
40    EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41  ******************************************************************************
42  $Release Name: TI-15.4Stack Linux x64 SDK$
43  $Release Date: Sept 27, 2017 (2.04.00.13)$
44  *****************************************************************************/
46 #include "compiler.h"
47 #include "stream.h"
48 #include "log.h"
49 #include "timer.h"
50 #include "void_ptr.h"
52 #define _STREAM_IMPLIMENTOR_ 1
53 #include "stream_private.h"
55 #include <string.h>
56 #include <stdarg.h>
57 #include <stdlib.h>
59 /*
60  * Globals defined in stream.h
61  */
62 intptr_t STREAM_stdout;
63 intptr_t STREAM_stderr;
64 intptr_t STREAM_stdin;
65 intptr_t STREAM_debug_stdin;
66 intptr_t STREAM_debug_stdout;
68 /* used to verify a stream pointer */
69 static const int stream_check = 'S' + 'C';
71 /*
72  * Destroy a pseudo-private stream internal structure
73  *
74  * Pseudo-private to stream implimentations, see stream_private.h
75  */
76 void STREAM_destroyPrivate(struct io_stream *pIO)
77 {
78     if(pIO == NULL)
79     {
80         return;
81     }
82     /* we have nothing to release */
83     memset((void *)(pIO), 0, sizeof(*pIO));
84     free((void *)(pIO));
85 }
87 /*
88  * Create a pseudo-private stream internal structure
89  *
90  * Pseudo-private to streams, see stream_private.h
91  */
92 struct io_stream *STREAM_createPrivate(const struct io_stream_funcs *pFuncs,
93                                         intptr_t opaque)
94 {
95     struct io_stream *pIO;
97     pIO = calloc(1, sizeof(*pIO));
98     if(pIO)
99     {
100         pIO->check_ptr  = &stream_check;
101         pIO->pFuncs     = pFuncs;
102         pIO->opaque_ptr = opaque;
103     }
104     return (pIO);
107 /*
108  * Determine if a stream is currently marked as "in-error"
109  *
110  * Public function defined in stream.h
111  */
112 bool STREAM_isError(intptr_t h)
114     bool b;
115     struct io_stream *pIO;
117     b = true;
118     if(h)
119     {
120         pIO = STREAM_hToStruct(h);
121         if(pIO)
122         {
123             b = pIO->is_error;
124         }
125     }
126     return (b);
129 /*
130  * Convert a stream structure into a stream handle
131  *
132  * Pseudo-private to stream implimentations, see stream_private.h
133  */
134 intptr_t STREAM_structToH(struct io_stream *pIO)
136     return (intptr_t)(pIO);
139 /*
140  * Convert a stream handle into a stream structure
141  *
142  * Pseudo-private to stream implimentations, see stream_private.h
143  */
144 struct io_stream *STREAM_hToStruct(intptr_t h)
146     struct io_stream *pIO;
148     pIO = (struct io_stream *)(h);
149     if(pIO)
150     {
151         if(pIO->check_ptr != &stream_check)
152         {
153             pIO = NULL;
154         }
155     }
156     if(pIO == NULL)
157     {
158         LOG_printf(LOG_ERROR, "not-a-stream: %p\n", (void *)(h));
159     }
160     return (pIO);
163 /*
164  * Initialize the stream module as a whole
165  *
166  * Public function defined in stream.h
167  */
168 void STREAM_init(void)
170     STREAM_FILE_init();
173 /*
174  * Get the type name of a stream
175  *
176  * Public function defined in stream.h
177  */
178 const char *STREAM_getTypeName(intptr_t s)
180     const struct io_stream *pIO;
182     pIO = STREAM_hToStruct(s);
183     if(pIO == NULL)
184     {
185         return ("(unknown)");
186     }
188     return (pIO->pFuncs->name);
191 /*
192  * printf() to a stream
193  *
194  * Public function defined in stream.h
195  */
196 int STREAM_printf(intptr_t s, _Printf_format_string_  const char *fmt, ...)
198     int r;
199     va_list ap;
201     va_start(ap,fmt);
202     r = STREAM_vprintf(s, fmt, ap);
203     va_end(ap);
204     return (r);
207 /*
208  * Building block for STREAM_printf()
209  *
210  * Public function defined in stream.h
211  */
212 int STREAM_vprintf(intptr_t s, const char *fmt, va_list ap)
214     int r;
215     /* Depending upon the internal "printf()" implimentation
216      * this function could be written many ways...
217      * this is a simple and fast method that works
218      * note we are on linux, we have plenty of stack space */
219     char buf[1024];
221     r = vsnprintf(buf, sizeof(buf), fmt, ap);
222     /* forcably terminate */
223     buf[ sizeof(buf)-1 ] = 0;
225     /* something go wrong/ */
226     if(r <= 0)
227     {
228         return (r);
229     }
231     /* in case users string is larger then expected */
232     if(r > 1024)
233     {
234         /* truncate */
235         r = 1024;
236     }
238     /* send it off */
239     return (STREAM_wrBytes(s, buf, r, -1));
242 /*
243  * Unix fputc() for a stream.
244  *
245  * Public function defined in stream.h
246  */
247 int STREAM_fputc(int c, intptr_t s)
249     uint8_t b;
250     int r;
252     b = (uint8_t)(c);
254     r = STREAM_wrBytes(s, &b, 1, -1);
255     if(r == 1)
256     {
257         c = c & 0x0ff;
258     }
259     else
260     {
261         c = EOF;
262     }
263     return (c);
266 /*
267  * Unix ungetc() against a stream
268  *
269  * Public function defined in stream.h
270  */
271 int STREAM_ungetc(int c, intptr_t s)
273     struct io_stream *pIO;
275     pIO = STREAM_hToStruct(s);
276     if(pIO == NULL)
277     {
278         return (-1);
279     }
280     pIO->unget_buf = (c & 0x0ff) | 0x0100;
281     return (0);
284 /*
285  * Unix fgetc() against a stream
286  *
287  * Public function defined in stream.h
288  */
289 int STREAM_fgetc(intptr_t s)
291     struct io_stream *pIO;
292     char c;
293     int r;
295     pIO = STREAM_hToStruct(s);
296     if(pIO == NULL)
297     {
298         return (-1);
299     }
301     if(pIO->unget_buf)
302     {
303         c = (char)(pIO->unget_buf);
304         pIO->unget_buf = 0;
305         return ((int)(c) & 0x0ff);
306     }
307     r = STREAM_rdBytes(s, &c, 1, -1);
308     if(r > 0)
309     {
310         r = c;
311         r = r & 0x0ff;
312     }
313     else if(r == 0)
314     {
315         /* we read nothing, thus we return EOF */
316         r = EOF;
317     }
318     else
319     {
320         pIO->is_error = true;
321         r = EOF;
322     }
323     return (r);
326 /*
327  * Unix fgets() against a stream
328  *
329  * Public function defined in stream.h
330  */
331 char *STREAM_fgets(char *buf, int size, intptr_t h)
333     /* read a line of ascii until a universal line ending is found. */
334     /* universal means: UNIX, DOS, or MAC - or MIXED formats are ok. */
335     int c;
336     int n;
338     /* for debug reasons */
339     buf[0] = 0;
340     /* always terminate */
341     buf[size-1] = 0;
343     /* always insure space for a null byte */
344     size--;
346     /* incase the string is zero length (can't really happen) */
347     /* but visual studio warnings thinks it can happen.. */
348     c = 0;
350     /* read till terminator */
351     for(n = 0 ; n < size ; )
352     {
353         c = STREAM_fgetc(h);
354         if(c < 0)
355         {
356             /* EOF or err */
357             break;
358         }
359         buf[n+1] = 0;
360         buf[n+0] = (char)(c & 0x0ff);
361         n++;
362         /* any type of line ending? */
363         if((c == '\n') || (c=='\r'))
364         {
365             /* Unix line endings */
366             break;
367         }
368     }
370     if(c == '\r')
371     {
372         /* we have 2 possible cases: */
373         /* MAC line endings: text<CR>text */
374         /* DOS line endings: text<CR><LF>text */
375         /* ----- */
376         /* Peek ahead look for the DOS <lf> */
377         c = STREAM_fgetc(h);
378         if(c < 0)
379         {
380             /* odd situation */
381             /* could be EOF, or ERROR */
382             /* we are not going to unget this. */
383         }
384         else if(c != '\n')
385         {
386             /* Undo! this is a MAC end of line */
387             STREAM_ungetc(c, h);
388         }
389         else
390         {
391             /* we need to store the <lf> */
392             if(n >= size)
393             {
394                 /* ERROR: Edge condition, No room for the LF */
395                 /* so we silently throw it away */
396             }
397             else
398             {
399                 /* we have room for the LF */
400                 buf[n+0] = ((char)(c));
401                 buf[n+1] = 0;
402                 n++;
403             }
404         }
405     }
406     if(n)
407     {
408         /* we got something */
409         /* we return buf (below); */
410     }
411     else
412     {
413         /* We must have an EOF */
414         buf = NULL;
415     }
416     return (buf);
419 /*
420  * Unix fputs() against a stream
421  *
422  * Public function defined in stream.h
423  */
424 int STREAM_fputs(const char *s, intptr_t h)
426     int r;
427     /* write an ascii string to the file */
428     r = STREAM_wrBytes(h, s, strlen(s),-1);
429     return (r);
432 /*
433  * Write bytes into a stream
434  *
435  * Public function defined in stream.h
436  */
437 int STREAM_wrBytes(intptr_t h,
438                     const void *databytes,
439                     size_t nbytes,
440                     int timeout_mSecs)
442     struct io_stream *pIO;
444     /* write bytes (raw) to the file */
445     pIO = STREAM_hToStruct(h);
446     if(pIO == NULL)
447     {
448         return (-1);
449     }
451     return ((*(pIO->pFuncs->wr_fn))(pIO, databytes, nbytes, timeout_mSecs));
454 /*
455  * Read bytes from a stream
456  *
457  * Public function defined in stream.h
458  */
459 int STREAM_rdBytes(intptr_t h,
460                     void *databytes,
461                     size_t nbytes,
462                     int timeout_mSecs)
464     /* read (raw) from file and honor the ungetc case. */
465     struct io_stream *pIO;
466     int n;
467     int r;
469     if(nbytes == 0)
470     {
471         return (0);
472     }
474     pIO = STREAM_hToStruct(h);
475     if(pIO == NULL)
476     {
477         return (-1);
478     }
480     n = 0;
481     /* do we have an unget case? */
482     if(pIO->unget_buf)
483     {
484         /* we have an unget byte! */
485         ((char *)(databytes))[0]  = (char)(pIO->unget_buf & 0x0ff);
486         pIO->unget_buf = 0;
487         nbytes    -= 1;
488         databytes = void_ptr_add(databytes, 1);
489         n = 1;
490         /* Do we have great success! */
491         if(nbytes == 0)
492         {
493             return (1);
494         }
495     }
497     /* call specific */
498     r = (*(pIO->pFuncs->rd_fn))(pIO, databytes, nbytes, timeout_mSecs);
500     /* if UNGET did not occur */
501     /*  just return what we got. */
502     if(n == 0)
503     {
504         return (r);
505     }
507     /* we did an UNGET */
508     /*  But maybe the read call failed? */
509     if(r >= 0)
510     {
511         /* no it did not, return succes */
512         r += n;
513         return (r);
514     }
516     /* we had a failure */
517     /* But we got something from the undo buffer. */
518     /* So... it is success (posix rules!) */
519     return (1);
522 /*
523  * Return positive number if bytes are available from a stream
524  *
525  * Note: it may return 1, when there are hundreds of bytes available.
526  * Some streams cannot perform 'deep' inspection.
527  *
528  * Public function defined in stream.h
529  */
530 int STREAM_rxAvail(intptr_t h, int timeout_mSec)
532     /* do we have bytes available? */
533     struct io_stream *pIO;
535     pIO = STREAM_hToStruct(h);
536     if(pIO == NULL)
537     {
538         /* we have nothing available. */
539         return (0);
540     }
541     /* yes we do have at least 1 */
542     if(pIO->unget_buf)
543     {
544         return (1);
545     }
547     /* call handler otherwise */
548     return ((*(pIO->pFuncs->poll_fn))(pIO,timeout_mSec));
551 /*
552  * Flush (write-commit) all data in a stream to the output device
553  *
554  * Public function defined in stream.h
555  */
556 int STREAM_flush(intptr_t h)
558     /* write/commit data */
559     struct io_stream *pIO;
561     pIO = STREAM_hToStruct(h);
562     if(pIO == NULL)
563     {
564         return (-1);
565     }
567     return ((*(pIO->pFuncs->flush_fn))(pIO));
570 /*
571  * Close a stream (does not always destroy the stream)
572  * In some cases this requires additional steps that are
573  * stream specific
574  *
575  * Public function defined in sream.h
576  */
577 void STREAM_close(intptr_t h)
579     /* close the stream */
580     struct io_stream *pIO;
582     pIO = STREAM_hToStruct(h);
583     if(pIO)
584     {
585         (*(pIO->pFuncs->close_fn))(pIO);
586     }
589 /*
590  * Clear stream error flag
591  *
592  * Public function defined in sream.h
593  */
594 void STREAM_clearErrors(intptr_t h)
596     struct io_stream *pIO;
598     pIO = STREAM_hToStruct(h);
599     if(pIO)
600     {
601         (*(pIO->pFuncs->clear_fn))(pIO);
602         pIO->is_error = false;
603     }
606 /*
607  * Dump (flush) all incomming data for a stream
608  *
609  * Public function defined in stream.h
610  */
611 void STREAM_rdDump(intptr_t h, int timeout_mSecs)
613     int r;
614     timertoken_t tstart;
615     uint8_t buf[256];
616     int total;
618     tstart = TIMER_timeoutStart();
620     total = 0;
621     for(;;)
622     {
623         r = STREAM_rdBytes(h, &buf, sizeof(buf), 0);
624         if(r > 0)
625         {
626             total += r;
627             if( total > __1K ){
628                 BUG_HERE("target has crashed, and is spewing bytes\n");
629             }
630             continue;
631         }
632         if(r < 0)
633         {
634             /* io error? */
635             break;
636         }
637         if(TIMER_timeoutIsExpired(tstart, timeout_mSecs))
638         {
639             break;
640         }
641     }
644 /*
645  *  ========================================
646  *  Texas Instruments Micro Controller Style
647  *  ========================================
648  *  Local Variables:
649  *  mode: c
650  *  c-file-style: "bsd"
651  *  tab-width: 4
652  *  c-basic-offset: 4
653  *  indent-tabs-mode: nil
654  *  End:
655  *  vim:set  filetype=c tabstop=4 shiftwidth=4 expandtab=true
656  */