Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (8.835 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

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

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

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

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

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

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

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

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

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

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

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

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

    
155
  return maxbytes;
156
}
157

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

    
167
  return 0;
168
}
169

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

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

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

    
188
  return ret;
189
}
190

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

    
198
  return 0;
199
}
200

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

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

    
220
  stream->vmt = &_streamvmt;
221
  stream->channel = NULL;
222

    
223
  return;
224
}
225

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

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

    
242
  return;
243
}
244

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

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

    
263
  return;
264
}
265

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

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

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

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

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

    
319
  channel->flags |= AOS_IOCHANNEL_INPUT_ENABLE;
320

    
321
  return;
322
}
323

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

    
333
  channel->flags &= ~AOS_IOCHANNEL_INPUT_ENABLE;
334

    
335
  return;
336
}
337

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

    
347
  channel->flags |= AOS_IOCHANNEL_OUTPUT_ENABLE;
348

    
349
  return;
350
}
351

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

    
361
  channel->flags &= ~AOS_IOCHANNEL_OUTPUT_ENABLE;
362

    
363
  return;
364
}