/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* */ /* file: Stream.h */ /* */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* */ /* description: Cross-Platform definition of stream I/O */ /* routines. */ /* */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* */ /* Copyright (c) 2018 Acroname Inc. - All Rights Reserved */ /* */ /* This file is part of the BrainStem release. See the license.txt */ /* file included with this package or go to */ /* https://acroname.com/software/brainstem-development-kit */ /* for full license details. */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef _Stream_H_ #define _Stream_H_ #include "aDefs.h" #include "aError.h" #include "aFile.h" ///////////////////////////////////////////////////////////////////// /// Platform Independent Stream Abstraction. /** \defgroup aStream Stream Interface * \ref aStream "aStream.h" provides a platform independent stream abstraction for * common I/O streams. Provides facilities for creating and destroying * as well as writing and reading from streams. */ ///////////////////////////////////////////////////////////////////// /// Typedef #aStreamRef Opaque reference to stream primitive. typedef void* aStreamRef; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Low level operation proc defs for I/O streams. These need to * be implimented for new stream types. */ ///////////////////////////////////////////////////////////////////// /// \defgroup StreamCallbacks (Stream Implementation Callbacks) /// @{ ///////////////////////////////////////////////////////////////////// /// Typedef #aStreamGetProc. /** * This callback is defined to read one byte from the concrete stream implementation. * \param pData The data Buffer to fill. * \param ref Opaque reference to concrete stream implementation. * * \return Function returns aErr values. * \retval aErrNone Successfully read the byte. * \retval aErrNotReady No bytes in stream to read. * \retval aErrEOF Reached the end of the stream. * \retval aErrIO An error encountered reading from stream. */ typedef aErr (*aStreamGetProc)(uint8_t* pData, void* ref); ///////////////////////////////////////////////////////////////////// /// Typedef #aStreamPutProc. /** * This callback is defined to write one byte to the concrete stream implementation. * \param pData The data Buffer to write. * \param ref opaque reference to concrete stream implementation. * * \return Function returns aErr values. * \retval aErrNone Successfully wrote the byte. * \retval aErrIO An error encountered reading from stream. */ typedef aErr (*aStreamPutProc)(const uint8_t* pData, void* ref); ///////////////////////////////////////////////////////////////////// /// Typedef #aStreamDeleteProc. /** * This callback is defined to destroy the concrete stream implementation. * \param ref opaque reference to concrete stream implementation. * * \return Function returns aErr values. * \retval aErrNone Successfully destroyed. * \retval aErrParam Invalid ref. */ typedef aErr (*aStreamDeleteProc)(void* ref); ///////////////////////////////////////////////////////////////////// /// Typedef #aStreamWriteProc. (Optional) /** * Optional multi-byte write for efficiency, not required.. * \param pData The pointer to the data to write to the stream. * \param nSize The size of the data buffer in bytes. * \param ref Opaque reference to concrete stream implementation. * * \return Function returns aErr values. * \retval aErrNone Successfully destroyed. * \retval aErrIO An error encountered reading from stream. */ typedef aErr (*aStreamWriteProc)(const uint8_t* pData, const size_t nSize, void* ref); //////////////////////////////////////////////////////////////////// /// @} ///////////////////////////////////////////////////////////////////// /// Enum #aBaudRate. /** * Accepted serial stream baudrates. */ typedef enum { aBAUD_2400, ///< 2400 baud aBAUD_4800, ///< 4800 baud aBAUD_9600, ///< 9600 baud aBAUD_19200, ///< 19,200 baud aBAUD_38400, ///< 38,400 baud aBAUD_57600, ///< 57,600 baud aBAUD_115200, ///< 115,200 baud aBAUD_230400 ///< 230,400 buad } aBaudRate; ///////////////////////////////////////////////////////////////////// /// Enum #aSerial_Bits. /** * The accepted number of serial bits per byte. */ typedef enum { aBITS_8, ///< 8 bits aBITS_7 ///< 7 bits } aSerial_Bits; ///////////////////////////////////////////////////////////////////// /// Enum #aSerial_Stop_bits. /** * The accepted number of serial stop bits. */ typedef enum { aSTOP_BITS_1, ///< 1 stop bit aSTOP_BITS_2 ///< 2 stop bits } aSerial_Stop_bits; #ifdef __cplusplus extern "C" { #endif ///////////////////////////////////////////////////////////////////// /// Base Stream creation procedure. /** * Creates a Stream Reference. * * \param getProc - Callback for reading bytes from the underlying stream. * \param putProc - Callback for writing bytes to the underlying stream. * \param writeProc - Optional callback for optimized writing of multiple * bytes. * \param deleteProc - Callback for safe destruction of underlying resource. * \param procRef - opaque reference to the underlying resource, * * \return Function returns aStreamRef on success and NULL on error. */ aLIBEXPORT aStreamRef aStream_Create(aStreamGetProc getProc, aStreamPutProc putProc, aStreamWriteProc writeProc, aStreamDeleteProc deleteProc, const void* procRef); ///////////////////////////////////////////////////////////////////// /// Create a file input stream. /** * Creates a file input stream. * * \param pFilename - The filename and path of the file to read from. * \param pStreamRef - The resulting stream accessor for the input file. * * \return Function returns aErr values. * \retval aErrNone - Successful creation. * \retval aErrNotFound - The file to read was not found. * \retval aErrIO - A communication error occurred. */ aLIBEXPORT aErr aStream_CreateFileInput(const char *pFilename, aStreamRef* pStreamRef); ///////////////////////////////////////////////////////////////////// /// Create a file output stream. /** * Creates a file output stream. * * \param pFilename - The filename and path of the file to write to. * \param pStreamRef - The resulting stream accessor for the output file. * * \return Function returns aErr values. * \retval aErrNone - Successful creation. * \retval aErrIO - A communication error occurred. */ aLIBEXPORT aErr aStream_CreateFileOutput(const char *pFilename, aStreamRef* pStreamRef); ///////////////////////////////////////////////////////////////////// /// Create a serial communication stream. /** * Creates a serial stream. * * \param pPortName - The portname of the serial device. * \param nBaudRate - The baudrate to connect to the device at. * \param parity - Whether serial parity is enabled. * \param bits - The number of bits per serial byte. * \param stop - The number of stop bits per byte. * \param pStreamRef - The resulting stream accessor for the serial device. * * \return Function returns aErr values. * \retval aErrNone - Successful creation. * \retval aErrConnection - The connection was unsuccessful. * \retval aErrIO - A communication error occurred. */ aLIBEXPORT aErr aStream_CreateSerial(const char *pPortName, const aBaudRate nBaudRate, const bool parity, const aSerial_Bits bits, const aSerial_Stop_bits stop, aStreamRef* pStreamRef); ///////////////////////////////////////////////////////////////////// /// Create a serial communication stream - COBS Encoded w/ Checksum /** * Creates a serial transport stream. * * \param pPortName - The portname of the serial device. * \param nBaudRate - The baudrate to connect to the device at. * \param parity - Whether serial parity is enabled. * \param bits - The number of bits per serial byte. * \param stop - The number of stop bits per byte. * \param pStreamRef - The resulting stream accessor for the serial device. * * \return Function returns aErr values. * \retval aErrNone - Successful creation. * \retval aErrConnection - The connection was unsuccessful. * \retval aErrIO - A communication error occurred. */ aLIBEXPORT aErr aStream_CreateSerial_Packetized(const char *pPortName, const aBaudRate nBaudRate, const bool parity, const aSerial_Bits bits, const aSerial_Stop_bits stop, aStreamRef* pStreamRef); ///////////////////////////////////////////////////////////////////// /// Create a TCP/IP socket stream. /** * Creates a TCP/IP socket stream. * * \param address - The IP4 address of the connection. * \param port - The TCP port to connect to. * \param pStreamRef - The resulting stream accessor for the TCP connection. * * \return Function returns aErr values. * \retval aErrNone - Successful creation. * \retval aErrConnection - The connection was unsuccessful. * \retval aErrIO - A communication error occurred. */ aLIBEXPORT aErr aStream_CreateSocket(const uint32_t address, const uint16_t port, aStreamRef* pStreamRef); ///////////////////////////////////////////////////////////////////// /// Create a client stream /** * Creates a client socket stream * * \param address - The IP4 address of the connection. * \param port - The port of the server to connect to. * \param pStreamRef - The resulting stream accessor for the client connection. * * \return Function returns aErr values. * \retval aErrNone - Successful creation. * \retval aErrConnection - The connection was unsuccessful. * \retval aErrParam - Bad input paremeter. * \retval aErrMemory - Unable to create resources. */ aLIBEXPORT aErr aStream_CreateClient(const uint32_t address, const uint16_t port, aStreamRef* pStreamRef); ///////////////////////////////////////////////////////////////////// /// Create a stream accessor for a block of memory. /** * Creates a stream accessor for a block of allocated memory. Reads and * Writes like any other stream. The memory stream does not make a copy * of the memory and doesn't free it but rather provides a stream layer to * access it. * * \param pMemory - a pointer to a block of memory. * \param size - The size of the block in bytes. * \param pStreamRef - The resulting stream accessor for the memory block. * * \return Function returns aErr values. * \retval aErrNone - Successful creation. * \retval aErrParam - The memory block is invalid. * \retval aErrIO - A communication error occurred. */ aLIBEXPORT aErr aStream_CreateMemory(const aMemPtr pMemory, const size_t size, aStreamRef* pStreamRef); ///////////////////////////////////////////////////////////////////// /// Create a stream to a USB device. /** * Creates a BrainStem link stream to a USB based module. * * \param serialNum - The BrainStem serial number. * \param pStreamRef - The resulting stream accessor for the BrainStem * module. * * \return Function returns aErr values. * \retval aErrNone - Successful creation. * \retval aErrNotFound - The brainstem device was not found. * \retval aErrIO - A communication error occurred. */ aLIBEXPORT aErr aStream_CreateUSB(const uint32_t serialNum, aStreamRef* pStreamRef); ///////////////////////////////////////////////////////////////////// /// Create a stream buffer. /** * Creates a stream buffer. * * StreamBuffers are typically used to aggregate a bunch of output * into a single pile of bytes. This pile can then be checked for * size or accessed as a single block of bytes using the * aStreamBuffer_Get call. Finally, these bytes can then be read * back out of the buffer until it is empty when it will report an * error of aErrEOF. While this stream is thread-safe for different * threads doing reads and writes, it is not the best candidate for * managing a pipe between threads. Use the aStream_CreatePipe in * that scenario as it can be filled and emptied over and over which * is typically the use case for cross-thread pipes. * * \param nIncSize - The Increment size to expand the buffer by when it * becomes full. * \param pBufferStreamRef - The buffer stream resulting from the call. * * \return Function returns aErr values. * \retval aErrNone - The buffer was successfully created. * \retval aErrResource - The resources were not available to create the buffer. */ aLIBEXPORT aErr aStreamBuffer_Create(const size_t nIncSize, aStreamRef* pBufferStreamRef); ///////////////////////////////////////////////////////////////////// /// Get the contents of the buffer. /** * Get the contents of the buffer. * * StreamBuffers are typically used to aggregate a bunch of output * into a single pile of bytes. This pile can then be checked for * size or accessed as a single block of bytes using the * aStreamBuffer_Get call. Finally, these bytes can then be read * back out of the buffer until it is empty when it will report an * error of aErrEOF. While this stream is thread-safe for different * threads doing reads and writes, it is not the best candidate for * managing a pipe between threads. Use the aStream_CreatePipe in * that scenario as it can be filled and emptied over and over which * is typically the use case for cross-thread pipes. * * * \param bufferStreamRef - The buffer stream resulting from the call. * \param aSize - The size of the buffered data in bytes. * \param ppData - The resulting buffer of the bytes. * * \return Function returns aErr values. * \retval aErrNone - The buffer was successfully created. * \retval aErrParam - An invalid stream ref was given. */ aLIBEXPORT aErr aStreamBuffer_Get(aStreamRef bufferStreamRef, size_t* aSize, uint8_t** ppData); ///////////////////////////////////////////////////////////////////// /// Create a pipe buffered stream. /** * Get the contents of the buffer. Offers a pipe that is thread-safe * for reading and writing between two different contexts. Returns * aErrNotReady when data is not available on reads. Expands a buffer * internally to hold data when written to until it is read out (FIFO). * * \param pBufferStreamRef - The buffered stream to create the pipe out of. * * \return Function returns aErr values. * \retval aErrNone - Successful creation. * \retval aErrParam - The bufferStream is invalid. */ aLIBEXPORT aErr aStream_CreatePipe(aStreamRef* pBufferStreamRef); ///////////////////////////////////////////////////////////////////// /// Flush the cotents of the buffer. /** * Flushes the content of the buffer into the flushStream. * * \param bufferStreamRef - The buffered stream to flush. * \param flushStream - the stream to flush the buffer into. * * \return Function returns aErr values. * \retval aErrNone - The flush succeeded. * \retval aErrParam - The bufferStream is invalid. * \retval aErrIO - IO error writing to flushStream. */ aLIBEXPORT aErr aStreamBuffer_Flush(aStreamRef bufferStreamRef, aStreamRef flushStream); ///////////////////////////////////////////////////////////////////// /// Create a Logging stream. /** * Creates a stream which contains an upstream log stream and a downstream * log stream. The logging stream logs reads to the upstream log and writes * to the downstream log, while passing all data to and from the * pLogStreamRef. * * \param streamToLog - The reference to the stream to log. * \param upStreamLog - Log stream for reads. * \param downStreamLog - Log stream for writes. * \param pLogStreamRef - The logged stream reference. * * \return Function returns aErr values. * \retval aErrNone - Successful creation. * \retval aErrParam - The stream to log is invalid. * \return aErrIO - A communication error occurred creating the logging stream. */ aLIBEXPORT aErr aStream_CreateLogStream(const aStreamRef streamToLog, const aStreamRef upStreamLog, const aStreamRef downStreamLog, aStreamRef* pLogStreamRef); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Stream Operations... READ and Write FLUSH.... * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ///////////////////////////////////////////////////////////////////// /// Read a byte array record from a stream. /** * Read a byte array record from a stream. * * \param streamRef - The reference to the stream to read from. * \param pBuffer - byte array buffer to read into. * \param length - the length of the read buffer. * * \return Function returns aErr values. * \retval aErrNone - Successful read. * \retval aErrMode - The streamRef is not readable. * \retval aErrIO - An error occurred reading the data. */ aLIBEXPORT aErr aStream_Read(aStreamRef streamRef, uint8_t* pBuffer, const size_t length); ///////////////////////////////////////////////////////////////////// /// Write a byte array to a Stream. /** * Write a byte array to a Stream. * * \param streamRef - The reference to the stream to write to. * \param pBuffer - byte array to write out to the stream. * \param length - the byte array length * * \return Function returns aErr values. * \retval aErrNone - Successful write. * \retval aErrMode - The streamRef is not writable. * \retval aErrIO - An error occurred writing the data. */ aLIBEXPORT aErr aStream_Write(aStreamRef streamRef, const uint8_t* pBuffer, const size_t length); ///////////////////////////////////////////////////////////////////// /// Read a byte array record from a stream with a record terminator. /** * Read a byte array record from a stream with a record terminator. * * \param streamRef - The reference to the stream to read from. * \param pBuffer - Byte array buffer to read into. * \param lengthRead - The length of the read buffer. * \param maxLength - The Maximum record length. * \param recordTerminator - The byte array representing the record terminator. * \param terminatorLength - The length of the record terminator. * * \return Function returns aErr values. * \retval aErrNone - Successful read. * \return aErrMode - The streamRef is not readable. * \return aErrIO - An error occurred reading the data. */ aLIBEXPORT aErr aStream_ReadRecord(aStreamRef streamRef, uint8_t* pBuffer, size_t* lengthRead, const size_t maxLength, const uint8_t* recordTerminator, const size_t terminatorLength); ///////////////////////////////////////////////////////////////////// /// Write a byte array with a record terminator to a Stream. /** * Write a byte array with a record terminator to a Stream. * * \param streamRef - The reference to the stream to write to. * \param pBuffer - byte array to write out to the stream. * \param bufferLength - the byte array length * \param recordTerminator - the byte array representing the record terminator * \param terminatorLength - the length of the record terminator. * * \return Function returns aErr values. * \retval aErrNone - Successful write. * \retval aErrMode - The streamRef is not writable. * \retval aErrIO - An error occurred writing the data. */ aLIBEXPORT aErr aStream_WriteRecord(aStreamRef streamRef, const uint8_t* pBuffer, const size_t bufferLength, const uint8_t* recordTerminator, const size_t terminatorLength); ///////////////////////////////////////////////////////////////////// /// Read a null terminated string from Stream. /** * Read a null terminated string from Stream. * * \param streamRef - The reference to the stream to read from. * \param pBuffer - Character array buffer to read into. * \param maxLength - The maximum length of the string. * * \return Function returns aErr values. * \retval aErrNone - Successful read. * \retval aErrMode - The streamRef is not readable. * \retval aErrIO - An error occurred reading the data. */ aLIBEXPORT aErr aStream_ReadCString(aStreamRef streamRef, char* pBuffer, const size_t maxLength); ///////////////////////////////////////////////////////////////////// /// Write a null terminated string. /** * Write a null terminated string. * * \param streamRef - The reference to the stream to write to. * \param pBuffer - character array to write. * * \return Function returns aErr values. * \retval aErrNone - Successful write. * \retval aErrMode - The streamRef is not writable. * \retval aErrIO - An error occurred writing the data. */ aLIBEXPORT aErr aStream_WriteCString(aStreamRef streamRef, const char* pBuffer); ///////////////////////////////////////////////////////////////////// /// Read a null terminated string with a record terminator to pBuffer. /** * Read a null terminated string with a record terminator to pBuffer. * * \param streamRef - The reference to the stream to read to. * \param pBuffer - character array to read to. * \param maxLength - The maximum number of characters to read. * \param recordTerminator - The record terminator to read to. * * \return Function returns aErr values. * \retval aErrNone - Successful read. * \retval aErrMode - The streamRef is not readable. * \retval aErrIO - An error occurred reading the data. */ aLIBEXPORT aErr aStream_ReadCStringRecord(aStreamRef streamRef, char* pBuffer, const size_t maxLength, const char* recordTerminator); ///////////////////////////////////////////////////////////////////// /// Write a null terminated string with a record terminator to the stream. /** * Write a null terminated string with a record terminator to the stream. * * \param streamRef - The reference to the stream to be written to. * \param pBuffer - Null terminated string to write to the stream. * \param recordTerminator - The record terminator to write after the contents. * * \return Function returns aErr values. * \retval aErrNone - Successful write. * \retval aErrMode - The streamRef is not writable. * \retval aErrIO - An error occurred writing the data. */ aLIBEXPORT aErr aStream_WriteCStringRecord(aStreamRef streamRef, const char* pBuffer, const char* recordTerminator); ///////////////////////////////////////////////////////////////////// /// Flush contents of inStream into outStream. /** * Flush the entire current content of the instream into the outstream. * * \param inStreamRef - The reference to the stream to be flushed into the outstream. * \param outStreamRef - The reference to the stream instream is flushed into. * * \return Function returns aErr values. * \retval aErrNone - Successful Flush. * \retval aErrMode - The outstream is not writable or instream is not readable. * \retval aErrIO - An error occurred flushing the data. */ aLIBEXPORT aErr aStream_Flush(aStreamRef inStreamRef, aStreamRef outStreamRef); ///////////////////////////////////////////////////////////////////// /// Destroy a Stream. /** * Safely destroy a stream and deallocate the associated resources. * * \param pStreamRef - A pointer to a pointer of a valid streamRef. The StreamRef * will be set to NULL on successful destruction of the stream. * * \return Function returns aErr values. * \retval aErrNone - The stream was successfully destroyed. * \retval aErrParam - If the streamRef is invalid. */ aLIBEXPORT aErr aStream_Destroy(aStreamRef* pStreamRef); #ifdef __cplusplus } #endif #endif /* _Stream_H_ */