diff options
Diffstat (limited to 'fw/esp32/components/eos/net.c')
-rw-r--r-- | fw/esp32/components/eos/net.c | 497 |
1 files changed, 338 insertions, 159 deletions
diff --git a/fw/esp32/components/eos/net.c b/fw/esp32/components/eos/net.c index 56ec940..0ba2a2d 100644 --- a/fw/esp32/components/eos/net.c +++ b/fw/esp32/components/eos/net.c @@ -16,20 +16,21 @@ #include "eos.h" #include "msgq.h" #include "power.h" +#include "app.h" #include "net.h" +#include "net_priv.h" -#define SPI_GPIO_RTS 22 -#define SPI_GPIO_CTS 21 -#define SPI_GPIO_MOSI 23 -#define SPI_GPIO_MISO 19 -#define SPI_GPIO_SCLK 18 -#define SPI_GPIO_CS 5 +#define SPI_GPIO_RTS 35 +#define SPI_GPIO_CTS 3 +#define SPI_GPIO_MOSI 40 +#define SPI_GPIO_MISO 39 +#define SPI_GPIO_SCLK 38 +#define SPI_GPIO_CS 8 #define SPI_SIZE_BUF (EOS_NET_SIZE_BUF + 4) #define SPI_SIZE_HDR 3 -static volatile int net_sleep = 0; -static volatile int net_wake = 0; +#define SPI_HOST SPI3_HOST static EOSBufQ net_buf_q; static unsigned char *net_bufq_array[EOS_NET_SIZE_BUFQ]; @@ -37,262 +38,440 @@ static unsigned char *net_bufq_array[EOS_NET_SIZE_BUFQ]; static EOSMsgQ net_send_q; static EOSMsgItem net_sndq_array[EOS_NET_SIZE_SNDQ]; -static SemaphoreHandle_t mutex; -static SemaphoreHandle_t semaph; -static TaskHandle_t net_xchg_task_handle; +static NETConfig net_config; +static eos_net_handler_t net_handler[EOS_NET_MAX_MTYPE]; + +static spi_bus_config_t net_spi_bus_cfg; +static spi_slave_interface_config_t net_spi_iface_cfg; +static spi_slave_transaction_t net_spi_tr_cfg; + static const char *TAG = "EOS NET"; -static eos_net_fptr_t net_handler[EOS_NET_MAX_MTYPE]; +static void bad_handler(unsigned char mtype, unsigned char *buffer, uint16_t buf_len) { + ESP_LOGE(TAG, "bad handler: 0x%.2X len: %d", mtype, buf_len); +} + +static void net_msg_handler(unsigned char mtype, unsigned char *buffer, uint16_t buf_len) { + uint8_t idx; -static void bad_handler(unsigned char mtype, unsigned char *buffer, uint16_t len) { - ESP_LOGE(TAG, "bad handler: %d len: %d", mtype, len); + idx = mtype & EOS_NET_MTYPE_MASK; + if (idx && (idx <= EOS_NET_MAX_MTYPE) && (buf_len <= EOS_NET_MTU)) { + net_handler[idx - 1](mtype, buffer, buf_len); + } else { + bad_handler(mtype, buffer, buf_len); + } } -// Called after a transaction is queued and ready for pickup by master. We use this to set the handshake line high. +/* Called after a transaction is queued and ready for pickup by master */ static void _post_setup_cb(spi_slave_transaction_t *trans) { - gpio_set_level(SPI_GPIO_CTS, 1); + NETConfig *config = trans->user; + + gpio_set_level(config->gpio_cts, 0); } -// Called after transaction is sent/received. We use this to set the handshake line low. +/* Called after transaction is sent/received */ static void _post_trans_cb(spi_slave_transaction_t *trans) { - gpio_set_level(SPI_GPIO_CTS, 0); + NETConfig *config = trans->user; + + gpio_set_level(config->gpio_cts, 1); +} + +static void net_goto_sleep(NETConfig *config) { + esp_err_t ret; + uint8_t msgq_len; + + + xSemaphoreTake(config->mutex, portMAX_DELAY); + msgq_len = eos_msgq_len(config->send_q); + if (msgq_len) { + gpio_set_level(config->gpio_rts, 0); + } else { + gpio_set_level(config->gpio_rts, 1); + } + xSemaphoreGive(config->mutex); + + ret = spi_slave_free(config->spi_host); + assert(ret == ESP_OK); + + /* for deep sleep */ + gpio_hold_en(config->gpio_cts); + + eos_power_sleep_rdy(config->dev); + vTaskSuspend(NULL); + + gpio_hold_dis(config->gpio_cts); + + ret = spi_slave_initialize(config->spi_host, config->spi_bus_cfg, config->spi_iface_cfg, SPI_DMA_CH_AUTO); + assert(ret == ESP_OK); + + xSemaphoreTake(config->mutex, portMAX_DELAY); + config->sleep = 0; + msgq_len = eos_msgq_len(config->send_q); + if (msgq_len) { + gpio_set_level(config->gpio_rts, 0); + } else { + gpio_set_level(config->gpio_rts, 1); + } + xSemaphoreGive(config->mutex); } -static void net_xchg_task(void *pvParameters) { - int wake = 0; - int skip_msg = 0; +void eos_net_xchg_task(void *param) { + NETConfig *config = param; + int present, skip_msg = 0, sleep_msg = 0; unsigned char mtype = 0; unsigned char mtype_flags = 0; unsigned char *buffer; - uint16_t len; unsigned char *buf_send = heap_caps_malloc(SPI_SIZE_BUF, MALLOC_CAP_DMA); unsigned char *buf_recv = heap_caps_malloc(SPI_SIZE_BUF, MALLOC_CAP_DMA); + uint16_t buf_len; + size_t trans_len; + spi_bus_config_t *spi_bus_cfg = config->spi_bus_cfg; + spi_slave_interface_config_t *spi_iface_cfg = config->spi_iface_cfg; + spi_slave_transaction_t *spi_tr_cfg = config->spi_tr_cfg; esp_err_t ret; - static spi_slave_transaction_t spi_tr; - - //Configuration for the SPI bus - static spi_bus_config_t spi_bus_cfg = { - .mosi_io_num = SPI_GPIO_MOSI, - .miso_io_num = SPI_GPIO_MISO, - .sclk_io_num = SPI_GPIO_SCLK - }; - - //Configuration for the SPI slave interface - static spi_slave_interface_config_t spi_slave_cfg = { - .mode = 0, - .spics_io_num = SPI_GPIO_CS, - .queue_size = 2, - .flags = 0, - .post_setup_cb = _post_setup_cb, - .post_trans_cb = _post_trans_cb - }; - - //Initialize SPI slave interface - ret = spi_slave_initialize(VSPI_HOST, &spi_bus_cfg, &spi_slave_cfg, 2); - assert(ret == ESP_OK); - - memset(&spi_tr, 0, sizeof(spi_tr)); - spi_tr.tx_buffer = buf_send; - spi_tr.rx_buffer = buf_recv; - spi_tr.length = SPI_SIZE_BUF * 8; - - if (eos_power_wakeup_cause() != EOS_PWR_WAKE_RST) { - wake = 1; - skip_msg = 1; + assert(buf_send != NULL); + assert(buf_recv != NULL); + + /* Configuration for the SPI bus */ + spi_bus_cfg->mosi_io_num = config->gpio_mosi; + spi_bus_cfg->miso_io_num = config->gpio_miso; + spi_bus_cfg->sclk_io_num = config->gpio_sclk; + + /* Configuration for the SPI slave interface */ + spi_iface_cfg->mode = 0; + spi_iface_cfg->spics_io_num = config->gpio_cs; + spi_iface_cfg->queue_size = 2; + spi_iface_cfg->flags = 0; + spi_iface_cfg->post_setup_cb = _post_setup_cb; + spi_iface_cfg->post_trans_cb = _post_trans_cb; + + spi_tr_cfg->tx_buffer = buf_send; + spi_tr_cfg->rx_buffer = buf_recv; + spi_tr_cfg->length = SPI_SIZE_BUF * 8; + spi_tr_cfg->user = config; + + xSemaphoreTake(config->mutex, portMAX_DELAY); + present = config->present; + xSemaphoreGive(config->mutex); + if (!present) { + vTaskSuspend(NULL); } - eos_power_wait4init(); + /* Initialize SPI slave interface */ + ret = spi_slave_initialize(config->spi_host, spi_bus_cfg, spi_iface_cfg, SPI_DMA_CH_AUTO); + assert(ret == ESP_OK); + while (1) { if (!skip_msg) { - xSemaphoreTake(mutex, portMAX_DELAY); + xSemaphoreTake(config->mutex, portMAX_DELAY); - eos_msgq_pop(&net_send_q, &mtype, &buffer, &len); + eos_msgq_pop(config->send_q, &mtype, &buffer, &buf_len); if (mtype) { buf_send[0] = mtype; - buf_send[1] = len >> 8; - buf_send[2] = len & 0xFF; + buf_send[1] = buf_len >> 8; + buf_send[2] = buf_len & 0xFF; if (buffer) { - memcpy(buf_send + SPI_SIZE_HDR, buffer, len); - eos_bufq_push(&net_buf_q, buffer); - xSemaphoreGive(semaph); + memcpy(buf_send + SPI_SIZE_HDR, buffer, buf_len); + xSemaphoreTake(config->bufq_mutex, portMAX_DELAY); + eos_bufq_push(config->buf_q, buffer); + xSemaphoreGive(config->bufq_mutex); + xSemaphoreGive(config->bufq_semaph); } + } else if (!sleep_msg && config->sleep_req) { + buf_send[0] = EOS_NET_MTYPE_SLEEP; + buf_send[1] = 0; + buf_send[2] = 0; + sleep_msg = 1; + config->sleep_req = 0; + if (config->dev == NET_DEV_NET) config->sleep = 1; } else { - gpio_set_level(SPI_GPIO_RTS, 0); + gpio_set_level(config->gpio_rts, 1); buf_send[0] = 0; buf_send[1] = 0; buf_send[2] = 0; } - xSemaphoreGive(mutex); + xSemaphoreGive(config->mutex); } skip_msg = 0; buf_recv[0] = 0; buf_recv[1] = 0; buf_recv[2] = 0; - spi_slave_transmit(VSPI_HOST, &spi_tr, portMAX_DELAY); - // ESP_LOGI(TAG, "RECV:%d", buf_recv[0]); + ret = spi_slave_transmit(config->spi_host, spi_tr_cfg, portMAX_DELAY); + assert(ret == ESP_OK); + + trans_len = spi_tr_cfg->trans_len / 8; + + ESP_LOGI(TAG, "RECV:0x%.2X DEV:0x%.8lX LEN:%d", buf_recv[0], config->dev, trans_len); + + if (sleep_msg && (config->dev == NET_DEV_NET)) { + net_goto_sleep(config); + sleep_msg = 0; + continue; + } + + if (trans_len < 1) { + ESP_LOGE(TAG, "RECV LEN:%d", trans_len); + continue; + } - if (wake) { - eos_power_net_ready(); - wake = 0; + /* SPI reset */ + if ((trans_len == 1) && (buf_recv[0] == 0)) { + if (buf_send[0]) skip_msg = 1; + continue; } - if ((spi_tr.trans_len / 8) < SPI_SIZE_HDR) continue; - if (buf_recv[0] == 0x00) continue; + mtype = buf_recv[0] & EOS_NET_MTYPE_MASK; + mtype_flags = buf_recv[0] & ~EOS_NET_MTYPE_MASK; + if (buf_send[0] && (mtype_flags & EOS_NET_MTYPE_FLAG_ONEW)) { + skip_msg = 1; + } - if (buf_recv[0] == 0xFF) { // Sleep req - if (buf_send[0] == 0) { - spi_slave_free(VSPI_HOST); - eos_power_sleep(); + if (buf_send[0] && (trans_len < buf_len + SPI_SIZE_HDR) && !skip_msg) { + spi_tr_cfg->tx_buffer = buf_send + trans_len; + spi_tr_cfg->rx_buffer = buf_recv + trans_len; + spi_tr_cfg->length = (SPI_SIZE_BUF - trans_len) * 8; + ret = spi_slave_transmit(config->spi_host, spi_tr_cfg, portMAX_DELAY); + assert(ret == ESP_OK); + trans_len += spi_tr_cfg->trans_len / 8; + spi_tr_cfg->tx_buffer = buf_send; + spi_tr_cfg->rx_buffer = buf_recv; + spi_tr_cfg->length = SPI_SIZE_BUF * 8; + } - xSemaphoreTake(mutex, portMAX_DELAY); - net_sleep = 1; - if (eos_msgq_len(&net_send_q)) net_wake = 1; - xSemaphoreGive(mutex); + if (mtype == 0) continue; - if (net_wake) eos_power_wake(EOS_PWR_WAKE_NETQ); - vTaskSuspend(NULL); + if (mtype == EOS_NET_MTYPE_SLEEP) { + uint8_t mode; - xSemaphoreTake(mutex, portMAX_DELAY); - net_sleep = 0; - net_wake = 0; - xSemaphoreGive(mutex); + mode = EOS_PWR_SMODE_LIGHT; - spi_slave_initialize(VSPI_HOST, &spi_bus_cfg, &spi_slave_cfg, 1); - wake = 1; - skip_msg = 1; + switch (config->dev) { + case NET_DEV_NET: { + eos_power_sleep_req(mode, EOS_PWR_DEV_ALL); + break; + } + case NET_DEV_APP: { + uint8_t msgq_len; + + xSemaphoreTake(config->mutex, portMAX_DELAY); + msgq_len = eos_msgq_len(config->send_q); + if (msgq_len == 0) { + config->sleep = 1; + config->sleep_req = 0; + } + xSemaphoreGive(config->mutex); + if (msgq_len == 0) { + net_goto_sleep(config); + sleep_msg = 0; + } + break; + } } continue; } - mtype = buf_recv[0] & ~EOS_NET_MTYPE_FLAG_MASK; - mtype_flags = buf_recv[0] & EOS_NET_MTYPE_FLAG_MASK; - len = (uint16_t)buf_recv[1] << 8; - len |= (uint16_t)buf_recv[2] & 0xFF; - buffer = buf_recv + SPI_SIZE_HDR; - if ((mtype <= EOS_NET_MAX_MTYPE) && (len <= EOS_NET_MTU)) { - net_handler[mtype - 1](buf_recv[0], buffer, len); - } else { - bad_handler(buf_recv[0], buffer, len); - } - if ((mtype_flags & EOS_NET_MTYPE_FLAG_ONEW) && buf_send[0]) { - skip_msg = 1; + if (trans_len < SPI_SIZE_HDR) { + ESP_LOGE(TAG, "RECV LEN:%d", trans_len); + continue; } + buf_len = (uint16_t)buf_recv[1] << 8; + buf_len |= (uint16_t)buf_recv[2] & 0xFF; + buffer = buf_recv + SPI_SIZE_HDR; + config->msg_handler(buf_recv[0], buffer, buf_len); + if (mtype_flags & EOS_NET_MTYPE_FLAG_REPL) { - spi_tr.tx_buffer = buf_recv; - spi_tr.rx_buffer = NULL; - spi_slave_transmit(VSPI_HOST, &spi_tr, portMAX_DELAY); - spi_tr.tx_buffer = buf_send; - spi_tr.rx_buffer = buf_recv; + spi_tr_cfg->tx_buffer = buf_recv; + spi_tr_cfg->rx_buffer = NULL; + ret = spi_slave_transmit(config->spi_host, spi_tr_cfg, portMAX_DELAY); + assert(ret == ESP_OK); + spi_tr_cfg->tx_buffer = buf_send; + spi_tr_cfg->rx_buffer = buf_recv; } } + vTaskDelete(NULL); } -void eos_net_init(void) { - int i; - - // Configuration for the handshake lines +void _eos_net_init_gpio(NETConfig *config) { + /* Configuration for the handshake lines */ gpio_config_t io_conf = {}; + gpio_set_level(config->gpio_rts, 1); + gpio_set_level(config->gpio_cts, 1); io_conf.intr_type = GPIO_INTR_DISABLE; io_conf.mode = GPIO_MODE_OUTPUT; - io_conf.pull_up_en = 0; - io_conf.pull_down_en = 0; - io_conf.pin_bit_mask = ((uint64_t)1 << SPI_GPIO_CTS); + io_conf.pull_up_en = GPIO_PULLUP_DISABLE; + io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; + io_conf.pin_bit_mask = BIT64(config->gpio_rts) | BIT64(config->gpio_cts); gpio_config(&io_conf); - gpio_set_level(SPI_GPIO_CTS, 0); +} - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_OUTPUT; - io_conf.pull_up_en = 0; - io_conf.pull_down_en = 0; - io_conf.pin_bit_mask = ((uint64_t)1 << SPI_GPIO_RTS); - gpio_config(&io_conf); - gpio_set_level(SPI_GPIO_RTS, 0); +void eos_net_init(void) { + SemaphoreHandle_t mutex; + SemaphoreHandle_t bufq_mutex; + SemaphoreHandle_t bufq_semaph; + int i; eos_msgq_init(&net_send_q, net_sndq_array, EOS_NET_SIZE_SNDQ); eos_bufq_init(&net_buf_q, net_bufq_array, EOS_NET_SIZE_BUFQ); for (i=0; i<EOS_NET_SIZE_BUFQ; i++) { - eos_bufq_push(&net_buf_q, malloc(EOS_NET_SIZE_BUF)); + unsigned char *buffer; + + buffer = malloc(EOS_NET_SIZE_BUF); + assert(buffer != NULL); + eos_bufq_push(&net_buf_q, buffer); } for (i=0; i<EOS_NET_MAX_MTYPE; i++) { net_handler[i] = bad_handler; } - semaph = xSemaphoreCreateCounting(EOS_NET_SIZE_BUFQ, EOS_NET_SIZE_BUFQ); mutex = xSemaphoreCreateBinary(); + assert(mutex != NULL); + bufq_mutex = xSemaphoreCreateBinary(); + assert(bufq_mutex != NULL); + bufq_semaph = xSemaphoreCreateCounting(EOS_NET_SIZE_BUFQ, EOS_NET_SIZE_BUFQ); + assert(bufq_semaph != NULL); + xSemaphoreGive(mutex); - xTaskCreate(&net_xchg_task, "net_xchg", EOS_TASK_SSIZE_NET_XCHG, NULL, EOS_TASK_PRIORITY_NET_XCHG, &net_xchg_task_handle); + xSemaphoreGive(bufq_mutex); + + net_config.sleep = 0; + net_config.sleep_req = 0; + net_config.present = 1; + net_config.dev = NET_DEV_NET; + net_config.gpio_mosi = SPI_GPIO_MOSI; + net_config.gpio_miso = SPI_GPIO_MISO; + net_config.gpio_sclk = SPI_GPIO_SCLK; + net_config.gpio_cs = SPI_GPIO_CS; + net_config.gpio_rts = SPI_GPIO_RTS; + net_config.gpio_cts = SPI_GPIO_CTS; + net_config.spi_host = SPI_HOST; + net_config.spi_bus_cfg = &net_spi_bus_cfg; + net_config.spi_iface_cfg = &net_spi_iface_cfg; + net_config.spi_tr_cfg = &net_spi_tr_cfg; + net_config.mutex = mutex; + net_config.bufq_mutex = bufq_mutex; + net_config.bufq_semaph = bufq_semaph; + net_config.buf_q = &net_buf_q; + net_config.send_q = &net_send_q; + net_config.msg_handler = net_msg_handler; + + _eos_net_init_gpio(&net_config); + + if (esp_reset_reason() == ESP_RST_DEEPSLEEP) { + gpio_hold_dis(net_config.gpio_cts); + } + ESP_LOGI(TAG, "INIT"); } -unsigned char *eos_net_alloc(void) { +void eos_net_run(void) { + BaseType_t rv; + + rv = xTaskCreate(&eos_net_xchg_task, "net_xchg", EOS_TASK_SSIZE_NET, &net_config, EOS_TASK_PRIORITY_NET, &net_config.xchg_task_handle); + assert(rv == pdPASS); + + ESP_LOGI(TAG, "RUN"); +} + +unsigned char *_eos_net_alloc(NETConfig *config) { unsigned char *ret; - xSemaphoreTake(semaph, portMAX_DELAY); - xSemaphoreTake(mutex, portMAX_DELAY); - ret = eos_bufq_pop(&net_buf_q); - xSemaphoreGive(mutex); + xSemaphoreTake(config->bufq_semaph, portMAX_DELAY); + xSemaphoreTake(config->bufq_mutex, portMAX_DELAY); + ret = eos_bufq_pop(config->buf_q); + xSemaphoreGive(config->bufq_mutex); return ret; } +void _eos_net_free(NETConfig *config, unsigned char *buf) { + xSemaphoreTake(config->bufq_mutex, portMAX_DELAY); + eos_bufq_push(config->buf_q, buf); + xSemaphoreGive(config->bufq_semaph); + xSemaphoreGive(config->bufq_mutex); +} + +unsigned char *eos_net_alloc(void) { + return _eos_net_alloc(&net_config); +} + void eos_net_free(unsigned char *buf) { - xSemaphoreTake(mutex, portMAX_DELAY); - eos_bufq_push(&net_buf_q, buf); - xSemaphoreGive(semaph); - xSemaphoreGive(mutex); + _eos_net_free(&net_config, buf); } -int eos_net_send(unsigned char mtype, unsigned char *buffer, uint16_t len) { +int _eos_net_send(NETConfig *config, unsigned char mtype, unsigned char *buffer, uint16_t buf_len) { int rv = EOS_OK; int sleep; - xSemaphoreTake(mutex, portMAX_DELAY); - sleep = net_sleep && !net_wake; - gpio_set_level(SPI_GPIO_RTS, 1); - rv = eos_msgq_push(&net_send_q, mtype, buffer, len); - xSemaphoreGive(mutex); - - if (rv) eos_net_free(buffer); + xSemaphoreTake(config->mutex, portMAX_DELAY); + sleep = config->sleep; + rv = eos_msgq_push(config->send_q, mtype, buffer, buf_len); + if (!rv && !sleep) gpio_set_level(config->gpio_rts, 0); + xSemaphoreGive(config->mutex); - if (sleep) eos_power_wake(EOS_PWR_WAKE_NETQ); + if (!rv && sleep) eos_power_wake(config->dev); + if (rv) _eos_net_free(config, buffer); return rv; } -void eos_net_reply(unsigned char mtype, unsigned char *buffer, uint16_t len) { +int eos_net_send(unsigned char mtype, unsigned char *buffer, uint16_t buf_len) { + return _eos_net_send(&net_config, mtype, buffer, buf_len); +} + +void eos_net_reply(unsigned char mtype, unsigned char *buffer, uint16_t buf_len) { buffer -= SPI_SIZE_HDR; buffer[0] = mtype; - buffer[1] = len >> 8; - buffer[2] = len & 0xFF; + buffer[1] = buf_len >> 8; + buffer[2] = buf_len & 0xFF; } -void eos_net_set_handler(unsigned char mtype, eos_net_fptr_t handler) { - if (handler == NULL) handler = bad_handler; - if (mtype && (mtype <= EOS_NET_MAX_MTYPE)) net_handler[mtype - 1] = handler; -} +void _eos_net_sleep_req(NETConfig *config) { + int sleep, present; + + xSemaphoreTake(config->mutex, portMAX_DELAY); + sleep = config->sleep; + present = config->present; + if (!sleep && present) { + config->sleep_req = 1; + gpio_set_level(config->gpio_rts, 0); + } + xSemaphoreGive(config->mutex); -void eos_net_sleep(void) { - gpio_set_level(SPI_GPIO_CTS, 1); - vTaskDelay(200 / portTICK_PERIOD_MS); - gpio_set_level(SPI_GPIO_CTS, 0); + if (!present) eos_power_sleep_rdy(config->dev); } -void eos_net_wake(uint8_t source, uint8_t mode) { - int sleep; +void _eos_net_wake(NETConfig *config) { + int sleep, present; + + xSemaphoreTake(config->mutex, portMAX_DELAY); + present = config->present; + xSemaphoreGive(config->mutex); - if (mode == EOS_PWR_SMODE_DEEP) return; + if (!present) return; do { - vTaskResume(net_xchg_task_handle); + vTaskResume(config->xchg_task_handle); vTaskDelay(10 / portTICK_PERIOD_MS); - - xSemaphoreTake(mutex, portMAX_DELAY); - sleep = net_sleep; - xSemaphoreGive(mutex); + xSemaphoreTake(config->mutex, portMAX_DELAY); + sleep = config->sleep; + xSemaphoreGive(config->mutex); } while (sleep); } + +void eos_net_sleep_req(void) { + _eos_net_sleep_req(&net_config); +} + +void eos_net_wake(void) { + _eos_net_wake(&net_config); +} + +void eos_net_set_handler(unsigned char mtype, eos_net_handler_t handler) { + if (handler == NULL) handler = bad_handler; + if (mtype && (mtype <= EOS_NET_MAX_MTYPE)) net_handler[mtype - 1] = handler; +} |