Statistics
| Branch: | Tag: | Revision:

amiro-os / os / core / src / aos_ssm.c @ e545e620

History | View | Annotate | Download (8.445 KB)

1 e545e620 Thomas Schöpping
/*
2
AMiRo-OS is an operating system designed for the Autonomous Mini Robot (AMiRo) platform.
3
Copyright (C) 2016..2018  Thomas Schöpping et al.
4

5
This program is free software: you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation, either version 3 of the License, or
8
(at your option) any later version.
9

10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
GNU General Public License for more details.
14

15
You should have received a copy of the GNU General Public License
16
along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
*/
18
19
#include <aos_ssm.h>
20
21
/**
22
 * @brief   Sequential Stream Multiplexer write.
23
 *
24
 * @param[in] ip      pointer to a @p SequentialStreamMux object
25
 * @param[in] bp      pointer to the data buffer
26
 * @param[in] n       the maximum amount of bytes to be transferred
27
 *
28
 * @return            The minimum number of bytes written to one of the BaseSequentialStreams.
29
 *                    If the return value is lower than n, one or multiple (or even all) streams could not write all bytes as requested.
30
 */
31
static size_t write(void *ip, const uint8_t *bp, size_t n)
32
{
33
  // initialize the number of written bytes
34
  size_t outbytes = ~0;
35
  // iterate over all output streams associated with te mux
36
  ssm_output_t* out = ((SequentialStreamMux*)ip)->outputs;
37
  while (out != NULL) {
38
    // if the output is enabled
39
    if (out->flags | SSM_OUTPUT_FLAG_ENABLED) {
40
      // write to the stream
41
      register const size_t ob = streamWrite(out->stream, bp, n);
42
      // retrieve the minimal number of bytes written across all streams
43
      outbytes = (ob < outbytes) ? ob : outbytes;
44
    }
45
    // iterate to the next stream
46
    out = out->next;
47
  }
48
49
  return (outbytes == (size_t)~0) ? 0 : outbytes;
50
}
51
52
/**
53
 * @brief   Sequential Stream Multiplexer read.
54
 *
55
 * @param[in]  ip     pointer to a @p SequentialStreamMux object
56
 * @param[out] bp     pointer to the data buffer
57
 * @param[in]  n      the maximum amount of data to be transferred
58
 *
59
 * @return            The number of bytes transferred.
60
 */
61
static size_t read(void *ip, uint8_t *bp, size_t n)
62
{
63
  // check whether a input stream is set
64
  if ( ((SequentialStreamMux*)ip)->input != NULL ) {
65
    // read from the input stream
66
    return streamRead(((SequentialStreamMux*)ip)->input, bp, n);
67
  } else {
68
    // return zero since
69
    return 0;
70
  }
71
}
72
73
/**
74
 * @brief   Sequential Stream Multiplexer blocking byte write
75
 *
76
 * @param[in] ip      pointer to a @p SequentialStreamMux object
77
 * @param[in] b       the byte value to be written
78
 *
79
 * @return            The operation status.
80
 *                    The operation status is ORed from all enabled output streams.
81
 *                    The operation status of each output stream depends on its implementation.
82
 */
83
static msg_t put(void *ip, uint8_t b)
84
{
85
  // initialize the return value
86
  msg_t retval = MSG_OK;
87
  // iterate over all output streams associated with the mux
88
  ssm_output_t* out = ((SequentialStreamMux*)ip)->outputs;
89
  while (out != NULL) {
90
    // if the output is enabled
91
    if (out->flags | SSM_OUTPUT_FLAG_ENABLED) {
92
      // put the given byte on the stream
93
      retval |= streamPut(out->stream, b);
94
    }
95
    // iterate to rhe next stream
96
    out = out->next;
97
  }
98
99
  return retval;
100
}
101
102
/**
103
 * @brief   Sequential Stream Multiplexer blocking byte read
104
 *
105
 * @param[in] ip      pointer to the @p SequentialStreamMux object
106
 *
107
 * @return            A byte value from the input.
108
 */
109
static msg_t get(void *ip)
110
{
111
  // check whether an input is set
112
  if ( ((SequentialStreamMux*)ip)->input != NULL) {
113
    // get a byte from the input
114
    return streamGet(((SequentialStreamMux*)ip)->input);
115
  } else {
116
    // return an error
117
    return MSG_RESET;
118
  }
119
}
120
121
static const struct SequentialStreamMuxVMT vmt = {
122
  write, read, put, get
123
};
124
125
/**
126
 * @brief   Initializes a @p SequentialStreamMux object
127
 *
128
 * @param[in] ssmp    pointer to the @p SequentialStreamMux object
129
 */
130
void ssmObjectInit(SequentialStreamMux *ssmp)
131
{
132
  aosDbgCheck(ssmp != NULL);
133
134
  // initialize object variables
135
  ssmp->vmt = &vmt;
136
  ssmp->outputs = NULL;
137
  ssmp->input = NULL;
138
139
  return;
140
}
141
142
/**
143
 * @brief   Initializes a @p ssm_output_t object
144
 *
145
 * @param[in] op    pointer to the @p ssm_output_t object
146
 */
147
void ssmOutputInit(ssm_output_t* op, BaseSequentialStream* stream)
148
{
149
  aosDbgCheck(op != NULL);
150
151
  // initialize object variables
152
  op->stream = stream;
153
  op->next = NULL;
154
  op->flags = 0;
155
156
  return;
157
}
158
159
/**
160
 * @brief   Adds an output to the SSM object.
161
 * @note    New outputs are always prepended to the list.
162
 *
163
 * @param[in] ssmp    pointer to the @p SequentialStreamMux object to be modified
164
 * @param[in] output  pointer to the @p ssm_output_t object to be inserted
165
 */
166
void ssmAddOutput(SequentialStreamMux* ssmp, ssm_output_t* output)
167
{
168
  aosDbgCheck(ssmp != NULL);
169
  aosDbgCheck(output != NULL);
170
  aosDbgCheck(output->next == NULL && output->flags ^ SSM_OUTPUT_FLAG_ATTACHED);
171
172
  // prepend output to the list
173
  output->flags = SSM_OUTPUT_FLAG_ATTACHED;
174
  output->next = ssmp->outputs;
175
  ssmp->outputs = output;
176
177
  return;
178
}
179
180
/**
181
 * @brief   Removes an output from the SSM object.
182
 *
183
 * @param[in] ssmp      pointer to the @p SequentialStreamMux object to be modified
184
 * @param[in] stream    pointer to the @p BaseSequentialStream to remove
185
 * @param[out] removed  pointer to the @p ssm_output_t that was removed, or NULL
186
 *
187
 * @return              Error code indicating any errors or warnings.
188
 * @retval AOS_SUCCESS  the stream was removed sucessfully
189
 * @retval AOS_ERROR    the stream was not found in the list
190
 */
191
aos_status_t ssmRemoveOutput(SequentialStreamMux* ssmp, BaseSequentialStream* stream, ssm_output_t** removed)
192
{
193
  aosDbgCheck(ssmp != NULL);
194
  aosDbgCheck(stream != NULL);
195
196
  // local varibales
197
  ssm_output_t* prev = NULL;
198
  ssm_output_t* curr = ssmp->outputs;
199
200
  // iterate through the list and search for the specified stream
201
  while (curr != NULL) {
202
    // if the stream was found, remove it
203
    if (curr->stream == stream) {
204
      // special case: the first stream matches
205
      if (prev == NULL) {
206
        ssmp->outputs->next = curr->next;
207
      } else {
208
        prev->next = curr->next;
209
      }
210
      curr->next = NULL;
211
      curr->flags &= ~SSM_OUTPUT_FLAG_ATTACHED;
212
      // set the optional output argument
213
      if (removed != NULL) {
214
        *removed = curr;
215
      }
216
      return AOS_SUCCESS;
217
    }
218
    // iterate through to the next item
219
    else {
220
      prev = curr;
221
      curr = curr->next;
222
    }
223
  }
224
225
  // if the stream was not found, return an error
226
  return AOS_ERROR;
227
}
228
229
/**
230
 * @brief   Enable an associated stream
231
 *
232
 * @param[in] ssmp    pointer to the @p SequentialStreamMux object
233
 * @param[in] stream  pointer to the @p BaseSequentialStream to enable
234
 *
235
 * @return            The operation status.
236
 * @retval AOS_SUCCESS  if the operation succeeded.
237
 * @retval AOS_ERROR    if the specified stream is not associated to the @p SequentialStreamMux.
238
 */
239
aos_status_t ssmEnableOutput(SequentialStreamMux *ssmp, BaseSequentialStream *stream)
240
{
241
  aosDbgCheck(ssmp != NULL);
242
  aosDbgCheck(stream != NULL);
243
244
  // iterate over all output streams associated to the given mux
245
  ssm_output_t* out = ssmp->outputs;
246
  while (out != NULL) {
247
    // if the output was found, activate the enabled flag
248
    if (out->stream == stream) {
249
      out->flags |= SSM_OUTPUT_FLAG_ENABLED;
250
      return AOS_SUCCESS;
251
    } else {
252
      out = out->next;
253
    }
254
  }
255
  // error if the stream is not associated with the mux
256
  return AOS_ERROR;
257
}
258
259
/**
260
 * @brief   Disable an associated stream
261
 *
262
 * @param[in] ssmp    pointer to the @p SequentialStreamMux or derived class
263
 * @param[in] stream  pointer to the stream to disable
264
 *
265
 *
266
 * @return            The operation status.
267
 * @retval AOS_OK     if the operation succeeded.
268
 * @retval AOS_ERROR  if the specified stream is not associated to the @p SequentialStreamMux.
269
 */
270
aos_status_t ssmDisableOutput(SequentialStreamMux *ssmp, BaseSequentialStream *stream)
271
{
272
  aosDbgCheck(ssmp != NULL);
273
  aosDbgCheck(stream != NULL);
274
275
  // iterate over all output streams associated to the given mux
276
  ssm_output_t* out = ssmp->outputs;
277
  while (out != NULL) {
278
    // if the output was found, activate the enabled flag
279
    if (out->stream == stream) {
280
      out->flags &= ~SSM_OUTPUT_FLAG_ENABLED;
281
      return AOS_SUCCESS;
282
    } else {
283
      out = out->next;
284
    }
285
  }
286
  // error if the stream is not associated with the mux
287
  return AOS_ERROR;
288
}