/* * ne_device.c -- provide iot-system device layer operation interface. * * * ORIGINAL AUTHOR: * * Copyright (c) 2018 Netease Corporation */ #include "c_types.h" #include "ne_device.h" #include "user_main.h" #include "cfg.h" #include "log.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" #include "freertos/semphr.h" #include "freertos/timers.h" #include "ne_sweeper.h" #include "ne_general.h" #define THIS_NE_DEVICE_CTX &ne_device_ctx #define NE_DEVICE_INIT_MAGIC 0xaabbccdd #define NE_DEVICE_MAX_QUEUE_COUNT 10 #define CONFIG_YANXUAN_SWEEPER_DEVICE #define CONFIG_NE_GENERAL_DEVICE #define NE_DEVICE_MSG_DELAY 5 #define NE_DEVICE_HEALTH_TIME 20*1000 //ms #define NE_DEVICE_INTERVAL_TIME 1 //sec enum{ NE_DEVICE_YANXUAN_SWEEPER, NE_DEVICE_GENERAL, }; typedef struct { uint8 *rbuf; uint32 rlen; uint8 *sbuf; uint32 slen; }ne_device_frame_t; typedef struct ne_device_ctx{ uint32 init; void * timer_handle; void * task_handle; void * queue_handle; ne_device_frame_t frame; ne_device_handler_t *ne_device_handler; }ne_device_ctx_t; static ne_device_ctx_t ne_device_ctx; static ne_device_handler_t ne_device_list[] = { #ifdef CONFIG_YANXUAN_SWEEPER_DEVICE [0] = { .device_init = yanxuan_sweeper_init, .device_deinit = yanxuan_sweeper_deinit, .device_read = yanxuan_sweeper_read, .device_write = yanxuan_sweeper_write, .device_parse = yanxuan_sweeper_process, .device_split = yanxuan_sweeper_split }, #endif #ifdef CONFIG_NE_GENERAL_DEVICE [1] = { .device_init = ne_general_init, .device_deinit = ne_general_deinit, .device_read = ne_general_read, .device_write = ne_general_write, .device_parse = ne_general_process, .device_split = ne_general_split }, #endif }; static uint32 ne_device_health_value; /* * system thread monitor check. */ static int32 ne_device_thread_check(uint32 cur_msec) { if (cur_msec > ne_device_health_value + NE_DEVICE_HEALTH_TIME) { LOG_EX(LOG_Error, "thread is sick! and system restart!\r\n"); system_restart(); return -ERR_FAIL; } return ERR_OK; } /* * system set msec. */ static void ne_device_set_last_msec(uint32 msec) { ne_device_health_value = msec; } /* * system register thread monitor. */ static int32 ne_device_thread_monitor_init(void *handle_name) { ne_device_health_value = ne_os_ticks_ms(xTaskGetTickCount()); return ne_thread_monitor_register(handle_name, NE_DEVICE_INTERVAL_TIME, ne_device_thread_check); } /* * netease get device handle. */ ne_device_handler_t * ne_get_device_handler(uint32 device_id) { return &ne_device_list[device_id]; } /* * netease queue send. */ int ne_device_send_queue(uint8 *data, uint32 len, uint8 msg_dir) { int ret; ne_device_ctx_t *ctx = THIS_NE_DEVICE_CTX; ne_device_msgtype_t msg; if (data == NULL || len == 0) { LOG_EX(LOG_Error,"Message Notify bad len, dir %x\r\n", msg_dir); return; } /* get datas */ msg.data = malloc(len); if (msg.data) { memcpy(msg.data, data, len); } msg.len = len; msg.msg_dir = msg_dir; { int i, len; LOG_EX(LOG_Info,"data len=%d msg_dir=%d\r\n", msg.len, msg_dir); len = msg.len; if (len > 32) len = 32; for(i=0;iqueue_handle, &msg, 0); if(ret != pdTRUE){ LOG_EX(LOG_Error,"send esp_msg_queue fail!\r\n"); } return ret; } /* * netease device frame process. */ void ne_device_frame_process(ne_device_ctx_t *ctx, uint8 *input, uint32 in_len) { int32 msgdir; uint32 offset = 0; while(in_len > offset){ /* frame filter */ msgdir = ctx->ne_device_handler->device_split(NULL, &offset, input , in_len, ctx->frame.rbuf, &ctx->frame.rlen); if(msgdir == MSG_DIRECTION_UART_UP || msgdir == MSG_DIRECTION_BDATA_UP){ /* frame send queue */ ne_device_send_queue(ctx->frame.rbuf, ctx->frame.rlen, msgdir); } LOG_EX(LOG_Info, "device_split offset=%d in_len=%d\r\n", offset, in_len); } ne_adjust_recv_info(offset); } /* * netease device timer polling cb. */ void ne_device_polling_cb(void *arg) { uint8_t *tbuf; int32 ret; uint32 tlen; ne_device_ctx_t *ctx = THIS_NE_DEVICE_CTX; /* read uart datas */ ret = ctx->ne_device_handler->device_read(NULL, &tbuf, &tlen); if(ret == ERR_OK){ LOG_EX(LOG_Info, "polling data tlen=%d\r\n", tlen); if(tbuf == NULL || tlen <= 0) return; /* uart filter and process */ ne_device_frame_process(ctx, tbuf, tlen); } } /* * netease device process. */ void ne_device_process(void * arg) { ne_device_ctx_t *ctx = THIS_NE_DEVICE_CTX; ne_device_msgtype_t msg; /* thread monitor */ ne_device_thread_monitor_init("device_thread"); while(1){ if(xQueueReceive(ctx->queue_handle, &msg, NE_DEVICE_MSG_DELAY) == pdPASS){ /* device parse */ ctx->frame.slen = ctx->ne_device_handler->device_parse(NULL, msg.msg_dir, msg.data, msg.len, ctx->frame.sbuf, NE_DEVICE_BUF_SIZE); if(ctx->frame.slen > 0){ /* send to mcu */ ctx->ne_device_handler->device_write(NULL, ctx->frame.sbuf, ctx->frame.slen); } free(msg.data); } ne_device_set_last_msec(ne_os_ticks_ms(xTaskGetTickCount())); } } /* * netease device process init. */ int32 ne_device_init(void) { uint32 device_type; ne_device_ctx_t *ctx = THIS_NE_DEVICE_CTX; ne_device_handler_t *handle; #if DEVICE_YANXUAN_SWEEPER device_type = NE_DEVICE_YANXUAN_SWEEPER; LOG_EX(LOG_Info, "device init for YANXUAN SWEEPER!\r\n"); #else device_type = NE_DEVICE_GENERAL; LOG_EX(LOG_Info, "device init for NETEASE GENERAL!\r\n"); #endif handle = ne_get_device_handler(device_type); /* interface check */ if(ctx->init == NE_DEVICE_INIT_MAGIC || handle == NULL) return -ERR_FAIL; if(handle->device_init == NULL || handle->device_deinit == NULL || handle->device_read == NULL \ || handle->device_read == NULL || handle->device_parse == NULL || handle->device_split == NULL) return -ERR_FAIL; /* get device driver handle */ memset(ctx, 0 , sizeof(ne_device_ctx_t)); ctx->ne_device_handler = handle; ctx->frame.rbuf = (uint8 *)malloc(NE_DEVICE_BUF_SIZE); ctx->frame.sbuf = (uint8 *)malloc(NE_DEVICE_BUF_SIZE); if(ctx->ne_device_handler->device_init(NULL) != ERR_OK) goto ERR_INIT; ctx->timer_handle = xTimerCreate("uart_time", 40 / portTICK_RATE_MS, pdTRUE, NULL, ne_device_polling_cb); if(ctx->timer_handle != NULL) xTimerStart(ctx->timer_handle, 0); ctx->queue_handle = xQueueCreate(NE_DEVICE_MAX_QUEUE_COUNT, sizeof(ne_device_msgtype_t)); if(ctx->queue_handle == NULL) goto ERR_INIT; xTaskCreate(ne_device_process, "device_process", 256, NULL, tskIDLE_PRIORITY + 1, NULL); goto OK_INIT; ERR_INIT: if(ctx->timer_handle != NULL){ xTimerStop(ctx->timer_handle, 0); xTimerDelete(ctx->timer_handle, 0); } if(ctx->queue_handle != NULL) vQueueDelete(ctx->queue_handle); if(ctx->ne_device_handler->device_deinit != NULL) ctx->ne_device_handler->device_deinit(NULL); LOG_EX(LOG_Info, "device init fail!\r\n"); return -ERR_FAIL; OK_INIT: ctx->init = NE_DEVICE_INIT_MAGIC; LOG_EX(LOG_Info, "device init success.\r\n"); return ERR_OK; }