Statistics
| Branch: | Tag: | Revision:

amiro-os / core / src / aos_iostream.c @ 1c1b3372

History | View | Annotate | Download (9.408 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 <aos_iostream.h>
29

    
30
#include <aos_debug.h>
31
#include <chprintf.h>
32

    
33
/**
34
 * @brief   Implementation of the BaseAsynchronousChannel write() method (inherited from BaseSequentialStream).
35
 */
36
static size_t _channelwrite(void *instance, const uint8_t *bp, size_t n)
37
{
38
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_OUTPUT_ENABLE) {
39
    return streamWrite(((AosIOChannel*)instance)->asyncchannel, bp, n);
40
  } else {
41
    return 0;
42
  }
43
}
44

    
45
/**
46
 * @brief   Implementation of the BaseAsynchronousChannel read() method (inherited from BaseSequentialStream).
47
 */
48
static size_t _channelread(void *instance, uint8_t *bp, size_t n)
49
{
50
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_INPUT_ENABLE) {
51
    return streamRead(((AosIOChannel*)instance)->asyncchannel, bp, n);
52
  } else {
53
    return 0;
54
  }
55
}
56

    
57
/**
58
 * @brief   Implementation of the BaseAsynchronousChannel put() method (inherited from BaseSequentialStream).
59
 */
60
static msg_t _channelput(void *instance, uint8_t b)
61
{
62
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_OUTPUT_ENABLE) {
63
    return streamPut(((AosIOChannel*)instance)->asyncchannel, b);
64
  } else {
65
    return MSG_RESET;
66
  }
67
}
68

    
69
/**
70
 * @brief   Implementation of the BaseAsynchronousChannel get() method (inherited from BaseSequentialStream).
71
 */
72
static msg_t _channelget(void *instance)
73
{
74
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_INPUT_ENABLE) {
75
    return streamGet(((AosIOChannel*)instance)->asyncchannel);
76
  } else {
77
    return MSG_RESET;
78
  }
79
}
80

    
81
/**
82
 * @brief   Implementation of the BaseAsynchronousChannel putt() method.
83
 */
84
static msg_t _channelputt(void *instance, uint8_t b, sysinterval_t time)
85
{
86
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_OUTPUT_ENABLE) {
87
    return chnPutTimeout(((AosIOChannel*)instance)->asyncchannel, b, time);
88
  } else {
89
    return MSG_RESET;
90
  }
91
}
92

    
93
/**
94
 * @brief   Implementation of the BaseAsynchronousChannel gett() method.
95
 */
96
static msg_t _channelgett(void *instance, sysinterval_t time)
97
{
98
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_INPUT_ENABLE) {
99
    return chnGetTimeout(((AosIOChannel*)instance)->asyncchannel, time);
100
  } else {
101
    return MSG_RESET;
102
  }
103
}
104

    
105
/**
106
 * @brief   Implementation of the BaseAsynchronousChannel writet() method.
107
 */
108
static size_t _channelwritet(void *instance, const uint8_t *bp, size_t n, sysinterval_t time)
109
{
110
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_OUTPUT_ENABLE) {
111
    return chnWriteTimeout(((AosIOChannel*)instance)->asyncchannel, bp, n, time);
112
  } else {
113
    return 0;
114
  }
115
}
116

    
117
/**
118
 * @brief   Implementation of the BaseAsynchronousChannel readt() method.
119
 */
120
static size_t _channelreadt(void *instance, uint8_t *bp, size_t n, sysinterval_t time)
121
{
122
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_INPUT_ENABLE) {
123
    return chnReadTimeout(((AosIOChannel*)instance)->asyncchannel, bp, n, time);
124
  } else {
125
    return 0;
126
  }
127
}
128

    
129
/**
130
 * @brief   Implementation of the BaseAsynchronousChannel ctl() method.
131
 */
132
static msg_t _channelctl(void *instance, unsigned int operation, void *arg)
133
{
134
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_OUTPUT_ENABLE) {
135
    return chnControl(((AosIOChannel*)instance)->asyncchannel, operation, arg);
136
  } else {
137
    return MSG_OK;
138
  }
139
}
140

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

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

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

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

    
176
  return maxbytes;
177
}
178

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

    
188
  return 0;
189
}
190

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

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

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

    
209
  return ret;
210
}
211

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

    
219
  return 0;
220
}
221

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

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

    
242
  stream->vmt = &_streamvmt;
243
  stream->channel = NULL;
244

    
245
  return;
246
}
247

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

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

    
264
  return;
265
}
266

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

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

    
285
  return;
286
}
287

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

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

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

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

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

    
341
  channel->flags |= AOS_IOCHANNEL_INPUT_ENABLE;
342

    
343
  return;
344
}
345

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

    
355
  channel->flags &= ~AOS_IOCHANNEL_INPUT_ENABLE;
356

    
357
  return;
358
}
359

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

    
369
  channel->flags |= AOS_IOCHANNEL_OUTPUT_ENABLE;
370

    
371
  return;
372
}
373

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

    
383
  channel->flags &= ~AOS_IOCHANNEL_OUTPUT_ENABLE;
384

    
385
  return;
386
}
387

    
388
/** @} */