xref: /nrf52832-nimble/rt-thread/components/net/lwip-2.0.2/src/arch/sys_arch.c (revision 104654410c56c573564690304ae786df310c91fc)
1 /*
2  * COPYRIGHT (C) 2006-2018, RT-Thread Development Team
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  * Change Logs:
28  * Date           Author       Notes
29  * 2012-12-8      Bernard      add file header
30  *                             export bsd socket symbol for RT-Thread Application Module
31  * 2017-11-15     Bernard      add lock for init_done callback.
32  */
33 
34 #include <rtthread.h>
35 
36 #include "lwip/sys.h"
37 #include "lwip/opt.h"
38 #include "lwip/stats.h"
39 #include "lwip/err.h"
40 #include "arch/sys_arch.h"
41 #include "lwip/debug.h"
42 #include "lwip/netif.h"
43 #include "lwip/netifapi.h"
44 #include "lwip/tcpip.h"
45 #include "netif/ethernetif.h"
46 #include "lwip/sio.h"
47 #include "lwip/init.h"
48 #include "lwip/dhcp.h"
49 #include "lwip/inet.h"
50 
51 #include <string.h>
52 
53 /*
54  * Initialize the network interface device
55  *
56  * @return the operation status, ERR_OK on OK, ERR_IF on error
57  */
netif_device_init(struct netif * netif)58 static err_t netif_device_init(struct netif *netif)
59 {
60     struct eth_device *ethif;
61 
62     ethif = (struct eth_device *)netif->state;
63     if (ethif != RT_NULL)
64     {
65         rt_device_t device;
66 
67         /* get device object */
68         device = (rt_device_t) ethif;
69         if (rt_device_init(device) != RT_EOK)
70         {
71             return ERR_IF;
72         }
73 
74         /* copy device flags to netif flags */
75         netif->flags = ethif->flags;
76 
77         return ERR_OK;
78     }
79 
80     return ERR_IF;
81 }
82 /*
83  * Initialize the ethernetif layer and set network interface device up
84  */
tcpip_init_done_callback(void * arg)85 static void tcpip_init_done_callback(void *arg)
86 {
87     rt_device_t device;
88     struct eth_device *ethif;
89     ip4_addr_t ipaddr, netmask, gw;
90     struct rt_list_node* node;
91     struct rt_object* object;
92     struct rt_object_information *information;
93 
94     LWIP_ASSERT("invalid arg.\n",arg);
95 
96     IP4_ADDR(&gw, 0,0,0,0);
97     IP4_ADDR(&ipaddr, 0,0,0,0);
98     IP4_ADDR(&netmask, 0,0,0,0);
99 
100     /* enter critical */
101     rt_enter_critical();
102 
103     /* for each network interfaces */
104     information = rt_object_get_information(RT_Object_Class_Device);
105     RT_ASSERT(information != RT_NULL);
106     for (node = information->object_list.next;
107          node != &(information->object_list);
108          node = node->next)
109     {
110         object = rt_list_entry(node, struct rt_object, list);
111         device = (rt_device_t)object;
112         if (device->type == RT_Device_Class_NetIf)
113         {
114             ethif = (struct eth_device *)device;
115 
116             /* leave critical */
117             rt_exit_critical();
118             LOCK_TCPIP_CORE();
119 
120             netif_add(ethif->netif, &ipaddr, &netmask, &gw,
121                       ethif, netif_device_init, tcpip_input);
122 
123             if (netif_default == RT_NULL)
124                 netif_set_default(ethif->netif);
125 
126 #if LWIP_DHCP
127             /* set interface up */
128             netif_set_up(ethif->netif);
129             /* if this interface uses DHCP, start the DHCP client */
130             dhcp_start(ethif->netif);
131 #else
132             /* set interface up */
133             netif_set_up(ethif->netif);
134 #endif
135 
136             if (ethif->flags & ETHIF_LINK_PHYUP)
137             {
138                 netif_set_link_up(ethif->netif);
139             }
140 
141             UNLOCK_TCPIP_CORE();
142             /* enter critical */
143             rt_enter_critical();
144         }
145     }
146 
147     /* leave critical */
148     rt_exit_critical();
149     rt_sem_release((rt_sem_t)arg);
150 }
151 
152 /**
153  * LwIP system initialization
154  */
155 extern int eth_system_device_init_private(void);
lwip_system_init(void)156 int lwip_system_init(void)
157 {
158     rt_err_t rc;
159     struct rt_semaphore done_sem;
160     static rt_bool_t init_ok = RT_FALSE;
161 
162     if (init_ok)
163     {
164         rt_kprintf("lwip system already init.\n");
165         return 0;
166     }
167 
168     eth_system_device_init_private();
169 
170     /* set default netif to NULL */
171     netif_default = RT_NULL;
172 
173     rc = rt_sem_init(&done_sem, "done", 0, RT_IPC_FLAG_FIFO);
174 
175     if (rc != RT_EOK)
176     {
177         LWIP_ASSERT("Failed to create semaphore", 0);
178 
179         return -1;
180     }
181 
182     tcpip_init(tcpip_init_done_callback, (void *)&done_sem);
183 
184     /* waiting for initialization done */
185     if (rt_sem_take(&done_sem, RT_WAITING_FOREVER) != RT_EOK)
186     {
187         rt_sem_detach(&done_sem);
188 
189         return -1;
190     }
191     rt_sem_detach(&done_sem);
192 
193     /* set default ip address */
194 #if !LWIP_DHCP
195     if (netif_default != RT_NULL)
196     {
197         struct ip4_addr ipaddr, netmask, gw;
198 
199         ipaddr.addr = inet_addr(RT_LWIP_IPADDR);
200         gw.addr = inet_addr(RT_LWIP_GWADDR);
201         netmask.addr = inet_addr(RT_LWIP_MSKADDR);
202 
203         netifapi_netif_set_addr(netif_default, &ipaddr, &netmask, &gw);
204     }
205 #endif
206     rt_kprintf("lwIP-%d.%d.%d initialized!\n", LWIP_VERSION_MAJOR, LWIP_VERSION_MINOR, LWIP_VERSION_REVISION);
207 
208     init_ok = RT_TRUE;
209 
210     return 0;
211 }
212 INIT_PREV_EXPORT(lwip_system_init);
213 
sys_init(void)214 void sys_init(void)
215 {
216     /* nothing on RT-Thread porting */
217 }
218 
lwip_sys_init(void)219 void lwip_sys_init(void)
220 {
221     lwip_system_init();
222 }
223 
224 /*
225  * Create a new semaphore
226  *
227  * @return the operation status, ERR_OK on OK; others on error
228  */
sys_sem_new(sys_sem_t * sem,u8_t count)229 err_t sys_sem_new(sys_sem_t *sem, u8_t count)
230 {
231     static unsigned short counter = 0;
232     char tname[RT_NAME_MAX];
233     sys_sem_t tmpsem;
234 
235     RT_DEBUG_NOT_IN_INTERRUPT;
236 
237     rt_snprintf(tname, RT_NAME_MAX, "%s%d", SYS_LWIP_SEM_NAME, counter);
238     counter ++;
239 
240     tmpsem = rt_sem_create(tname, count, RT_IPC_FLAG_FIFO);
241     if (tmpsem == RT_NULL)
242         return ERR_MEM;
243     else
244     {
245         *sem = tmpsem;
246 
247         return ERR_OK;
248     }
249 }
250 
251 /*
252  * Deallocate a semaphore
253  */
sys_sem_free(sys_sem_t * sem)254 void sys_sem_free(sys_sem_t *sem)
255 {
256     RT_DEBUG_NOT_IN_INTERRUPT;
257     rt_sem_delete(*sem);
258 }
259 
260 /*
261  * Signal a semaphore
262  */
sys_sem_signal(sys_sem_t * sem)263 void sys_sem_signal(sys_sem_t *sem)
264 {
265     rt_sem_release(*sem);
266 }
267 
268 /*
269  * Block the thread while waiting for the semaphore to be signaled
270  *
271  * @return If the timeout argument is non-zero, it will return the number of milliseconds
272  *         spent waiting for the semaphore to be signaled; If the semaphore isn't signaled
273  *         within the specified time, it will return SYS_ARCH_TIMEOUT; If the thread doesn't
274  *         wait for the semaphore, it will return zero
275  */
sys_arch_sem_wait(sys_sem_t * sem,u32_t timeout)276 u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
277 {
278     rt_err_t ret;
279     s32_t t;
280     u32_t tick;
281 
282     RT_DEBUG_NOT_IN_INTERRUPT;
283 
284     /* get the begin tick */
285     tick = rt_tick_get();
286     if (timeout == 0)
287         t = RT_WAITING_FOREVER;
288     else
289     {
290         /* convert msecond to os tick */
291         if (timeout < (1000/RT_TICK_PER_SECOND))
292             t = 1;
293         else
294             t = timeout / (1000/RT_TICK_PER_SECOND);
295     }
296 
297     ret = rt_sem_take(*sem, t);
298 
299     if (ret == -RT_ETIMEOUT)
300         return SYS_ARCH_TIMEOUT;
301     else
302     {
303         if (ret == RT_EOK)
304             ret = 1;
305     }
306 
307     /* get elapse msecond */
308     tick = rt_tick_get() - tick;
309 
310     /* convert tick to msecond */
311     tick = tick * (1000 / RT_TICK_PER_SECOND);
312     if (tick == 0)
313         tick = 1;
314 
315     return tick;
316 }
317 
318 #ifndef sys_sem_valid
319 /** Check if a semaphore is valid/allocated:
320  *  return 1 for valid, 0 for invalid
321  */
sys_sem_valid(sys_sem_t * sem)322 int sys_sem_valid(sys_sem_t *sem)
323 {
324     return (int)(*sem);
325 }
326 #endif
327 
328 #ifndef sys_sem_set_invalid
329 /** Set a semaphore invalid so that sys_sem_valid returns 0
330  */
sys_sem_set_invalid(sys_sem_t * sem)331 void sys_sem_set_invalid(sys_sem_t *sem)
332 {
333     *sem = RT_NULL;
334 }
335 #endif
336 
337 /* ====================== Mutex ====================== */
338 
339 /** Create a new mutex
340  * @param mutex pointer to the mutex to create
341  * @return a new mutex
342  */
sys_mutex_new(sys_mutex_t * mutex)343 err_t sys_mutex_new(sys_mutex_t *mutex)
344 {
345     static unsigned short counter = 0;
346     char tname[RT_NAME_MAX];
347     sys_mutex_t tmpmutex;
348 
349     RT_DEBUG_NOT_IN_INTERRUPT;
350 
351     rt_snprintf(tname, RT_NAME_MAX, "%s%d", SYS_LWIP_MUTEX_NAME, counter);
352     counter ++;
353 
354     tmpmutex = rt_mutex_create(tname, RT_IPC_FLAG_FIFO);
355     if (tmpmutex == RT_NULL)
356         return ERR_MEM;
357     else
358     {
359         *mutex = tmpmutex;
360 
361         return ERR_OK;
362     }
363 }
364 
365 /** Lock a mutex
366  * @param mutex the mutex to lock
367  */
sys_mutex_lock(sys_mutex_t * mutex)368 void sys_mutex_lock(sys_mutex_t *mutex)
369 {
370     RT_DEBUG_NOT_IN_INTERRUPT;
371     rt_mutex_take(*mutex, RT_WAITING_FOREVER);
372 
373     return;
374 }
375 
376 /** Unlock a mutex
377  * @param mutex the mutex to unlock
378  */
sys_mutex_unlock(sys_mutex_t * mutex)379 void sys_mutex_unlock(sys_mutex_t *mutex)
380 {
381     rt_mutex_release(*mutex);
382 }
383 
384 /** Delete a semaphore
385  * @param mutex the mutex to delete
386  */
sys_mutex_free(sys_mutex_t * mutex)387 void sys_mutex_free(sys_mutex_t *mutex)
388 {
389     RT_DEBUG_NOT_IN_INTERRUPT;
390 
391     rt_mutex_delete(*mutex);
392 }
393 
394 #ifndef sys_mutex_valid
395 /** Check if a mutex is valid/allocated:
396  *  return 1 for valid, 0 for invalid
397  */
sys_mutex_valid(sys_mutex_t * mutex)398 int sys_mutex_valid(sys_mutex_t *mutex)
399 {
400     return (int)(*mutex);
401 }
402 #endif
403 
404 #ifndef sys_mutex_set_invalid
405 /** Set a mutex invalid so that sys_mutex_valid returns 0
406  */
sys_mutex_set_invalid(sys_mutex_t * mutex)407 void sys_mutex_set_invalid(sys_mutex_t *mutex)
408 {
409     *mutex = RT_NULL;
410 }
411 #endif
412 
413 /* ====================== Mailbox ====================== */
414 
415 /*
416  * Create an empty mailbox for maximum "size" elements
417  *
418  * @return the operation status, ERR_OK on OK; others on error
419  */
sys_mbox_new(sys_mbox_t * mbox,int size)420 err_t sys_mbox_new(sys_mbox_t *mbox, int size)
421 {
422     static unsigned short counter = 0;
423     char tname[RT_NAME_MAX];
424     sys_mbox_t tmpmbox;
425 
426     RT_DEBUG_NOT_IN_INTERRUPT;
427 
428     rt_snprintf(tname, RT_NAME_MAX, "%s%d", SYS_LWIP_MBOX_NAME, counter);
429     counter ++;
430 
431     tmpmbox = rt_mb_create(tname, size, RT_IPC_FLAG_FIFO);
432     if (tmpmbox != RT_NULL)
433     {
434         *mbox = tmpmbox;
435 
436         return ERR_OK;
437     }
438 
439     return ERR_MEM;
440 }
441 
442 /*
443  * Deallocate a mailbox
444  */
sys_mbox_free(sys_mbox_t * mbox)445 void sys_mbox_free(sys_mbox_t *mbox)
446 {
447     RT_DEBUG_NOT_IN_INTERRUPT;
448 
449     rt_mb_delete(*mbox);
450 
451     return;
452 }
453 
454 /** Post a message to an mbox - may not fail
455  * -> blocks if full, only used from tasks not from ISR
456  * @param mbox mbox to posts the message
457  * @param msg message to post (ATTENTION: can be NULL)
458  */
sys_mbox_post(sys_mbox_t * mbox,void * msg)459 void sys_mbox_post(sys_mbox_t *mbox, void *msg)
460 {
461     RT_DEBUG_NOT_IN_INTERRUPT;
462 
463     rt_mb_send_wait(*mbox, (rt_uint32_t)msg, RT_WAITING_FOREVER);
464 
465     return;
466 }
467 
468 /*
469  * Try to post the "msg" to the mailbox
470  *
471  * @return return ERR_OK if the "msg" is posted, ERR_MEM if the mailbox is full
472  */
sys_mbox_trypost(sys_mbox_t * mbox,void * msg)473 err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
474 {
475     if (rt_mb_send(*mbox, (rt_uint32_t)msg) == RT_EOK)
476         return ERR_OK;
477 
478     return ERR_MEM;
479 }
480 
481 /** Wait for a new message to arrive in the mbox
482  * @param mbox mbox to get a message from
483  * @param msg pointer where the message is stored
484  * @param timeout maximum time (in milliseconds) to wait for a message
485  * @return time (in milliseconds) waited for a message, may be 0 if not waited
486            or SYS_ARCH_TIMEOUT on timeout
487  *         The returned time has to be accurate to prevent timer jitter!
488  */
sys_arch_mbox_fetch(sys_mbox_t * mbox,void ** msg,u32_t timeout)489 u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
490 {
491     rt_err_t ret;
492     s32_t t;
493     u32_t tick;
494 
495     RT_DEBUG_NOT_IN_INTERRUPT;
496 
497     /* get the begin tick */
498     tick = rt_tick_get();
499 
500     if(timeout == 0)
501         t = RT_WAITING_FOREVER;
502     else
503     {
504         /* convirt msecond to os tick */
505         if (timeout < (1000/RT_TICK_PER_SECOND))
506             t = 1;
507         else
508             t = timeout / (1000/RT_TICK_PER_SECOND);
509     }
510 
511     ret = rt_mb_recv(*mbox, (rt_ubase_t *)msg, t);
512 
513     if(ret == -RT_ETIMEOUT)
514         return SYS_ARCH_TIMEOUT;
515     else
516     {
517         LWIP_ASSERT("rt_mb_recv returned with error!", ret == RT_EOK);
518     }
519 
520     /* get elapse msecond */
521     tick = rt_tick_get() - tick;
522 
523     /* convert tick to msecond */
524     tick = tick * (1000 / RT_TICK_PER_SECOND);
525     if (tick == 0)
526         tick = 1;
527 
528     return tick;
529 }
530 
531 /** Wait for a new message to arrive in the mbox
532  * @param mbox mbox to get a message from
533  * @param msg pointer where the message is stored
534  * @param timeout maximum time (in milliseconds) to wait for a message
535  * @return 0 (milliseconds) if a message has been received
536  *         or SYS_MBOX_EMPTY if the mailbox is empty
537  */
sys_arch_mbox_tryfetch(sys_mbox_t * mbox,void ** msg)538 u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
539 {
540     int ret;
541 
542     ret = rt_mb_recv(*mbox, (rt_ubase_t *)msg, 0);
543 
544     if(ret == -RT_ETIMEOUT)
545         return SYS_ARCH_TIMEOUT;
546     else
547     {
548         if (ret == RT_EOK)
549             ret = 1;
550     }
551 
552     return ret;
553 }
554 
555 #ifndef sys_mbox_valid
556 /** Check if an mbox is valid/allocated:
557  *  return 1 for valid, 0 for invalid
558  */
sys_mbox_valid(sys_mbox_t * mbox)559 int sys_mbox_valid(sys_mbox_t *mbox)
560 {
561     return (int)(*mbox);
562 }
563 #endif
564 
565 #ifndef sys_mbox_set_invalid
566 /** Set an mbox invalid so that sys_mbox_valid returns 0
567  */
sys_mbox_set_invalid(sys_mbox_t * mbox)568 void sys_mbox_set_invalid(sys_mbox_t *mbox)
569 {
570     *mbox = RT_NULL;
571 }
572 #endif
573 
574 /* ====================== System ====================== */
575 
576 /*
577  * Start a new thread named "name" with priority "prio" that will begin
578  * its execution in the function "thread()". The "arg" argument will be
579  * passed as an argument to the thread() function
580  */
sys_thread_new(const char * name,lwip_thread_fn thread,void * arg,int stacksize,int prio)581 sys_thread_t sys_thread_new(const char    *name,
582                             lwip_thread_fn thread,
583                             void          *arg,
584                             int            stacksize,
585                             int            prio)
586 {
587     rt_thread_t t;
588 
589     RT_DEBUG_NOT_IN_INTERRUPT;
590 
591     /* create thread */
592     t = rt_thread_create(name, thread, arg, stacksize, prio, 20);
593     RT_ASSERT(t != RT_NULL);
594 
595     /* startup thread */
596     rt_thread_startup(t);
597 
598     return t;
599 }
600 
sys_arch_protect(void)601 sys_prot_t sys_arch_protect(void)
602 {
603     rt_base_t level;
604 
605     /* disable interrupt */
606     level = rt_hw_interrupt_disable();
607 
608     return level;
609 }
610 
sys_arch_unprotect(sys_prot_t pval)611 void sys_arch_unprotect(sys_prot_t pval)
612 {
613     /* enable interrupt */
614     rt_hw_interrupt_enable(pval);
615 
616     return;
617 }
618 
sys_arch_assert(const char * file,int line)619 void sys_arch_assert(const char *file, int line)
620 {
621     rt_kprintf("\nAssertion: %d in %s, thread %s\n",
622                line, file, rt_thread_self()->name);
623     RT_ASSERT(0);
624 }
625 
sys_jiffies(void)626 u32_t sys_jiffies(void)
627 {
628     return rt_tick_get();
629 }
630 
sys_now(void)631 u32_t sys_now(void)
632 {
633     return rt_tick_get() * (1000 / RT_TICK_PER_SECOND);
634 }
635 
636 
637 RT_WEAK
mem_init(void)638 void mem_init(void)
639 {
640 }
641 
mem_calloc(mem_size_t count,mem_size_t size)642 void *mem_calloc(mem_size_t count, mem_size_t size)
643 {
644     return rt_calloc(count, size);
645 }
646 
mem_trim(void * mem,mem_size_t size)647 void *mem_trim(void *mem, mem_size_t size)
648 {
649     // return rt_realloc(mem, size);
650     /* not support trim yet */
651     return mem;
652 }
653 
mem_malloc(mem_size_t size)654 void *mem_malloc(mem_size_t size)
655 {
656     return rt_malloc(size);
657 }
658 
mem_free(void * mem)659 void  mem_free(void *mem)
660 {
661     rt_free(mem);
662 }
663 
664 #ifdef RT_LWIP_PPP
sio_read(sio_fd_t fd,u8_t * buf,u32_t size)665 u32_t sio_read(sio_fd_t fd, u8_t *buf, u32_t size)
666 {
667     u32_t len;
668 
669     RT_ASSERT(fd != RT_NULL);
670 
671     len = rt_device_read((rt_device_t)fd, 0, buf, size);
672     if (len <= 0)
673         return 0;
674 
675     return len;
676 }
677 
sio_write(sio_fd_t fd,u8_t * buf,u32_t size)678 u32_t sio_write(sio_fd_t fd, u8_t *buf, u32_t size)
679 {
680     RT_ASSERT(fd != RT_NULL);
681 
682     return rt_device_write((rt_device_t)fd, 0, buf, size);
683 }
684 
sio_read_abort(sio_fd_t fd)685 void sio_read_abort(sio_fd_t fd)
686 {
687     rt_kprintf("read_abort\n");
688 }
689 
ppp_trace(int level,const char * format,...)690 void ppp_trace(int level, const char *format, ...)
691 {
692     va_list args;
693     rt_size_t length;
694     static char rt_log_buf[RT_CONSOLEBUF_SIZE];
695 
696     va_start(args, format);
697     length = rt_vsprintf(rt_log_buf, format, args);
698     rt_device_write((rt_device_t)rt_console_get_device(), 0, rt_log_buf, length);
699     va_end(args);
700 }
701 #endif
702 
703 /*
704  * export bsd socket symbol for RT-Thread Application Module
705  */
706 #if LWIP_SOCKET
707 #include <lwip/sockets.h>
708 RTM_EXPORT(lwip_accept);
709 RTM_EXPORT(lwip_bind);
710 RTM_EXPORT(lwip_shutdown);
711 RTM_EXPORT(lwip_getpeername);
712 RTM_EXPORT(lwip_getsockname);
713 RTM_EXPORT(lwip_getsockopt);
714 RTM_EXPORT(lwip_setsockopt);
715 RTM_EXPORT(lwip_close);
716 RTM_EXPORT(lwip_connect);
717 RTM_EXPORT(lwip_listen);
718 RTM_EXPORT(lwip_recv);
719 RTM_EXPORT(lwip_read);
720 RTM_EXPORT(lwip_recvfrom);
721 RTM_EXPORT(lwip_send);
722 RTM_EXPORT(lwip_sendto);
723 RTM_EXPORT(lwip_socket);
724 RTM_EXPORT(lwip_write);
725 RTM_EXPORT(lwip_select);
726 RTM_EXPORT(lwip_ioctl);
727 RTM_EXPORT(lwip_fcntl);
728 
729 RTM_EXPORT(lwip_htons);
730 RTM_EXPORT(lwip_htonl);
731 
732 #if LWIP_DNS
733 #include <lwip/netdb.h>
734 RTM_EXPORT(lwip_gethostbyname);
735 RTM_EXPORT(lwip_gethostbyname_r);
736 RTM_EXPORT(lwip_freeaddrinfo);
737 RTM_EXPORT(lwip_getaddrinfo);
738 #endif
739 
740 #endif
741 
742 #if LWIP_DHCP
743 #include <lwip/dhcp.h>
744 RTM_EXPORT(dhcp_start);
745 RTM_EXPORT(dhcp_renew);
746 RTM_EXPORT(dhcp_stop);
747 #endif
748 
749 #if LWIP_NETIF_API
750 #include <lwip/netifapi.h>
751 RTM_EXPORT(netifapi_netif_set_addr);
752 #endif
753 
754 #if LWIP_NETIF_LINK_CALLBACK
755 RTM_EXPORT(netif_set_link_callback);
756 #endif
757 
758 #if LWIP_NETIF_STATUS_CALLBACK
759 RTM_EXPORT(netif_set_status_callback);
760 #endif
761 
762 RTM_EXPORT(netif_find);
763 RTM_EXPORT(netif_set_addr);
764 RTM_EXPORT(netif_set_ipaddr);
765 RTM_EXPORT(netif_set_gw);
766 RTM_EXPORT(netif_set_netmask);
767