clonestream.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /*
  2. * Copyright (c) 2019 Actions Semiconductor Co., Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * @file clone stream interface
  8. */
  9. #define SYS_LOG_DOMAIN "clonestream"
  10. #include <mem_manager.h>
  11. #include <clone_stream.h>
  12. #include <mem_manager.h>
  13. #include <stream.h>
  14. #include <assert.h>
  15. #include <errno.h>
  16. #include <sys/util.h>
  17. static bool validate_stream_state(io_stream_t handle, uint8_t state)
  18. {
  19. return handle->state == state;
  20. }
  21. static int clone_stream_init(io_stream_t handle, void *param)
  22. {
  23. struct clone_stream_info *info = param;
  24. int i;
  25. if (!validate_stream_state(info->origin, STATE_INIT)) {
  26. SYS_LOG_ERR("state not init\n");
  27. return -EINVAL;
  28. }
  29. for (i = 0; i < ARRAY_SIZE(info->clones); i++) {
  30. if (!info->clones[i])
  31. break;
  32. if (!validate_stream_state(info->clones[i], STATE_OPEN)) {
  33. SYS_LOG_ERR("state not open\n", i);
  34. return -EINVAL;
  35. }
  36. if (!(info->clones[i]->mode & MODE_OUT)) {
  37. SYS_LOG_ERR("stream clone[%d] not writable\n", i);
  38. return -EINVAL;
  39. }
  40. }
  41. handle->data = mem_malloc(sizeof(*info));
  42. if (!handle->data) {
  43. SYS_LOG_ERR("malloc data\n", i);
  44. return -ENOMEM;
  45. }
  46. memcpy(handle->data, info, sizeof(*info));
  47. return 0;
  48. }
  49. static int clone_stream_open(io_stream_t handle, stream_mode mode)
  50. {
  51. struct clone_stream_info *info = handle->data;
  52. int res;
  53. SYS_LOG_DBG(" call\n");
  54. res = stream_open(info->origin, mode);
  55. if (res)
  56. return res;
  57. handle->write_finished = 0;
  58. return 0;
  59. }
  60. static int clone_stream_read(io_stream_t handle, unsigned char *buf,int num)
  61. {
  62. struct clone_stream_info *info = handle->data;
  63. int len, i;
  64. len = stream_read(info->origin, buf, num);
  65. if (len <= 0)
  66. return len;
  67. /* clone read data */
  68. if (handle->mode & info->clone_mode) {
  69. for (i = 0; i < ARRAY_SIZE(info->clones); i++) {
  70. if (!info->clones[i])
  71. break;
  72. info->clones[i]->ops->write(info->clones[i], buf, len);
  73. }
  74. }
  75. return len;
  76. }
  77. static int clone_stream_write(io_stream_t handle, unsigned char *buf,int num)
  78. {
  79. struct clone_stream_info *info = handle->data;
  80. int len, i;
  81. len = stream_write(info->origin, buf, num);
  82. if (len <= 0)
  83. return len;
  84. /* clone write data */
  85. if (handle->mode & info->clone_mode) {
  86. for (i = 0; i < ARRAY_SIZE(info->clones); i++) {
  87. if (!info->clones[i])
  88. break;
  89. info->clones[i]->ops->write(info->clones[i], buf, len);
  90. }
  91. }
  92. return len;
  93. }
  94. static int clone_stream_seek(io_stream_t handle, int offset, seek_dir origin)
  95. {
  96. /* FIXME: seek ops will make clone stream data disordered */
  97. return -ENOSYS;
  98. }
  99. static int clone_stream_tell(io_stream_t handle)
  100. {
  101. struct clone_stream_info *info = handle->data;
  102. return stream_tell(info->origin);
  103. }
  104. static int clone_stream_get_length(io_stream_t handle)
  105. {
  106. struct clone_stream_info *info = handle->data;
  107. return stream_get_length(info->origin);
  108. }
  109. static int clone_stream_get_space(io_stream_t handle)
  110. {
  111. struct clone_stream_info *info = handle->data;
  112. return stream_get_space(info->origin);
  113. }
  114. static int clone_stream_flush(io_stream_t handle)
  115. {
  116. struct clone_stream_info *info = handle->data;
  117. int res, i;
  118. res = stream_flush(info->origin);
  119. for (i = 0; i < ARRAY_SIZE(info->clones); i++) {
  120. if (!info->clones[i])
  121. break;
  122. if (info->clones[i]->ops->flush)
  123. info->clones[i]->ops->flush(info->clones[i]);
  124. }
  125. return res;
  126. }
  127. static int clone_stream_close(io_stream_t handle)
  128. {
  129. struct clone_stream_info *info = handle->data;
  130. int i;
  131. /* notify write finished */
  132. for (i = 0; i < ARRAY_SIZE(info->clones); i++) {
  133. if (!info->clones[i])
  134. break;
  135. info->clones[i]->ops->write(info->clones[i], NULL, 0);
  136. }
  137. return stream_close(info->origin);
  138. }
  139. static int clone_stream_destroy(io_stream_t handle)
  140. {
  141. struct clone_stream_info *info = handle->data;
  142. int res;
  143. res = stream_destroy(info->origin);
  144. mem_free(info);
  145. return res;
  146. }
  147. const stream_ops_t clone_stream_ops = {
  148. .init = clone_stream_init,
  149. .open = clone_stream_open,
  150. .read = clone_stream_read,
  151. .seek = clone_stream_seek,
  152. .tell = clone_stream_tell,
  153. .get_length = clone_stream_get_length,
  154. .get_space = clone_stream_get_space,
  155. .write = clone_stream_write,
  156. .flush = clone_stream_flush,
  157. .close = clone_stream_close,
  158. .destroy = clone_stream_destroy,
  159. };
  160. io_stream_t clone_stream_create(struct clone_stream_info *info)
  161. {
  162. return stream_create(&clone_stream_ops, info);
  163. }