OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [Common/] [ethernet/] [FreeRTOS-uIP/] [psock.c] - Blame information for rev 606

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 606 jeremybenn
/*
2
 * Copyright (c) 2004, Swedish Institute of Computer Science.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 * 3. Neither the name of the Institute nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 *
29
 * This file is part of the uIP TCP/IP stack
30
 *
31
 * Author: Adam Dunkels <adam@sics.se>
32
 *
33
 * $Id: psock.c 2 2011-07-17 20:13:17Z filepang@gmail.com $
34
 */
35
#include <stdio.h>
36
#include <string.h>
37
 
38
#include "uipopt.h"
39
#include "psock.h"
40
#include "uip.h"
41
 
42
#define STATE_NONE                              0
43
#define STATE_ACKED                             1
44
#define STATE_READ                              2
45
#define STATE_BLOCKED_NEWDATA   3
46
#define STATE_BLOCKED_CLOSE             4
47
#define STATE_BLOCKED_SEND              5
48
#define STATE_DATA_SENT                 6
49
 
50
/*
51
 * Return value of the buffering functions that indicates that a
52
 * buffer was not filled by incoming data.
53
 *
54
 */
55
#define BUF_NOT_FULL    0
56
#define BUF_NOT_FOUND   0
57
 
58
/*
59
 * Return value of the buffering functions that indicates that a
60
 * buffer was completely filled by incoming data.
61
 *
62
 */
63
#define BUF_FULL        1
64
 
65
/*
66
 * Return value of the buffering functions that indicates that an
67
 * end-marker byte was found.
68
 *
69
 */
70
#define BUF_FOUND       2
71
 
72
/*---------------------------------------------------------------------------*/
73
static void buf_setup( struct psock_buf *buf, u8_t *bufptr, u16_t bufsize )
74
{
75
        buf->ptr = bufptr;
76
        buf->left = bufsize;
77
}
78
 
79
/*---------------------------------------------------------------------------*/
80
static u8_t buf_bufdata( struct psock_buf *buf, u16_t len, u8_t **dataptr, u16_t *datalen )
81
{
82
        ( void ) len;
83
 
84
        if( *datalen < buf->left )
85
        {
86
                memcpy( buf->ptr, *dataptr, *datalen );
87
                buf->ptr += *datalen;
88
                buf->left -= *datalen;
89
                *dataptr += *datalen;
90
                *datalen = 0;
91
                return BUF_NOT_FULL;
92
        }
93
        else if( *datalen == buf->left )
94
        {
95
                memcpy( buf->ptr, *dataptr, *datalen );
96
                buf->ptr += *datalen;
97
                buf->left = 0;
98
                *dataptr += *datalen;
99
                *datalen = 0;
100
                return BUF_FULL;
101
        }
102
        else
103
        {
104
                memcpy( buf->ptr, *dataptr, buf->left );
105
                buf->ptr += buf->left;
106
                *datalen -= buf->left;
107
                *dataptr += buf->left;
108
                buf->left = 0;
109
                return BUF_FULL;
110
        }
111
}
112
 
113
/*---------------------------------------------------------------------------*/
114
static u8_t buf_bufto( register struct psock_buf *buf, u8_t endmarker, register u8_t **dataptr, register u16_t *datalen )
115
{
116
        u8_t    c;
117
        while( buf->left > 0 && *datalen > 0 )
118
        {
119
                c = *buf->ptr = **dataptr;
120
                ++ *dataptr;
121
                ++buf->ptr;
122
                -- *datalen;
123
                --buf->left;
124
 
125
                if( c == endmarker )
126
                {
127
                        return BUF_FOUND;
128
                }
129
        }
130
 
131
        if( *datalen == 0 )
132
        {
133
                return BUF_NOT_FOUND;
134
        }
135
 
136
        while( *datalen > 0 )
137
        {
138
                c = **dataptr;
139
                -- *datalen;
140
                ++ *dataptr;
141
 
142
                if( c == endmarker )
143
                {
144
                        return BUF_FOUND | BUF_FULL;
145
                }
146
        }
147
 
148
        return BUF_FULL;
149
}
150
 
151
/*---------------------------------------------------------------------------*/
152
static char send_data( register struct psock *s )
153
{
154
        if( s->state != STATE_DATA_SENT || uip_rexmit() )
155
        {
156
                if( s->sendlen > uip_mss() )
157
                {
158
                        uip_send( s->sendptr, uip_mss() );
159
                }
160
                else
161
                {
162
                        uip_send( s->sendptr, s->sendlen );
163
                }
164
 
165
                s->state = STATE_DATA_SENT;
166
                return 1;
167
        }
168
 
169
        return 0;
170
}
171
 
172
/*---------------------------------------------------------------------------*/
173
static char data_acked( register struct psock *s )
174
{
175
        if( s->state == STATE_DATA_SENT && uip_acked() )
176
        {
177
                if( s->sendlen > uip_mss() )
178
                {
179
                        s->sendlen -= uip_mss();
180
                        s->sendptr += uip_mss();
181
                }
182
                else
183
                {
184
                        s->sendptr += s->sendlen;
185
                        s->sendlen = 0;
186
                }
187
 
188
                s->state = STATE_ACKED;
189
                return 1;
190
        }
191
 
192
        return 0;
193
}
194
 
195
/*---------------------------------------------------------------------------*/
196
PT_THREAD( psock_send ( register struct psock *s, const char *buf, unsigned int len ) )
197
{
198
        PT_BEGIN( &s->psockpt );
199
 
200
        /* If there is no data to send, we exit immediately. */
201
        if( len == 0 )
202
        {
203
                PT_EXIT( &s->psockpt );
204
        }
205
 
206
        /* Save the length of and a pointer to the data that is to be
207
     sent. */
208
        s->sendptr = ( u8_t * ) buf;
209
        s->sendlen = len;
210
 
211
        s->state = STATE_NONE;
212
 
213
        /* We loop here until all data is sent. The s->sendlen variable is
214
     updated by the data_sent() function. */
215
        while( s->sendlen > 0 )
216
        {
217
                /*
218
     * The condition for this PT_WAIT_UNTIL is a little tricky: the
219
     * protothread will wait here until all data has been acknowledged
220
     * (data_acked() returns true) and until all data has been sent
221
     * (send_data() returns true). The two functions data_acked() and
222
     * send_data() must be called in succession to ensure that all
223
     * data is sent. Therefore the & operator is used instead of the
224
     * && operator, which would cause only the data_acked() function
225
     * to be called when it returns false.
226
     */
227
                PT_WAIT_UNTIL( &s->psockpt, data_acked(s) & send_data(s) );
228
        }
229
 
230
        s->state = STATE_NONE;
231
 
232
        PT_END( &s->psockpt );
233
}
234
 
235
/*---------------------------------------------------------------------------*/
236
PT_THREAD( psock_generator_send ( register struct psock *s, unsigned short ( *generate ) ( void * ), void *arg ) )
237
{
238
        PT_BEGIN( &s->psockpt );
239
 
240
        /* Ensure that there is a generator function to call. */
241
        if( generate == NULL )
242
        {
243
                PT_EXIT( &s->psockpt );
244
        }
245
 
246
        /* Call the generator function to generate the data in the
247
     uip_appdata buffer. */
248
        s->sendlen = generate( arg );
249
        s->sendptr = uip_appdata;
250
 
251
        s->state = STATE_NONE;
252
        do
253
        {
254
                /* Call the generator function again if we are called to perform a
255
       retransmission. */
256
                if( uip_rexmit() )
257
                {
258
                        generate( arg );
259
                }
260
 
261
                /* Wait until all data is sent and acknowledged. */
262
                PT_WAIT_UNTIL( &s->psockpt, data_acked(s) & send_data(s) );
263
        } while( s->sendlen > 0 );
264
 
265
        s->state = STATE_NONE;
266
 
267
        PT_END( &s->psockpt );
268
}
269
 
270
/*---------------------------------------------------------------------------*/
271
u16_t psock_datalen( struct psock *psock )
272
{
273
        return psock->bufsize - psock->buf.left;
274
}
275
 
276
/*---------------------------------------------------------------------------*/
277
char psock_newdata( struct psock *s )
278
{
279
        if( s->readlen > 0 )
280
        {
281
                /* There is data in the uip_appdata buffer that has not yet been
282
       read with the PSOCK_READ functions. */
283
                return 1;
284
        }
285
        else if( s->state == STATE_READ )
286
        {
287
                /* All data in uip_appdata buffer already consumed. */
288
                s->state = STATE_BLOCKED_NEWDATA;
289
                return 0;
290
        }
291
        else if( uip_newdata() )
292
        {
293
                /* There is new data that has not been consumed. */
294
                return 1;
295
        }
296
        else
297
        {
298
                /* There is no new data. */
299
                return 0;
300
        }
301
}
302
 
303
/*---------------------------------------------------------------------------*/
304
PT_THREAD( psock_readto ( register struct psock *psock, unsigned char c ) )
305
{
306
        PT_BEGIN( &psock->psockpt );
307
 
308
        buf_setup( &psock->buf, ( u8_t * ) psock->bufptr, psock->bufsize );
309
 
310
        /* XXX: Should add buf_checkmarker() before do{} loop, if
311
     incoming data has been handled while waiting for a write. */
312
        do
313
        {
314
                if( psock->readlen == 0 )
315
                {
316
                        PT_WAIT_UNTIL( &psock->psockpt, psock_newdata(psock) );
317
                        psock->state = STATE_READ;
318
                        psock->readptr = ( u8_t * ) uip_appdata;
319
                        psock->readlen = uip_datalen();
320
                }
321
        } while( (buf_bufto(&psock->buf, c, &psock->readptr, &psock->readlen) & BUF_FOUND) == 0 );
322
 
323
        if( psock_datalen(psock) == 0 )
324
        {
325
                psock->state = STATE_NONE;
326
                PT_RESTART( &psock->psockpt );
327
        }
328
 
329
        PT_END( &psock->psockpt );
330
}
331
 
332
/*---------------------------------------------------------------------------*/
333
PT_THREAD( psock_readbuf ( register struct psock *psock ) )
334
{
335
        PT_BEGIN( &psock->psockpt );
336
 
337
        buf_setup( &psock->buf, ( u8_t * ) psock->bufptr, psock->bufsize );
338
 
339
        /* XXX: Should add buf_checkmarker() before do{} loop, if
340
     incoming data has been handled while waiting for a write. */
341
        do
342
        {
343
                if( psock->readlen == 0 )
344
                {
345
                        PT_WAIT_UNTIL( &psock->psockpt, psock_newdata(psock) );
346
                        printf( "Waited for newdata\n" );
347
                        psock->state = STATE_READ;
348
                        psock->readptr = ( u8_t * ) uip_appdata;
349
                        psock->readlen = uip_datalen();
350
                }
351
        } while( buf_bufdata(&psock->buf, psock->bufsize, &psock->readptr, &psock->readlen) != BUF_FULL );
352
 
353
        if( psock_datalen(psock) == 0 )
354
        {
355
                psock->state = STATE_NONE;
356
                PT_RESTART( &psock->psockpt );
357
        }
358
 
359
        PT_END( &psock->psockpt );
360
}
361
 
362
/*---------------------------------------------------------------------------*/
363
void psock_init( register struct psock *psock, char *buffer, unsigned int buffersize )
364
{
365
        psock->state = STATE_NONE;
366
        psock->readlen = 0;
367
        psock->bufptr = buffer;
368
        psock->bufsize = buffersize;
369
        buf_setup( &psock->buf, ( u8_t * ) buffer, buffersize );
370
        PT_INIT( &psock->pt );
371
        PT_INIT( &psock->psockpt );
372
}
373
 
374
/*---------------------------------------------------------------------------*/

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.