Statistics
| Branch: | Tag: | Revision:

amiro-os / os / core / src / aos_iostream.c @ 2c99037f

History | View | Annotate | Download (9.276 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, sysinterval_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, sysinterval_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, sysinterval_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, sysinterval_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   Implementation of the BaseAsynchronousChannel ctl() method.
122
 */
123
static msg_t _channelctl(void *instance, unsigned int operation, void *arg) {
124
  (void) instance;
125

    
126
  switch (operation) {
127
  case CHN_CTL_NOP:
128
    osalDbgCheck(arg == NULL);
129
    break;
130
  case CHN_CTL_INVALID:
131
    osalDbgAssert(false, "invalid CTL operation");
132
    break;
133
  default:
134
    break;
135
  }
136
  return MSG_OK;
137
}
138

    
139
/**
140
 * @brief   Virtual methods table for all AosIOChannel objects.
141
 */
142
static const struct AosIOChannelVMT _channelvmt = {
143
  (size_t) 0,
144
  _channelwrite,
145
  _channelread,
146
  _channelput,
147
  _channelget,
148
  _channelputt,
149
  _channelgett,
150
  _channelwritet,
151
  _channelreadt,
152
  _channelctl,
153
};
154

    
155
/**
156
 * @brief   Implementation of the BaseSequentialStream write() method.
157
 */
158
static size_t _streamwrite(void *instance, const uint8_t *bp, size_t n)
159
{
160
  aosDbgCheck(instance != NULL);
161

    
162
  // local variables
163
  AosIOChannel* channel = ((AosIOStream*)instance)->channel;
164
  size_t bytes;
165
  size_t maxbytes = 0;
166

    
167
  // iterate through the list of channels
168
  while (channel != NULL) {
169
    bytes = streamWrite(channel, bp, n);
170
    maxbytes = (bytes > maxbytes) ? bytes : maxbytes;
171
    channel = channel->next;
172
  }
173

    
174
  return maxbytes;
175
}
176

    
177
/**
178
 * @brief   Implementation of the BaseSequentialStream read() method.
179
 */
180
static size_t _stremread(void *instance, uint8_t *bp, size_t n)
181
{
182
  (void)instance;
183
  (void)bp;
184
  (void)n;
185

    
186
  return 0;
187
}
188

    
189
/**
190
 * @brief   Implementation of the BaseSequentialStream put() method.
191
 */
192
static msg_t _streamput(void *instance, uint8_t b)
193
{
194
  aosDbgCheck(instance != NULL);
195

    
196
  // local variables
197
  AosIOChannel* channel = ((AosIOStream*)instance)->channel;
198
  msg_t ret = MSG_OK;
199

    
200
  // iterate through the list of channels
201
  while (channel != NULL) {
202
    msg_t ret_ = streamPut(channel, b);
203
    ret = (ret_ < ret) ? ret_ : ret;
204
    channel = channel->next;
205
  }
206

    
207
  return ret;
208
}
209

    
210
/**
211
 * @brief   Implementation of the BaseSequentialStream get() method.
212
 */
213
static msg_t _streamget(void *instance)
214
{
215
  (void)instance;
216

    
217
  return 0;
218
}
219

    
220
/**
221
 * @brief   Virtual methods table for all AosIOStream objects.
222
 */
223
static const struct AosIOStreamVMT _streamvmt = {
224
  (size_t) 0,
225
  _streamwrite,
226
  _stremread,
227
  _streamput,
228
  _streamget,
229
};
230

    
231
/**
232
 * @brief   Initializes an aos_iostream_t object.
233
 *
234
 * @param[in] stream    Th aos_iostream_t object to initialize.
235
 */
236
void aosIOStreamInit(AosIOStream* stream)
237
{
238
  aosDbgCheck(stream != NULL);
239

    
240
  stream->vmt = &_streamvmt;
241
  stream->channel = NULL;
242

    
243
  return;
244
}
245

    
246
/**
247
 * @brief   Initializes an aos_iostream_channel_t object.
248
 *
249
 * @param[in] channel       The aos_iostream_channel_t to initialize.
250
 * @param[in] asyncchannel  The BaseAsynchronousChannel object to associate with te channel.
251
 */
252
void aosIOChannelInit(AosIOChannel *channel, BaseAsynchronousChannel *asyncchannel)
253
{
254
  aosDbgCheck(channel != NULL);
255
  aosDbgCheck(asyncchannel != NULL);
256

    
257
  channel->vmt = &_channelvmt;
258
  channel->asyncchannel = asyncchannel;
259
  channel->next = NULL;
260
  channel->flags = 0;
261

    
262
  return;
263
}
264

    
265
/**
266
 * @brief   Adds a channel to a stream.
267
 *
268
 * @param[in] stream    The stream to be expanded.
269
 * @param[in] channel   The channel to be added.
270
 */
271
void aosIOStreamAddChannel(AosIOStream *stream, AosIOChannel* channel)
272
{
273
  aosDbgCheck(stream != NULL);
274
  aosDbgCheck(channel != NULL && channel->asyncchannel != NULL && channel->next == NULL && (channel->flags & AOS_IOCHANNEL_ATTACHED) == 0);
275

    
276
  // prepend the new channel
277
  chSysLock();
278
  channel->flags |= AOS_IOCHANNEL_ATTACHED;
279
  channel->next = stream->channel;
280
  stream->channel = channel;
281
  chSysUnlock();
282

    
283
  return;
284
}
285

    
286
/**
287
 * @brief   Removes a channel from a stream.
288
 *
289
 * @param[in] stream        The stream to remove the channel from.
290
 * @param[in] asyncchannel  The BaseAsynchronousChannel to remove.
291
 * @param[out] removed      Pointer to the removed aos_iostream_channel_t.
292
 * @return
293
 */
294
aos_status_t aosIOStreamRemoveChannel(AosIOStream* stream, AosIOChannel* channel)
295
{
296
  aosDbgCheck(stream != NULL);
297
  aosDbgCheck(channel != NULL);
298

    
299
  // local variables
300
  AosIOChannel* prev = NULL;
301
  AosIOChannel* curr = stream->channel;
302

    
303
  // iterate through the list and search for the specified channel
304
  while (curr != NULL) {
305
    // if the channel was found, remove it
306
    if (curr == channel) {
307
      chSysLock();
308
      // special case: the first channel matches (prev is NULL)
309
      if (prev == NULL) {
310
        stream->channel = curr->next;
311
      } else {
312
        prev->next = curr->next;
313
      }
314
      curr->next = NULL;
315
      curr->flags &= ~AOS_IOCHANNEL_ATTACHED;
316
      chSysUnlock();
317
      return AOS_SUCCESS;
318
    }
319
    // iterate to the next channel
320
    else {
321
      prev = curr;
322
      curr = curr->next;
323
    }
324
  }
325

    
326
  // if the channel was not found, return an error
327
  return AOS_ERROR;
328
}
329

    
330
/**
331
 * @brief   Enable input for a AosIOChannel.
332
 *
333
 * @param[in] channel   The AosIOChannel to enable as input.
334
 */
335
void aosIOChannelInputEnable(AosIOChannel* channel)
336
{
337
  aosDbgCheck(channel != NULL);
338

    
339
  channel->flags |= AOS_IOCHANNEL_INPUT_ENABLE;
340

    
341
  return;
342
}
343

    
344
/**
345
 * @brief   Disable input for a AosIOChannel.
346
 *
347
 * @param[in] channel   The AosIOChannel to disable as input.
348
 */
349
void aosIOChannelInputDisable(AosIOChannel* channel)
350
{
351
  aosDbgCheck(channel != NULL);
352

    
353
  channel->flags &= ~AOS_IOCHANNEL_INPUT_ENABLE;
354

    
355
  return;
356
}
357

    
358
/**
359
 * @brief   Enable output for a AosIOChannel.
360
 *
361
 * @param[in] channel   The AosIOChannel to enable as output.
362
 */
363
void aosIOChannelOutputEnable(AosIOChannel* channel)
364
{
365
  aosDbgCheck(channel != NULL);
366

    
367
  channel->flags |= AOS_IOCHANNEL_OUTPUT_ENABLE;
368

    
369
  return;
370
}
371

    
372
/**
373
 * @brief   Disable output for a AosIOChannel.
374
 *
375
 * @param[in] channel   The AosIOChannel to disable as output.
376
 */
377
void aosIOChannelOutputDisable(AosIOChannel* channel)
378
{
379
  aosDbgCheck(channel != NULL);
380

    
381
  channel->flags &= ~AOS_IOCHANNEL_OUTPUT_ENABLE;
382

    
383
  return;
384
}