| /**************************************************************************** |
| * |
| * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved |
| * |
| ****************************************************************************/ |
| |
| /** |
| * Circular buffer backed packet stream (Interface) |
| */ |
| |
| #ifndef CPACKET_BUFFER_H__ |
| #define CPACKET_BUFFER_H__ |
| |
| /* Uses */ |
| #include <linux/types.h> |
| #include "scsc_mx_impl.h" |
| #include "mxconf.h" |
| #include "scsc_logring_common.h" |
| |
| struct cpacketbuffer; |
| |
| /** |
| * Initialises the circular buffer. |
| * The memory buffer length must be a multiple of the packet size. |
| */ |
| int cpacketbuffer_init(struct cpacketbuffer *buffer, uint32_t num_packets, uint32_t packet_size, struct scsc_mx *mx); |
| void cpacketbuffer_release(struct cpacketbuffer *buffer); |
| |
| /** |
| * Reads the gven amount of data from the buffer, copying it to the provided address. |
| * This automatically removes the read data from the buffer. |
| * |
| * If the amount of data requested is not a multiple of the packet size |
| * only the requested number of bytes will be read, but the partially read packet |
| * will still be removed from the buffer. |
| * |
| * Returns true if the packet was read. |
| */ |
| uint32_t cpacketbuffer_read(struct cpacketbuffer *buffer, void *buf, uint32_t num_bytes); |
| |
| /** |
| * Returns a pointer to the next packet of data within the buffer, without |
| * removing it. This can be used to processss data in place without needing to |
| * copy it first. |
| * |
| * If multiple packets are present these can be read in turn by setting the value |
| * of current_packet to the returned value from the previous call to cpacketbuffer_peek. |
| * |
| * cpacketbuffer_peek_complete must be called to remove the packet(s) from the buffer. |
| * |
| * Returns a pointer to the beginning of the packet to read, or NULL if there is no |
| * packet to process. |
| * |
| * Example use: |
| * // Get the first data packet |
| * void *current_packet = cpacketbuffer_peek( buffer, NULL ); |
| * void *last_packet = NULL; |
| * while( current_packet != NULL ) |
| * { |
| * // Process data packet |
| * ... |
| * |
| * // Get the next data packet |
| * last_packet = current_packet; |
| * current_packet = cpacketbuffer_peek( buffer, current_packet ); |
| * } |
| * |
| * // Remove all processed packets from the buffer |
| * if( last_packet != NULL ) |
| * { |
| * cpacketbuffer_peek_complete( buffer, last_packet ); |
| * } |
| */ |
| const void *cpacketbuffer_peek(struct cpacketbuffer *buffer, const void *current_packet); |
| |
| /** |
| * Removes all packets from the buffer up to and including the given |
| * packet. |
| * |
| * This must be called after using cpacketbuffer_peek to indicate that packet(s) |
| * can be removed from the buffer. |
| */ |
| void cpacketbuffer_peek_complete(struct cpacketbuffer *buffer, const void *packet); |
| |
| /** |
| * Writes a number of bytes to the buffer. This will always use up whole packets in the buffer |
| * even if the amount of data written is not an exact multiple of the packet size. |
| * |
| * Returns true if the data was written, false if there is not enough free space in the buffer. |
| */ |
| bool cpacketbuffer_write(struct cpacketbuffer *buffer, const void *buf, uint32_t num_bytes); |
| |
| /** |
| * Writes a set of non-contiguous data blocks to the buffer as a contiguous set. |
| * This will always use up whole packets even if the |
| * amount of data written is not an exact multiple of the packet size. |
| * |
| * Returns true if the blocks were written, false if there is not enough |
| * free space in the buffer for all the blocks. |
| */ |
| bool cpacketbuffer_write_gather(struct cpacketbuffer *buffer, const void **bufs, uint32_t *num_bytes, uint32_t num_bufs); |
| |
| /** |
| * Returns the number of free packets in the buffer. |
| */ |
| uint32_t cpacketbuffer_free_space(const struct cpacketbuffer *buffer); |
| |
| /** |
| * Returns true if the buffer is empty. |
| */ |
| bool cpacketbuffer_is_empty(const struct cpacketbuffer *buffer); |
| |
| /** |
| * Returns true if the buffer is full. |
| */ |
| bool cpacketbuffer_is_full(const struct cpacketbuffer *buffer); |
| |
| /** |
| * Returns the packet size the buffer was initialised with. This is the same value |
| * as the packet_size argument passed to cpacketbuffer_init(). |
| */ |
| uint32_t cpacketbuffer_packet_size(const struct cpacketbuffer *buffer); |
| |
| void cpacketbuffer_config_serialise(const struct cpacketbuffer *buffer, struct mxcbufconf *buf_conf); |
| |
| /** |
| * Log the state of this packet buffer at the specified log_level. |
| */ |
| void cpacketbuffer_log(const struct cpacketbuffer *buffer, enum scsc_log_level log_level); |
| |
| /** |
| * Buffer context object. |
| */ |
| struct cpacketbuffer { |
| struct scsc_mx *mx; |
| void *buffer; /* Buffer location */ |
| uint32_t num_packets; /* Total number of packets that can be stored in the buffer */ |
| uint32_t packet_size; /* Size of each individual packet within the buffer */ |
| |
| /** Pointers to 32bit R/W indexes - these should point to uint32_ts */ |
| uint32_t *read_index; /* Pointer to the location of the read index, which |
| * contains the index of the next packet to read. */ |
| uint32_t *write_index; /* Pointer to the location of the write index, which |
| * contains the index after the last packet written. */ |
| }; |
| |
| #endif /* CPACKET_BUFFER_H__ */ |