Statistics
| Branch: | Tag: | Revision:

amiro-os / core / src / aos_iostream.c @ 7e674331

History | View | Annotate | Download (11.663 KB)

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

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