Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (9.23 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
{
125
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_OUTPUT_ENABLE) {
126
    return chnControl(((AosIOChannel*)instance)->asyncchannel, operation, arg));
127
  } else {
128
    return MSG_OK;
129
  }
130
}
131

    
132
/**
133
 * @brief   Virtual methods table for all AosIOChannel objects.
134
 */
135
static const struct AosIOChannelVMT _channelvmt = {
136
  (size_t) 0,
137
  _channelwrite,
138
  _channelread,
139
  _channelput,
140
  _channelget,
141
  _channelputt,
142
  _channelgett,
143
  _channelwritet,
144
  _channelreadt,
145
  _channelctl,
146
};
147

    
148
/**
149
 * @brief   Implementation of the BaseSequentialStream write() method.
150
 */
151
static size_t _streamwrite(void *instance, const uint8_t *bp, size_t n)
152
{
153
  aosDbgCheck(instance != NULL);
154

    
155
  // local variables
156
  AosIOChannel* channel = ((AosIOStream*)instance)->channel;
157
  size_t bytes;
158
  size_t maxbytes = 0;
159

    
160
  // iterate through the list of channels
161
  while (channel != NULL) {
162
    bytes = streamWrite(channel, bp, n);
163
    maxbytes = (bytes > maxbytes) ? bytes : maxbytes;
164
    channel = channel->next;
165
  }
166

    
167
  return maxbytes;
168
}
169

    
170
/**
171
 * @brief   Implementation of the BaseSequentialStream read() method.
172
 */
173
static size_t _stremread(void *instance, uint8_t *bp, size_t n)
174
{
175
  (void)instance;
176
  (void)bp;
177
  (void)n;
178

    
179
  return 0;
180
}
181

    
182
/**
183
 * @brief   Implementation of the BaseSequentialStream put() method.
184
 */
185
static msg_t _streamput(void *instance, uint8_t b)
186
{
187
  aosDbgCheck(instance != NULL);
188

    
189
  // local variables
190
  AosIOChannel* channel = ((AosIOStream*)instance)->channel;
191
  msg_t ret = MSG_OK;
192

    
193
  // iterate through the list of channels
194
  while (channel != NULL) {
195
    msg_t ret_ = streamPut(channel, b);
196
    ret = (ret_ < ret) ? ret_ : ret;
197
    channel = channel->next;
198
  }
199

    
200
  return ret;
201
}
202

    
203
/**
204
 * @brief   Implementation of the BaseSequentialStream get() method.
205
 */
206
static msg_t _streamget(void *instance)
207
{
208
  (void)instance;
209

    
210
  return 0;
211
}
212

    
213
/**
214
 * @brief   Virtual methods table for all AosIOStream objects.
215
 */
216
static const struct AosIOStreamVMT _streamvmt = {
217
  (size_t) 0,
218
  _streamwrite,
219
  _stremread,
220
  _streamput,
221
  _streamget,
222
};
223

    
224
/**
225
 * @brief   Initializes an aos_iostream_t object.
226
 *
227
 * @param[in] stream    Th aos_iostream_t object to initialize.
228
 */
229
void aosIOStreamInit(AosIOStream* stream)
230
{
231
  aosDbgCheck(stream != NULL);
232

    
233
  stream->vmt = &_streamvmt;
234
  stream->channel = NULL;
235

    
236
  return;
237
}
238

    
239
/**
240
 * @brief   Initializes an aos_iostream_channel_t object.
241
 *
242
 * @param[in] channel       The aos_iostream_channel_t to initialize.
243
 * @param[in] asyncchannel  The BaseAsynchronousChannel object to associate with te channel.
244
 */
245
void aosIOChannelInit(AosIOChannel *channel, BaseAsynchronousChannel *asyncchannel)
246
{
247
  aosDbgCheck(channel != NULL);
248
  aosDbgCheck(asyncchannel != NULL);
249

    
250
  channel->vmt = &_channelvmt;
251
  channel->asyncchannel = asyncchannel;
252
  channel->next = NULL;
253
  channel->flags = 0;
254

    
255
  return;
256
}
257

    
258
/**
259
 * @brief   Adds a channel to a stream.
260
 *
261
 * @param[in] stream    The stream to be expanded.
262
 * @param[in] channel   The channel to be added.
263
 */
264
void aosIOStreamAddChannel(AosIOStream *stream, AosIOChannel* channel)
265
{
266
  aosDbgCheck(stream != NULL);
267
  aosDbgCheck(channel != NULL && channel->asyncchannel != NULL && channel->next == NULL && (channel->flags & AOS_IOCHANNEL_ATTACHED) == 0);
268

    
269
  // prepend the new channel
270
  chSysLock();
271
  channel->flags |= AOS_IOCHANNEL_ATTACHED;
272
  channel->next = stream->channel;
273
  stream->channel = channel;
274
  chSysUnlock();
275

    
276
  return;
277
}
278

    
279
/**
280
 * @brief   Removes a channel from a stream.
281
 *
282
 * @param[in] stream        The stream to remove the channel from.
283
 * @param[in] asyncchannel  The BaseAsynchronousChannel to remove.
284
 * @param[out] removed      Pointer to the removed aos_iostream_channel_t.
285
 * @return
286
 */
287
aos_status_t aosIOStreamRemoveChannel(AosIOStream* stream, AosIOChannel* channel)
288
{
289
  aosDbgCheck(stream != NULL);
290
  aosDbgCheck(channel != NULL);
291

    
292
  // local variables
293
  AosIOChannel* prev = NULL;
294
  AosIOChannel* curr = stream->channel;
295

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

    
319
  // if the channel was not found, return an error
320
  return AOS_ERROR;
321
}
322

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

    
332
  channel->flags |= AOS_IOCHANNEL_INPUT_ENABLE;
333

    
334
  return;
335
}
336

    
337
/**
338
 * @brief   Disable input for a AosIOChannel.
339
 *
340
 * @param[in] channel   The AosIOChannel to disable as input.
341
 */
342
void aosIOChannelInputDisable(AosIOChannel* channel)
343
{
344
  aosDbgCheck(channel != NULL);
345

    
346
  channel->flags &= ~AOS_IOCHANNEL_INPUT_ENABLE;
347

    
348
  return;
349
}
350

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

    
360
  channel->flags |= AOS_IOCHANNEL_OUTPUT_ENABLE;
361

    
362
  return;
363
}
364

    
365
/**
366
 * @brief   Disable output for a AosIOChannel.
367
 *
368
 * @param[in] channel   The AosIOChannel to disable as output.
369
 */
370
void aosIOChannelOutputDisable(AosIOChannel* channel)
371
{
372
  aosDbgCheck(channel != NULL);
373

    
374
  channel->flags &= ~AOS_IOCHANNEL_OUTPUT_ENABLE;
375

    
376
  return;
377
}