Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (11.663 KB)

1
/*
2
AMiRo-OS is an operating system designed for the Autonomous Mini Robot (AMiRo) platform.
3
Copyright (C) 2016..2019  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
/**
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
#include <amiroos.h>
29

    
30
/******************************************************************************/
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

    
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
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_INPUT_ENABLE) {
112
    return streamRead(((AosIOChannel*)instance)->asyncchannel, bp, n);
113
  } else {
114
    return 0;
115
  }
116
}
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
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_INPUT_ENABLE) {
136
    return streamGet(((AosIOChannel*)instance)->asyncchannel);
137
  } else {
138
    return MSG_RESET;
139
  }
140
}
141

    
142
/**
143
 * @brief   Implementation of the BaseAsynchronousChannel putt() method.
144
 */
145
static msg_t _channelputt(void *instance, uint8_t b, sysinterval_t time)
146
{
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
static msg_t _channelgett(void *instance, sysinterval_t time)
158
{
159
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_INPUT_ENABLE) {
160
    return chnGetTimeout(((AosIOChannel*)instance)->asyncchannel, time);
161
  } else {
162
    return MSG_RESET;
163
  }
164
}
165

    
166
/**
167
 * @brief   Implementation of the BaseAsynchronousChannel writet() method.
168
 */
169
static size_t _channelwritet(void *instance, const uint8_t *bp, size_t n, sysinterval_t time)
170
{
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
static size_t _channelreadt(void *instance, uint8_t *bp, size_t n, sysinterval_t time)
182
{
183
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_INPUT_ENABLE) {
184
    return chnReadTimeout(((AosIOChannel*)instance)->asyncchannel, bp, n, time);
185
  } else {
186
    return 0;
187
  }
188
}
189

    
190
/**
191
 * @brief   Implementation of the BaseAsynchronousChannel ctl() method.
192
 */
193
static msg_t _channelctl(void *instance, unsigned int operation, void *arg)
194
{
195
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_OUTPUT_ENABLE) {
196
    return chnControl(((AosIOChannel*)instance)->asyncchannel, operation, arg);
197
  } else {
198
    return MSG_OK;
199
  }
200
}
201

    
202
/**
203
 * @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
  msg_t ret = MSG_OK;
246

    
247
  // iterate through the list of channels
248
  while (channel != NULL) {
249
    msg_t ret_ = streamPut(channel, b);
250
    ret = (ret_ < ret) ? ret_ : ret;
251
    channel = channel->next;
252
  }
253

    
254
  return ret;
255
}
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
/******************************************************************************/
268
/* EXPORTED FUNCTIONS                                                         */
269
/******************************************************************************/
270

    
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
 * @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
 * @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

    
426
/** @} */