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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [Common/] [ethernet/] [lwIP/] [api/] [api_lib.c] - Blame information for rev 606

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 606 jeremybenn
/*
2
 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without modification,
6
 * are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. The name of the author may not be used to endorse or promote products
14
 *    derived from this software without specific prior written permission.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
25
 * OF SUCH DAMAGE.
26
 *
27
 * This file is part of the lwIP TCP/IP stack.
28
 *
29
 * Author: Adam Dunkels <adam@sics.se>
30
 *
31
 */
32
 
33
/* This is the part of the API that is linked with
34
   the application */
35
 
36
#include "lwip/opt.h"
37
#include "lwip/api.h"
38
#include "lwip/api_msg.h"
39
#include "lwip/memp.h"
40
 
41
 
42
struct
43
netbuf *netbuf_new(void)
44
{
45
  struct netbuf *buf;
46
 
47
  buf = memp_malloc(MEMP_NETBUF);
48
  if (buf != NULL) {
49
    buf->p = NULL;
50
    buf->ptr = NULL;
51
    return buf;
52
  } else {
53
    return NULL;
54
  }
55
}
56
 
57
void
58
netbuf_delete(struct netbuf *buf)
59
{
60
  if (buf != NULL) {
61
    if (buf->p != NULL) {
62
      pbuf_free(buf->p);
63
      buf->p = buf->ptr = NULL;
64
    }
65
    memp_free(MEMP_NETBUF, buf);
66
  }
67
}
68
 
69
void *
70
netbuf_alloc(struct netbuf *buf, u16_t size)
71
{
72
  /* Deallocate any previously allocated memory. */
73
  if (buf->p != NULL) {
74
    pbuf_free(buf->p);
75
  }
76
  buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM);
77
  if (buf->p == NULL) {
78
     return NULL;
79
  }
80
  buf->ptr = buf->p;
81
  return buf->p->payload;
82
}
83
 
84
void
85
netbuf_free(struct netbuf *buf)
86
{
87
  if (buf->p != NULL) {
88
    pbuf_free(buf->p);
89
  }
90
  buf->p = buf->ptr = NULL;
91
}
92
 
93
void
94
netbuf_ref(struct netbuf *buf, void *dataptr, u16_t size)
95
{
96
  if (buf->p != NULL) {
97
    pbuf_free(buf->p);
98
  }
99
  buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
100
  buf->p->payload = dataptr;
101
  buf->p->len = buf->p->tot_len = size;
102
  buf->ptr = buf->p;
103
}
104
 
105
void
106
netbuf_chain(struct netbuf *head, struct netbuf *tail)
107
{
108
  pbuf_chain(head->p, tail->p);
109
  head->ptr = head->p;
110
  memp_free(MEMP_NETBUF, tail);
111
}
112
 
113
u16_t
114
netbuf_len(struct netbuf *buf)
115
{
116
  return buf->p->tot_len;
117
}
118
 
119
err_t
120
netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)
121
{
122
  if (buf->ptr == NULL) {
123
    return ERR_BUF;
124
  }
125
  *dataptr = buf->ptr->payload;
126
  *len = buf->ptr->len;
127
  return ERR_OK;
128
}
129
 
130
s8_t
131
netbuf_next(struct netbuf *buf)
132
{
133
  if (buf->ptr->next == NULL) {
134
    return -1;
135
  }
136
  buf->ptr = buf->ptr->next;
137
  if (buf->ptr->next == NULL) {
138
    return 1;
139
  }
140
  return 0;
141
}
142
 
143
void
144
netbuf_first(struct netbuf *buf)
145
{
146
  buf->ptr = buf->p;
147
}
148
 
149
void
150
netbuf_copy_partial(struct netbuf *buf, void *dataptr, u16_t len, u16_t offset)
151
{
152
  struct pbuf *p;
153
  u16_t i, left;
154
 
155
  left = 0;
156
 
157
  if(buf == NULL || dataptr == NULL) {
158
    return;
159
  }
160
 
161
  /* This implementation is bad. It should use bcopy
162
     instead. */
163
  for(p = buf->p; left < len && p != NULL; p = p->next) {
164
    if (offset != 0 && offset >= p->len) {
165
      offset -= p->len;
166
    } else {
167
      for(i = offset; i < p->len; ++i) {
168
  ((u8_t *)dataptr)[left] = ((u8_t *)p->payload)[i];
169
  if (++left >= len) {
170
    return;
171
  }
172
      }
173
      offset = 0;
174
    }
175
  }
176
}
177
 
178
void
179
netbuf_copy(struct netbuf *buf, void *dataptr, u16_t len)
180
{
181
  netbuf_copy_partial(buf, dataptr, len, 0);
182
}
183
 
184
struct ip_addr *
185
netbuf_fromaddr(struct netbuf *buf)
186
{
187
  return buf->fromaddr;
188
}
189
 
190
u16_t
191
netbuf_fromport(struct netbuf *buf)
192
{
193
  return buf->fromport;
194
}
195
 
196
struct
197
netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto,
198
                                   void (*callback)(struct netconn *, enum netconn_evt, u16_t len))
199
{
200
  struct netconn *conn;
201
  struct api_msg *msg;
202
 
203
  conn = memp_malloc(MEMP_NETCONN);
204
  if (conn == NULL) {
205
    return NULL;
206
  }
207
 
208
  conn->err = ERR_OK;
209
  conn->type = t;
210
  conn->pcb.tcp = NULL;
211
 
212
  if ((conn->mbox = sys_mbox_new()) == SYS_MBOX_NULL) {
213
    memp_free(MEMP_NETCONN, conn);
214
    return NULL;
215
  }
216
  conn->recvmbox = SYS_MBOX_NULL;
217
  conn->acceptmbox = SYS_MBOX_NULL;
218
  conn->sem = sys_sem_new(0);
219
  if (conn->sem == SYS_SEM_NULL) {
220
    memp_free(MEMP_NETCONN, conn);
221
    return NULL;
222
  }
223
  conn->state = NETCONN_NONE;
224
  conn->socket = 0;
225
  conn->callback = callback;
226
  conn->recv_avail = 0;
227
 
228
  if((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
229
    memp_free(MEMP_NETCONN, conn);
230
    return NULL;
231
  }
232
 
233
  msg->type = API_MSG_NEWCONN;
234
  msg->msg.msg.bc.port = proto; /* misusing the port field */
235
  msg->msg.conn = conn;
236
  api_msg_post(msg);
237
  sys_mbox_fetch(conn->mbox, NULL);
238
  memp_free(MEMP_API_MSG, msg);
239
 
240
  if ( conn->err != ERR_OK ) {
241
    memp_free(MEMP_NETCONN, conn);
242
    return NULL;
243
  }
244
 
245
  return conn;
246
}
247
 
248
 
249
struct
250
netconn *netconn_new(enum netconn_type t)
251
{
252
  return netconn_new_with_proto_and_callback(t,0,NULL);
253
}
254
 
255
struct
256
netconn *netconn_new_with_callback(enum netconn_type t,
257
                                   void (*callback)(struct netconn *, enum netconn_evt, u16_t len))
258
{
259
  return netconn_new_with_proto_and_callback(t,0,callback);
260
}
261
 
262
 
263
err_t
264
netconn_delete(struct netconn *conn)
265
{
266
  struct api_msg *msg;
267
  void *mem;
268
 
269
  if (conn == NULL) {
270
    return ERR_OK;
271
  }
272
 
273
  if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
274
    return ERR_MEM;
275
  }
276
 
277
  msg->type = API_MSG_DELCONN;
278
  msg->msg.conn = conn;
279
  api_msg_post(msg);
280
  sys_mbox_fetch(conn->mbox, NULL);
281
  memp_free(MEMP_API_MSG, msg);
282
 
283
  /* Drain the recvmbox. */
284
  if (conn->recvmbox != SYS_MBOX_NULL) {
285
    while (sys_arch_mbox_fetch(conn->recvmbox, &mem, 1) != SYS_ARCH_TIMEOUT) {
286
      if (conn->type == NETCONN_TCP) {
287
        if(mem != NULL)
288
          pbuf_free((struct pbuf *)mem);
289
      } else {
290
        netbuf_delete((struct netbuf *)mem);
291
      }
292
    }
293
    sys_mbox_free(conn->recvmbox);
294
    conn->recvmbox = SYS_MBOX_NULL;
295
  }
296
 
297
 
298
  /* Drain the acceptmbox. */
299
  if (conn->acceptmbox != SYS_MBOX_NULL) {
300
    while (sys_arch_mbox_fetch(conn->acceptmbox, &mem, 1) != SYS_ARCH_TIMEOUT) {
301
      netconn_delete((struct netconn *)mem);
302
    }
303
 
304
    sys_mbox_free(conn->acceptmbox);
305
    conn->acceptmbox = SYS_MBOX_NULL;
306
  }
307
 
308
  sys_mbox_free(conn->mbox);
309
  conn->mbox = SYS_MBOX_NULL;
310
  if (conn->sem != SYS_SEM_NULL) {
311
    sys_sem_free(conn->sem);
312
  }
313
  /*  conn->sem = SYS_SEM_NULL;*/
314
  memp_free(MEMP_NETCONN, conn);
315
  return ERR_OK;
316
}
317
 
318
enum netconn_type
319
netconn_type(struct netconn *conn)
320
{
321
  return conn->type;
322
}
323
 
324
err_t
325
netconn_peer(struct netconn *conn, struct ip_addr *addr,
326
       u16_t *port)
327
{
328
  switch (conn->type) {
329
  case NETCONN_RAW:
330
    /* return an error as connecting is only a helper for upper layers */
331
    return ERR_CONN;
332
  case NETCONN_UDPLITE:
333
  case NETCONN_UDPNOCHKSUM:
334
  case NETCONN_UDP:
335
    if (conn->pcb.udp == NULL ||
336
  ((conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0))
337
     return ERR_CONN;
338
    *addr = (conn->pcb.udp->remote_ip);
339
    *port = conn->pcb.udp->remote_port;
340
    break;
341
  case NETCONN_TCP:
342
    if (conn->pcb.tcp == NULL)
343
      return ERR_CONN;
344
    *addr = (conn->pcb.tcp->remote_ip);
345
    *port = conn->pcb.tcp->remote_port;
346
    break;
347
  }
348
  return (conn->err = ERR_OK);
349
}
350
 
351
err_t
352
netconn_addr(struct netconn *conn, struct ip_addr **addr,
353
       u16_t *port)
354
{
355
  switch (conn->type) {
356
  case NETCONN_RAW:
357
    *addr = &(conn->pcb.raw->local_ip);
358
    *port = conn->pcb.raw->protocol;
359
    break;
360
  case NETCONN_UDPLITE:
361
  case NETCONN_UDPNOCHKSUM:
362
  case NETCONN_UDP:
363
    *addr = &(conn->pcb.udp->local_ip);
364
    *port = conn->pcb.udp->local_port;
365
    break;
366
  case NETCONN_TCP:
367
    *addr = &(conn->pcb.tcp->local_ip);
368
    *port = conn->pcb.tcp->local_port;
369
    break;
370
  }
371
  return (conn->err = ERR_OK);
372
}
373
 
374
err_t
375
netconn_bind(struct netconn *conn, struct ip_addr *addr,
376
      u16_t port)
377
{
378
  struct api_msg *msg;
379
 
380
  if (conn == NULL) {
381
    return ERR_VAL;
382
  }
383
 
384
  if (conn->type != NETCONN_TCP &&
385
     conn->recvmbox == SYS_MBOX_NULL) {
386
    if ((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) {
387
      return ERR_MEM;
388
    }
389
  }
390
 
391
  if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
392
    return (conn->err = ERR_MEM);
393
  }
394
  msg->type = API_MSG_BIND;
395
  msg->msg.conn = conn;
396
  msg->msg.msg.bc.ipaddr = addr;
397
  msg->msg.msg.bc.port = port;
398
  api_msg_post(msg);
399
  sys_mbox_fetch(conn->mbox, NULL);
400
  memp_free(MEMP_API_MSG, msg);
401
  return conn->err;
402
}
403
 
404
 
405
err_t
406
netconn_connect(struct netconn *conn, struct ip_addr *addr,
407
       u16_t port)
408
{
409
  struct api_msg *msg;
410
 
411
  if (conn == NULL) {
412
    return ERR_VAL;
413
  }
414
 
415
 
416
  if (conn->recvmbox == SYS_MBOX_NULL) {
417
    if ((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) {
418
      return ERR_MEM;
419
    }
420
  }
421
 
422
  if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
423
    return ERR_MEM;
424
  }
425
  msg->type = API_MSG_CONNECT;
426
  msg->msg.conn = conn;
427
  msg->msg.msg.bc.ipaddr = addr;
428
  msg->msg.msg.bc.port = port;
429
  api_msg_post(msg);
430
  sys_mbox_fetch(conn->mbox, NULL);
431
  memp_free(MEMP_API_MSG, msg);
432
  return conn->err;
433
}
434
 
435
err_t
436
netconn_disconnect(struct netconn *conn)
437
{
438
  struct api_msg *msg;
439
 
440
  if (conn == NULL) {
441
    return ERR_VAL;
442
  }
443
 
444
  if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
445
    return ERR_MEM;
446
  }
447
  msg->type = API_MSG_DISCONNECT;
448
  msg->msg.conn = conn;
449
  api_msg_post(msg);
450
  sys_mbox_fetch(conn->mbox, NULL);
451
  memp_free(MEMP_API_MSG, msg);
452
  return conn->err;
453
 
454
}
455
 
456
err_t
457
netconn_listen(struct netconn *conn)
458
{
459
  struct api_msg *msg;
460
 
461
  if (conn == NULL) {
462
    return ERR_VAL;
463
  }
464
 
465
  if (conn->acceptmbox == SYS_MBOX_NULL) {
466
    conn->acceptmbox = sys_mbox_new();
467
    if (conn->acceptmbox == SYS_MBOX_NULL) {
468
      return ERR_MEM;
469
    }
470
  }
471
 
472
  if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
473
    return (conn->err = ERR_MEM);
474
  }
475
  msg->type = API_MSG_LISTEN;
476
  msg->msg.conn = conn;
477
  api_msg_post(msg);
478
  sys_mbox_fetch(conn->mbox, NULL);
479
  memp_free(MEMP_API_MSG, msg);
480
  return conn->err;
481
}
482
 
483
struct netconn *
484
netconn_accept(struct netconn *conn)
485
{
486
  struct netconn *newconn;
487
 
488
  if (conn == NULL) {
489
    return NULL;
490
  }
491
 
492
  sys_mbox_fetch(conn->acceptmbox, (void *)&newconn);
493
  /* Register event with callback */
494
  if (conn->callback)
495
      (*conn->callback)(conn, NETCONN_EVT_RCVMINUS, 0);
496
 
497
  return newconn;
498
}
499
 
500
struct netbuf *
501
netconn_recv(struct netconn *conn)
502
{
503
  struct api_msg *msg;
504
  struct netbuf *buf;
505
  struct pbuf *p;
506
  u16_t len;
507
 
508
  if (conn == NULL) {
509
    return NULL;
510
  }
511
 
512
  if (conn->recvmbox == SYS_MBOX_NULL) {
513
    conn->err = ERR_CONN;
514
    return NULL;
515
  }
516
 
517
  if (conn->err != ERR_OK) {
518
    return NULL;
519
  }
520
 
521
  if (conn->type == NETCONN_TCP) {
522
    if (conn->pcb.tcp->state == LISTEN) {
523
      conn->err = ERR_CONN;
524
      return NULL;
525
    }
526
 
527
 
528
    buf = memp_malloc(MEMP_NETBUF);
529
 
530
    if (buf == NULL) {
531
      conn->err = ERR_MEM;
532
      return NULL;
533
    }
534
 
535
    sys_mbox_fetch(conn->recvmbox, (void *)&p);
536
 
537
    if (p != NULL)
538
    {
539
        len = p->tot_len;
540
        conn->recv_avail -= len;
541
    }
542
    else
543
        len = 0;
544
 
545
    /* Register event with callback */
546
      if (conn->callback)
547
        (*conn->callback)(conn, NETCONN_EVT_RCVMINUS, len);
548
 
549
    /* If we are closed, we indicate that we no longer wish to receive
550
       data by setting conn->recvmbox to SYS_MBOX_NULL. */
551
    if (p == NULL) {
552
      memp_free(MEMP_NETBUF, buf);
553
      sys_mbox_free(conn->recvmbox);
554
      conn->recvmbox = SYS_MBOX_NULL;
555
      return NULL;
556
    }
557
 
558
    buf->p = p;
559
    buf->ptr = p;
560
    buf->fromport = 0;
561
    buf->fromaddr = NULL;
562
 
563
    /* Let the stack know that we have taken the data. */
564
    if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
565
      conn->err = ERR_MEM;
566
      return buf;
567
    }
568
    msg->type = API_MSG_RECV;
569
    msg->msg.conn = conn;
570
    if (buf != NULL) {
571
      msg->msg.msg.len = buf->p->tot_len;
572
    } else {
573
      msg->msg.msg.len = 1;
574
    }
575
    api_msg_post(msg);
576
 
577
    sys_mbox_fetch(conn->mbox, NULL);
578
    memp_free(MEMP_API_MSG, msg);
579
  } else {
580
    sys_mbox_fetch(conn->recvmbox, (void *)&buf);
581
  conn->recv_avail -= buf->p->tot_len;
582
    /* Register event with callback */
583
    if (conn->callback)
584
        (*conn->callback)(conn, NETCONN_EVT_RCVMINUS, buf->p->tot_len);
585
  }
586
 
587
 
588
 
589
 
590
  LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv: received %p (err %d)\n", (void *)buf, conn->err));
591
 
592
 
593
  return buf;
594
}
595
 
596
err_t
597
netconn_send(struct netconn *conn, struct netbuf *buf)
598
{
599
  struct api_msg *msg;
600
 
601
  if (conn == NULL) {
602
    return ERR_VAL;
603
  }
604
 
605
  if (conn->err != ERR_OK) {
606
    return conn->err;
607
  }
608
 
609
  if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
610
    return (conn->err = ERR_MEM);
611
  }
612
 
613
  LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %d bytes\n", buf->p->tot_len));
614
  msg->type = API_MSG_SEND;
615
  msg->msg.conn = conn;
616
  msg->msg.msg.p = buf->p;
617
  api_msg_post(msg);
618
 
619
  sys_mbox_fetch(conn->mbox, NULL);
620
  memp_free(MEMP_API_MSG, msg);
621
  return conn->err;
622
}
623
 
624
err_t
625
netconn_write(struct netconn *conn, void *dataptr, u16_t size, u8_t copy)
626
{
627
  struct api_msg *msg;
628
  u16_t len;
629
 
630
  if (conn == NULL) {
631
    return ERR_VAL;
632
  }
633
 
634
  if (conn->err != ERR_OK) {
635
    return conn->err;
636
  }
637
 
638
  if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
639
    return (conn->err = ERR_MEM);
640
  }
641
  msg->type = API_MSG_WRITE;
642
  msg->msg.conn = conn;
643
 
644
 
645
  conn->state = NETCONN_WRITE;
646
  while (conn->err == ERR_OK && size > 0) {
647
    msg->msg.msg.w.dataptr = dataptr;
648
    msg->msg.msg.w.copy = copy;
649
 
650
    if (conn->type == NETCONN_TCP) {
651
      if (tcp_sndbuf(conn->pcb.tcp) == 0) {
652
  sys_sem_wait(conn->sem);
653
  if (conn->err != ERR_OK) {
654
    goto ret;
655
  }
656
      }
657
      if (size > tcp_sndbuf(conn->pcb.tcp)) {
658
  /* We cannot send more than one send buffer's worth of data at a
659
     time. */
660
  len = tcp_sndbuf(conn->pcb.tcp);
661
      } else {
662
  len = size;
663
      }
664
    } else {
665
      len = size;
666
    }
667
 
668
    LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_write: writing %d bytes (%d)\n", len, copy));
669
    msg->msg.msg.w.len = len;
670
    api_msg_post(msg);
671
    sys_mbox_fetch(conn->mbox, NULL);
672
    if (conn->err == ERR_OK) {
673
      dataptr = (void *)((u8_t *)dataptr + len);
674
      size -= len;
675
    } else if (conn->err == ERR_MEM) {
676
      conn->err = ERR_OK;
677
      sys_sem_wait(conn->sem);
678
    } else {
679
      goto ret;
680
    }
681
  }
682
 ret:
683
  memp_free(MEMP_API_MSG, msg);
684
  conn->state = NETCONN_NONE;
685
 
686
  return conn->err;
687
}
688
 
689
err_t
690
netconn_close(struct netconn *conn)
691
{
692
  struct api_msg *msg;
693
 
694
  if (conn == NULL) {
695
    return ERR_VAL;
696
  }
697
  if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
698
    return (conn->err = ERR_MEM);
699
  }
700
 
701
  conn->state = NETCONN_CLOSE;
702
 again:
703
  msg->type = API_MSG_CLOSE;
704
  msg->msg.conn = conn;
705
  api_msg_post(msg);
706
  sys_mbox_fetch(conn->mbox, NULL);
707
  if (conn->err == ERR_MEM &&
708
     conn->sem != SYS_SEM_NULL) {
709
    sys_sem_wait(conn->sem);
710
    goto again;
711
  }
712
  conn->state = NETCONN_NONE;
713
  memp_free(MEMP_API_MSG, msg);
714
  return conn->err;
715
}
716
 
717
err_t
718
netconn_err(struct netconn *conn)
719
{
720
  return conn->err;
721
}
722
 

powered by: WebSVN 2.1.0

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