/* * Copyright (C) 2017 XRADIO TECHNOLOGY CO., LTD. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * 3. Neither the name of XRADIO TECHNOLOGY CO., LTD. nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include "sys/interrupt.h" #include "kernel/os/os.h" #include "atcmd/at_command.h" #include "common/cmd/cmd_util.h" #include "common/cmd/cmd_wlan.h" #include "net/wlan/wlan.h" #include "common/cmd/cmd_ping.h" #include "lwip/inet.h" #include "common/framework/net_ctrl.h" #include "driver/chip/hal_rtc.h" #include "image/fdcm.h" #include "serial.h" #include "lwip/sockets.h" #include "lwip/netdb.h" #include "errno.h" #include "common/framework/sys_ctrl/sys_ctrl.h" #include "common/framework/sysinfo.h" #include "driver/chip/hal_wdg.h" #include "driver/chip/hal_gpio.h" #include "net/wlan/wlan_ext_req.h" #include "lwip/dns.h" #include "ap_socket.h" #include "ota/ota.h" #include "atcmd.h" #include "driver/chip/hal_wakeup.h" #define FUN_DEBUG_ON 0 #if FUN_DEBUG_ON == 1 #define FUN_DEBUG(fmt...) \ do { \ printf("file:%s line:%d ", __FILE__, __LINE__); \ printf(fmt); \ } while (0) #else #define FUN_DEBUG(fmt...) #endif #define MANUFACTURER "XRADIO" #define MODEL "serial-to-wifi" #define SERIAL "01234567" //#define MAC {0x00, 0x11, 0x22, 0x33, 0x44, 0x55} #define CONFIG_FDCM_FLASH (0) #define CONFIG_FDCM_ADDR (0x200000UL - 0x8000UL) #define CONFIG_FDCM_SIZE (0x4000UL) #define CONFIG_CONTAINNER_SIZE sizeof(config_containner_t) #define MAX_SCAN_RESULTS 50 #define MAX_SOCKET_NUM 4 #define IP_ADDR_SIZE 15 #define SOCKET_CACHE_BUFFER_SIZE 1024 #define SERVER_THREAD_STACK_SIZE (2 * 1024) typedef struct { s32 cmd; AT_ERROR_CODE (*handler)(at_callback_para_t *para, at_callback_rsp_t *rsp); } callback_handler_t; typedef struct { u32 cnt; at_config_t cfg; } config_containner_t; typedef struct { char ip[IP_ADDR_SIZE + 1]; char hostname[AT_PARA_MAX_SIZE]; at_text_t type[4]; u32 port; s32 protocol; // 1:TCP , 2:UDP s32 fd; u32 flag; u32 ThreadHd; } connect_t; typedef struct { s32 count; connect_t connect[MAX_SOCKET_NUM]; } network_t; typedef struct { s32 mode; //0:no connections 1: sta connections 2:ap connections } system_status_t; typedef struct { u32 flag; s32 offset; s32 cnt; u8 buffer[SOCKET_CACHE_BUFFER_SIZE]; } socket_cache_t; typedef struct { s16 port; s32 protocol; } server_arg_t; typedef struct { u32 flag; /* 0: disconnect 1: connect */ s32 sock_fd; s32 conn_fd; } server_net_t; typedef struct { u32 flag; s16 port; s32 protocol; s32 conn_fd; } server_ctrl_t; static socket_cache_t socket_cache[MAX_SOCKET_NUM + 1]; static OS_Thread_t g_server_thread; static OS_Mutex_t g_server_mutex; static server_arg_t g_server_arg; static server_net_t g_server_net; static server_ctrl_t g_server_ctrl; static u32 g_errorcode = 0; static network_t networks; static u32 g_server_enable = 0; static OS_Semaphore_t g_server_sem; static uint16_t net_evevt_state = NET_CTRL_MSG_NETWORK_DOWN; int is_disp_ipd = 1; enum atc_cwjap_cur_type { ATC_CWJAP_CUR_OK = 0, ATC_CWJAP_CUR_TIMEOUT = '1', ATC_CWJAP_CUR_PSK_INVALID = '2', ATC_CWJAP_CUR_SSID_NOMATCH = '3', }; static AT_ERROR_CODE callback(AT_CALLBACK_CMD cmd, at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE act(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE reset(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE mode(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE save(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE load(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE status(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE factory(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE peer(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE ping(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE sockon(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE sockw(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE sockq(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE sockr(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE sockc(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE sockd(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE wifi(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE reassociate(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE gpioc(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE gpior(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE gpiow(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE scan(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE version(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE restory(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE uart_def(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE sleep(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE wakeupgpio(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE cwmode_cur(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE cwjap_cur(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE cwjap_info(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE cwlapopt(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE cwlap(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE cwqap(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE cwdhcp_cur(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE cipstamac_cur(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE cipsta_cur(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE cwhostname(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE set_apcfg(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE cipstatus(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE cipdomain(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE cipstart(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE cipsendbuf(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE cipclose(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE tcpserver(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE tcpservermaxconn(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE cipmux(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE cipmode(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE cipdns_cur(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE ciprecvdata(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE ciprecvmode(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE cipsend(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE sysiosetcfg(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE sysiogetcfg(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE syssetiodir(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE syssetgpio(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE sysreadgpio(at_callback_para_t *para, at_callback_rsp_t *rsp); static AT_ERROR_CODE httpota(at_callback_para_t *para, at_callback_rsp_t *rsp); static const callback_handler_t callback_tbl[] = { {ACC_ACT, act}, {ACC_RST, reset}, {ACC_MODE, mode}, {ACC_SAVE, save}, {ACC_LOAD, load}, {ACC_STATUS, status}, {ACC_FACTORY, factory}, {ACC_PEER, peer}, {ACC_PING, ping}, {ACC_SOCKON, sockon}, {ACC_SOCKW, sockw}, {ACC_SOCKQ, sockq}, {ACC_SOCKR, sockr}, {ACC_SOCKC, sockc}, {ACC_SOCKD, sockd}, {ACC_WIFI, wifi}, {ACC_REASSOCIATE, reassociate}, {ACC_GPIOC, gpioc}, {ACC_GPIOR, gpior}, {ACC_GPIOW, gpiow}, {ACC_SCAN, scan}, {ACC_CIPSTATUS, cipstatus}, {ACC_GMR, version}, {ACC_RESTORE, restory}, {ACC_UART_DEF, uart_def}, {ACC_SLEEP, sleep}, {ACC_WAKEUPGPIO, wakeupgpio}, {ACC_CWMODE_CUR, cwmode_cur}, {ACC_CWJAP_CUR, cwjap_cur}, {ACC_CWJAP_INFO, cwjap_info}, {ACC_CWLAPOPT, cwlapopt}, {ACC_CWLAP, cwlap}, {ACC_CWQAP, cwqap}, {ACC_CWDHCP_CUR, cwdhcp_cur}, {ACC_CIPSTAMAC_CUR, cipstamac_cur}, {ACC_CIPSTA_CUR, cipsta_cur}, {ACC_CWHOSTNAME, cwhostname}, {ACC_APCFG, set_apcfg}, {ACC_CIPDOMAIN, cipdomain}, {ACC_CIPSTART, cipstart}, {ACC_CIPSENDBUF, cipsendbuf}, {ACC_CIPCLOSE, cipclose}, {ACC_TCPSERVER, tcpserver}, {ACC_TCPSERVERMAXCONN, tcpservermaxconn}, {ACC_CIPMUX, cipmux}, {ACC_CIPMODE, cipmode}, {ACC_CIPDNS_CUR, cipdns_cur}, {ACC_CIPRECVDATA, ciprecvdata}, {ACC_CIPRECVMODE, ciprecvmode}, {ACC_CIPSEND, cipsend}, {ACC_SYSIOSETCFG, sysiosetcfg}, {ACC_SYSIOGETCFG, sysiogetcfg}, {ACC_SYSGPIODIR, syssetiodir}, {ACC_SYSGPIOWRITE, syssetgpio}, {ACC_SYSGPIOREAD, sysreadgpio}, {ACC_HTTPOTA, httpota}, }; static const u32 channel_freq_tbl[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462, 2467, 2472 }; static const char *event[] = { "wlan connected", "wlan disconnected", "wlan scan success", "wlan scan failed", "wlan 4way handshake failed", "wlan connect failed", "wlan connect loss", "network up", "network down", }; static const fdcm_handle_t fdcm_hdl_tbl[] = { {CONFIG_FDCM_FLASH, CONFIG_FDCM_ADDR, CONFIG_FDCM_SIZE}, {CONFIG_FDCM_FLASH, CONFIG_FDCM_ADDR - CONFIG_FDCM_SIZE, CONFIG_FDCM_SIZE} }; /* factory default */ static const at_config_t default_cfg = { .blink_led = 0, .wind_off_low = 0x0, .wind_off_medium = 0x0, .wind_off_high = 0x0, .user_desc = "XRADIO-AP", .escape_seq = "at+s.", .localecho1 = 0, .console1_speed = 115200, .console1_hwfc = 0, .console1_enabled = 0, .sleep_enabled = 0, .standby_enabled = 0, .standby_time = 10, .wifi_tx_msdu_lifetime = 0, .wifi_rx_msdu_lifetime = 0, .wifi_operational_mode = 0x00000011, .wifi_beacon_wakeup = 1, .wifi_beacon_interval = 100, .wifi_listen_interval = 0, .wifi_rts_threshold = 3000, .wifi_ssid = "iot-ap", .wifi_ssid_len = 6, .wifi_channelnum = 6, .wifi_opr_rate_mask = 0xFFFFFFFF, .wifi_bas_rate_mask = 0x0000000F, .wifi_mode = 1, .wifi_auth_type = 0, .wifi_powersave = 1, .wifi_tx_power = 18, .wifi_rssi_thresh = -50, .wifi_rssi_hyst = 10, .wifi_ap_idle_timeout = 120, .wifi_beacon_loss_thresh = 10, .wifi_priv_mode = 2, /*.wifi_wep_keys[4][16], */ /*.wifi_wep_key_lens[4], */ .wifi_wep_default_key = 0, /*.wifi_wpa_psk_raw[32], */ /*.wifi_wpa_psk_text[64], */ .ip_use_dhcp = 1, .ip_use_httpd = 1, .ip_mtu = 1500, .ip_hostname = "xr-iot-dev", .ip_apdomainname = "xradio.com", .ip_ipaddr = {192, 168, 0, 123}, .ip_netmask = {255, 255, 255, 0}, .ip_gw = {192, 168, 0, 1}, .ip_dns = {192, 168, 0, 1}, .ip_http_get_recv_timeout = 1000, .ip_dhcp_timeout = 20, .ip_sockd_timeout = 250, }; static __always_inline int server_is_isr_context(void) { return __get_IPSR(); } static void server_mutex_lock(void) { if (server_is_isr_context() || !OS_ThreadIsSchedulerRunning()) { return; } if (OS_MutexIsValid(&g_server_mutex)) { OS_RecursiveMutexLock(&g_server_mutex, OS_WAIT_FOREVER); } else { OS_RecursiveMutexCreate(&g_server_mutex); OS_RecursiveMutexLock(&g_server_mutex, OS_WAIT_FOREVER); } } static void server_mutex_unlock(void) { if (server_is_isr_context() || !OS_ThreadIsSchedulerRunning()) { return; } if (OS_MutexIsValid(&g_server_mutex)) { OS_RecursiveMutexUnlock(&g_server_mutex); } } u32 at_get_errorcode(void) { return g_errorcode; } s32 at_cmdline(char *buf, u32 size) { u32 i; for (i = 0; i < size; i++) { if (buf[i] == AT_LF) { return i + 1; } else if (buf[i] == AT_CR) { if (((i + 1) < size) && (buf[i + 1] == AT_LF)) { return i + 2; } else { return i + 1; } } } return -1; } static u8 queue_buf[1024 + 4]; void occur(uint32_t evt, uint32_t data, void *arg); static void at_wakeup_pin_irq_cb(void *arg) { printf("SYSTE wake up!\r\n"); } static int wkgpio_pins[] = { GPIO_PIN_4, GPIO_PIN_5, GPIO_PIN_6, GPIO_PIN_7, GPIO_PIN_7, GPIO_PIN_19, GPIO_PIN_20, GPIO_PIN_21, GPIO_PIN_22, GPIO_PIN_23 }; void at_wakeup_gpio_init(int gpioId, int edge) { GPIO_InitParam param; GPIO_IrqParam Irq_param; if (edge == 1) { param.driving = GPIO_DRIVING_LEVEL_1; param.pull = GPIO_PULL_DOWN; param.mode = GPIOx_Pn_F6_EINT; HAL_GPIO_Init(GPIO_PORT_A, wkgpio_pins[gpioId], ¶m); Irq_param.event = GPIO_IRQ_EVT_RISING_EDGE; Irq_param.callback = at_wakeup_pin_irq_cb; Irq_param.arg = (void *)NULL; HAL_GPIO_EnableIRQ(GPIO_PORT_A, wkgpio_pins[gpioId], &Irq_param); HAL_Wakeup_SetIO(gpioId, WKUPIO_WK_MODE_RISING_EDGE, GPIO_PULL_DOWN); } else if (edge == 0) { param.driving = GPIO_DRIVING_LEVEL_1; param.pull = GPIO_PULL_UP; param.mode = GPIOx_Pn_F6_EINT; HAL_GPIO_Init(GPIO_PORT_A, wkgpio_pins[gpioId], ¶m); Irq_param.event = GPIO_IRQ_EVT_FALLING_EDGE; Irq_param.callback = at_wakeup_pin_irq_cb; Irq_param.arg = (void *)NULL; HAL_GPIO_EnableIRQ(GPIO_PORT_A, wkgpio_pins[gpioId], &Irq_param); HAL_Wakeup_SetIO(gpioId, WKUPIO_WK_MODE_FALLING_EDGE, GPIO_PULL_UP); } } void at_cmd_init(void) { at_callback_t at_cb; at_wakeup_gpio_init(5, 0); at_queue_init(queue_buf, sizeof(queue_buf), serial_read); at_cb.handle_cb = callback; at_cb.dump_cb = serial_write; at_init(&at_cb); observer_base *obs = sys_callback_observer_create(CTRL_MSG_TYPE_NETWORK, NET_CTRL_MSG_ALL, occur, NULL); sys_ctrl_attach(obs); } void at_cmd_reinit(void) { at_callback_t at_cb; at_queue_init(queue_buf, sizeof(queue_buf), serial_read); at_cb.handle_cb = callback; at_cb.dump_cb = serial_write; at_init(&at_cb); } void at_cmd_exec(void) { at_parse(); } static AT_ERROR_CODE callback(AT_CALLBACK_CMD cmd, at_callback_para_t *para, at_callback_rsp_t *rsp) { s32 i; FUN_DEBUG("callback cmd = %d\n", cmd); for (i = 0; i < TABLE_SIZE(callback_tbl); i++) { if (cmd == callback_tbl[i].cmd) { if (callback_tbl[i].handler != NULL) { return callback_tbl[i].handler(para, rsp); } else { /* FUN_DEBUG("callback cmd = %d is unimplimented!\n", cmd); */ return AEC_UNDEFINED; } } } FUN_DEBUG("callback cmd = %d is unsupported!\n", cmd); return AEC_UNSUPPORTED; } static AT_ERROR_CODE act(at_callback_para_t *para, at_callback_rsp_t *rsp) { AT_ERROR_CODE aec = AEC_OK; uint8_t ap_ssid[32 + 1]; uint8_t ap_psk[] = "12345678"; switch (para->cfg->wifi_mode) { case 0: /* IDLE */ net_switch_mode(WLAN_MODE_STA); wlan_sta_disable(); break; case 1: /* STA */ net_switch_mode(WLAN_MODE_STA); wlan_sta_set(para->cfg->wifi_ssid, para->cfg->wifi_ssid_len, (uint8_t *) para->cfg->wifi_wpa_psk_text); wlan_sta_enable(); break; case 2: /* AP */ net_switch_mode(WLAN_MODE_HOSTAP); wlan_ap_disable(); snprintf((char *)ap_ssid, 32, "xr-ap-%02x%02x%02x", para->cfg->nv_wifi_macaddr[3], para->cfg->nv_wifi_macaddr[4], para->cfg->nv_wifi_macaddr[5]); wlan_ap_set(ap_ssid, strlen((char *)ap_ssid), ap_psk); wlan_ap_enable(); break; #if 0 case 3: /* IBSS */ break; #endif default: aec = AEC_PARA_ERROR; break; } return aec; } static AT_ERROR_CODE reset(at_callback_para_t *para, at_callback_rsp_t *rsp) { AT_ERROR_CODE aec = AEC_OK; at_dump("\r\nOK\r\n"); OS_MSleep(2); HAL_WDG_Reboot(); return aec; } static AT_ERROR_CODE mode(at_callback_para_t *para, at_callback_rsp_t *rsp) { AT_ERROR_CODE res = AEC_OK; s32 id; u8 *buffer; s32 len; s32 timeout_ms = 10; fd_set fdset_r, fdset_w; int fd; struct sockaddr_in address; socklen_t addr_len; char ip[IP_ADDR_SIZE + 1]; s16 port; s32 protocol; if (!g_server_enable) { /* as client */ id = 0; fd = networks.connect[id].fd; protocol = networks.connect[id].protocol; port = networks.connect[id].port; strncpy(ip, networks.connect[id].ip, sizeof(ip)); if (networks.count > 0) { if (networks.connect[id].flag) { int rc = -1; struct timeval tv; FD_ZERO(&fdset_w); FD_ZERO(&fdset_r); FD_SET(fd, &fdset_w); FD_SET(fd, &fdset_r); tv.tv_sec = timeout_ms / 1000; tv.tv_usec = (timeout_ms % 1000) * 1000; rc = select(fd + 1, &fdset_r, NULL, NULL, &tv); if (rc > 0) { if (FD_ISSET(fd, &fdset_r)) { buffer = socket_cache[id].buffer; len = SOCKET_CACHE_BUFFER_SIZE; if (protocol == 0) { /* TCP */ rc = recv(fd, buffer, len, 0); } else if (protocol == 1) { /* UDP */ address.sin_port = htons(port); address.sin_family = AF_INET; address.sin_addr.s_addr = inet_addr(ip); addr_len = sizeof(address); rc = recvfrom(fd, buffer, len, 0, (struct sockaddr *)&address, &addr_len); } if (rc > 0) { /* received normally */ serial_write(buffer, rc); } else if (rc == 0) { /* has disconnected with server */ res = AEC_DISCONNECT; } else { /* network error */ res = AEC_NETWORK_ERROR; } } } else if (rc == 0) { /* timeouted and sent 0 bytes */ } else { /* network error */ res = AEC_NETWORK_ERROR; } rc = select(fd + 1, NULL, &fdset_w, NULL, &tv); if (rc > 0) { if (FD_ISSET(fd, &fdset_w)) { buffer = para->u.mode.buf; len = para->u.mode.len; if (buffer != NULL && len > 0) { if (protocol == 0) { /* TCP */ rc = send(fd, buffer, len, 0); } else if (protocol == 1) { /* UDP */ address.sin_port = htons(port); address.sin_family = AF_INET; address.sin_addr.s_addr = inet_addr(ip); addr_len = sizeof(address); rc = sendto(fd, buffer, len, 0, (struct sockaddr *)&address, sizeof(address)); } if (rc > 0) { /* do nothing */ } else if (rc == 0) { /* disconnected with server */ res = AEC_DISCONNECT; } else { /* network error */ res = AEC_NETWORK_ERROR; } } } } else if (rc == 0) { /* timeouted and sent 0 bytes */ } else { /* network error */ res = AEC_NETWORK_ERROR; } } else { res = AEC_SWITCH_MODE; } } else { res = AEC_SWITCH_MODE; } } else { /* as server */ if (!g_server_ctrl.flag) { g_server_ctrl.protocol = g_server_arg.protocol; server_mutex_lock(); g_server_ctrl.conn_fd = g_server_net.conn_fd; g_server_ctrl.flag = g_server_net.flag; server_mutex_unlock(); } if (g_server_ctrl.flag) { int rc = -1; struct timeval tv; port = g_server_ctrl.port; protocol = g_server_ctrl.protocol; fd = g_server_ctrl.conn_fd; FD_ZERO(&fdset_w); FD_ZERO(&fdset_r); FD_SET(fd, &fdset_w); FD_SET(fd, &fdset_r); tv.tv_sec = timeout_ms / 1000; tv.tv_usec = (timeout_ms % 1000) * 1000; rc = select(fd + 1, &fdset_r, NULL, NULL, &tv); if (rc > 0) { if (FD_ISSET(fd, &fdset_r)) { buffer = socket_cache[MAX_SOCKET_NUM].buffer; len = SOCKET_CACHE_BUFFER_SIZE; if (protocol == 0) { /* TCP */ rc = recv(fd, buffer, len, 0); } else if (protocol == 1) { /* UDP */ address.sin_port = htons(port); address.sin_family = AF_INET; address.sin_addr.s_addr = inet_addr(ip); addr_len = sizeof(address); rc = recvfrom(fd, buffer, len, 0, (struct sockaddr *)&address, &addr_len); } if (rc > 0) { /* received normally */ serial_write(buffer, rc); } else if (rc == 0) { /* has disconnected with server */ if (protocol == 0) { /* TCP */ server_mutex_lock(); g_server_net.conn_fd = -1; g_server_net.flag = 0; server_mutex_unlock(); OS_SemaphoreRelease(&g_server_sem); g_server_ctrl.flag = 0; } res = AEC_DISCONNECT; } else { /* network error */ res = AEC_NETWORK_ERROR; } } } else if (rc == 0) { /* timeouted and sent 0 bytes */ } else { /* network error */ res = AEC_NETWORK_ERROR; } rc = select(fd + 1, NULL, &fdset_w, NULL, &tv); if (rc > 0) { if (FD_ISSET(fd, &fdset_w)) { buffer = para->u.mode.buf; len = para->u.mode.len; if (buffer != NULL && len > 0) { if (protocol == 0) { /* TCP */ rc = send(fd, buffer, len, 0); } else if (protocol == 1) { /* UDP */ FUN_DEBUG("Unsupported!\n"); } if (rc > 0) { /* do nothing */ } else if (rc == 0) { /* disconnected with server */ res = AEC_DISCONNECT; } else { /* network error */ res = AEC_NETWORK_ERROR; } } } } else if (rc == 0) { /* timeouted and sent 0 bytes */ } else { /* network error */ res = AEC_NETWORK_ERROR; } } else { res = AEC_DISCONNECT; } } return res; } static AT_ERROR_CODE save(at_callback_para_t *para, at_callback_rsp_t *rsp) { config_containner_t *containner; s32 i; fdcm_handle_t *fdcm_hdl; u32 flag[2]; s32 idx, cnt; containner = (config_containner_t *)malloc(2*sizeof(config_containner_t)); if (containner == NULL) { FUN_DEBUG("malloc faild.\n"); return AEC_NOT_ENOUGH_MEMORY; } for (i = 0; i < TABLE_SIZE(fdcm_hdl_tbl); i++) { flag[i] = 1; fdcm_hdl = fdcm_open(fdcm_hdl_tbl[i].flash, fdcm_hdl_tbl[i].addr, fdcm_hdl_tbl[i].size); if (fdcm_hdl == NULL) { FUN_DEBUG("fdcm_open faild.\n"); free(containner); return AEC_UNDEFINED; } if (fdcm_read(fdcm_hdl, &containner[i], CONFIG_CONTAINNER_SIZE) != CONFIG_CONTAINNER_SIZE) { flag[i] = 0; } fdcm_close(fdcm_hdl); } if (flag[0] && flag[1]) { if (containner[0].cnt > containner[1].cnt) { idx = 1; cnt = containner[0].cnt; } else { idx = 0; cnt = containner[1].cnt; } } else if (flag[0]) { idx = 1; cnt = containner[0].cnt; } else if (flag[1]) { idx = 0; cnt = containner[1].cnt; } else { idx = 0; cnt = 0; } fdcm_hdl = fdcm_open(fdcm_hdl_tbl[idx].flash, fdcm_hdl_tbl[idx].addr, fdcm_hdl_tbl[idx].size); if (fdcm_hdl == NULL) { FUN_DEBUG("fdcm_open faild.\n"); free(containner); return AEC_UNDEFINED; } containner[idx].cnt = cnt + 1; memcpy(&containner[idx].cfg, para->cfg, sizeof(at_config_t)); if (fdcm_write(fdcm_hdl, &containner[idx], CONFIG_CONTAINNER_SIZE) != CONFIG_CONTAINNER_SIZE) { FUN_DEBUG("fdcm_write faild.\n"); fdcm_close(fdcm_hdl); free(containner); return AEC_UNDEFINED; } fdcm_close(fdcm_hdl); free(containner); return AEC_OK; } static AT_ERROR_CODE load(at_callback_para_t *para, at_callback_rsp_t *rsp) { config_containner_t *containner; s32 i; fdcm_handle_t *fdcm_hdl; u32 flag[2]; s32 idx; containner = (config_containner_t *)malloc(2*sizeof(config_containner_t)); if (containner == NULL) { FUN_DEBUG("malloc faild.\n"); free(containner); return AEC_UNDEFINED; } for (i = 0; i < TABLE_SIZE(fdcm_hdl_tbl); i++) { flag[i] = 1; fdcm_hdl = fdcm_open(fdcm_hdl_tbl[i].flash, fdcm_hdl_tbl[i].addr, fdcm_hdl_tbl[i].size); if (fdcm_hdl == NULL) { FUN_DEBUG("fdcm_open faild.\n"); free(containner); return AEC_UNDEFINED; } if (fdcm_read(fdcm_hdl, &containner[i], CONFIG_CONTAINNER_SIZE) != CONFIG_CONTAINNER_SIZE) { flag[i] = 0; } fdcm_close(fdcm_hdl); } if (flag[0] && flag[1]) { if (containner[0].cnt > containner[1].cnt) { idx = 0; } else { idx = 1; } } else if (flag[0]) { idx = 0; } else if (flag[1]) { idx = 1; } else { FUN_DEBUG("load fiald.\n"); free(containner); return AEC_UNDEFINED; } memcpy(para->cfg, &containner[idx].cfg, sizeof(at_config_t)); free(containner); return AEC_OK; } static AT_ERROR_CODE status(at_callback_para_t *para, at_callback_rsp_t *rsp) { struct netif *nif = wlan_netif_get(WLAN_MODE_NONE); s32 i; memset(para->sts, 0, sizeof(*para->sts)); if (nif == NULL) { return AEC_UNDEFINED; } if (NET_IS_IP4_VALID(nif) && netif_is_link_up(nif)) { memcpy(para->sts->ip_ipaddr, &nif->ip_addr, 4); memcpy(para->sts->ip_gw, &nif->gw, 4); memcpy(para->sts->ip_netmask, &nif->netmask, 4); } para->sts->current_time = time(NULL); para->sts->ip_sock_open = 0; for (i = 0; i < MAX_SOCKET_NUM; i++) { if (networks.connect[i].flag) { para->sts->ip_sock_open |= (1 << i); } } if (g_server_enable) { para->sts->ip_sockd_port = g_server_arg.port; } wlan_ap_sta_num(¶->sts->wifi_num_assoc); return AEC_OK; } static AT_ERROR_CODE factory(at_callback_para_t *para, at_callback_rsp_t *rsp) { struct sysinfo *psysinfo; memcpy(para->cfg, &default_cfg, sizeof(at_config_t)); /* non-volatile config */ strcpy(para->cfg->nv_manuf, MANUFACTURER); strcpy(para->cfg->nv_model, MODEL); strcpy(para->cfg->nv_serial, SERIAL); #if PRJCONF_SYSINFO_SAVE_TO_FLASH sysinfo_load(); #endif psysinfo = sysinfo_get(); memcpy(para->cfg->nv_wifi_macaddr, psysinfo->mac_addr, sizeof(para->cfg->nv_wifi_macaddr)); save(para, NULL); return AEC_OK; } uint16_t net_get_status(void) { return net_evevt_state; } extern s32 test_ping(char *hostname, int count); static AT_ERROR_CODE ping(at_callback_para_t *para, at_callback_rsp_t *rsp) { test_ping(para->u.ping.hostname, 3); return AEC_OK; } static AT_ERROR_CODE peer(at_callback_para_t *para, at_callback_rsp_t *rsp) { return AEC_OK; } static AT_ERROR_CODE disconnect(s32 id) { at_dump("+IPS:%d,-1\r\n", id); FUN_DEBUG("disconnect id = %d!\n", id); if (networks.connect[id].flag) { networks.connect[id].flag = 0; OS_MSleep(200); closesocket(networks.connect[id].fd); FUN_DEBUG("disconnect closesocket id = %d!\n", id); networks.connect[id].fd = -1; networks.connect[id].flag = 0; networks.count--; return AEC_OK; } return AEC_DISCONNECT; } static OS_Thread_t OS_Thread_sockon_handler; static OS_Queue_t OS_queue_sockon_handler; extern void at_response(AT_ERROR_CODE aec); AT_ERROR_CODE socket_task_create(at_callback_para_t *para); typedef struct { at_callback_para_t para; at_callback_rsp_t rsp; } at_sockontask_para_t; at_sockontask_para_t sockontask_data; static void sockon_task(void *arg) { AT_ERROR_CODE ret; OS_Status status; at_sockontask_para_t sockpara; while (1) { status = OS_QueueReceive(&OS_queue_sockon_handler, &sockpara, OS_WAIT_FOREVER); if (status == OS_OK) { ret = sockon(&sockpara.para, &sockpara.rsp); if (AEC_OK == ret) { ret = socket_task_create(&sockpara.para); } if (AEC_SOCKET_EXISTING == ret) { at_dump("socket%d is ALREADY CONNECT\r\n", sockpara.para.u.sockon.fd); } if (AEC_OK == ret) { at_dump("+IPS:%d,0\n", sockpara.para.u.sockon.fd); } else { at_dump("+IPS:%d,-1\n", sockpara.para.u.sockon.fd); } ret = AEC_UNDEFINED; memset(&sockpara, 0, sizeof(at_sockontask_para_t)); } } } int connect_timeout(int sockfd, const struct sockaddr *addr, socklen_t addrlen, struct timeval *timeout) { int flags = fcntl(sockfd, F_GETFL, 0); if (flags == -1) { return -1; } if (fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) < 0) { return -1; } int status = connect(sockfd, addr, addrlen); if (status == 0) { return 1; } if (status == -1 && errno != EINPROGRESS) { return -1; } //fd_set read_events; fd_set write_events; FD_ZERO(&write_events); FD_SET(sockfd, &write_events); int error = -1; socklen_t len = sizeof(int); int rc = select(sockfd + 1, NULL, &write_events, NULL, timeout); if (rc > 0) { if (FD_ISSET(sockfd, &write_events)) { if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) >= 0) { if (error == 0) return 1; } } } return -1; } static AT_ERROR_CODE sockon(at_callback_para_t *para, at_callback_rsp_t *rsp) { int type; int family; struct addrinfo hints_tcp = {0, AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, NULL, NULL, NULL }; struct addrinfo hints_udp = {0, AF_INET, SOCK_DGRAM, IPPROTO_UDP, 0, NULL, NULL, NULL }; int rc = -1; struct sockaddr_in address; struct addrinfo *result = NULL; s32 id = -1; int fd = 0; int socketid = para->u.net_param.linkId; rsp->status = 0; if (socketid >= 4) return AEC_PARA_ERROR; if (networks.connect[socketid].flag) { sprintf(rsp->vptr, "ALREADY CONNECT"); rsp->type = 1; rsp->status = 1; return AEC_SOCKET_EXISTING; } strncpy(networks.connect[socketid].type, para->u.net_param.type, 4); /* if (networks.connect[socketid].fd != -1) { return AEC_SOCKET_FAIL; } */ strncpy(networks.connect[socketid].ip, para->u.net_param.hostname, IP_ADDR_SIZE); networks.connect[socketid].port = para->u.net_param.port; if (strcmp(para->u.net_param.networkType, "TCP") == 0) { networks.connect[socketid].protocol = 0; } else if (strcmp(para->u.net_param.networkType, "UDP") == 0) { networks.connect[socketid].protocol = 1; } else { return AEC_PARA_ERROR; } if (networks.connect[socketid].protocol == 0) { /* TCP */ type = SOCK_STREAM; family = AF_INET; rc = getaddrinfo(networks.connect[socketid].ip, NULL, &hints_tcp, &result); if (rc == 0) { struct addrinfo *res = result; while (res) { if (res->ai_family == family) { result = res; break; } res = res->ai_next; } if (result->ai_family == family) { address.sin_port = htons(networks.connect[socketid].port); address.sin_family = family; address.sin_addr = ((struct sockaddr_in *)(result->ai_addr))->sin_addr; } else rc = -1; freeaddrinfo(result); } if (rc == 0) { fd = socket(family, type, 0); if (fd < 0) return AEC_SOCKET_FAIL; struct timeval tv = { 8, 0 }; rc = connect_timeout(fd, (struct sockaddr *)&address, sizeof(address), &tv); // use timeout mode //rc = connect(fd, (struct sockaddr *)&address, sizeof(address)); // no use timeout mode if (rc < 0) { closesocket(fd); return AEC_CONNECT_FAIL; } } else { return AEC_CONNECT_FAIL; } networks.connect[socketid].fd = fd; networks.connect[socketid].flag = 1; networks.count++; memset(&socket_cache[socketid], 0, sizeof(socket_cache_t)); rsp->type = 0; return AEC_OK; } else if (networks.connect[socketid].protocol == 1) { /* UDP */ type = SOCK_DGRAM; family = AF_INET; rc = getaddrinfo(networks.connect[socketid].ip, NULL, &hints_udp, &result); if (rc == 0) { struct addrinfo *res = result; while (res) { if (res->ai_family == family) { result = res; FUN_DEBUG("sockon UDP getaddrinfo aifamily!\n"); break; } res = res->ai_next; } if (result->ai_family == family) { address.sin_port = htons(networks.connect[socketid].port); address.sin_family = family; address.sin_addr.s_addr = htonl(INADDR_ANY); } else rc = -1; freeaddrinfo(result); } if (rc == 0) { fd = socket(family, type, 0); if (fd < 0) return AEC_SOCKET_FAIL; /* for receive */ FUN_DEBUG("sockon UDP bind address prot = %d!\n", networks.connect[socketid].port); rc = bind(fd, (struct sockaddr *)&address, sizeof(address)); if (rc < 0) { closesocket(fd); return AEC_BIND_FAIL; } } else { return AEC_BIND_FAIL; } networks.connect[socketid].fd = fd; networks.connect[socketid].flag = 1; networks.count++; memset(&socket_cache[socketid], 0, sizeof(socket_cache_t)); rsp->type = 0; rsp->vptr = (void *)id; return AEC_OK; } return AEC_CMD_FAIL; } static AT_ERROR_CODE sockw(at_callback_para_t *para, at_callback_rsp_t *rsp) { s32 id; u8 *buffer; s32 len; struct sockaddr_in address; s32 timeout_ms = 10; int sentLen = 0; id = para->u.sockw.id; buffer = para->u.sockw.buf; len = para->u.sockw.len; if (networks.count > 0) { if (networks.connect[id].flag) { if (networks.connect[id].protocol == 0) { /* TCP */ int rc = -1; fd_set fdset; struct timeval tv; FD_ZERO(&fdset); FD_SET(networks.connect[id].fd, &fdset); tv.tv_sec = timeout_ms / 1000; tv.tv_usec = (timeout_ms % 1000) * 1000; rc = select(networks.connect[id].fd + 1, NULL, &fdset, NULL, &tv); if (rc > 0) { rc = send(networks.connect[id].fd, buffer, len, 0); if (rc > 0) sentLen = rc; else if (rc == 0) { disconnect(id); sentLen = -1; /* disconnected with server */ } else { sentLen = -2; /* network error */ } } else if (rc == 0) { sentLen = 0; /* timeouted and sent 0 bytes */ } else { sentLen = -2; /* network error */ } } else if (networks.connect[id].protocol == 1) { /* UDP */ int rc = -1; fd_set fdset; struct timeval tv; FD_ZERO(&fdset); FD_SET(networks.connect[id].fd, &fdset); tv.tv_sec = timeout_ms / 1000; tv.tv_usec = (timeout_ms % 1000) * 1000; address.sin_port = htons(networks.connect[id].port); address.sin_family = AF_INET; address.sin_addr.s_addr = inet_addr(networks.connect[id].ip); rc = select(networks.connect[id].fd + 1, NULL, &fdset, NULL, &tv); if (rc > 0) { rc = sendto(networks.connect[id].fd, buffer, len, 0, (struct sockaddr *)&address, sizeof(address)); if (rc > 0) sentLen = rc; else if (rc == 0) { disconnect(id); sentLen = -1; /* disconnected with server */ } else { sentLen = -2; /* network error */ } } else if (rc == 0) { sentLen = 0; /* timeouted and sent 0 bytes */ } else { sentLen = -2; /* network error */ } } } else { return AEC_DISCONNECT; } } else { return AEC_DISCONNECT; } if (sentLen == -1) { return AEC_DISCONNECT; } else if (sentLen == -2) { return AEC_NETWORK_ERROR; } else if (sentLen == len) { return AEC_OK; } else { return AEC_SEND_FAIL; } } typedef struct Timer Timer; struct Timer { unsigned int end_time; }; /** countdown_ms - set timeout value in mil seconds * @param timer - timeout timer where the timeout value save * @param timeout_ms - timeout in timeout_ms mil seconds */ static void countdown_ms(Timer *timer, unsigned int timeout_ms) { timer->end_time = OS_TicksToMSecs(OS_GetTicks()) + timeout_ms; } /** countdown - set timeout value in seconds * @param timer - timeout timer where the timeout value save * @param timeout - timeout in timeout seconds */ /* static void countdown(Timer *timer, unsigned int timeout) { countdown_ms(timer, timeout * 1000); } */ /** left_ms - calculate how much time left before timeout * @param timer - timeout timer * @return the time left befor timeout, or 0 if it has expired */ static int left_ms(Timer *timer) { int diff = (int)(timer->end_time) - (int)(OS_TicksToMSecs(OS_GetTicks())); return (diff < 0) ? 0 : diff; } /** expired - has it already timeouted * @param timer - timeout timer * @return 0 if it has already timeout, or otherwise. */ static char expired(Timer *timer) { return 0 <= (int)OS_TicksToMSecs(OS_GetTicks()) - (int)(timer->end_time); /* is time_now over than end time */ } static AT_ERROR_CODE read_socket(s32 id) { int recvLen = 0; int leftms; int rc = -1; struct timeval tv; Timer timer; fd_set fdset; struct sockaddr_in address; socklen_t addr_len; u8 *buffer; s32 len; s32 timeout_ms = 10; buffer = socket_cache[id].buffer; len = SOCKET_CACHE_BUFFER_SIZE; countdown_ms(&timer, timeout_ms); do { leftms = left_ms(&timer); tv.tv_sec = leftms / 1000; tv.tv_usec = (leftms % 1000) * 1000; FD_ZERO(&fdset); FD_SET(networks.connect[id].fd, &fdset); rc = select(networks.connect[id].fd + 1, &fdset, NULL, NULL, &tv); if (rc > 0) { if (networks.connect[id].protocol == 0) { /* TCP */ rc = recv(networks.connect[id].fd, buffer + recvLen, len - recvLen, 0); } else if (networks.connect[id].protocol == 1) { /* UDP */ address.sin_port = htons(networks.connect[id].port); address.sin_family = AF_INET; address.sin_addr.s_addr = inet_addr(networks.connect[id].ip); addr_len = sizeof(address); rc = recvfrom(networks.connect[id].fd, buffer + recvLen, len - recvLen, 0, (struct sockaddr *)&address, &addr_len); } if (rc > 0) { /* received normally */ recvLen += rc; } else if (rc == 0) { /* has disconnected with server */ recvLen = -1; break; } else { /* network error */ recvLen = -2; break; } } else if (rc == 0) { /* timeouted and return the length received */ break; } else { /* network error */ recvLen = -2; break; } } while (recvLen < len && !expired(&timer)); /* expired() is redundant? */ if (recvLen >= 0) { if (recvLen > 0) { socket_cache[id].cnt = recvLen; socket_cache[id].offset = 0; socket_cache[id].flag = 1; } return AEC_OK; } else if (recvLen == -1) { return AEC_DISCONNECT; } else if (recvLen == -2) { return AEC_NETWORK_ERROR; } else { return AEC_UNDEFINED; } } static AT_ERROR_CODE sockq(at_callback_para_t *para, at_callback_rsp_t *rsp) { AT_ERROR_CODE aec; s32 id; id = para->u.sockq.id; if (networks.count > 0) { if (networks.connect[id].flag) { if (socket_cache[id].flag) { rsp->type = 0; rsp->vptr = (void *)socket_cache[id].cnt; return AEC_OK; } aec = read_socket(id); if (aec != AEC_OK) { return aec; } if (socket_cache[id].flag) { rsp->type = 0; rsp->vptr = (void *)socket_cache[id].cnt; return AEC_OK; } else { rsp->type = 0; rsp->vptr = (void *)0; return AEC_OK; } } else { return AEC_DISCONNECT; } } else { return AEC_DISCONNECT; } } static AT_ERROR_CODE sockr(at_callback_para_t *para, at_callback_rsp_t *rsp) { AT_ERROR_CODE aec; s32 id; u8 *buffer; s32 len, rlen; id = para->u.sockr.id; len = para->u.sockr.len; if (networks.count > 0) { if (networks.connect[id].flag) { /* FUN_DEBUG("len = %d\n", len); */ if (len > 0) { if (!socket_cache[id].flag) { aec = read_socket(id); if (aec != AEC_OK) { return aec; } } if (socket_cache[id].flag) { buffer = socket_cache[id].buffer; rlen = len < socket_cache[id].cnt ? len : socket_cache[id].cnt; serial_write(&buffer[socket_cache[id].offset], rlen); socket_cache[id].cnt -= rlen; socket_cache[id].offset += rlen; len -= rlen; if (socket_cache[id].cnt <= 0) { socket_cache[id].flag = 0; } } } } else { return AEC_DISCONNECT; } } else { return AEC_DISCONNECT; } return AEC_OK; } static AT_ERROR_CODE sockc(at_callback_para_t *para, at_callback_rsp_t *rsp) { s32 id; id = para->u.sockc.id; if (networks.count > 0) { if (networks.connect[id].flag) { closesocket(networks.connect[id].fd); networks.connect[id].flag = 0; networks.count--; return AEC_OK; } } return AEC_DISCONNECT; } static void server_task(void *arg) { server_arg_t *server_arg; server_arg = arg; do { if (server_arg->protocol == 0) { /* TCP */ struct sockaddr_in server_addr; struct sockaddr_in conn_addr; int sock_fd; /* server socked */ int sock_conn; /* request socked */ socklen_t addr_len; int err; int option; sock_fd = socket(AF_INET, SOCK_STREAM, 0); if (sock_fd == -1) { FUN_DEBUG("failed to create sock_fd!\n"); break; } server_mutex_lock(); g_server_net.sock_fd = sock_fd; server_mutex_unlock(); FUN_DEBUG("sock fd = %d\n", sock_fd); memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(server_arg->port); option = 1; if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&option, sizeof(option)) < 0) { FUN_DEBUG("failed to setsockopt sock_fd!\n"); closesocket(sock_fd); break; } option = 1; if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEPORT, (char *)&option, sizeof(option)) < 0) { FUN_DEBUG("failed to setsockopt sock_fd!\n"); closesocket(sock_fd); break; } err = bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)); if (err < 0) { FUN_DEBUG("bind err = %d\n", err); FUN_DEBUG("failed to bind sock_fd!\n"); closesocket(sock_fd); break; } err = listen(sock_fd, 1); if (err < 0) { FUN_DEBUG("failed to listen sock_fd!\n"); closesocket(sock_fd); break; } addr_len = sizeof(struct sockaddr_in); while (1) { if (OS_SemaphoreWait(&g_server_sem, OS_WAIT_FOREVER) != OS_OK) continue; FUN_DEBUG("before accept!\n"); sock_conn = accept(sock_fd, (struct sockaddr *)&conn_addr, &addr_len); FUN_DEBUG("after accept!\n"); if (sock_conn > 0) { server_mutex_lock(); g_server_net.flag = 1; g_server_net.conn_fd = sock_conn; server_mutex_unlock(); } FUN_DEBUG("conn fd = %d\n", sock_conn); } } else if (server_arg->protocol == 1) { /* UDP */ /* do nothing */ } } while (0); server_mutex_lock(); g_server_net.flag = 0; g_server_net.sock_fd = -1; g_server_net.conn_fd = -1; server_mutex_unlock(); FUN_DEBUG("%s() end\n", __func__); OS_ThreadDelete(&g_server_thread); } static AT_ERROR_CODE sockd(at_callback_para_t *para, at_callback_rsp_t *rsp) { s16 port; s32 protocol; port = para->u.sockd.port; protocol = para->u.sockd.protocol; if (port > 0) { if (!g_server_enable) { g_server_arg.port = para->u.sockd.port; g_server_arg.protocol = para->u.sockd.protocol; memset(&socket_cache[MAX_SOCKET_NUM], 0, sizeof(socket_cache_t)); if (protocol == 0) { /* TCP */ server_mutex_lock(); g_server_net.flag = 0; g_server_net.sock_fd = -1; g_server_net.conn_fd = -1; server_mutex_unlock(); if (OS_SemaphoreCreate(&g_server_sem, 1, 1) != OS_OK) { FUN_DEBUG("create semaphore failed\n"); return AEC_UNDEFINED; } if (OS_ThreadCreate(&g_server_thread, "", server_task, &g_server_arg, OS_PRIORITY_NORMAL, SERVER_THREAD_STACK_SIZE) != OS_OK) { FUN_DEBUG("create server task failed\n"); return AEC_UNDEFINED; } memset(&g_server_ctrl, 0, sizeof(g_server_ctrl)); } else if (protocol == 1) { /* UDP */ struct sockaddr_in address; int rc; int fd; fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { return AEC_SOCKET_FAIL; } memset(&address, 0, sizeof(address)); address.sin_family = AF_INET; address.sin_addr.s_addr = htonl(INADDR_ANY); address.sin_port = htons(port); /* for receive */ rc = bind(fd, (struct sockaddr *)&address, sizeof(address)); if (rc < 0) { closesocket(fd); return AEC_BIND_FAIL; } server_mutex_lock(); g_server_net.flag = 1; g_server_net.sock_fd = -1; g_server_net.conn_fd = fd; server_mutex_unlock(); } g_server_enable = 1; return AEC_OK; } } else if (g_server_enable) { u32 flag; s32 sock_fd, conn_fd; server_mutex_lock(); flag = g_server_net.flag; sock_fd = g_server_net.sock_fd; conn_fd = g_server_net.conn_fd; server_mutex_unlock(); if (g_server_arg.protocol == 0) { /* TCP */ if (sock_fd != -1) { FUN_DEBUG("close fd = %d\n", sock_fd); closesocket(sock_fd); } if (flag) { FUN_DEBUG("close fd = %d\n", conn_fd); closesocket(conn_fd); } OS_SemaphoreDelete(&g_server_sem); OS_ThreadDelete(&g_server_thread); } else if (g_server_arg.protocol == 1) { /* UDP */ if (flag) { FUN_DEBUG("close fd = %d\n", conn_fd); closesocket(conn_fd); } } g_server_enable = 0; return AEC_OK; } return AEC_UNDEFINED; } static AT_ERROR_CODE wifi(at_callback_para_t *para, at_callback_rsp_t *rsp) { AT_ERROR_CODE aec = AEC_OK; switch (para->cfg->wifi_mode) { case 0: /* IDLE */ aec = AEC_IMPROPER_OPERATION; break; case 1: /* STA */ if (para->u.wifi.value == 0) { wlan_sta_disable(); } else if (para->u.wifi.value == 1) { wlan_sta_enable(); } else { aec = AEC_PARA_ERROR; } break; case 2: /* AP */ if (para->u.wifi.value == 0) { wlan_ap_disable(); } else if (para->u.wifi.value == 1) { wlan_ap_enable(); } else { aec = AEC_PARA_ERROR; } break; case 3: /* IBSS */ aec = AEC_IMPROPER_OPERATION; break; default: aec = AEC_PARA_ERROR; break; } return aec; } static AT_ERROR_CODE reassociate(at_callback_para_t *para, at_callback_rsp_t *rsp) { wlan_sta_connect(); return AEC_OK; } static AT_ERROR_CODE gpioc(at_callback_para_t *para, at_callback_rsp_t *rsp) { return AEC_OK; } static AT_ERROR_CODE gpior(at_callback_para_t *para, at_callback_rsp_t *rsp) { return AEC_OK; } static AT_ERROR_CODE gpiow(at_callback_para_t *para, at_callback_rsp_t *rsp) { return AEC_OK; } static s32 freq_to_chan(s32 freq) { s32 i; for (i = 0; i < TABLE_SIZE(channel_freq_tbl); ++i) { if (freq == channel_freq_tbl[i]) { break; } } if (i >= TABLE_SIZE(channel_freq_tbl)) { return -1; } return i + 1; } static AT_ERROR_CODE scan(at_callback_para_t *para, at_callback_rsp_t *rsp) { AT_ERROR_CODE aec = AEC_OK; int ret = -1; int size; char ssid[32 + 1]; wlan_sta_scan_results_t results; if (para->cfg->wifi_mode != 1) { /* STA */ return AEC_IMPROPER_OPERATION; } wlan_sta_scan_once(); size = MAX_SCAN_RESULTS; results.ap = cmd_malloc(size * sizeof(wlan_sta_ap_t)); if (results.ap == NULL) { aec = AEC_SCAN_FAIL; } if (aec == AEC_OK) { results.size = size; ret = wlan_sta_scan_result(&results); if (ret == 0) { /* cmd_wlan_sta_print_scan_results(&results); */ int i; for (i = 0; i < results.num; i++) { memcpy(ssid, results.ap[i].ssid.ssid, results.ap[i].ssid.ssid_len); ssid[results.ap[i].ssid.ssid_len] = '\0'; at_dump("%2d BSS %02X:%02X:%02X:%02X:%02X:%02X SSID: %-32.32s " "CHAN: %2d RSSI: %d flags: %08x wpa_key_mgmt: %08x " "wpa_cipher: %08x rsn_key_mgmt: %08x rsn_cipher: %08x\n", i + 1, (results.ap[i].bssid)[0], (results.ap[i].bssid)[1], (results.ap[i].bssid)[2], (results.ap[i].bssid)[3], (results.ap[i].bssid)[4], (results.ap[i].bssid)[5], ssid, freq_to_chan(results.ap[i].freq), results.ap[i].level, results.ap[i].wpa_flags, results.ap[i].wpa_key_mgmt, results.ap[i].wpa_cipher, results.ap[i].rsn_key_mgmt, results.ap[i].rsn_cipher); } } cmd_free(results.ap); } return aec; } #include "version.h" #include "common/framework/fwk_debug.h" static AT_ERROR_CODE version(at_callback_para_t *para, at_callback_rsp_t *rsp) { at_dump("+GMR:fw:\"%s\"\n", SDK_VERSION_STR); at_dump("+GMR:sdk:\"" SDK_VERSION_STR "\"\n"); at_dump("+GMR:tm:\"%s %s\"\n", __DATE__, __TIME__); return AEC_OK; } static AT_ERROR_CODE restory(at_callback_para_t *para, at_callback_rsp_t *rsp) { FUN_DEBUG("----->\n"); factory(para, rsp); return AEC_OK; } static AT_ERROR_CODE uart_def(at_callback_para_t *para, at_callback_rsp_t *rsp) { FUN_DEBUG("----->\n"); return AEC_OK; } /* enum suspend_state_t { PM_MODE_ON = 0, PM_MODE_SLEEP = 1, PM_MODE_STANDBY = 2, PM_MODE_HIBERNATION = 3, PM_MODE_MAX = 4, }; */ #include "pm/pm.h" static AT_ERROR_CODE sleep(at_callback_para_t *para, at_callback_rsp_t *rsp) { FUN_DEBUG("----->\n"); if (para->u.sleep.sleepMode < 0 || para->u.sleep.sleepMode > 4) { printf("The sleep mode is not support \r\n"); return AEC_CMD_ERROR; } else { at_dump("OK"); at_wakeup_gpio_init(5, 0); OS_MSleep(5); pm_enter_mode(para->u.sleep.sleepMode); } return AEC_BLANK_LINE; } static AT_ERROR_CODE wakeupgpio(at_callback_para_t *para, at_callback_rsp_t *rsp) { FUN_DEBUG("-->%s\n", __func__); at_wakeup_gpio_init(para->u.wakeupgpio.gpioId, para->u.wakeupgpio.edge); return AEC_OK; } /* enum wlan_mode { WLAN_MODE_STA = 0, WLAN_MODE_HOSTAP, WLAN_MODE_MONITOR, WLAN_MODE_NUM, WLAN_MODE_INVALID = WLAN_MODE_NUM }; */ static AT_ERROR_CODE cwmode_cur(at_callback_para_t *para, at_callback_rsp_t *rsp) { FUN_DEBUG("----->\n"); struct sysinfo *sysinfo = sysinfo_get(); if (para->u.wifiMode.mode < 0 || para->u.wifiMode.mode > 4) { printf("The mode is not support \r\n"); return AEC_CMD_ERROR; } else { if (para->u.wifiMode.mode == 0 || para->u.wifiMode.mode == 1) { sysinfo->wlan_mode = para->u.wifiMode.mode; sysinfo_save(); } if (para->u.wifiMode.mode == 1) { net_switch_mode(WLAN_MODE_HOSTAP); wlan_ap_disable(); wlan_ap_set((uint8_t *)sysinfo->wlan_ap_param.ssid, sysinfo->wlan_ap_param.ssid_len, (uint8_t *)sysinfo->wlan_ap_param.psk); wlan_ap_enable(); } else { net_switch_mode(para->u.wifiMode.mode); } } return AEC_OK; } static char cur_ssid[SYSINFO_SSID_LEN_MAX]; static char cur_psk[SYSINFO_PSK_LEN_MAX]; static AT_ERROR_CODE cwjap_cur(at_callback_para_t *para, at_callback_rsp_t *rsp) { uint32_t wep_open_connect_timeout_ms = 15500; uint32_t timeout = OS_GetTicks() + OS_TicksToMSecs(wep_open_connect_timeout_ms); struct netif *nif; memset(cur_ssid, 0, SYSINFO_SSID_LEN_MAX * sizeof(char)); memset(cur_psk, 0, SYSINFO_PSK_LEN_MAX * sizeof(char)); memcpy(cur_ssid, para->u.joinParam.ssid, strlen(para->u.joinParam.ssid)); memcpy(cur_psk, para->u.joinParam.pwd, strlen(para->u.joinParam.pwd)); FUN_DEBUG("----->\n"); if (para->u.joinParam.ssid == NULL) { printf("The ssid is NULL"); return AEC_CMD_ERROR; } else { wlan_sta_disable(); OS_MSleep(50); if (strlen(para->u.joinParam.pwd) == 0) { wlan_sta_set((unsigned char *)para->u.joinParam.ssid, strlen(para->u.joinParam.ssid), NULL); } else { printf("The ssid = %s, pwd = %s", para->u.joinParam.ssid, para->u.joinParam.pwd); wlan_sta_set((unsigned char *)para->u.joinParam.ssid, strlen(para->u.joinParam.ssid), (unsigned char *)para->u.joinParam.pwd); } wlan_sta_enable(); wlan_sta_connect(); } nif = wlan_netif_get(WLAN_MODE_NONE); while (OS_TimeBeforeEqual(OS_GetTicks(), timeout)) { if (nif && NETIF_IS_AVAILABLE(nif)) { g_errorcode = ATC_CWJAP_CUR_OK; OS_MSleep(30); return AEC_OK; } OS_MSleep(20); } wlan_sta_disable(); g_errorcode = ATC_CWJAP_CUR_TIMEOUT; return AEC_CMD_ERROR; } static AT_ERROR_CODE cwjap_info(at_callback_para_t *para, at_callback_rsp_t *rsp) { wlan_sta_ap_t *ap = NULL; struct sysinfo *_sysinfo = NULL; wlan_ext_signal_t signal; struct netif *nif; _sysinfo = sysinfo_get(); FUN_DEBUG("----->\n"); ap = malloc(sizeof(wlan_sta_ap_t)); nif = wlan_netif_get(WLAN_MODE_NONE); if (nif && NETIF_IS_AVAILABLE(nif)) { if (wlan_sta_ap_info(ap) == -1) { free(ap); at_dump("NO AP\r\n"); return AEC_OK; } wlan_ext_request(nif, WLAN_EXT_CMD_GET_SIGNAL, (int)(&signal)); at_dump("+CWJAP:\"%s\",\"%02x:%02x:%02x:%02x:%02x:%02x\",%d,%d,\"%02x:%02x:%02x:%02x:%02x:%02x\"\r\n", ap->ssid.ssid, ap->bssid[0], ap->bssid[1], ap->bssid[2], ap->bssid[3], ap->bssid[4], ap->bssid[5], ap->channel, (signal.noise + (signal.rssi/2)), _sysinfo->mac_addr[0], _sysinfo->mac_addr[1], _sysinfo->mac_addr[2], _sysinfo->mac_addr[3], _sysinfo->mac_addr[4], _sysinfo->mac_addr[5]); free(ap); return AEC_OK; } else { free(ap); at_dump("NO AP\r\n"); return AEC_OK; } } static AT_ERROR_CODE cwlapopt(at_callback_para_t *para, at_callback_rsp_t *rsp) { FUN_DEBUG("----->\n"); return AEC_OK; } static AT_ERROR_CODE cwlap(at_callback_para_t *para, at_callback_rsp_t *rsp) { FUN_DEBUG("----->\n"); scan(para, rsp); return AEC_OK; } static AT_ERROR_CODE cwqap(at_callback_para_t *para, at_callback_rsp_t *rsp) { FUN_DEBUG("----->\n"); wlan_sta_disable(); return AEC_OK; } static AT_ERROR_CODE httpota(at_callback_para_t *para, at_callback_rsp_t *rsp) { uint32_t *verify_value; ota_verify_t verify_type; ota_verify_data_t verify_data; if (ota_get_image(OTA_PROTOCOL_HTTP, para->u.http_url_para.http_url) != OTA_STATUS_OK) { at_dump("OTA http get image failed\n"); return AEC_UPGRADE_FAILED; } if (ota_get_verify_data(&verify_data) != OTA_STATUS_OK) { verify_type = OTA_VERIFY_NONE; verify_value = NULL; } else { verify_type = verify_data.ov_type; verify_value = (uint32_t *) (verify_data.ov_data); } if (ota_verify_image(verify_type, verify_value) != OTA_STATUS_OK) { at_dump("OTA http verify image failed\n"); return AEC_UPGRADE_FAILED; } ota_reboot(); return AEC_OK; } static AT_ERROR_CODE cwdhcp_cur(at_callback_para_t *para, at_callback_rsp_t *rsp) { FUN_DEBUG("----->\n"); save(para, rsp); return AEC_OK; } static AT_ERROR_CODE cipstamac_cur(at_callback_para_t *para, at_callback_rsp_t *rsp) { FUN_DEBUG("----->\n"); save(para, rsp); return AEC_OK; } static AT_ERROR_CODE cipsta_cur(at_callback_para_t *para, at_callback_rsp_t *rsp) { FUN_DEBUG("----->\n"); save(para, rsp); //ip_ipaddr return AEC_OK; } static AT_ERROR_CODE cwhostname(at_callback_para_t *para, at_callback_rsp_t *rsp) { FUN_DEBUG("----->\n"); save(para, rsp); return AEC_OK; } static AT_ERROR_CODE set_apcfg(at_callback_para_t *para, at_callback_rsp_t *rsp) { FUN_DEBUG("----->\n"); int ssid_len; ssid_len = strlen(para->u.apcfgParam.ssid); printf("para->u.apcfgParam.ssid=%s,para->u.apcfgParam.psk=%s\r\n", para->u.apcfgParam.ssid, para->u.apcfgParam.psk); net_switch_mode(WLAN_MODE_HOSTAP); wlan_ap_disable(); wlan_ap_set((uint8_t *)para->u.apcfgParam.ssid, ssid_len, (uint8_t *)para->u.apcfgParam.psk); wlan_ap_enable(); return AEC_OK; } static AT_ERROR_CODE cipstatus(at_callback_para_t *para, at_callback_rsp_t *rsp) { uint16_t net_event; uint16_t net_event_index; FUN_DEBUG("----->\n"); net_event = net_get_status(); switch (net_event) { case NET_CTRL_MSG_NETWORK_UP: net_event_index = 2; if ((networks.connect[0].flag) | (networks.connect[1].flag) | (networks.connect[2].flag) | (networks.connect[3].flag)) net_event_index = 3; break; case NET_CTRL_MSG_NETWORK_DOWN: net_event_index = 5; break; case NET_CTRL_MSG_WLAN_DISCONNECTED: net_event_index = 4; break; default: net_event_index = 5; break; } sprintf(rsp->vptr, "STATUS:%d\r\n", net_event_index); if (net_event_index == 3) { sprintf(((char *)rsp->vptr + strlen((char *)rsp->vptr)), "+CIPSTATUS:"); if (networks.connect[0].flag) { sprintf(((char *)rsp->vptr + strlen((char *)rsp->vptr)), "%d,\"%s\",\"%s\",%d ", 0, networks.connect[0].type, networks.connect[0].ip, networks.connect[0].port); } if (networks.connect[1].flag) { sprintf(((char *)rsp->vptr + strlen((char *)rsp->vptr)), "%d,\"%s\",\"%s\",%d ", 1, networks.connect[1].type, networks.connect[1].ip, networks.connect[1].port); } if (networks.connect[2].flag) { sprintf(((char *)rsp->vptr + strlen((char *)rsp->vptr)), "%d,\"%s\",\"%s\",%d ", 2, networks.connect[2].type, networks.connect[2].ip, networks.connect[2].port); } if (networks.connect[3].flag) { sprintf(((char *)rsp->vptr + strlen((char *)rsp->vptr)), "%d,\"%s\",\"%s\",%d ", 3, networks.connect[3].type, networks.connect[3].ip, networks.connect[3].port); } } rsp->status = 1; rsp->type = 1; return AEC_OK; } static AT_ERROR_CODE cipdomain(at_callback_para_t *para, at_callback_rsp_t *rsp) { FUN_DEBUG("----->\n"); struct hostent *server; server = gethostbyname(para->u.dns_parse.hostname); if (server == NULL) { printf("not find the host \r\n"); return AEC_CMD_FAIL; } for (int i = 0; server->h_addr_list[i]; i++) { printf("IP addr %d: %s\n", i+1, inet_ntoa(*(struct in_addr *)server->h_addr_list[i])); } at_dump("+IPDNS:\"%s\"\n", inet_ntoa(*(struct in_addr *)server->h_addr_list[0])); return AEC_OK; } #define SOCKET_TASK_STACK_SIZE (8*1024) static OS_Thread_t socket_task_handler[5]; typedef struct SocketSend_queueinf_def { int datalen; uint8_t *p_senddata; } SocketSend_queueinf_t; #define QLEN_ATCMDSEND 5 OS_Queue_t q_SocketSend[5]; void socket0_task(void *pvParameters) { SocketSend_queueinf_t sendinf; int rc = -1; fd_set fdset; s32 timeout_ms = 100; fd_set frset; struct sockaddr_in address; socklen_t addr_len; struct timeval tv; uint8_t id = (u32) pvParameters; OS_QueueCreate(&q_SocketSend[id], QLEN_ATCMDSEND, sizeof(SocketSend_queueinf_t)); while (1) { if (networks.connect[id].flag == 0) { OS_QueueReceive(&q_SocketSend[id], &sendinf, 1); //release the useless data OS_MSleep(100); continue; } if (OS_QueueReceive(&q_SocketSend[id], &sendinf, 100) == OS_OK) { if (networks.connect[id].fd == -1) { at_dump("SOCKET %d ERROR\n", id); free(sendinf.p_senddata); continue; } if (networks.connect[id].protocol == 0) { /* TCP */ FD_ZERO(&fdset); FD_SET(networks.connect[id].fd, &fdset); tv.tv_sec = timeout_ms / 1000; tv.tv_usec = (timeout_ms % 1000) * 1000; rc = select(networks.connect[id].fd + 1, NULL, &fdset, NULL, &tv); if (rc > 0) { rc = send(networks.connect[id].fd, sendinf.p_senddata, sendinf.datalen, 0); if (rc > 0) { at_dump("SOCKET %d SEND done\n", id); } else if (rc == 0) { disconnect(id); } else { disconnect(id); } } else if (rc == 0) { at_dump("+IPS: %d SEND TIMEOUT\n", id); } else { disconnect(id); } } else if (networks.connect[id].protocol == 1) { /* UDP */ FD_ZERO(&fdset); FD_SET(networks.connect[id].fd, &fdset); tv.tv_sec = timeout_ms / 1000; tv.tv_usec = (timeout_ms % 1000) * 1000; address.sin_port = htons(networks.connect[id].port); address.sin_family = AF_INET; address.sin_addr.s_addr = inet_addr(networks.connect[id].ip); rc = select(networks.connect[id].fd + 1, NULL, &fdset, NULL, &tv); if (rc > 0) { rc = sendto(networks.connect[id].fd, sendinf.p_senddata, sendinf.datalen, 0, (struct sockaddr *)&address, sizeof(address)); if (rc > 0) { at_dump("SOCKET %d SEND OK\n", id); } else if (rc == 0) { disconnect(id); } else { disconnect(id); } } else if (rc == 0) { at_dump("+IPS: SOCKET %d SEND TIMEOUT\n", id); } else { disconnect(id); } } free(sendinf.p_senddata); } tv.tv_sec = timeout_ms / 1000; tv.tv_usec = (timeout_ms % 1000) * 1000; FD_ZERO(&frset); FD_SET(networks.connect[id].fd, &frset); memset(socket_cache[id].buffer, 0, SOCKET_CACHE_BUFFER_SIZE); rc = select(networks.connect[id].fd + 1, &frset, NULL, NULL, &tv); if (rc > 0) { if (networks.connect[id].protocol == 0) { /* TCP */ rc = recv(networks.connect[id].fd, socket_cache[id].buffer, SOCKET_CACHE_BUFFER_SIZE, 0); } else if (networks.connect[id].protocol == 1) { /* UDP */ address.sin_port = htons(networks.connect[id].port); address.sin_family = AF_INET; address.sin_addr.s_addr = inet_addr(networks.connect[id].ip); addr_len = sizeof(address); rc = recvfrom(networks.connect[id].fd, socket_cache[id].buffer, SOCKET_CACHE_BUFFER_SIZE, 0, (struct sockaddr *)&address, &addr_len); } if (rc > 0) { at_dump("+IPD:"); if (is_disp_ipd == 1) at_dump("%d,%d\r\n", id, rc); at_data_output((char *)socket_cache[id].buffer, rc); } else if (rc == 0) { disconnect(id); } else { disconnect(id); } } else if (rc == 0) { } else { disconnect(id); } } } AT_ERROR_CODE socket_task_create(at_callback_para_t *para) { if (para->u.net_param.linkId >= MAX_SOCKET_NUM) { return AEC_SOCKET_FAIL; } int sockfd = para->u.net_param.linkId; if (networks.connect[para->u.net_param.linkId].ThreadHd == 0) { if (OS_ThreadCreate(&socket_task_handler[para->u.net_param.linkId], "socket0_task", socket0_task, ((void *)sockfd), OS_THREAD_PRIO_DRV_BH, SOCKET_TASK_STACK_SIZE) != OS_OK) { FUN_DEBUG("socket task create error\n"); return AEC_SOCKET_FAIL; } networks.connect[para->u.net_param.linkId].ThreadHd = 1; } return AEC_OK; } static AT_ERROR_CODE cipstart(at_callback_para_t *para, at_callback_rsp_t *rsp) { FUN_DEBUG("----->\n"); static int is_sockon_task_create = 0; OS_Status ret = OS_OK; memset(&sockontask_data, 0, sizeof(at_sockontask_para_t)); memcpy(&sockontask_data.para, para, sizeof(at_callback_para_t)); memcpy(&sockontask_data.rsp, rsp, sizeof(at_callback_rsp_t)); if (0 == is_sockon_task_create) { is_sockon_task_create = 1; ret = OS_QueueCreate(&OS_queue_sockon_handler, 10, sizeof(at_sockontask_para_t)); if (ret != OS_OK) FUN_DEBUG("------>%s xQueueCreate ERROR\n", __func__); ret = OS_ThreadCreate(&OS_Thread_sockon_handler, "sockon_task", sockon_task, ((void *)0), OS_THREAD_PRIO_APP, 2 * 1024); OS_MSleep(1); if (OS_QueueSend(&OS_queue_sockon_handler, &sockontask_data, 200) != OS_OK) { ret = OS_FAIL; } } else { if (OS_QueueSend(&OS_queue_sockon_handler, &sockontask_data, 200) != OS_OK) { ret = OS_FAIL; } } if (ret == OS_OK) { return AEC_OK; } else { FUN_DEBUG("sockon_task create error\n"); return AEC_SOCKET_FAIL; } } static AT_ERROR_CODE cipsendbuf(at_callback_para_t *para, at_callback_rsp_t *rsp) { FUN_DEBUG("----->\n"); return AEC_OK; } static AT_ERROR_CODE cipclose(at_callback_para_t *para, at_callback_rsp_t *rsp) { FUN_DEBUG("----->\n"); if (para->u.close_id.id < MAX_SOCKET_NUM) disconnect(para->u.close_id.id); return AEC_OK; } static AT_ERROR_CODE tcpservermaxconn(at_callback_para_t *para, at_callback_rsp_t *rsp) { FUN_DEBUG("----->\n"); set_maxconn(para->u.tcp_server.max_conn); return AEC_OK; } static AT_ERROR_CODE tcpserver(at_callback_para_t *para, at_callback_rsp_t *rsp) { FUN_DEBUG("----->\n"); s16 port; s32 protocol; port = para->u.tcp_server.port; protocol = 0; //tcp if (port > 0) { if (!g_server_enable) { g_server_arg.port = para->u.tcp_server.port; g_server_arg.protocol = 0; memset(&socket_cache[MAX_SOCKET_NUM], 0, sizeof(socket_cache_t)); if (protocol == 0) { /* TCP */ server_mutex_lock(); g_server_net.flag = 0; g_server_net.sock_fd = -1; g_server_net.conn_fd = -1; server_mutex_unlock(); if (OS_SemaphoreCreate(&g_server_sem, 1, 1) != OS_OK) { FUN_DEBUG("create semaphore failed\n"); return AEC_UNDEFINED; } if (OS_ThreadCreate(&g_server_thread, "server task", server_task, &g_server_arg, OS_PRIORITY_NORMAL, SERVER_THREAD_STACK_SIZE) != OS_OK) { FUN_DEBUG("create server task failed\n"); return AEC_UNDEFINED; } memset(&g_server_ctrl, 0, sizeof(g_server_ctrl)); } else if (protocol == 1) { /* UDP */ struct sockaddr_in address; int rc; int fd; fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { return AEC_SOCKET_FAIL; } memset(&address, 0, sizeof(address)); address.sin_family = AF_INET; address.sin_addr.s_addr = htonl(INADDR_ANY); address.sin_port = htons(port); /* for receive */ rc = bind(fd, (struct sockaddr *)&address, sizeof(address)); if (rc < 0) { closesocket(fd); return AEC_BIND_FAIL; } server_mutex_lock(); g_server_net.flag = 1; g_server_net.sock_fd = -1; g_server_net.conn_fd = fd; server_mutex_unlock(); } g_server_enable = 1; return AEC_OK; } } else if (g_server_enable) { u32 flag; s32 sock_fd, conn_fd; server_mutex_lock(); flag = g_server_net.flag; sock_fd = g_server_net.sock_fd; conn_fd = g_server_net.conn_fd; server_mutex_unlock(); if (g_server_arg.protocol == 0) { /* TCP */ if (sock_fd != -1) { FUN_DEBUG("close fd = %d\n", sock_fd); closesocket(sock_fd); } if (flag) { FUN_DEBUG("close fd = %d\n", conn_fd); closesocket(conn_fd); } OS_SemaphoreDelete(&g_server_sem); OS_ThreadDelete(&g_server_thread); } else if (g_server_arg.protocol == 1) { /* UDP */ if (flag) { FUN_DEBUG("close fd = %d\n", conn_fd); closesocket(conn_fd); } } g_server_enable = 0; return AEC_OK; } return AEC_UNDEFINED; return AEC_OK; } static AT_ERROR_CODE cipmux(at_callback_para_t *para, at_callback_rsp_t *rsp) { FUN_DEBUG("----->\n"); return AEC_OK; } static AT_ERROR_CODE cipmode(at_callback_para_t *para, at_callback_rsp_t *rsp) { FUN_DEBUG("----->\n"); return AEC_OK; } static AT_ERROR_CODE cipdns_cur(at_callback_para_t *para, at_callback_rsp_t *rsp) { FUN_DEBUG("----->\n"); ip_addr_t dnsip; memcpy((char *)(&dnsip), ¶->u.set_dns.setdnsip, sizeof(at_ip_t)); dns_setserver(0, &dnsip); return AEC_OK; } static AT_ERROR_CODE ciprecvdata(at_callback_para_t *para, at_callback_rsp_t *rsp) { FUN_DEBUG("----->\n"); return AEC_OK; } static AT_ERROR_CODE ciprecvmode(at_callback_para_t *para, at_callback_rsp_t *rsp) { FUN_DEBUG("----->\n"); return AEC_OK; } extern void close_server_socket(int id); extern int xr_client_fd[5]; extern int current_connections; int ap_server_send(int socket_fd, int datalen, uint8_t *p_senddata) { int rec_len; struct timeval tv; fd_set fdset; s32 timeout_ms = 10; if (socket_fd == -1) { at_dump("SOCKET %d ERROR\n", 0); return -1; } FD_ZERO(&fdset); FD_SET(socket_fd, &fdset); tv.tv_sec = timeout_ms / 1000; tv.tv_usec = (timeout_ms % 1000) * 1000; rec_len = select(socket_fd + 1, NULL, &fdset, NULL, &tv); if (rec_len > 0) { rec_len = send(socket_fd, p_senddata, datalen, 0); if (rec_len > 0) { at_dump("SOCKET %d SEND done\n", 0); } else if (rec_len == 0) { close_server_socket(0); } else { close_server_socket(0); } } else if (rec_len == 0) { at_dump("+IPS: %d SEND TIMEOUT\n", 0); } else { close_server_socket(0); } return 0; } int get_is_tcp_socket_empty(void) { if (current_connections == 0 && networks.count == 0) { return 0; } else { return 1; } } static AT_ERROR_CODE cipsend(at_callback_para_t *para, at_callback_rsp_t *rsp) { s32 id; u8 *buffer; s32 len; FUN_DEBUG("------>%s\n", __func__); SocketSend_queueinf_t sendinf; id = para->u.sockw.id; buffer = para->u.sockw.buf; len = para->u.sockw.len; if (id >= MAX_SOCKET_NUM) { return AEC_DISCONNECT; } sendinf.p_senddata = malloc(SOCKET_CACHE_BUFFER_SIZE); if (sendinf.p_senddata == NULL) { at_dump("malloc buffer for atcmdSend failed \n"); return AEC_CMD_ERROR; } sendinf.datalen = len; FUN_DEBUG("------>%s memcpy id = %d\n", __func__, id); memcpy(sendinf.p_senddata, buffer, len); if (current_connections == 0 && networks.count == 0) { at_dump("link is not valid\r\n"); free(sendinf.p_senddata); return AEC_CMD_ERROR; } if (current_connections <= 0) { if (OS_QueueSend(&q_SocketSend[id], &sendinf, 10) != OS_OK) { at_dump("LinkId %d Send ERROR \n", id); FUN_DEBUG("LinkId %d Send ERROR \n", id); free(sendinf.p_senddata); } } else { if (ap_server_send(xr_client_fd[id], sendinf.datalen, sendinf.p_senddata) == -1) { free(sendinf.p_senddata); return AEC_SEND_FAIL; } } FUN_DEBUG("------>%s xQueueSend Success\n", __func__); return AEC_OK; } int is_netconnet_ap(void) { if ((net_evevt_state == NET_CTRL_MSG_NETWORK_UP) || (net_evevt_state == NET_CTRL_MSG_WLAN_CONNECTED)) return 1; return 0; } typedef struct { GPIO_Pin GPIONum; GPIO_Port GPIOPort; GPIO_InitParam GPIOPara; } GPIO_CFG; GPIO_CFG BoardGPIO[3] = { {GPIO_PIN_19, GPIO_PORT_A, {GPIOx_Pn_F0_INPUT, GPIO_DRIVING_LEVEL_1, GPIO_PULL_NONE} }, {GPIO_PIN_19, GPIO_PORT_A, {GPIOx_Pn_F0_INPUT, GPIO_DRIVING_LEVEL_1, GPIO_PULL_NONE} }, {GPIO_PIN_19, GPIO_PORT_A, {GPIOx_Pn_F0_INPUT, GPIO_DRIVING_LEVEL_1, GPIO_PULL_NONE} } }; static AT_ERROR_CODE sysiosetcfg(at_callback_para_t *para, at_callback_rsp_t *rsp) { if (para->u.setgpio_para.ID > 2) return AEC_PARA_ERROR; para->u.setgpio_para.ID -= para->u.setgpio_para.ID; BoardGPIO[para->u.setgpio_para.ID].GPIOPara.driving = GPIO_DRIVING_LEVEL_1; if (para->u.setgpio_para.mode <= 1) BoardGPIO[para->u.setgpio_para.ID].GPIOPara.mode = para->u.setgpio_para.mode; else return AEC_PARA_ERROR; if (para->u.setgpio_para.pull <= 2) BoardGPIO[para->u.setgpio_para.ID].GPIOPara.pull = para->u.setgpio_para.pull; else return AEC_PARA_ERROR; HAL_GPIO_Init(BoardGPIO[para->u.setgpio_para.ID].GPIOPort, BoardGPIO[para->u.setgpio_para.ID].GPIONum, &BoardGPIO[para->u.setgpio_para.ID].GPIOPara); return AEC_OK; } static AT_ERROR_CODE sysiogetcfg(at_callback_para_t *para, at_callback_rsp_t *rsp) { char *modestr[] = { "Input", "Output" }; char *pullstr[] = { "pull none", "pull up", "pull down" }; at_dump("OI1 driver level is %d\r\n", BoardGPIO[0].GPIOPara.driving); at_dump("OI1 mode is %s\r\n", modestr[BoardGPIO[0].GPIOPara.mode]); at_dump("OI1 pull is %s\r\n", pullstr[BoardGPIO[0].GPIOPara.pull]); at_dump("OI2 driver level is %d\r\n", BoardGPIO[1].GPIOPara.driving); at_dump("OI2 mode is %s\r\n", modestr[BoardGPIO[1].GPIOPara.mode]); at_dump("OI2 pull is %s\r\n", pullstr[BoardGPIO[1].GPIOPara.pull]); at_dump("OI3 driver level is %d\r\n", BoardGPIO[2].GPIOPara.driving); at_dump("OI3 mode is %s\r\n", modestr[BoardGPIO[2].GPIOPara.mode]); at_dump("OI3 pull is %s\r\n", pullstr[BoardGPIO[2].GPIOPara.pull]); return AEC_OK; } static AT_ERROR_CODE syssetiodir(at_callback_para_t *para, at_callback_rsp_t *rsp) { if (para->u.setiodir_para.ID > 2) return AEC_PARA_ERROR; if (para->u.setiodir_para.mode <= 1) BoardGPIO[para->u.setiodir_para.ID].GPIOPara.mode = para->u.setiodir_para.mode; else return AEC_PARA_ERROR; HAL_GPIO_Init(BoardGPIO[para->u.setiodir_para.ID].GPIOPort, BoardGPIO[para->u.setiodir_para.ID].GPIONum, &BoardGPIO[para->u.setiodir_para.ID].GPIOPara); return AEC_OK; } static AT_ERROR_CODE syssetgpio(at_callback_para_t *para, at_callback_rsp_t *rsp) { if (para->u.writeiodata_para.ID > 2) return AEC_PARA_ERROR; if (para->u.writeiodata_para.data == 0) { HAL_GPIO_WritePin(BoardGPIO[para->u.writeiodata_para.ID]. GPIOPort, BoardGPIO[para->u.writeiodata_para.ID]. GPIONum, GPIO_PIN_LOW); } else { HAL_GPIO_WritePin(BoardGPIO[para->u.writeiodata_para.ID]. GPIOPort, BoardGPIO[para->u.writeiodata_para.ID]. GPIONum, GPIO_PIN_HIGH); } return AEC_OK; } static AT_ERROR_CODE sysreadgpio(at_callback_para_t *para, at_callback_rsp_t *rsp) { if (para->u.readiodata_para.ID > 2) return AEC_PARA_ERROR; at_dump("Level is %d\r\n", HAL_GPIO_ReadPin(BoardGPIO[para->u.readiodata_para.ID].GPIOPort, BoardGPIO[para->u.readiodata_para.ID].GPIONum)); return AEC_OK; } void occur(uint32_t evt, uint32_t data, void *arg) { int idx = EVENT_SUBTYPE(evt); switch (idx) { case NET_CTRL_MSG_WLAN_CONNECTED: net_evevt_state = NET_CTRL_MSG_WLAN_CONNECTED; at_dump("+EVT:2\n"); break; case NET_CTRL_MSG_WLAN_DISCONNECTED: net_evevt_state = NET_CTRL_MSG_WLAN_DISCONNECTED; at_dump("+EVT:3\n"); break; case NET_CTRL_MSG_WLAN_SCAN_SUCCESS: break; case NET_CTRL_MSG_WLAN_CONNECT_FAILED: break; case NET_CTRL_MSG_NETWORK_UP: net_evevt_state = NET_CTRL_MSG_NETWORK_UP; at_dump("+EVT:4\n"); break; case NET_CTRL_MSG_NETWORK_DOWN: break; case NET_CTRL_MSG_WLAN_SCAN_FAILED: case NET_CTRL_MSG_WLAN_4WAY_HANDSHAKE_FAILED: break; default: break; } if (idx >= 0 && idx < TABLE_SIZE(event)) { if (at_event(idx)) { at_dump("msg:%d\r\n%s\r\n", idx, event[idx]); } } else { FUN_DEBUG("Unsupported.\r\n"); } } OS_Thread_t ap_task_ctrl_thread; static int create_port; void tcp_server_task(void *pvParameters) { while (1) { ap_socket_task(create_port); } } void ap_server_task(int port) { create_port = port; if (OS_ThreadCreate(&ap_task_ctrl_thread, "tcp_server_task", tcp_server_task, NULL, OS_THREAD_PRIO_APP, (2 * 1024)) != OS_OK) { printf("thread create error\n"); } } void ap_task_delete(void) { OS_ThreadDelete(&ap_task_ctrl_thread); }