123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- /*
- * Copyright (c) 2019 Actions Semiconductor Co., Ltd
- *
- * SPDX-License-Identifier: Apache-2.0
- */
- /**
- * @file clone stream interface
- */
- #define SYS_LOG_DOMAIN "clonestream"
- #include <mem_manager.h>
- #include <clone_stream.h>
- #include <mem_manager.h>
- #include <stream.h>
- #include <assert.h>
- #include <errno.h>
- #include <sys/util.h>
- static bool validate_stream_state(io_stream_t handle, uint8_t state)
- {
- return handle->state == state;
- }
- static int clone_stream_init(io_stream_t handle, void *param)
- {
- struct clone_stream_info *info = param;
- int i;
- if (!validate_stream_state(info->origin, STATE_INIT)) {
- SYS_LOG_ERR("state not init\n");
- return -EINVAL;
- }
- for (i = 0; i < ARRAY_SIZE(info->clones); i++) {
- if (!info->clones[i])
- break;
- if (!validate_stream_state(info->clones[i], STATE_OPEN)) {
- SYS_LOG_ERR("state not open\n", i);
- return -EINVAL;
- }
- if (!(info->clones[i]->mode & MODE_OUT)) {
- SYS_LOG_ERR("stream clone[%d] not writable\n", i);
- return -EINVAL;
- }
- }
- handle->data = mem_malloc(sizeof(*info));
- if (!handle->data) {
- SYS_LOG_ERR("malloc data\n", i);
- return -ENOMEM;
- }
- memcpy(handle->data, info, sizeof(*info));
- return 0;
- }
- static int clone_stream_open(io_stream_t handle, stream_mode mode)
- {
- struct clone_stream_info *info = handle->data;
- int res;
- SYS_LOG_DBG(" call\n");
- res = stream_open(info->origin, mode);
- if (res)
- return res;
- handle->write_finished = 0;
- return 0;
- }
- static int clone_stream_read(io_stream_t handle, unsigned char *buf,int num)
- {
- struct clone_stream_info *info = handle->data;
- int len, i;
- len = stream_read(info->origin, buf, num);
- if (len <= 0)
- return len;
- /* clone read data */
- if (handle->mode & info->clone_mode) {
- for (i = 0; i < ARRAY_SIZE(info->clones); i++) {
- if (!info->clones[i])
- break;
- info->clones[i]->ops->write(info->clones[i], buf, len);
- }
- }
- return len;
- }
- static int clone_stream_write(io_stream_t handle, unsigned char *buf,int num)
- {
- struct clone_stream_info *info = handle->data;
- int len, i;
- len = stream_write(info->origin, buf, num);
- if (len <= 0)
- return len;
- /* clone write data */
- if (handle->mode & info->clone_mode) {
- for (i = 0; i < ARRAY_SIZE(info->clones); i++) {
- if (!info->clones[i])
- break;
- info->clones[i]->ops->write(info->clones[i], buf, len);
- }
- }
- return len;
- }
- static int clone_stream_seek(io_stream_t handle, int offset, seek_dir origin)
- {
- /* FIXME: seek ops will make clone stream data disordered */
- return -ENOSYS;
- }
- static int clone_stream_tell(io_stream_t handle)
- {
- struct clone_stream_info *info = handle->data;
- return stream_tell(info->origin);
- }
- static int clone_stream_get_length(io_stream_t handle)
- {
- struct clone_stream_info *info = handle->data;
- return stream_get_length(info->origin);
- }
- static int clone_stream_get_space(io_stream_t handle)
- {
- struct clone_stream_info *info = handle->data;
- return stream_get_space(info->origin);
- }
- static int clone_stream_flush(io_stream_t handle)
- {
- struct clone_stream_info *info = handle->data;
- int res, i;
- res = stream_flush(info->origin);
- for (i = 0; i < ARRAY_SIZE(info->clones); i++) {
- if (!info->clones[i])
- break;
- if (info->clones[i]->ops->flush)
- info->clones[i]->ops->flush(info->clones[i]);
- }
- return res;
- }
- static int clone_stream_close(io_stream_t handle)
- {
- struct clone_stream_info *info = handle->data;
- int i;
- /* notify write finished */
- for (i = 0; i < ARRAY_SIZE(info->clones); i++) {
- if (!info->clones[i])
- break;
- info->clones[i]->ops->write(info->clones[i], NULL, 0);
- }
- return stream_close(info->origin);
- }
- static int clone_stream_destroy(io_stream_t handle)
- {
- struct clone_stream_info *info = handle->data;
- int res;
- res = stream_destroy(info->origin);
- mem_free(info);
- return res;
- }
- const stream_ops_t clone_stream_ops = {
- .init = clone_stream_init,
- .open = clone_stream_open,
- .read = clone_stream_read,
- .seek = clone_stream_seek,
- .tell = clone_stream_tell,
- .get_length = clone_stream_get_length,
- .get_space = clone_stream_get_space,
- .write = clone_stream_write,
- .flush = clone_stream_flush,
- .close = clone_stream_close,
- .destroy = clone_stream_destroy,
- };
- io_stream_t clone_stream_create(struct clone_stream_info *info)
- {
- return stream_create(&clone_stream_ops, info);
- }
|