Statistics
| Branch: | Tag: | Revision:

amiro-os / os / core / src / aos_iostream.c @ 2674917e

History | View | Annotate | Download (8.83 KB)

1
/*
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_iostream.h>
20

    
21
#include <aos_debug.h>
22
#include <chprintf.h>
23

    
24
/**
25
 * @brief   Implementation of the BaseAsynchronousChannel write() method (inherited from BaseSequentialStream).
26
 */
27
static size_t _channelwrite(void *instance, const uint8_t *bp, size_t n)
28
{
29
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_OUTPUT_ENABLE) {
30
    return streamWrite(((AosIOChannel*)instance)->asyncchannel, bp, n);
31
  } else {
32
    return 0;
33
  }
34
}
35

    
36
/**
37
 * @brief   Implementation of the BaseAsynchronousChannel read() method (inherited from BaseSequentialStream).
38
 */
39
static size_t _channelread(void *instance, uint8_t *bp, size_t n)
40
{
41
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_INPUT_ENABLE) {
42
    return streamRead(((AosIOChannel*)instance)->asyncchannel, bp, n);
43
  } else {
44
    return 0;
45
  }
46
}
47

    
48
/**
49
 * @brief   Implementation of the BaseAsynchronousChannel put() method (inherited from BaseSequentialStream).
50
 */
51
static msg_t _channelput(void *instance, uint8_t b)
52
{
53
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_OUTPUT_ENABLE) {
54
    return streamPut(((AosIOChannel*)instance)->asyncchannel, b);
55
  } else {
56
    return MSG_RESET;
57
  }
58
}
59

    
60
/**
61
 * @brief   Implementation of the BaseAsynchronousChannel get() method (inherited from BaseSequentialStream).
62
 */
63
static msg_t _channelget(void *instance)
64
{
65
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_INPUT_ENABLE) {
66
    return streamGet(((AosIOChannel*)instance)->asyncchannel);
67
  } else {
68
    return MSG_RESET;
69
  }
70
}
71

    
72
/**
73
 * @brief   Implementation of the BaseAsynchronousChannel putt() method.
74
 */
75
static msg_t _channelputt(void *instance, uint8_t b, systime_t time)
76
{
77
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_OUTPUT_ENABLE) {
78
    return chnPutTimeout(((AosIOChannel*)instance)->asyncchannel, b, time);
79
  } else {
80
    return MSG_RESET;
81
  }
82
}
83

    
84
/**
85
 * @brief   Implementation of the BaseAsynchronousChannel gett() method.
86
 */
87
static msg_t _channelgett(void *instance, systime_t time)
88
{
89
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_INPUT_ENABLE) {
90
    return chnGetTimeout(((AosIOChannel*)instance)->asyncchannel, time);
91
  } else {
92
    return MSG_RESET;
93
  }
94
}
95

    
96
/**
97
 * @brief   Implementation of the BaseAsynchronousChannel writet() method.
98
 */
99
static size_t _channelwritet(void *instance, const uint8_t *bp, size_t n, systime_t time)
100
{
101
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_OUTPUT_ENABLE) {
102
    return chnWriteTimeout(((AosIOChannel*)instance)->asyncchannel, bp, n, time);
103
  } else {
104
    return 0;
105
  }
106
}
107

    
108
/**
109
 * @brief   Implementation of the BaseAsynchronousChannel readt() method.
110
 */
111
static size_t _channelreadt(void *instance, uint8_t *bp, size_t n, systime_t time)
112
{
113
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_INPUT_ENABLE) {
114
    return chnReadTimeout(((AosIOChannel*)instance)->asyncchannel, bp, n, time);
115
  } else {
116
    return 0;
117
  }
118
}
119

    
120
/**
121
 * @brief   Virtual methods table for all AosIOChannel objects.
122
 */
123
static const struct AosIOChannelVMT _channelvmt = {
124
  _channelwrite,
125
  _channelread,
126
  _channelput,
127
  _channelget,
128
  _channelputt,
129
  _channelgett,
130
  _channelwritet,
131
  _channelreadt,
132
};
133

    
134
/**
135
 * @brief   Implementation of the BaseSequentialStream write() method.
136
 */
137
static size_t _streamwrite(void *instance, const uint8_t *bp, size_t n)
138
{
139
  aosDbgCheck(instance != NULL);
140

    
141
  // local variables
142
  AosIOChannel* channel = ((AosIOStream*)instance)->channel;
143
  size_t bytes;
144
  size_t maxbytes = 0;
145

    
146
  // iterate through the list of channels
147
  while (channel != NULL) {
148
    bytes = streamWrite(channel, bp, n);
149
    maxbytes = (bytes > maxbytes) ? bytes : maxbytes;
150
    channel = channel->next;
151
  }
152

    
153
  return maxbytes;
154
}
155

    
156
/**
157
 * @brief   Implementation of the BaseSequentialStream read() method.
158
 */
159
static size_t _stremread(void *instance, uint8_t *bp, size_t n)
160
{
161
  (void)instance;
162
  (void)bp;
163
  (void)n;
164

    
165
  return 0;
166
}
167

    
168
/**
169
 * @brief   Implementation of the BaseSequentialStream put() method.
170
 */
171
static msg_t _streamput(void *instance, uint8_t b)
172
{
173
  aosDbgCheck(instance != NULL);
174

    
175
  // local variables
176
  AosIOChannel* channel = ((AosIOStream*)instance)->channel;
177
  msg_t ret = MSG_OK;
178

    
179
  // iterate through the list of channels
180
  while (channel != NULL) {
181
    msg_t ret_ = streamPut(channel, b);
182
    ret = (ret_ < ret) ? ret_ : ret;
183
    channel = channel->next;
184
  }
185

    
186
  return ret;
187
}
188

    
189
/**
190
 * @brief   Implementation of the BaseSequentialStream get() method.
191
 */
192
static msg_t _streamget(void *instance)
193
{
194
  (void)instance;
195

    
196
  return 0;
197
}
198

    
199
/**
200
 * @brief   Virtual methods table for all AosIOStream objects.
201
 */
202
static const struct AosIOStreamVMT _streamvmt = {
203
  _streamwrite,
204
  _stremread,
205
  _streamput,
206
  _streamget,
207
};
208

    
209
/**
210
 * @brief   Initializes an aos_iostream_t object.
211
 *
212
 * @param[in] stream    Th aos_iostream_t object to initialize.
213
 */
214
void aosIOStreamInit(AosIOStream* stream)
215
{
216
  aosDbgCheck(stream != NULL);
217

    
218
  stream->vmt = &_streamvmt;
219
  stream->channel = NULL;
220

    
221
  return;
222
}
223

    
224
/**
225
 * @brief   Initializes an aos_iostream_channel_t object.
226
 *
227
 * @param[in] channel       The aos_iostream_channel_t to initialize.
228
 * @param[in] asyncchannel  The BaseAsynchronousChannel object to associate with te channel.
229
 */
230
void aosIOChannelInit(AosIOChannel *channel, BaseAsynchronousChannel *asyncchannel)
231
{
232
  aosDbgCheck(channel != NULL);
233
  aosDbgCheck(asyncchannel != NULL);
234

    
235
  channel->vmt = &_channelvmt;
236
  channel->asyncchannel = asyncchannel;
237
  channel->next = NULL;
238
  channel->flags = 0;
239

    
240
  return;
241
}
242

    
243
/**
244
 * @brief   Adds a channel to a stream.
245
 *
246
 * @param[in] stream    The stream to be expanded.
247
 * @param[in] channel   The channel to be added.
248
 */
249
void aosIOStreamAddChannel(AosIOStream *stream, AosIOChannel* channel)
250
{
251
  aosDbgCheck(stream != NULL);
252
  aosDbgCheck(channel != NULL && channel->asyncchannel != NULL && channel->next == NULL && (channel->flags & AOS_IOCHANNEL_ATTACHED) == 0);
253

    
254
  // prepend the new channel
255
  chSysLock();
256
  channel->flags |= AOS_IOCHANNEL_ATTACHED;
257
  channel->next = stream->channel;
258
  stream->channel = channel;
259
  chSysUnlock();
260

    
261
  return;
262
}
263

    
264
/**
265
 * @brief   Removes a channel from a stream.
266
 *
267
 * @param[in] stream        The stream to remove the channel from.
268
 * @param[in] asyncchannel  The BaseAsynchronousChannel to remove.
269
 * @param[out] removed      Pointer to the removed aos_iostream_channel_t.
270
 * @return
271
 */
272
aos_status_t aosIOStreamRemoveChannel(AosIOStream* stream, AosIOChannel* channel)
273
{
274
  aosDbgCheck(stream != NULL);
275
  aosDbgCheck(channel != NULL);
276

    
277
  // local variables
278
  AosIOChannel* prev = NULL;
279
  AosIOChannel* curr = stream->channel;
280

    
281
  // iterate through the list and search for the specified channel
282
  while (curr != NULL) {
283
    // if the channel was found, remove it
284
    if (curr == channel) {
285
      chSysLock();
286
      // special case: the first channel matches (prev is NULL)
287
      if (prev == NULL) {
288
        stream->channel = curr->next;
289
      } else {
290
        prev->next = curr->next;
291
      }
292
      curr->next = NULL;
293
      curr->flags &= ~AOS_IOCHANNEL_ATTACHED;
294
      chSysUnlock();
295
      return AOS_SUCCESS;
296
    }
297
    // iterate to the next channel
298
    else {
299
      prev = curr;
300
      curr = curr->next;
301
    }
302
  }
303

    
304
  // if the channel was not found, return an error
305
  return AOS_ERROR;
306
}
307

    
308
/**
309
 * @brief   Enable input for a AosIOChannel.
310
 *
311
 * @param[in] channel   The AosIOChannel to enable as input.
312
 */
313
void aosIOChannelInputEnable(AosIOChannel* channel)
314
{
315
  aosDbgCheck(channel != NULL);
316

    
317
  channel->flags |= AOS_IOCHANNEL_INPUT_ENABLE;
318

    
319
  return;
320
}
321

    
322
/**
323
 * @brief   Disable input for a AosIOChannel.
324
 *
325
 * @param[in] channel   The AosIOChannel to disable as input.
326
 */
327
void aosIOChannelInputDisable(AosIOChannel* channel)
328
{
329
  aosDbgCheck(channel != NULL);
330

    
331
  channel->flags &= ~AOS_IOCHANNEL_INPUT_ENABLE;
332

    
333
  return;
334
}
335

    
336
/**
337
 * @brief   Enable output for a AosIOChannel.
338
 *
339
 * @param[in] channel   The AosIOChannel to enable as output.
340
 */
341
void aosIOChannelOutputEnable(AosIOChannel* channel)
342
{
343
  aosDbgCheck(channel != NULL);
344

    
345
  channel->flags |= AOS_IOCHANNEL_OUTPUT_ENABLE;
346

    
347
  return;
348
}
349

    
350
/**
351
 * @brief   Disable output for a AosIOChannel.
352
 *
353
 * @param[in] channel   The AosIOChannel to disable as output.
354
 */
355
void aosIOChannelOutputDisable(AosIOChannel* channel)
356
{
357
  aosDbgCheck(channel != NULL);
358

    
359
  channel->flags &= ~AOS_IOCHANNEL_OUTPUT_ENABLE;
360

    
361
  return;
362
}