static void do_disconnect(struct api_msg_msg *msg) { switch (msg->conn->type) { #if LWIP_RAW case NETCONN_RAW: /* Do nothing as connecting is only a helper for upper lwip layers */ break; #endif #if LWIP_UDP case NETCONN_UDPLITE: /* FALLTHROUGH */ case NETCONN_UDPNOCHKSUM: /* FALLTHROUGH */ case NETCONN_UDP: udp_disconnect(msg->conn->pcb.udp); break; #endif case NETCONN_TCP: break; default: LWIP_ASSERT( "do_newconn: msg->conn->type unknown\n", 0 ); } sys_mbox_post(msg->conn->mbox, NULL); }
static void do_send(struct api_msg_msg *msg) { if (msg->conn->pcb.tcp != NULL) { switch (msg->conn->type) { #if LWIP_RAW case NETCONN_RAW: raw_send(msg->conn->pcb.raw, msg->msg.p); break; #endif #if LWIP_UDP case NETCONN_UDPLITE: /* FALLTHROUGH */ case NETCONN_UDPNOCHKSUM: /* FALLTHROUGH */ case NETCONN_UDP: udp_send(msg->conn->pcb.udp, msg->msg.p); break; #endif /* LWIP_UDP */ case NETCONN_TCP: break; default: LWIP_ASSERT( "do_newconn: msg->conn->type unknown\n", 0 ); } } sys_mbox_post(msg->conn->mbox, NULL); }
/** * Sends a message to TCPIP thread to call a function. Caller thread blocks on * on a provided semaphore, which ist NOT automatically signalled by TCPIP thread, * this has to be done by the user. * It is recommended to use LWIP_TCPIP_CORE_LOCKING since this is the way * with least runtime overhead. * * @param fn function to be called from TCPIP thread * @param apimsg argument to API function * @param sem semaphore to wait on * @return ERR_OK if the function was called, another err_t if not */ err_t tcpip_send_msg_wait_sem(tcpip_callback_fn fn, void *apimsg, sys_sem_t* sem) { #if LWIP_TCPIP_CORE_LOCKING LWIP_UNUSED_ARG(sem); LOCK_TCPIP_CORE(); fn(apimsg); UNLOCK_TCPIP_CORE(); return ERR_OK; #else /* LWIP_TCPIP_CORE_LOCKING */ TCPIP_MSG_VAR_DECLARE(msg); LWIP_ASSERT("semaphore not initialized", sys_sem_valid(sem)); LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); TCPIP_MSG_VAR_ALLOC(msg); TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API; TCPIP_MSG_VAR_REF(msg).msg.api_msg.function = fn; TCPIP_MSG_VAR_REF(msg).msg.api_msg.msg = apimsg; sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg)); sys_arch_sem_wait(sem, 0); TCPIP_MSG_VAR_FREE(msg); return ERR_OK; #endif /* LWIP_TCPIP_CORE_LOCKING */ }
/** * Call a specific function in the thread context of * tcpip_thread for easy access synchronization. * A function called in that way may access lwIP core code * without fearing concurrent access. * * @param f the function to call * @param ctx parameter passed to f * @param block 1 to block until the request is posted, 0 to non-blocking mode * @return ERR_OK if the function was called, another err_t if not */ err_t tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block) { struct tcpip_msg *msg; if (sys_mbox_valid(&mbox)) { msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); if (msg == NULL) { return ERR_MEM; } msg->type = TCPIP_MSG_CALLBACK; msg->msg.cb.function = function; msg->msg.cb.ctx = ctx; if (block) { sys_mbox_post(&mbox, msg); } else { if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { memp_free(MEMP_TCPIP_MSG_API, msg); return ERR_MEM; } } return ERR_OK; } return ERR_VAL; }
/** * Call a specific function in the thread context of * tcpip_thread for easy access synchronization. * A function called in that way may access lwIP core code * without fearing concurrent access. * * @param f the function to call * @param ctx parameter passed to f * @param block 1 to block until the request is posted, 0 to non-blocking mode * @return ERR_OK if the function was called, another err_t if not */ err_t tcpip_callback_with_block(void (*f)(void *ctx), void *ctx, u8_t block) { struct tcpip_msg *msg; if (mbox != SYS_MBOX_NULL) { msg = memp_malloc(MEMP_TCPIP_MSG_API); if (msg == NULL) { return ERR_MEM; } msg->type = TCPIP_MSG_CALLBACK; msg->msg.cb.f = f; msg->msg.cb.ctx = ctx; if (block) { sys_mbox_post(mbox, msg); } else { if (sys_mbox_trypost(mbox, msg) != ERR_OK) { memp_free(MEMP_TCPIP_MSG_API, msg); return ERR_MEM; } } return ERR_OK; } return ERR_VAL; }
static void recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port) { struct netbuf *buf; struct netconn *conn; conn = arg; if (conn == NULL) { pbuf_free(p); return; } if (conn->recvmbox != SYS_MBOX_NULL) { buf = memp_malloc(MEMP_NETBUF); if (buf == NULL) { pbuf_free(p); return; } else { buf->p = p; buf->ptr = p; buf->fromaddr = addr; buf->fromport = port; } conn->recv_avail += p->tot_len; /* Register event with callback */ if (conn->callback) (*conn->callback)(conn, NETCONN_EVT_RCVPLUS, p->tot_len); sys_mbox_post(conn->recvmbox, buf); } }
static void do_close(struct api_msg_msg *msg) { err_t err; err = ERR_OK; if (msg->conn->pcb.tcp != NULL) { switch (msg->conn->type) { #if LWIP_RAW case NETCONN_RAW: break; #endif #if LWIP_UDP case NETCONN_UDPLITE: /* FALLTHROUGH */ case NETCONN_UDPNOCHKSUM: /* FALLTHROUGH */ case NETCONN_UDP: break; #endif /* LWIP_UDP */ #if LWIP_TCP case NETCONN_TCP: if (msg->conn->pcb.tcp->state == LISTEN) { err = tcp_close(msg->conn->pcb.tcp); } msg->conn->err = err; #endif default: break; } } sys_mbox_post(msg->conn->mbox, NULL); }
static err_t recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) { struct netconn *conn; u16_t len; conn = arg; if (conn == NULL) { pbuf_free(p); return ERR_VAL; } if (conn->recvmbox != SYS_MBOX_NULL) { conn->err = err; if (p != NULL) { len = p->tot_len; conn->recv_avail += len; } else len = 0; /* Register event with callback */ if (conn->callback) (*conn->callback)(conn, NETCONN_EVT_RCVPLUS, len); sys_mbox_post(conn->recvmbox, p); } return ERR_OK; }
static u8_t recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *addr) { struct netbuf *buf; struct netconn *conn; conn = arg; if (!conn) return 0; if (conn->recvmbox != SYS_MBOX_NULL) { if (!(buf = memp_malloc(MEMP_NETBUF))) { return 0; } pbuf_ref(p); buf->p = p; buf->ptr = p; buf->fromaddr = addr; buf->fromport = pcb->protocol; conn->recv_avail += p->tot_len; /* Register event with callback */ if (conn->callback) (*conn->callback)(conn, NETCONN_EVT_RCVPLUS, p->tot_len); sys_mbox_post(conn->recvmbox, buf); } return 0; /* do not eat the packet */ }
err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) { sys_mbox_post(mbox, msg); return ERR_OK; }
/** * Post a callback-message to the tcpip_thread mbox. * * This is used to send "static" messages. Not necessarily "from * interrupt context" - avoiding unnecessary malloc() is always good. * * To prevent confusion and to provide API symmetry there's a * counterpart macro tcpip_trycallbackmsg() that aliases * tcpip_trycallback() above. * * @param msg pointer to the message to post * @return sys_mbox_trypost() return code */ err_t tcpip_callbackmsg(struct tcpip_callback_msg* msg) { if (!sys_mbox_valid(&mbox)) { return ERR_VAL; } sys_mbox_post(&mbox, msg); return ERR_OK; }
static err_t accept_function(void *arg, struct tcp_pcb *newpcb, err_t err) { sys_mbox_t mbox; struct netconn *newconn; struct netconn *conn; #if API_MSG_DEBUG #if TCP_DEBUG tcp_debug_print_state(newpcb->state); #endif /* TCP_DEBUG */ #endif /* API_MSG_DEBUG */ conn = (struct netconn *)arg; mbox = conn->acceptmbox; newconn = memp_malloc(MEMP_NETCONN); if (newconn == NULL) { return ERR_MEM; } newconn->recvmbox = sys_mbox_new(); if (newconn->recvmbox == SYS_MBOX_NULL) { memp_free(MEMP_NETCONN, newconn); return ERR_MEM; } newconn->mbox = sys_mbox_new(); if (newconn->mbox == SYS_MBOX_NULL) { sys_mbox_free(newconn->recvmbox); memp_free(MEMP_NETCONN, newconn); return ERR_MEM; } newconn->sem = sys_sem_new(0); if (newconn->sem == SYS_SEM_NULL) { sys_mbox_free(newconn->recvmbox); sys_mbox_free(newconn->mbox); memp_free(MEMP_NETCONN, newconn); return ERR_MEM; } /* Allocations were OK, setup the PCB etc */ newconn->type = NETCONN_TCP; newconn->pcb.tcp = newpcb; setup_tcp(newconn); newconn->acceptmbox = SYS_MBOX_NULL; newconn->err = err; /* Register event with callback */ if (conn->callback) { (*conn->callback)(conn, NETCONN_EVT_RCVPLUS, 0); } /* We have to set the callback here even though * the new socket is unknown. Mark the socket as -1. */ newconn->callback = conn->callback; newconn->socket = -1; newconn->recv_avail = 0; sys_mbox_post(mbox, newconn); return ERR_OK; }
void tcpip_terminate(void) { struct tcpip_msg *msg; msg = memp_malloc(MEMP_TCPIP_MSG); if (msg == NULL) { return; } msg->type = TCPIP_MSG_TERM; sys_mbox_post(mbox, msg); }
void tcpip_apimsg(struct api_msg *apimsg) { struct tcpip_msg *msg; msg = memp_malloc(MEMP_TCPIP_MSG); if (msg == NULL) { memp_free(MEMP_API_MSG, apimsg); return; } msg->type = TCPIP_MSG_API; msg->msg.apimsg = apimsg; sys_mbox_post(mbox, msg); }
static void do_recv(struct api_msg_msg *msg) { #if LWIP_TCP if (msg->conn->pcb.tcp != NULL) { if (msg->conn->type == NETCONN_TCP) { tcp_recved(msg->conn->pcb.tcp, msg->msg.len); } } #endif sys_mbox_post(msg->conn->mbox, NULL); }
static void do_delconn(struct api_msg_msg *msg) { if (msg->conn->pcb.tcp != NULL) { switch (msg->conn->type) { #if LWIP_RAW case NETCONN_RAW: raw_remove(msg->conn->pcb.raw); break; #endif #if LWIP_UDP case NETCONN_UDPLITE: /* FALLTHROUGH */ case NETCONN_UDPNOCHKSUM: /* FALLTHROUGH */ case NETCONN_UDP: msg->conn->pcb.udp->recv_arg = NULL; udp_remove(msg->conn->pcb.udp); break; #endif /* LWIP_UDP */ #if LWIP_TCP case NETCONN_TCP: if (msg->conn->pcb.tcp->state == LISTEN) { tcp_arg(msg->conn->pcb.tcp, NULL); tcp_accept(msg->conn->pcb.tcp, NULL); tcp_close(msg->conn->pcb.tcp); } else { tcp_arg(msg->conn->pcb.tcp, NULL); tcp_sent(msg->conn->pcb.tcp, NULL); tcp_recv(msg->conn->pcb.tcp, NULL); tcp_poll(msg->conn->pcb.tcp, NULL, 0); tcp_err(msg->conn->pcb.tcp, NULL); if (tcp_close(msg->conn->pcb.tcp) != ERR_OK) { tcp_abort(msg->conn->pcb.tcp); } } #endif default: break; } } /* Trigger select() in socket layer */ if (msg->conn->callback) { (*msg->conn->callback)(msg->conn, NETCONN_EVT_RCVPLUS, 0); (*msg->conn->callback)(msg->conn, NETCONN_EVT_SENDPLUS, 0); } if (msg->conn->mbox != SYS_MBOX_NULL) { sys_mbox_post(msg->conn->mbox, NULL); } }
/** * Call the lower part of a netconn_* function * This function is then running in the thread context * of tcpip_thread and has exclusive access to lwIP core code. * * @param apimsg a struct containing the function to call and its parameters * @return ERR_OK if the function was called, another err_t if not */ err_t tcpip_apimsg(struct api_msg *apimsg) { struct tcpip_msg msg; if (mbox != SYS_MBOX_NULL) { msg.type = TCPIP_MSG_API; msg.msg.apimsg = apimsg; sys_mbox_post(mbox, &msg); sys_arch_sem_wait(apimsg->msg.conn->op_completed, 0); return ERR_OK; } return ERR_VAL; }
/*-----------------------------------------------------------------------------------*/ static void do_bind(struct api_msg_msg *msg) { if (msg->conn->pcb.tcp == NULL) { switch (msg->conn->type) { #if LWIP_UDP case NETCONN_UDPLITE: msg->conn->pcb.udp = udp_new(); udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); break; case NETCONN_UDPNOCHKSUM: msg->conn->pcb.udp = udp_new(); udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM); udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); break; case NETCONN_UDP: msg->conn->pcb.udp = udp_new(); udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); break; #endif /* LWIP_UDP */ #if LWIP_TCP case NETCONN_TCP: msg->conn->pcb.tcp = tcp_new(); setup_tcp(msg->conn); #endif /* LWIP_TCP */ default: break; } } switch (msg->conn->type) { #if LWIP_UDP case NETCONN_UDPLITE: /* FALLTHROUGH */ case NETCONN_UDPNOCHKSUM: /* FALLTHROUGH */ case NETCONN_UDP: msg->conn->err = udp_bind(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port); break; #endif /* LWIP_UDP */ #if LWIP_TCP case NETCONN_TCP: msg->conn->err = tcp_bind(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port); #endif /* LWIP_TCP */ default: break; } sys_mbox_post(msg->conn->mbox, NULL); }
static void do_write(struct api_msg_msg *msg) { #if LWIP_TCP err_t err; #endif if (msg->conn->pcb.tcp != NULL) { switch (msg->conn->type) { #if LWIP_RAW case NETCONN_RAW: msg->conn->err = ERR_VAL; break; #endif #if LWIP_UDP case NETCONN_UDPLITE: /* FALLTHROUGH */ case NETCONN_UDPNOCHKSUM: /* FALLTHROUGH */ case NETCONN_UDP: msg->conn->err = ERR_VAL; break; #endif /* LWIP_UDP */ #if LWIP_TCP case NETCONN_TCP: err = tcp_write(msg->conn->pcb.tcp, msg->msg.w.dataptr, msg->msg.w.len, msg->msg.w.copy); /* This is the Nagle algorithm: inhibit the sending of new TCP segments when new outgoing data arrives from the user if any previously transmitted data on the connection remains unacknowledged. */ if(err == ERR_OK && (msg->conn->pcb.tcp->unacked == NULL || (msg->conn->pcb.tcp->flags & TF_NODELAY) || (msg->conn->pcb.tcp->snd_queuelen) > 1)) { tcp_output(msg->conn->pcb.tcp); } msg->conn->err = err; if (msg->conn->callback) if (err == ERR_OK) { if (tcp_sndbuf(msg->conn->pcb.tcp) <= TCP_SNDLOWAT) (*msg->conn->callback)(msg->conn, NETCONN_EVT_SENDMINUS, msg->msg.w.len); } #endif default: break; } } sys_mbox_post(msg->conn->mbox, NULL); }
/* prio:10 */ static void task2(void *pdata) { char *m1 = "task2 message1"; char *m2 = "task2 message2"; char *m3 = "task2 message3"; char *m4 = "task2 message4"; while(1) { sys_mutex_lock(&sys_mutex); dprintf("task2,%s\r\n",pdata); #if 0 dprintf("task2 post m1\r\n"); OSQPost(mbox, m1); dprintf("task2 post m2\r\n"); OSQPost(mbox, m2); dprintf("task2 post m3\r\n"); OSQPost(mbox, m3); dprintf("task2 post m4\r\n"); OSQPost(mbox, m4); #endif dprintf("task2 post message1\r\n"); sys_mbox_post(&sys_mbox, m1); dprintf("task2 post message2\r\n"); sys_mbox_post(&sys_mbox, m2); dprintf("task2 post message3\r\n"); sys_mbox_post(&sys_mbox, m3); dprintf("task2 post message4\r\n"); sys_mbox_post(&sys_mbox, m4); sys_mutex_unlock(&sys_mutex); //OSTaskSuspend(OS_PRIO_SELF); //sys_sem_wait(&sys_sem); //OSTaskResume(9); } }
err_t tcpip_callback(void (*f)(void *ctx), void *ctx) { struct tcpip_msg *msg; msg = memp_malloc(MEMP_TCPIP_MSG); if (msg == NULL) { return ERR_MEM; } msg->type = TCPIP_MSG_CALLBACK; msg->msg.cb.f = f; msg->msg.cb.ctx = ctx; sys_mbox_post(tcp_mbox, msg); return ERR_OK; }
err_t tcpip_input(struct pbuf *p, struct netif *inp) { struct tcpip_msg *msg; msg = memp_malloc(MEMP_TCPIP_MSG); if (msg == NULL) { pbuf_free(p); return ERR_MEM; } msg->type = TCPIP_MSG_INPUT; msg->msg.inp.p = p; msg->msg.inp.netif = inp; sys_mbox_post(tcp_mbox, msg); return ERR_OK; }
/** * Call the lower part of a netconn_* function * This function is then running in the thread context * of tcpip_thread and has exclusive access to lwIP core code. * * @param apimsg a struct containing the function to call and its parameters * @return ERR_OK if the function was called, another err_t if not */ err_t tcpip_apimsg(struct api_msg *apimsg) { struct tcpip_msg msg; if (mbox != SYS_MBOX_NULL) { msg.type = TCPIP_MSG_API; msg.msg.apimsg = apimsg; //acoral_prints("\r\ntcpip_apimsg_post\r\n"); sys_mbox_post(mbox, &msg); //lwip_printf("\r\n %s \r\n====\r\n", apimsg->msg.msg.w.dataptr); //acoral_prints("\r\ntcpip_apimsg_op_completed\r\n"); sys_arch_sem_wait(apimsg->msg.conn->op_completed, 0); return ERR_OK; } return ERR_VAL; }
/** * call sys_untimeout in tcpip_thread * * @param h function to be called on timeout * @param arg argument to pass to timeout function h * @return ERR_MEM on memory error, ERR_OK otherwise */ err_t tcpip_untimeout(sys_timeout_handler h, void *arg) { struct tcpip_msg *msg; LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); if (msg == NULL) { return ERR_MEM; } msg->type = TCPIP_MSG_UNTIMEOUT; msg->msg.tmo.h = h; msg->msg.tmo.arg = arg; sys_mbox_post(&mbox, msg); return ERR_OK; }
static err_t do_connected(void *arg, struct tcp_pcb *pcb, err_t err) { struct netconn *conn; conn = arg; if (conn == NULL) { return ERR_VAL; } conn->err = err; if (conn->type == NETCONN_TCP && err == ERR_OK) { setup_tcp(conn); } sys_mbox_post(conn->mbox, NULL); return ERR_OK; }
/** * Call the lower part of a netconn_* function * This function is then running in the thread context * of tcpip_thread and has exclusive access to lwIP core code. * * @param apimsg a struct containing the function to call and its parameters * @return ERR_OK if the function was called, another err_t if not */ err_t tcpip_apimsg(struct api_msg *apimsg) { struct tcpip_msg msg; #ifdef LWIP_DEBUG /* catch functions that don't set err */ apimsg->msg.err = ERR_VAL; #endif if (sys_mbox_valid(&mbox)) { msg.type = TCPIP_MSG_API; msg.msg.apimsg = apimsg; sys_mbox_post(&mbox, &msg); sys_arch_sem_wait(&apimsg->msg.conn->op_completed, 0); return apimsg->msg.err; } return ERR_VAL; }
static void do_disconnect(struct api_msg_msg *msg) { switch (msg->conn->type) { #if LWIP_UDP case NETCONN_UDPLITE: /* FALLTHROUGH */ case NETCONN_UDPNOCHKSUM: /* FALLTHROUGH */ case NETCONN_UDP: udp_disconnect(msg->conn->pcb.udp); break; #endif case NETCONN_TCP: break; } sys_mbox_post(msg->conn->mbox, NULL); }
/** * call sys_untimeout in tcpip_thread * * @param msec time in miliseconds for timeout * @param h function to be called on timeout * @param arg argument to pass to timeout function h * @return ERR_MEM on memory error, ERR_OK otherwise */ err_t tcpip_untimeout(sys_timeout_handler h, void *arg) { struct tcpip_msg *msg; if (mbox != SYS_MBOX_NULL) { msg = memp_malloc(MEMP_TCPIP_MSG_API); if (msg == NULL) { return ERR_MEM; } msg->type = TCPIP_MSG_UNTIMEOUT; msg->msg.tmo.h = h; msg->msg.tmo.arg = arg; sys_mbox_post(mbox, msg); return ERR_OK; } return ERR_VAL; }
static void do_listen(struct api_msg_msg *msg) { if (msg->conn->pcb.tcp != NULL) { switch (msg->conn->type) { #if LWIP_RAW case NETCONN_RAW: LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: listen RAW: cannot listen for RAW.\n")); break; #endif #if LWIP_UDP case NETCONN_UDPLITE: /* FALLTHROUGH */ case NETCONN_UDPNOCHKSUM: /* FALLTHROUGH */ case NETCONN_UDP: LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: listen UDP: cannot listen for UDP.\n")); break; #endif /* LWIP_UDP */ #if LWIP_TCP case NETCONN_TCP: msg->conn->pcb.tcp = tcp_listen(msg->conn->pcb.tcp); if (msg->conn->pcb.tcp == NULL) { msg->conn->err = ERR_MEM; } else { if (msg->conn->acceptmbox == SYS_MBOX_NULL) { msg->conn->acceptmbox = sys_mbox_new(); if (msg->conn->acceptmbox == SYS_MBOX_NULL) { msg->conn->err = ERR_MEM; break; } } tcp_arg(msg->conn->pcb.tcp, msg->conn); tcp_accept(msg->conn->pcb.tcp, accept_function); } #endif default: break; } } sys_mbox_post(msg->conn->mbox, NULL); }
/** * call sys_timeout in tcpip_thread * * @param msec time in milliseconds for timeout * @param h function to be called on timeout * @param arg argument to pass to timeout function h * @return ERR_MEM on memory error, ERR_OK otherwise */ err_t tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg) { struct tcpip_msg *msg; if (sys_mbox_valid(&mbox)) { msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); if (msg == NULL) { return ERR_MEM; } msg->type = TCPIP_MSG_TIMEOUT; msg->msg.tmo.msecs = msecs; msg->msg.tmo.h = h; msg->msg.tmo.arg = arg; sys_mbox_post(&mbox, msg); return ERR_OK; } return ERR_VAL; }