Statistics
| Branch: | Tag: | Revision:

amiro-os / os / core / src / aos_iostream.c @ 0128be0f

History | View | Annotate | Download (8.86 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
  (size_t) 0,
125
  _channelwrite,
126
  _channelread,
127
  _channelput,
128
  _channelget,
129
  _channelputt,
130
  _channelgett,
131
  _channelwritet,
132
  _channelreadt,
133
};
134

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

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

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

    
154
  return maxbytes;
155
}
156

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

    
166
  return 0;
167
}
168

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

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

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

    
187
  return ret;
188
}
189

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

    
197
  return 0;
198
}
199

    
200
/**
201
 * @brief   Virtual methods table for all AosIOStream objects.
202
 */
203
static const struct AosIOStreamVMT _streamvmt = {
204
  (size_t) 0,
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
}