Statistics
| Branch: | Tag: | Revision:

amiro-os / core / src / aos_iostream.c @ b309b751

History | View | Annotate | Download (9.408 KB)

1 ba516b61 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 53710ca3 Marc Rothmann
/**
20
 * @file    aos_iostream.c
21
 * @brief   Stream and channel code.
22
 * @details Implementation of the aos_ostrem and aos_iochannel.
23
 *
24
 * @addtogroup aos_stream
25
 * @{
26
 */
27
28 ba516b61 Thomas Schöpping
#include <aos_iostream.h>
29
30
#include <aos_debug.h>
31
#include <chprintf.h>
32
33
/**
34
 * @brief   Implementation of the BaseAsynchronousChannel write() method (inherited from BaseSequentialStream).
35
 */
36
static size_t _channelwrite(void *instance, const uint8_t *bp, size_t n)
37
{
38
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_OUTPUT_ENABLE) {
39
    return streamWrite(((AosIOChannel*)instance)->asyncchannel, bp, n);
40
  } else {
41
    return 0;
42
  }
43
}
44
45
/**
46
 * @brief   Implementation of the BaseAsynchronousChannel read() method (inherited from BaseSequentialStream).
47
 */
48
static size_t _channelread(void *instance, uint8_t *bp, size_t n)
49
{
50 dd8738ea Thomas Schöpping
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_INPUT_ENABLE) {
51
    return streamRead(((AosIOChannel*)instance)->asyncchannel, bp, n);
52
  } else {
53
    return 0;
54
  }
55 ba516b61 Thomas Schöpping
}
56
57
/**
58
 * @brief   Implementation of the BaseAsynchronousChannel put() method (inherited from BaseSequentialStream).
59
 */
60
static msg_t _channelput(void *instance, uint8_t b)
61
{
62
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_OUTPUT_ENABLE) {
63
    return streamPut(((AosIOChannel*)instance)->asyncchannel, b);
64
  } else {
65
    return MSG_RESET;
66
  }
67
}
68
69
/**
70
 * @brief   Implementation of the BaseAsynchronousChannel get() method (inherited from BaseSequentialStream).
71
 */
72
static msg_t _channelget(void *instance)
73
{
74 dd8738ea Thomas Schöpping
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_INPUT_ENABLE) {
75
    return streamGet(((AosIOChannel*)instance)->asyncchannel);
76
  } else {
77
    return MSG_RESET;
78
  }
79 ba516b61 Thomas Schöpping
}
80
81
/**
82
 * @brief   Implementation of the BaseAsynchronousChannel putt() method.
83
 */
84 2c99037f Marc Rothmann
static msg_t _channelputt(void *instance, uint8_t b, sysinterval_t time)
85 ba516b61 Thomas Schöpping
{
86
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_OUTPUT_ENABLE) {
87
    return chnPutTimeout(((AosIOChannel*)instance)->asyncchannel, b, time);
88
  } else {
89
    return MSG_RESET;
90
  }
91
}
92
93
/**
94
 * @brief   Implementation of the BaseAsynchronousChannel gett() method.
95
 */
96 2c99037f Marc Rothmann
static msg_t _channelgett(void *instance, sysinterval_t time)
97 ba516b61 Thomas Schöpping
{
98 dd8738ea Thomas Schöpping
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_INPUT_ENABLE) {
99
    return chnGetTimeout(((AosIOChannel*)instance)->asyncchannel, time);
100
  } else {
101
    return MSG_RESET;
102
  }
103 ba516b61 Thomas Schöpping
}
104
105
/**
106
 * @brief   Implementation of the BaseAsynchronousChannel writet() method.
107
 */
108 2c99037f Marc Rothmann
static size_t _channelwritet(void *instance, const uint8_t *bp, size_t n, sysinterval_t time)
109 ba516b61 Thomas Schöpping
{
110
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_OUTPUT_ENABLE) {
111
    return chnWriteTimeout(((AosIOChannel*)instance)->asyncchannel, bp, n, time);
112
  } else {
113
    return 0;
114
  }
115
}
116
117
/**
118
 * @brief   Implementation of the BaseAsynchronousChannel readt() method.
119
 */
120 2c99037f Marc Rothmann
static size_t _channelreadt(void *instance, uint8_t *bp, size_t n, sysinterval_t time)
121 ba516b61 Thomas Schöpping
{
122 dd8738ea Thomas Schöpping
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_INPUT_ENABLE) {
123
    return chnReadTimeout(((AosIOChannel*)instance)->asyncchannel, bp, n, time);
124
  } else {
125
    return 0;
126
  }
127 ba516b61 Thomas Schöpping
}
128
129
/**
130 2c99037f Marc Rothmann
 * @brief   Implementation of the BaseAsynchronousChannel ctl() method.
131
 */
132 1e5f7648 Thomas Schöpping
static msg_t _channelctl(void *instance, unsigned int operation, void *arg)
133
{
134
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_OUTPUT_ENABLE) {
135 40d4810c Thomas Schöpping
    return chnControl(((AosIOChannel*)instance)->asyncchannel, operation, arg);
136 1e5f7648 Thomas Schöpping
  } else {
137
    return MSG_OK;
138 2c99037f Marc Rothmann
  }
139
}
140
141
/**
142 ba516b61 Thomas Schöpping
 * @brief   Virtual methods table for all AosIOChannel objects.
143
 */
144
static const struct AosIOChannelVMT _channelvmt = {
145 0128be0f Marc Rothmann
  (size_t) 0,
146 ba516b61 Thomas Schöpping
  _channelwrite,
147
  _channelread,
148
  _channelput,
149
  _channelget,
150
  _channelputt,
151
  _channelgett,
152
  _channelwritet,
153
  _channelreadt,
154 2c99037f Marc Rothmann
  _channelctl,
155 ba516b61 Thomas Schöpping
};
156
157
/**
158
 * @brief   Implementation of the BaseSequentialStream write() method.
159
 */
160
static size_t _streamwrite(void *instance, const uint8_t *bp, size_t n)
161
{
162
  aosDbgCheck(instance != NULL);
163
164
  // local variables
165
  AosIOChannel* channel = ((AosIOStream*)instance)->channel;
166
  size_t bytes;
167
  size_t maxbytes = 0;
168
169
  // iterate through the list of channels
170
  while (channel != NULL) {
171
    bytes = streamWrite(channel, bp, n);
172
    maxbytes = (bytes > maxbytes) ? bytes : maxbytes;
173
    channel = channel->next;
174
  }
175
176
  return maxbytes;
177
}
178
179
/**
180
 * @brief   Implementation of the BaseSequentialStream read() method.
181
 */
182
static size_t _stremread(void *instance, uint8_t *bp, size_t n)
183
{
184
  (void)instance;
185
  (void)bp;
186
  (void)n;
187
188
  return 0;
189
}
190
191
/**
192
 * @brief   Implementation of the BaseSequentialStream put() method.
193
 */
194
static msg_t _streamput(void *instance, uint8_t b)
195
{
196
  aosDbgCheck(instance != NULL);
197
198
  // local variables
199
  AosIOChannel* channel = ((AosIOStream*)instance)->channel;
200 dd8738ea Thomas Schöpping
  msg_t ret = MSG_OK;
201 ba516b61 Thomas Schöpping
202
  // iterate through the list of channels
203
  while (channel != NULL) {
204 dd8738ea Thomas Schöpping
    msg_t ret_ = streamPut(channel, b);
205
    ret = (ret_ < ret) ? ret_ : ret;
206 ba516b61 Thomas Schöpping
    channel = channel->next;
207
  }
208
209 dd8738ea Thomas Schöpping
  return ret;
210 ba516b61 Thomas Schöpping
}
211
212
/**
213
 * @brief   Implementation of the BaseSequentialStream get() method.
214
 */
215
static msg_t _streamget(void *instance)
216
{
217
  (void)instance;
218
219
  return 0;
220
}
221
222
/**
223
 * @brief   Virtual methods table for all AosIOStream objects.
224
 */
225
static const struct AosIOStreamVMT _streamvmt = {
226 0128be0f Marc Rothmann
  (size_t) 0,
227 ba516b61 Thomas Schöpping
  _streamwrite,
228
  _stremread,
229
  _streamput,
230
  _streamget,
231
};
232
233
/**
234
 * @brief   Initializes an aos_iostream_t object.
235
 *
236
 * @param[in] stream    Th aos_iostream_t object to initialize.
237
 */
238
void aosIOStreamInit(AosIOStream* stream)
239
{
240
  aosDbgCheck(stream != NULL);
241
242
  stream->vmt = &_streamvmt;
243
  stream->channel = NULL;
244
245
  return;
246
}
247
248
/**
249
 * @brief   Initializes an aos_iostream_channel_t object.
250
 *
251
 * @param[in] channel       The aos_iostream_channel_t to initialize.
252
 * @param[in] asyncchannel  The BaseAsynchronousChannel object to associate with te channel.
253
 */
254
void aosIOChannelInit(AosIOChannel *channel, BaseAsynchronousChannel *asyncchannel)
255
{
256
  aosDbgCheck(channel != NULL);
257
  aosDbgCheck(asyncchannel != NULL);
258
259
  channel->vmt = &_channelvmt;
260
  channel->asyncchannel = asyncchannel;
261
  channel->next = NULL;
262
  channel->flags = 0;
263
264
  return;
265
}
266
267
/**
268
 * @brief   Adds a channel to a stream.
269
 *
270
 * @param[in] stream    The stream to be expanded.
271
 * @param[in] channel   The channel to be added.
272
 */
273
void aosIOStreamAddChannel(AosIOStream *stream, AosIOChannel* channel)
274
{
275
  aosDbgCheck(stream != NULL);
276
  aosDbgCheck(channel != NULL && channel->asyncchannel != NULL && channel->next == NULL && (channel->flags & AOS_IOCHANNEL_ATTACHED) == 0);
277
278
  // prepend the new channel
279
  chSysLock();
280
  channel->flags |= AOS_IOCHANNEL_ATTACHED;
281
  channel->next = stream->channel;
282
  stream->channel = channel;
283
  chSysUnlock();
284
285
  return;
286
}
287
288
/**
289
 * @brief   Removes a channel from a stream.
290
 *
291
 * @param[in] stream        The stream to remove the channel from.
292
 * @param[in] asyncchannel  The BaseAsynchronousChannel to remove.
293
 * @param[out] removed      Pointer to the removed aos_iostream_channel_t.
294
 * @return
295
 */
296
aos_status_t aosIOStreamRemoveChannel(AosIOStream* stream, AosIOChannel* channel)
297
{
298
  aosDbgCheck(stream != NULL);
299
  aosDbgCheck(channel != NULL);
300
301
  // local variables
302
  AosIOChannel* prev = NULL;
303
  AosIOChannel* curr = stream->channel;
304
305
  // iterate through the list and search for the specified channel
306
  while (curr != NULL) {
307
    // if the channel was found, remove it
308
    if (curr == channel) {
309
      chSysLock();
310
      // special case: the first channel matches (prev is NULL)
311
      if (prev == NULL) {
312
        stream->channel = curr->next;
313
      } else {
314
        prev->next = curr->next;
315
      }
316
      curr->next = NULL;
317
      curr->flags &= ~AOS_IOCHANNEL_ATTACHED;
318
      chSysUnlock();
319
      return AOS_SUCCESS;
320
    }
321
    // iterate to the next channel
322
    else {
323
      prev = curr;
324
      curr = curr->next;
325
    }
326
  }
327
328
  // if the channel was not found, return an error
329
  return AOS_ERROR;
330
}
331
332
/**
333 dd8738ea Thomas Schöpping
 * @brief   Enable input for a AosIOChannel.
334
 *
335
 * @param[in] channel   The AosIOChannel to enable as input.
336
 */
337
void aosIOChannelInputEnable(AosIOChannel* channel)
338
{
339
  aosDbgCheck(channel != NULL);
340
341
  channel->flags |= AOS_IOCHANNEL_INPUT_ENABLE;
342
343
  return;
344
}
345
346
/**
347
 * @brief   Disable input for a AosIOChannel.
348
 *
349
 * @param[in] channel   The AosIOChannel to disable as input.
350
 */
351
void aosIOChannelInputDisable(AosIOChannel* channel)
352
{
353
  aosDbgCheck(channel != NULL);
354
355
  channel->flags &= ~AOS_IOCHANNEL_INPUT_ENABLE;
356
357
  return;
358
}
359
360
/**
361 ba516b61 Thomas Schöpping
 * @brief   Enable output for a AosIOChannel.
362
 *
363
 * @param[in] channel   The AosIOChannel to enable as output.
364
 */
365
void aosIOChannelOutputEnable(AosIOChannel* channel)
366
{
367
  aosDbgCheck(channel != NULL);
368
369
  channel->flags |= AOS_IOCHANNEL_OUTPUT_ENABLE;
370
371
  return;
372
}
373
374
/**
375
 * @brief   Disable output for a AosIOChannel.
376
 *
377
 * @param[in] channel   The AosIOChannel to disable as output.
378
 */
379
void aosIOChannelOutputDisable(AosIOChannel* channel)
380
{
381
  aosDbgCheck(channel != NULL);
382
383
  channel->flags &= ~AOS_IOCHANNEL_OUTPUT_ENABLE;
384
385
  return;
386
}
387 53710ca3 Marc Rothmann
388
/** @} */