Statistics
| Branch: | Tag: | Revision:

amiro-os / os / core / src / aos_iostream.c @ ba516b61

History | View | Annotate | Download (7.9 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

    
26
/**
27
 * @brief   Implementation of the BaseAsynchronousChannel write() method (inherited from BaseSequentialStream).
28
 */
29
static size_t _channelwrite(void *instance, const uint8_t *bp, size_t n)
30
{
31
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_OUTPUT_ENABLE) {
32
    return streamWrite(((AosIOChannel*)instance)->asyncchannel, bp, n);
33
  } else {
34
    return 0;
35
  }
36
}
37

    
38
/**
39
 * @brief   Implementation of the BaseAsynchronousChannel read() method (inherited from BaseSequentialStream).
40
 */
41
static size_t _channelread(void *instance, uint8_t *bp, size_t n)
42
{
43
  return streamRead(((AosIOChannel*)instance)->asyncchannel, bp, n);
44
}
45

    
46
/**
47
 * @brief   Implementation of the BaseAsynchronousChannel put() method (inherited from BaseSequentialStream).
48
 */
49
static msg_t _channelput(void *instance, uint8_t b)
50
{
51
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_OUTPUT_ENABLE) {
52
    return streamPut(((AosIOChannel*)instance)->asyncchannel, b);
53
  } else {
54
    return MSG_RESET;
55
  }
56
}
57

    
58
/**
59
 * @brief   Implementation of the BaseAsynchronousChannel get() method (inherited from BaseSequentialStream).
60
 */
61
static msg_t _channelget(void *instance)
62
{
63
  return streamGet(((AosIOChannel*)instance)->asyncchannel);
64
}
65

    
66
/**
67
 * @brief   Implementation of the BaseAsynchronousChannel putt() method.
68
 */
69
static msg_t _channelputt(void *instance, uint8_t b, systime_t time)
70
{
71
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_OUTPUT_ENABLE) {
72
    return chnPutTimeout(((AosIOChannel*)instance)->asyncchannel, b, time);
73
  } else {
74
    return MSG_RESET;
75
  }
76
}
77

    
78
/**
79
 * @brief   Implementation of the BaseAsynchronousChannel gett() method.
80
 */
81
static msg_t _channelgett(void *instance, systime_t time)
82
{
83
  return chnGetTimeout(((AosIOChannel*)instance)->asyncchannel, time);
84
}
85

    
86
/**
87
 * @brief   Implementation of the BaseAsynchronousChannel writet() method.
88
 */
89
static size_t _channelwritet(void *instance, const uint8_t *bp, size_t n, systime_t time)
90
{
91
  if (((AosIOChannel*)instance)->flags & AOS_IOCHANNEL_OUTPUT_ENABLE) {
92
    return chnWriteTimeout(((AosIOChannel*)instance)->asyncchannel, bp, n, time);
93
  } else {
94
    return 0;
95
  }
96
}
97

    
98
/**
99
 * @brief   Implementation of the BaseAsynchronousChannel readt() method.
100
 */
101
static size_t _channelreadt(void *instance, uint8_t *bp, size_t n, systime_t time)
102
{
103
  return chnReadTimeout(((AosIOChannel*)instance)->asyncchannel, bp, n, time);
104
}
105

    
106
/**
107
 * @brief   Virtual methods table for all AosIOChannel objects.
108
 */
109
static const struct AosIOChannelVMT _channelvmt = {
110
  _channelwrite,
111
  _channelread,
112
  _channelput,
113
  _channelget,
114
  _channelputt,
115
  _channelgett,
116
  _channelwritet,
117
  _channelreadt,
118
};
119

    
120
/**
121
 * @brief   Implementation of the BaseSequentialStream write() method.
122
 */
123
static size_t _streamwrite(void *instance, const uint8_t *bp, size_t n)
124
{
125
  aosDbgCheck(instance != NULL);
126

    
127
  // local variables
128
  AosIOChannel* channel = ((AosIOStream*)instance)->channel;
129
  size_t bytes;
130
  size_t maxbytes = 0;
131

    
132
  // iterate through the list of channels
133
  while (channel != NULL) {
134
    bytes = streamWrite(channel, bp, n);
135
    maxbytes = (bytes > maxbytes) ? bytes : maxbytes;
136
    channel = channel->next;
137
  }
138

    
139
  return maxbytes;
140
}
141

    
142
/**
143
 * @brief   Implementation of the BaseSequentialStream read() method.
144
 */
145
static size_t _stremread(void *instance, uint8_t *bp, size_t n)
146
{
147
  (void)instance;
148
  (void)bp;
149
  (void)n;
150

    
151
  return 0;
152
}
153

    
154
/**
155
 * @brief   Implementation of the BaseSequentialStream put() method.
156
 */
157
static msg_t _streamput(void *instance, uint8_t b)
158
{
159
  aosDbgCheck(instance != NULL);
160

    
161
  // local variables
162
  AosIOChannel* channel = ((AosIOStream*)instance)->channel;
163
  msg_t ret;
164

    
165
  // iterate through the list of channels
166
  while (channel != NULL) {
167
    ret = streamPut(channel, b);
168
    if (ret != MSG_OK) {
169
      return ret;
170
    }
171
    channel = channel->next;
172
  }
173

    
174
  return MSG_OK;
175
}
176

    
177
/**
178
 * @brief   Implementation of the BaseSequentialStream get() method.
179
 */
180
static msg_t _streamget(void *instance)
181
{
182
  (void)instance;
183

    
184
  return 0;
185
}
186

    
187
/**
188
 * @brief   Virtual methods table for all AosIOStream objects.
189
 */
190
static const struct AosIOStreamVMT _streamvmt = {
191
  _streamwrite,
192
  _stremread,
193
  _streamput,
194
  _streamget,
195
};
196

    
197
/**
198
 * @brief   Initializes an aos_iostream_t object.
199
 *
200
 * @param[in] stream    Th aos_iostream_t object to initialize.
201
 */
202
void aosIOStreamInit(AosIOStream* stream)
203
{
204
  aosDbgCheck(stream != NULL);
205

    
206
  stream->vmt = &_streamvmt;
207
  stream->channel = NULL;
208

    
209
  return;
210
}
211

    
212
/**
213
 * @brief   Initializes an aos_iostream_channel_t object.
214
 *
215
 * @param[in] channel       The aos_iostream_channel_t to initialize.
216
 * @param[in] asyncchannel  The BaseAsynchronousChannel object to associate with te channel.
217
 */
218
void aosIOChannelInit(AosIOChannel *channel, BaseAsynchronousChannel *asyncchannel)
219
{
220
  aosDbgCheck(channel != NULL);
221
  aosDbgCheck(asyncchannel != NULL);
222

    
223
  channel->vmt = &_channelvmt;
224
  channel->asyncchannel = asyncchannel;
225
  channel->next = NULL;
226
  channel->flags = 0;
227

    
228
  return;
229
}
230

    
231
/**
232
 * @brief   Adds a channel to a stream.
233
 *
234
 * @param[in] stream    The stream to be expanded.
235
 * @param[in] channel   The channel to be added.
236
 */
237
void aosIOStreamAddChannel(AosIOStream *stream, AosIOChannel* channel)
238
{
239
  aosDbgCheck(stream != NULL);
240
  aosDbgCheck(channel != NULL && channel->asyncchannel != NULL && channel->next == NULL && (channel->flags & AOS_IOCHANNEL_ATTACHED) == 0);
241

    
242
  // prepend the new channel
243
  chSysLock();
244
  channel->flags |= AOS_IOCHANNEL_ATTACHED;
245
  channel->next = stream->channel;
246
  stream->channel = channel;
247
  chSysUnlock();
248

    
249
  return;
250
}
251

    
252
/**
253
 * @brief   Removes a channel from a stream.
254
 *
255
 * @param[in] stream        The stream to remove the channel from.
256
 * @param[in] asyncchannel  The BaseAsynchronousChannel to remove.
257
 * @param[out] removed      Pointer to the removed aos_iostream_channel_t.
258
 * @return
259
 */
260
aos_status_t aosIOStreamRemoveChannel(AosIOStream* stream, AosIOChannel* channel)
261
{
262
  aosDbgCheck(stream != NULL);
263
  aosDbgCheck(channel != NULL);
264

    
265
  // local variables
266
  AosIOChannel* prev = NULL;
267
  AosIOChannel* curr = stream->channel;
268

    
269
  // iterate through the list and search for the specified channel
270
  while (curr != NULL) {
271
    // if the channel was found, remove it
272
    if (curr == channel) {
273
      chSysLock();
274
      // special case: the first channel matches (prev is NULL)
275
      if (prev == NULL) {
276
        stream->channel = curr->next;
277
      } else {
278
        prev->next = curr->next;
279
      }
280
      curr->next = NULL;
281
      curr->flags &= ~AOS_IOCHANNEL_ATTACHED;
282
      chSysUnlock();
283
      return AOS_SUCCESS;
284
    }
285
    // iterate to the next channel
286
    else {
287
      prev = curr;
288
      curr = curr->next;
289
    }
290
  }
291

    
292
  // if the channel was not found, return an error
293
  return AOS_ERROR;
294
}
295

    
296
/**
297
 * @brief   Enable output for a AosIOChannel.
298
 *
299
 * @param[in] channel   The AosIOChannel to enable as output.
300
 */
301
void aosIOChannelOutputEnable(AosIOChannel* channel)
302
{
303
  aosDbgCheck(channel != NULL);
304

    
305
  channel->flags |= AOS_IOCHANNEL_OUTPUT_ENABLE;
306

    
307
  return;
308
}
309

    
310
/**
311
 * @brief   Disable output for a AosIOChannel.
312
 *
313
 * @param[in] channel   The AosIOChannel to disable as output.
314
 */
315
void aosIOChannelOutputDisable(AosIOChannel* channel)
316
{
317
  aosDbgCheck(channel != NULL);
318

    
319
  channel->flags &= ~AOS_IOCHANNEL_OUTPUT_ENABLE;
320

    
321
  return;
322
}