5745 lines
		
	
	
		
			171 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			5745 lines
		
	
	
		
			171 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /****************************************************************************
 | |
| 
 | |
| Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
 | |
| 
 | |
| This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
 | |
| be copied by any method or incorporated into another program without
 | |
| the express written consent of Aerospace C.Power. This Information or any portion
 | |
| thereof remains the property of Aerospace C.Power. The Information contained herein
 | |
| is believed to be accurate and Aerospace C.Power assumes no responsibility or
 | |
| liability for its use in any way and conveys no license or title under
 | |
| any patent or copyright and makes no representation or warranty that this
 | |
| Information is free from patent or copyright infringement.
 | |
| 
 | |
| ****************************************************************************/
 | |
| #include "iot_string_api.h"
 | |
| #include "os_task_api.h"
 | |
| #include "os_event_api.h"
 | |
| #include "os_timer_api.h"
 | |
| #include "os_utils_api.h"
 | |
| #include "iot_task_api.h"
 | |
| #include "iot_module_api.h"
 | |
| #include "os_lock_api.h"
 | |
| #include "iot_plc_cco_api.h"
 | |
| #include "iot_config_api.h"
 | |
| #include "iot_app_api.h"
 | |
| #include "iot_errno_api.h"
 | |
| #include "iot_io_api.h"
 | |
| #include "iot_uart_api.h"
 | |
| #include "iot_utils_api.h"
 | |
| #include "iot_board_api.h"
 | |
| #include "iot_grapp.h"
 | |
| #include "iot_plctxrx.h"
 | |
| #include "iot_proto_common.h"
 | |
| #include "iot_system_api.h"
 | |
| #include "iot_version_api.h"
 | |
| #include "iot_oem_api.h"
 | |
| #include "iot_flash_api.h"
 | |
| #include "iot_crc_api.h"
 | |
| #include "iot_spi_api.h"
 | |
| #include "iot_gpio_api.h"
 | |
| #include "iot_i2c_api.h"
 | |
| 
 | |
| #define plctxrx_force_skip_resp(p_resp)   \
 | |
|     ((0xFFFF == p_resp->index.current) && (0xFFFF == p_resp->index.total))
 | |
| 
 | |
| 
 | |
| #if IOT_GR_APP_ENABLE
 | |
| 
 | |
| #if INCLUDE_AT_COMMAND_MODULE
 | |
| 
 | |
| #define IOT_AT_MODULE_VERSION "1.0.005"
 | |
| 
 | |
| /* The priority of commands */
 | |
| #define AT_PRIO_MIN         5
 | |
| #define AT_PRIO_NOR         7
 | |
| #define AT_PRIO_MAX         9
 | |
| 
 | |
| #define AT_DEF_TIMEOUT      15
 | |
| #define AT_DEF_PRIO         AT_PRIO_NOR
 | |
| /* Message queue items count. */
 | |
| #define AT_TASK_MSG_CNT     32
 | |
| 
 | |
| #define AT_LIST_ITEMS_PER_COMMAND   10
 | |
| #define AT_LIST_ITEMS_CONTINUE      "\r\nPress <ENTER> to continue..."
 | |
| #define TRANSPARENT_KEYWORDS        "###\r\n"
 | |
| #define TRANSPARENT_KEYWORDS_LEN    5
 | |
| #define STRING_ENABLE               "\"E\""
 | |
| 
 | |
| #define AT_TMR_CHECK_END_PMODE (1000 * 3) // //unit ms
 | |
| 
 | |
| const uint8_t INVALID_MACADDR_6BYTE[IOT_MAC_ADDR_LEN] =
 | |
| {
 | |
|     0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 | |
| };
 | |
| const uint8_t IOT_AT_BROADCAST_MAC_6BYTES[IOT_MAC_ADDR_LEN] =
 | |
| {
 | |
|     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
 | |
| };
 | |
| 
 | |
| static uint32_t recv_blen = 0;
 | |
| /* Uniform flash struct used by GE and AT layer. */
 | |
| static custom_flash_info_t uniform_flashinfo_at;
 | |
| 
 | |
| 
 | |
| /* AT command name string, reference to enum at_command_id_list_e */
 | |
| char *at_command_name[AT_CID_MAX]={
 | |
|     "HELP",     /*
 | |
|                 Show the command items of this table.
 | |
|                 Query: AT+HELP?
 | |
|                 */
 | |
|     "MEMORY",   /*
 | |
|                 Show a block of memory:
 | |
|                 Query: AT+MEMORY?ADDRESS
 | |
|                 Set  : AT+MEMORY=ADDRESS,VALUE
 | |
|                 ADDRESS is the memory address in 32 bits,VALUE is the value in
 | |
|                 32 bits too.
 | |
|                 */
 | |
|     "TASK",     /*
 | |
|                 Show current task list.
 | |
|                 Query: AT+TASK?
 | |
|                 */
 | |
|     "TIME",     /*
 | |
|                 Set or query system time.(Realtime.)
 | |
|                 Query: AT+TIME?
 | |
|                 Set  : AT+TIME=YEAR-MOUNTH-DAY,HOUR:MIN:SEC
 | |
|                 */
 | |
|     "SYSINFO", /*
 | |
|                 Show the system information like:
 | |
|                 1. OS running time.
 | |
|                 2. Last boot reason.
 | |
|                 3. Total boot time.
 | |
|                 4. Firmware version & built time.
 | |
|                 5. RAM / CPU utilization percentage.
 | |
|                 Query: AT+SYSINFO?
 | |
|                 Clear: AT+SYSINFO=
 | |
|                 */
 | |
|     "UART",     /*
 | |
|                 Show or set the configuration of current uart port.
 | |
|                 Query: AT+UART?
 | |
|                 Set  : AT+UART=BRATE,DLEN,STOP,PARITY
 | |
|                 DLEN is the data length, <5-8>.
 | |
|                 STOP is the stop bit, 1 -> 1 bits, 2 -> 1.5 bits, 3 -> 2 bits.
 | |
|                 PARITY is the parity, 0 -> none, 1 -> odd, 2 -> even.
 | |
|                 */
 | |
|     "MAC",      /*
 | |
|                 Set or query MAC address.
 | |
|                 Query: AT+MAC?
 | |
|                 Set  : AT+MAC="xx:xx:xx:xx:xx:xx"
 | |
|                 */
 | |
|     "TOPO",     /*
 | |
|                 Show the topo of current network.
 | |
|                 Query: AT+TOPO?
 | |
|                 */
 | |
|     "PING",     /*
 | |
|                 Ping a target device with mac address.
 | |
|                 Excute: AT+PING="xx:xx:xx:xx:xx:xx",SIZE,TIMES,TIMEOUT
 | |
|                 */
 | |
|     "SEND",     /*
 | |
|                 Send data to remote device.
 | |
|                 Excute: AT+SEND="xx:xx:xx:xx:xx:xx","XX XX XX..."[,try_times]
 | |
|                 */
 | |
|     "REBOOT",   /*
 | |
|                 Reboot a target device with mac address.
 | |
|                 Excute: AT+REBOOT="xx:xx:xx:xx:xx:xx"
 | |
|                 Current device will reboot if mac address is NULL.
 | |
|                 */
 | |
|     "WHO",      /*
 | |
|                 Show basic information about me:
 | |
|                 1. Role.
 | |
|                 2. MAC address.
 | |
|                 3. NID.
 | |
|                 Query: AT+WHO?
 | |
|                 */
 | |
|     "RFPOWER",  /*
 | |
|                 Set or query TX power.
 | |
|                 Query: AT+RFPOWER?
 | |
|                 Set  : AT+RFPOWER=xx
 | |
|                 xx is the power value <85-137>.
 | |
|                 */
 | |
|     "WHITELIST",/*
 | |
|                 Set or query white list.
 | |
|                 Query: AT+WHITELIST?
 | |
|                 Excute: AT+WHITELIST= "A or D","xx:xx:xx:xx:xx:xx"
 | |
|                 A: Add. D: Delete.
 | |
|                 */
 | |
|     "NETWORK",  /*
 | |
|                 Show avaliable network:
 | |
|                 Query: AT+NETWORK?
 | |
|                 Only for STA ,connect/disconnect to an avalibale network
 | |
|                 with its MAC.This will case STA join/leave a valid network.
 | |
|                 Excute: AT+NETWORK="A or D","xx:xx:xx:xx:xx:xx"
 | |
|                 */
 | |
|     "FLASH",  /*
 | |
|                 Query/Read/Write customer flash info saved in the AT layer:
 | |
|                 Query: AT+FLASH?
 | |
|                 Excute:AT+FLASH="R", OFFSET, LEN
 | |
|                        AT+FLASH="W", OFFSET, "XX XX XX..."
 | |
|                        R: Read; W: Write.
 | |
|                 */
 | |
|     "PMODE",  /*
 | |
|                 SET transparent mode, data received from UART will be
 | |
|                 transparent transmitted to remote device .
 | |
|                 Set: AT+PMODE="E","xx:xx:xx:xx:xx:xx" or
 | |
|                 Set: AT+PMODE="E"
 | |
|                 */
 | |
|     "SPI",      /*
 | |
|                 SPI device Query/Set/Read/Write operation:
 | |
|                 Query: AT+SPI?
 | |
|                 Set:  AT+SPI=CLK_PIN, CS_PIN, MISO_PIN, MOSI_PIN,
 | |
|                         "DEV_TYPE | TRS_MODE<<2 | FRM_FMT<<4
 | |
|                             | DFRM_SZ<<6 | CS_EN << 11",
 | |
|                         FRQ, RX_THD, TX_RHD
 | |
|                 Excute:AT+SPI="R", LEN
 | |
|                       AT+SPI="W", "XX XX XX..."
 | |
|                       R: Read; W: Write.
 | |
|                 */
 | |
|     "IIC",      /*
 | |
|                 Query/Set/Read/Write IIC:
 | |
|                 Query: AT+IIC?
 | |
|                 Set:  AT+IIC=PORT, SPEED, SDA_PIN, SCL_PIN,
 | |
|                              NAK_WAIT_NUM,REG_ADDR_LEN
 | |
|                 Excute:AT+IIC="R", SLAVE_ADDR, REG_ADDR, LEN
 | |
|                       AT+IIC="W", SLAVE_ADDR, REG_ADDR, VALUE
 | |
|                       R: Read; W: Write.
 | |
|                 */
 | |
|     "GPIOCFG",  /*
 | |
|                 Config GPIO pin,
 | |
|                 Config  : AT+GPIOCFG=gpio_x,"I or O","U or D"
 | |
|                 I : input, O : output.
 | |
|                 U : pull-up, D : pull-down.
 | |
|                 */
 | |
|     "GPIOVAL",  /*
 | |
|                 Read / set the value of GPIO.
 | |
|                 Set  : AT+GPIOVAL=gpio_x,VAL.
 | |
|                 Query: AT+GPIOVAL?gpio_x.
 | |
|                 */
 | |
|     "SWMODE",  /*
 | |
|                 SWITCH uart mode to GR_MCU_OP_MODE
 | |
|                 Excute:AT+SWMODE="E"
 | |
|                 */
 | |
|     "NETGROUP", /*
 | |
|                 Start/End group network.
 | |
|                 Excute:AT+NETGROUP="S" or "E"
 | |
|                 S: start; E: end.
 | |
|                 */
 | |
|     "HOSTPORT", /*
 | |
|                 Set host port
 | |
|                 Query: AT+HOSTPORT?
 | |
|                 Excute:AT+HOSTPORT="UART" or "ETH"
 | |
|                 */
 | |
| };
 | |
| 
 | |
| /* Return status of this command. */
 | |
| enum at_command_response_e
 | |
| {
 | |
|     AT_RESP_OK,
 | |
|     AT_RESP_ERROR,
 | |
|     AT_RESP_BUSY,
 | |
|     AT_RESP_UNKNOWN_CMD,
 | |
|     AT_RESP_INVALID_ARGUMENT,
 | |
|     AT_RESP_WAIT_RESP_TIMEOUT,
 | |
|     AT_RESP_SET_FINISH_WITHOUT_ECHO,
 | |
|     AT_RESP_FORCE_ECHO
 | |
| };
 | |
| 
 | |
| /* Message type of at command module. */
 | |
| enum at_command_message_type_e
 | |
| {
 | |
|     AT_MSG_TYPE_COMMAND     = 0x1 << 4,    /* This message is a command. */
 | |
|     AT_MSG_TYPE_RESPONSE    = 0x2 << 4,   /* This message is a response. */
 | |
|     AT_MSG_TYPE_TIMEOUT     = 0x3 << 4
 | |
| };
 | |
| 
 | |
| /*
 | |
| This defined the sources of message handled in this module.
 | |
| It's filled in the msg_id block for AT_MSG_TYPE_COMMAND/AT_MSG_TYPE_RESPONSE.
 | |
| */
 | |
| enum at_command_message_source_e
 | |
| {
 | |
|     AT_MSG_SOURCE_LOCAL     = 0x1, /* This message comes from this module. */
 | |
|     AT_MSG_SOURCE_PLCTXRX   = 0x2, /* This message comes from plc module. */
 | |
|     AT_MSG_SOURCE_UART      = 0x3  /* This message comes from uart flow. */
 | |
| };
 | |
| 
 | |
| /* Message.type = at_command_message_type_e | at_command_message_source_e */
 | |
| #define MSG_TYPE(type)   ((type) & 0x0000FFF0)
 | |
| #define MSG_SRC(type)    ((type) & 0x0000000F)
 | |
| 
 | |
| #define SET_TRANSP_MODE(type)  ((type) | (1 << 15))
 | |
| #define GET_TRANSP_MODE(type)  ((type) >> 15)
 | |
| #define GET_PAYLOAD_TYPE(type) ((type) & 0x7FFF)
 | |
| 
 | |
| #define AT_RESP_STR_OK           "\r\n<%2.64s> response OK.\r\n"
 | |
| #define AT_RESP_STR_ERROR        "\r\n<%2.64s> response ERROR.\r\n"
 | |
| #define AT_RESP_STR_BUSY         "\r\n<%2.64s> response BUSY.Command dropped.\r\n"
 | |
| #define AT_RESP_STR_UNKNOWN      "\r\nCommand not found.\r\n"
 | |
| #define AT_RESP_STR_INVALID_ARG  "\r\n<%2.64s> response Invalid arguments.\r\n"
 | |
| #define AT_RESP_STR_TIMEOUT      "\r\n<%2.64s> response Time out.\r\n"
 | |
| 
 | |
| /* Recommended buffer size. */
 | |
| #define AT_SMALL_BUF_SIZE   64
 | |
| #define AT_MID_BUF_SIZE      128
 | |
| #define AT_LARGE_BUF_SIZE   256
 | |
| 
 | |
| #define USER_INPUT_ADD_STR      "A"
 | |
| #define USER_INPUT_DEL_STR      "D"
 | |
| #define USER_INPUT_READ_STR     "R"
 | |
| #define USER_INPUT_WRITE_STR    "W"
 | |
| #define USER_INPUT_GPIOCFG_INPUT_STR        "I"
 | |
| #define USER_INPUT_GPIOCFG_OUTPUT_STR       "O"
 | |
| #define USER_INPUT_GPIOCFG_PULLUP_STR       "U"
 | |
| #define USER_INPUT_GPIOCFG_PULLDOWN_STR     "D"
 | |
| #define USER_INPUT_NETGROUP_START_STR       "S"
 | |
| #define USER_INPUT_NETGROUP_END_STR         "E"
 | |
| #define USER_INPUT_HOST_PORT_UART_STR       "UART"
 | |
| #define USER_INPUT_HOST_PORT_ETH_STR        "ETH"
 | |
| 
 | |
| /* Operatopn code for downlayer */
 | |
| enum at_command_opcode_e
 | |
| {
 | |
|     AT_OP_TEST,     /* Queries the Set Commands internal parameters and
 | |
|                         their range of values. AT+<x>=? */
 | |
|     AT_OP_QUERY,    /* Returns the current value of parameters. AT+<x>? */
 | |
|     AT_OP_SET,      /* Sets the value of user-defined parameters in commands,
 | |
|                         and runs these commands. AT+<x>=... */
 | |
|     AT_OP_EXECUTE,  /* Runs commands with no user-defined parameters. AT+<x> */
 | |
| 
 | |
|     AT_OP_INVALID
 | |
| };
 | |
| 
 | |
| #define AT_SEND_DEF_RETRY_TIME  0
 | |
| 
 | |
| /*
 | |
| 
 | |
| AT command down flow:
 | |
| 
 | |
| at_fn_send_to_at_t (AT registerd to uplayer.
 | |
|                     Put command string to AT)
 | |
| -> at_fn_handle_send_t (AT local functions in commands table.
 | |
|                         Convert command string to at_arg_t.)
 | |
| -> at_fn_send_from_at_t (downlayer registerd to AT.
 | |
|                         Post at_arg_t to downlayer )
 | |
| 
 | |
| AT command up flow :
 | |
| 
 | |
| at_fn_response_to_at_t (AT registerd to downlayer.
 | |
|                         Put at_resp_t to AT)
 | |
| -> at_fn_handle_resp_t (AT local functions in commands table.
 | |
|                         Convert at_arg_t to response string)
 | |
| -> at_fn_response_from_at_t (uplayer registerd to AT
 | |
|                             Post response string to uplayer)
 | |
| 
 | |
| */
 | |
| 
 | |
| #define AT_COMMAND_MID      0 /* TODO */
 | |
| 
 | |
| 
 | |
| typedef struct _at_command_message_t
 | |
| {
 | |
|     iot_task_msg_t  msg;    /* The main entity of message. */
 | |
|     iot_pkt_t       *data;  /* The pointer of message. */
 | |
| }at_msg_t;
 | |
| 
 | |
| typedef enum _at_send_payload_type_e
 | |
| {
 | |
|    /* transparent app data, plc forward */
 | |
|    AT_PAYLOAD_RAWDATA     = 1,
 | |
|    /* at ping req, at internal msg. at in charge to handle */
 | |
|    AT_PAYLOAD_PING        = 2,
 | |
|    /* at ping reply, at internal msg, at in charge to handle*/
 | |
|    AT_PAYLOAD_PING_REPLY  = 3
 | |
| }at_pl_type_e;
 | |
| 
 | |
| typedef struct _at_send_payload_t
 | |
| {
 | |
|     /* Length of payload data. Hint: move len ahead, for easy txrx aggr */
 | |
|     uint16_t     dlen;
 | |
|     /* Type of payload. Ref-to _at_send_payload_type_e */
 | |
|     uint16_t     type;
 | |
|     /* Data of payload. */
 | |
|     uint8_t      data[0];
 | |
| }at_payload_t;
 | |
| 
 | |
| typedef struct _at_send_ping_t
 | |
| {
 | |
|     uint8_t     org_mac[IOT_MAC_ADDR_LEN];
 | |
|     uint8_t     dst_mac[IOT_MAC_ADDR_LEN];
 | |
|     uint32_t    stamp; /* Timestamp from sender. */
 | |
|     uint16_t    index; /* Ping packet index. */
 | |
|     uint16_t    dlen;  /* Data length. */
 | |
|     uint8_t     data[0];
 | |
| }at_ping_t;
 | |
| 
 | |
| struct at_ping_host_data
 | |
| {
 | |
|     uint8_t             dst_mac[IOT_MAC_ADDR_LEN];
 | |
|     volatile uint16_t   started;
 | |
|     volatile uint16_t   reply_index;
 | |
|     volatile uint32_t   stamp;
 | |
| }g_ping_host;
 | |
| 
 | |
| typedef struct _at_iic_gpio_sel
 | |
| {
 | |
|     uint16_t scl;             /* SCL pin. */
 | |
|     uint16_t sda;             /* SDA pin. */
 | |
| } at_iic_gpio_sel_t;
 | |
| 
 | |
| typedef struct _at_command_iic_cfg_t
 | |
| {
 | |
|     uint32_t inited;          /* IIC initialization completed? 0, not yet, 1, done. */
 | |
|     uint32_t port;            /* IIC port number. */
 | |
|     uint32_t baud;            /* IIC baudrate, unit is Kb. */
 | |
|     uint32_t nack_wait_num;   /* wait nack number. */
 | |
|     at_iic_gpio_sel_t gpio;   /* gpio number select. */
 | |
|     uint32_t reg_addr_len;    /* read/write register address length. */
 | |
| } at_iic_cfg_t;
 | |
| 
 | |
| typedef struct _at_command_uart_cfg_t
 | |
| {
 | |
|     uint8_t port;             /* The uart port num. */
 | |
|     uint8_t dlen;             /* The uart data length. */
 | |
|     uint8_t stop;             /* The uart stop bit. */
 | |
|     uint8_t parity;           /* The uart parity bit. */
 | |
|     uint32_t brate;           /* The uart baudrate. */
 | |
| }at_uart_cfg_t;
 | |
| 
 | |
| typedef struct _at_command_spi_cfg_t
 | |
| {
 | |
|     uint32_t        inited;   /* SPI initialization completed? 0, not yet, 1, done. */
 | |
|     int             port;     /* SPI device port number. */
 | |
|     iot_spi_gpio_sel_t gpio;  /* SPI gpio select config. */
 | |
|     spi_cfg         cfg;      /* SPI config. */
 | |
|     tm_cfg          tm;       /* SPI timing. */
 | |
| }at_spi_cfg_t;
 | |
| 
 | |
| /* The whitelist action type, ensure each item value same with proto defined. */
 | |
| typedef enum _at_whitelist_action_type_e
 | |
| {
 | |
|     AT_WL_ACTION_DEL,
 | |
|     AT_WL_ACTION_ADD,
 | |
|     AT_WL_ACTION_DISABLE,
 | |
|     AT_WL_ACTION_ENABLE,
 | |
|     AT_WL_ACTION_NONE,
 | |
| }at_wl_action_type;
 | |
| 
 | |
| typedef struct _at_whitelist_operation_info_t
 | |
| {
 | |
|     /* Whitelist add or delete signle device info. */
 | |
|     at_dev_t            signle_dev;
 | |
|     /* The latest whitelist action type.*/
 | |
|     at_wl_action_type   latest_wl_action;
 | |
| }at_wl_op_t;
 | |
| 
 | |
| /* The AT command context. */
 | |
| static at_context_t at_command_context;
 | |
| 
 | |
| #define AT_IIC_INIT_COMPLETED       1
 | |
| #define AT_IIC_INIT_UNCOMPLETED     0
 | |
| #define AT_IIC_DEF_PORT             0    /* Port#0 or port#1 */
 | |
| #define AT_IIC_DEF_SPEED            50   /* 50K */
 | |
| #define AT_IIC_DEF_NACK_NUM         1    /* N-ACK number */
 | |
| #define AT_IIC_DEF_GPIO_SCL         35   /* UART1_RX*/
 | |
| #define AT_IIC_DEF_GPIO_SDA         34   /* UART1_TX */
 | |
| /* Maximum of the iic one time read or write operation. */
 | |
| #define AT_IIC_MAX_RD_WR_BYTES      32
 | |
| /* The common len and max val used in IIC read/write operation, for reg addr and data. */
 | |
| #define AT_IIC_OP_COMMON_LEN_1BYTE  1
 | |
| #define AT_IIC_OP_COMMON_LEN_2BYTE  2
 | |
| #define AT_IIC_OP_MAX_VAL_1BYTE     0xFF
 | |
| #define AT_IIC_OP_MAX_VAL_2BYTE     0xFFFF
 | |
| 
 | |
| 
 | |
| /* The iic config of AT layer. */
 | |
| static at_iic_cfg_t at_command_iic_cfg =
 | |
| {
 | |
|     AT_IIC_INIT_UNCOMPLETED,       /* IIC initialization uncompleted. */
 | |
|     AT_IIC_DEF_PORT,               /* IIC device port number. */
 | |
|     AT_IIC_DEF_SPEED,              /* Baudrate, unit is Kb. */
 | |
|     AT_IIC_DEF_NACK_NUM,           /* Wait nack number. */
 | |
|     {
 | |
|         AT_IIC_DEF_GPIO_SCL,       /* SCL pin. */
 | |
|         AT_IIC_DEF_GPIO_SDA        /* SDA pin. */
 | |
|     },
 | |
|     AT_IIC_OP_COMMON_LEN_1BYTE,    /* Register address length. */
 | |
| };
 | |
| 
 | |
| /* The uart config of AT layer. */
 | |
| static at_uart_cfg_t at_command_uart_cfg =
 | |
| {
 | |
|     0,                                      /* UART Port num. */
 | |
|     IOT_UART_DLEN_8_BITS,                   /* UART Data length. */
 | |
|     IOT_UART_STOP_1_BITS,                   /* UART Stop bit. */
 | |
|     IOT_UART_PARITY_NONE,                   /* UART Parity bit. */
 | |
|     IOT_UART_BANDRATE_DEFAULT,              /* UART baudrate. */
 | |
| };
 | |
| 
 | |
| #define AT_SPI_INIT_COMPLETED               1
 | |
| #define AT_SPI_INIT_UNCOMPLETED             0
 | |
| /* Maximum of the spi one time read or write operation. */
 | |
| #define AT_SPI_MAX_RD_WR_BYTES              32
 | |
| /* Max size of the spi one time write operation buffer. */
 | |
| #define AT_SPI_MAX_WR_BUF_SIZE              (AT_SPI_MAX_RD_WR_BYTES + 1)
 | |
| /* SPI read or write dummy data in at layer. */
 | |
| #define AT_SPI_RD_WR_DUMMY_DATA             0x5A
 | |
| 
 | |
| /* The spi config of AT layer, initialized to the default configuration. */
 | |
| static at_spi_cfg_t at_command_spi_cfg =
 | |
| {
 | |
|     AT_SPI_INIT_UNCOMPLETED,              /* SPI initialization uncompleted. */
 | |
|     DEVICE_SPI0_MASTER,                   /* SPI device port number. */
 | |
|     /* 35<->CLK, 34<-> CS, 8<->MISO, 9<->MOSI */
 | |
|     {35, 34, 8, 9},
 | |
|     {
 | |
|         SPI_MASTER,                        /* Master or slaver. */
 | |
|         TMOD_TRANCIEVER,                   /* Trans_mode. */
 | |
|         FRM_STD,                           /* Frame_format. */
 | |
|         SPI_DFRAME_SIZE_8,                 /* Data frame size. */
 | |
|         DEVICE_SPI_DEFAULT_CS_EN,          /* Slave select enable*/
 | |
|         0,                                 /* Reserved. */
 | |
|         DEVICE_SPI_DEFAULT_FREQUENCY,      /* Device frequency. */
 | |
|         DEVICE_SPI_DEFAULT_RX_THRESHOULD,  /* Threshold for reviecing fifo. */
 | |
|         DEVICE_SPI_DEFAULT_TX_THRESHOULD   /* Threshold for transmitting fifo. */
 | |
|     },
 | |
|     /* scpol bit: 0, scph bit: 0, scph_tgl bit: 0, sste bit: 1, reserved: 0. */
 | |
|     {0, 0, 0, 1, 0},
 | |
| };
 | |
| 
 | |
| /* The whitelist operation info recorded in AT layer*/
 | |
| static at_wl_op_t at_command_wl_op;
 | |
| #define AT_WL_OP_DELAY_MS       (1000)     /* The unit of delay time is ms. */
 | |
| 
 | |
| #define at_sem_lock()           os_acquire_mutex(at_command_context.sem)
 | |
| #define at_sem_release()        os_release_mutex(at_command_context.sem)
 | |
| 
 | |
| #define at_is_firedup()         (0x569a4323 == at_command_context.mkey)
 | |
| #define at_fire_now()           (at_command_context.mkey = 0x569a4323)
 | |
| 
 | |
| #define AT_MAX_ARGC             30
 | |
| 
 | |
| #define CR_OR_LF(ch)    (('\r' == ch) || ('\n' == ch))
 | |
| #define CH_EOS          '\0'
 | |
| #define CH_SET          '='
 | |
| #define CH_QUR          '?'
 | |
| #define CH_SPL          ','
 | |
| 
 | |
| #define ISSPACE(ch) ((CR_OR_LF(ch) || ' ' == ch || '\t' == ch || '\v' == ch\
 | |
|     || '\f' == ch) ? 1 : 0)
 | |
| 
 | |
| #define AT_MAX_SEND_BYTES       256
 | |
| #define AT_MAX_PING_BYTES       64
 | |
| #define AT_DEF_PING_TIMES       3
 | |
| 
 | |
| 
 | |
| #define CH_IS_SPLIT(ch) (((':' == (ch)) || ('-' == (ch))\
 | |
|                             || (' ' == (ch))) ? 1 : 0)
 | |
| 
 | |
| #if !defined(min)
 | |
| #define min(a, b) (((a) < (b)) ? (a) : (b))
 | |
| #endif
 | |
| 
 | |
| #if !defined(max)
 | |
| #define max(a, b) (((a) < (b)) ? (b) : (a))
 | |
| #endif
 | |
| 
 | |
| /* The macro for add AT command. */
 | |
| #define AT_CMD(id, timout, prio, handle_send, handle_resp)\
 | |
|     {&at_command_name[id], 0, timout, prio, handle_send, handle_resp}
 | |
| 
 | |
| /* The AT command table. */
 | |
| static at_cmd_t at_command_table[AT_CID_MAX] = {
 | |
|     AT_CMD(AT_CID_HELP, AT_DEF_TIMEOUT, AT_DEF_PRIO, at_handle_command_help, NULL),
 | |
|     AT_CMD(AT_CID_MEMORY, AT_DEF_TIMEOUT, AT_DEF_PRIO, at_handle_command_memory, NULL),
 | |
|     AT_CMD(AT_CID_TASK, AT_DEF_TIMEOUT, AT_DEF_PRIO, at_handle_command_task, NULL),
 | |
|     AT_CMD(AT_CID_TIME, AT_DEF_TIMEOUT, AT_DEF_PRIO, at_handle_command_time, at_handle_response_time),
 | |
|     AT_CMD(AT_CID_SYSTEMINFO, AT_DEF_TIMEOUT, AT_DEF_PRIO, at_handle_command_systeminfo, at_handle_response_systeminfo),
 | |
|     AT_CMD(AT_CID_UART, AT_DEF_TIMEOUT, AT_DEF_PRIO, at_handle_command_uart, at_handle_response_uart),
 | |
|     AT_CMD(AT_CID_MAC, AT_DEF_TIMEOUT, AT_DEF_PRIO, at_handle_command_mac, at_handle_response_mac),
 | |
|     AT_CMD(AT_CID_TOPO, AT_DEF_TIMEOUT, AT_DEF_PRIO, at_handle_command_topo, at_handle_response_topo),
 | |
|     AT_CMD(AT_CID_PING, AT_DEF_TIMEOUT, AT_DEF_PRIO, at_handle_command_ping, NULL),
 | |
|     AT_CMD(AT_CID_SEND, AT_DEF_TIMEOUT, AT_DEF_PRIO, at_handle_command_send, at_handle_response_send_receive),
 | |
|     AT_CMD(AT_CID_REBOOT, AT_DEF_TIMEOUT, AT_DEF_PRIO, at_handle_command_reboot, at_handle_response_reboot),
 | |
|     AT_CMD(AT_CID_WHO, AT_DEF_TIMEOUT, AT_DEF_PRIO, at_handle_command_who, at_handle_response_who),
 | |
|     AT_CMD(AT_CID_RFPOWER, AT_DEF_TIMEOUT, AT_DEF_PRIO, at_handle_command_rfpower, at_handle_response_rfpower),
 | |
|     AT_CMD(AT_CID_WHITELIST, AT_DEF_TIMEOUT, AT_DEF_PRIO, at_handle_command_whitelist, at_handle_response_whitelist),
 | |
|     AT_CMD(AT_CID_NETWORK, AT_DEF_TIMEOUT, AT_DEF_PRIO, at_handle_command_network, at_handle_response_network),
 | |
|     AT_CMD(AT_CID_FLASH, AT_DEF_TIMEOUT, AT_DEF_PRIO, at_handle_command_flash, NULL),
 | |
|     AT_CMD(AT_CID_PMODE, AT_DEF_TIMEOUT, AT_DEF_PRIO, at_handle_command_pmode, NULL),
 | |
|     AT_CMD(AT_CID_SPI, AT_DEF_TIMEOUT, AT_DEF_PRIO, at_handle_command_spi, NULL),
 | |
|     AT_CMD(AT_CID_IIC, AT_DEF_TIMEOUT, AT_DEF_PRIO, at_handle_command_iic, NULL),
 | |
|     AT_CMD(AT_CID_GPIOCFG, AT_DEF_TIMEOUT, AT_DEF_PRIO, at_handle_command_gpiocfg, NULL),
 | |
|     AT_CMD(AT_CID_GPIOVAL, AT_DEF_TIMEOUT, AT_DEF_PRIO, at_handle_command_gpioval, NULL),
 | |
|     AT_CMD(AT_CID_SWMODE, AT_DEF_TIMEOUT, AT_DEF_PRIO, at_handle_cmd_sw_uartmode, NULL),
 | |
|     AT_CMD(AT_CID_NETGROUP, AT_DEF_TIMEOUT, AT_DEF_PRIO, at_handle_command_netgroup, NULL),
 | |
| #if SUPPORT_HOST_PORT_ETH
 | |
|     AT_CMD(AT_CID_HOSTPORT, AT_DEF_TIMEOUT, AT_DEF_PRIO, at_handle_command_host_port, NULL),
 | |
| #endif
 | |
| };
 | |
| 
 | |
| /* Offset the start addr by 0 bytes, same with proto flash info. */
 | |
| #define AT_CUST_FLASH_START_OFFSET          0
 | |
| /* Customer flash start offset addr that users do read or write operation. */
 | |
| #define AT_CUST_FLASH_USER_OP_START_OFFSET  \
 | |
|     (AT_CUST_FLASH_START_OFFSET + sizeof(custom_flash_info_t))
 | |
| /* Customer flash maximum size that users do read and write operation. */
 | |
| #define AT_CUST_FLASH_USER_OP_MAX_SIZE      \
 | |
|     (custom_dev_query_rw_size() - AT_CUST_FLASH_USER_OP_START_OFFSET)
 | |
| /* Maximum of the one time read or write operation. */
 | |
| #define AT_CUST_FLASH_MAX_RD_WR_BYTES       48
 | |
| /* Max size of the one time flash operation buffer. */
 | |
| #define AT_CUST_FLASH_MAX_OP_BUF_SIZE (AT_CUST_FLASH_MAX_RD_WR_BYTES + 1)
 | |
| /* The number of flash read data are displayed on the same row. */
 | |
| #define AT_FLASH_DIS_ON_SAME_ROW_DATA_NUM   8
 | |
| 
 | |
| void at_command_at_response_to_proto
 | |
|     (uint32_t resp, uint8_t* buf, uint32_t blen, uint16_t resp_finished);
 | |
| 
 | |
| void iot_common_bin_dump(uint8_t *data, uint32_t dlen);
 | |
| void at_command_cvg_wl_add_del(uint8_t action, uint8_t *mac, bool_t need_ack_cfm);
 | |
| void at_command_cvg_wl_en_disable(uint8_t action, bool_t need_ack_cfm);
 | |
| 
 | |
| /*
 | |
|  * at_command_spi_write_data() - write data using spi module, this function is excuted when
 | |
|  *                  cs pin is controled by customs
 | |
|  * @data: pointer to write data buf
 | |
|  * @len:   data lenth
 | |
|  * @return ERR_OK -- Operation Successful, ERR_FAIL -- Operation failed.
 | |
|  */
 | |
| uint32_t at_command_spi_write_data(char *data, uint16_t len)
 | |
| {
 | |
|     char spi_rx_buf[AT_SPI_MAX_RD_WR_BYTES];
 | |
|     xfer_buf spi_tx;
 | |
| 
 | |
|     if ((NULL == data) || (0 == len))
 | |
|     {
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     spi_tx.p_nt = NULL;
 | |
|     spi_tx.txbuf = data;
 | |
|     spi_tx.rxbuf = spi_rx_buf;
 | |
|     spi_tx.size = len;
 | |
| 
 | |
|     os_mem_set(spi_rx_buf, AT_SPI_RD_WR_DUMMY_DATA, AT_SPI_MAX_RD_WR_BYTES);
 | |
| 
 | |
|     /* before reading, enalbe the cs pin-- pull low */
 | |
|     if(ERR_FAIL == iot_spi_poll_transfer(at_command_spi_cfg.port, &spi_tx))
 | |
|     {
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
|     /* after read, disable the cs pin-- pull high */
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * at_command_spi_read_data() - read data using spi module, this function is excuted when
 | |
|  *                  cs pin is controled by customs
 | |
|  * @data: pointer to received data buf
 | |
|  * @len:   data lenth
 | |
|  * @return ERR_OK -- Operation Successful, ERR_FAIL -- Operation failed.
 | |
|  */
 | |
| uint32_t at_command_spi_read_data(char *data, uint16_t len)
 | |
| {
 | |
|     int cnt;
 | |
|     char spi_tx_buf[AT_SPI_MAX_RD_WR_BYTES];
 | |
|     xfer_buf spi_rx;
 | |
| 
 | |
|     if ((NULL == data) || (0 == len))
 | |
|     {
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     spi_rx.p_nt = NULL;
 | |
|     spi_rx.txbuf = spi_tx_buf;
 | |
|     spi_rx.rxbuf = data;
 | |
|     spi_rx.size = len;
 | |
| 
 | |
|     os_mem_set(spi_tx_buf, AT_SPI_RD_WR_DUMMY_DATA, AT_SPI_MAX_RD_WR_BYTES);
 | |
| 
 | |
|     (void)iot_spi_get_rx_data_cnt(at_command_spi_cfg.port, &cnt);
 | |
|     DINFOR("cnt:%d", cnt);
 | |
|     /* clear fifo */
 | |
|     (void)iot_spi_read_data(at_command_spi_cfg.port, NULL, cnt);
 | |
| 
 | |
|     /* before reading, enalbe the cs pin-- pull low */
 | |
|     if(ERR_FAIL == iot_spi_poll_transfer(at_command_spi_cfg.port, &spi_rx))
 | |
|     {
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
|     /* after read, disable the cs pin-- pull high */
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| /* To dump our config info on flash. */
 | |
| void at_command_dump_uniform_flash(custom_flash_info_t* p_info)
 | |
| {
 | |
|     uint8_t i;
 | |
|     proto_dev_t *p_dev_table;
 | |
| 
 | |
|     if (NULL == p_info)
 | |
|     {
 | |
|         DERROR("Invalid argument!");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_dev_table = p_info->dev_tbl;
 | |
| 
 | |
|     DINFOR("The whitelist table number = %d",
 | |
|         p_info->dev_cnt);
 | |
|     for (i = 0; i < p_info->dev_cnt; i++)
 | |
|     {
 | |
|         DINFOR("WL table#%02d,Role:%d,MAC:%02x-%02x-%02x-%02x-%02x-%02x.",
 | |
|             i, p_dev_table->dev_role,
 | |
|             p_dev_table->mac[0], p_dev_table->mac[1],
 | |
|             p_dev_table->mac[2], p_dev_table->mac[3],
 | |
|             p_dev_table->mac[4], p_dev_table->mac[5]);
 | |
|         p_dev_table++;
 | |
|     }
 | |
| 
 | |
|     DINFOR("load transpmode = %d,mac=%02X,%02X,%02X,%02X,%02X,%02X",
 | |
|         p_info->transp.transpmode,
 | |
|         p_info->transp.trans_addr[0],p_info->transp.trans_addr[1],
 | |
|         p_info->transp.trans_addr[2],p_info->transp.trans_addr[3],
 | |
|         p_info->transp.trans_addr[4],p_info->transp.trans_addr[5]);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /* This will write data onto customer flash area. */
 | |
| uint32_t at_command_flash_write
 | |
|     (uint32_t write_offset, uint32_t write_len, void *p_write_buf)
 | |
| {
 | |
| #if (HW_PLATFORM == HW_PLATFORM_SIMU)
 | |
|     (void)write_offset;
 | |
|     (void)write_len;
 | |
|     (void)p_write_buf;
 | |
| #else
 | |
|     int fd;
 | |
| 
 | |
|     if ((NULL == p_write_buf)
 | |
|         || ((write_offset + write_len) > custom_dev_query_rw_size()))
 | |
|     {
 | |
|         DERROR("Invalid argument!");
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     if (-1 == (fd = custom_dev_open()))
 | |
|     {
 | |
|         DERROR("Cannot open flash!");
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     if (-1 == custom_dev_seek
 | |
|             (fd, write_offset, DEV_SEEK_SET))
 | |
|     {
 | |
|         DERROR("Cannot seek flash!");
 | |
|         (void)custom_dev_close(fd);
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     if (-1 == custom_dev_write(fd, (void*)p_write_buf, write_len))
 | |
|     {
 | |
|         DERROR("Cannot write flash!");
 | |
|         (void)custom_dev_close(fd);
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     (void)custom_dev_close(fd);
 | |
| #endif
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| /* Load config from customer flash. */
 | |
| uint32_t at_command_flash_read
 | |
|     (uint32_t read_offset, uint32_t read_len, void *p_read_buf)
 | |
| {
 | |
| #if (HW_PLATFORM == HW_PLATFORM_SIMU)
 | |
|     (void)read_offset;
 | |
|     (void)read_len;
 | |
|     (void)p_read_buf;
 | |
| #else
 | |
|     int fd;
 | |
| 
 | |
|     if ((NULL == p_read_buf)
 | |
|         || ((read_offset + read_len) > custom_dev_query_rw_size()))
 | |
|     {
 | |
|         DERROR("Invalid argument!");
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     if (-1 == (fd = custom_dev_open()))
 | |
|     {
 | |
|         DERROR("Cannot open flash!");
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     if (-1 == custom_dev_seek
 | |
|             (fd, read_offset, DEV_SEEK_SET))
 | |
|     {
 | |
|         DERROR("Cannot seek flash!");
 | |
|         (void)custom_dev_close(fd);
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     if (-1 == custom_dev_read(fd, (void*)p_read_buf, read_len))
 | |
|     {
 | |
|         DERROR("Cannot write flash!");
 | |
|         (void)custom_dev_close(fd);
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     (void)custom_dev_close(fd);
 | |
| #endif
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| /* This will store config onto customer flash area. */
 | |
| uint32_t at_command_uniform_flashsave(custom_flash_info_t *p_info)
 | |
| {
 | |
|     if (NULL == p_info) {
 | |
|         DERROR("Invalid argument!");
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     return at_command_flash_write(AT_CUST_FLASH_START_OFFSET,
 | |
|         sizeof(*p_info), p_info);
 | |
| }
 | |
| 
 | |
| /* Load config from customer flash. */
 | |
| uint32_t at_command_uniform_flashload(custom_flash_info_t *p_info)
 | |
| {
 | |
|     if (NULL == p_info)
 | |
|     {
 | |
|         DERROR("Invalid argument!");
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     return at_command_flash_read(AT_CUST_FLASH_START_OFFSET,
 | |
|         sizeof(*p_info), p_info);
 | |
| }
 | |
| 
 | |
| /* Check the magic code to tell if our config damaged. */
 | |
| uint32_t at_command_uniform_flashinfo_check(custom_flash_info_t *p_info)
 | |
| {
 | |
|     int32_t magic1, magic2;
 | |
| 
 | |
|     if (NULL == p_info)
 | |
|     {
 | |
|         DERROR("Invalid argument!");
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     magic1 = (p_info->magic1[0] << 24) | (p_info->magic1[1] << 16)
 | |
|             | (p_info->magic1[2] << 8) | p_info->magic1[3];
 | |
| 
 | |
|     magic2 = (p_info->magic2[0] << 24) | (p_info->magic2[1] << 16)
 | |
|             | (p_info->magic2[2] << 8) | p_info->magic2[3];
 | |
| 
 | |
|     DINFOR("Magic = 0x%08x, 0x%08x!", magic1, magic2);
 | |
| 
 | |
|     if ((IOT_PROTO_CUST_FLASHINFO_MAGIC1 != magic1)
 | |
|         ||(IOT_PROTO_CUST_FLASHINFO_MAGIC2 != magic2))
 | |
|     {
 | |
|         DERROR("Magic dismatch!");
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| /* Repair this config when it is damaged. */
 | |
| void at_command_uniform_flashinfo_repair(custom_flash_info_t *p_info)
 | |
| {
 | |
|     if (NULL == p_info)
 | |
|     {
 | |
|         DERROR("Invalid argument!");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     os_mem_set(p_info, 0x0, sizeof(*p_info));
 | |
| 
 | |
|     p_info->magic1[0] = (IOT_PROTO_CUST_FLASHINFO_MAGIC1 >> 24) & 0xFF;
 | |
|     p_info->magic1[1] = (IOT_PROTO_CUST_FLASHINFO_MAGIC1 >> 16) & 0xFF;
 | |
|     p_info->magic1[2] = (IOT_PROTO_CUST_FLASHINFO_MAGIC1 >> 8) & 0xFF;
 | |
|     p_info->magic1[3] = (IOT_PROTO_CUST_FLASHINFO_MAGIC1) & 0xFF;
 | |
| 
 | |
|     p_info->magic2[0] = (IOT_PROTO_CUST_FLASHINFO_MAGIC2 >> 24) & 0xFF;
 | |
|     p_info->magic2[1] = (IOT_PROTO_CUST_FLASHINFO_MAGIC2 >> 16) & 0xFF;
 | |
|     p_info->magic2[2] = (IOT_PROTO_CUST_FLASHINFO_MAGIC2 >> 8) & 0xFF;
 | |
|     p_info->magic2[3] = (IOT_PROTO_CUST_FLASHINFO_MAGIC2) & 0xFF;
 | |
| 
 | |
|     /* Write flash. */
 | |
|     if(ERR_OK == at_command_uniform_flashsave(p_info))
 | |
|     {
 | |
|         DINFOR("Repair flash successfully!");
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         DERROR("Repair flash failed!");
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_command_uniform_flashinfo_init(void)
 | |
| {
 | |
|     custom_flash_info_t *p_flash = &uniform_flashinfo_at;
 | |
| 
 | |
|     DINFOR("sizeof(custom_flash_info_t) = %d", sizeof(custom_flash_info_t));
 | |
| 
 | |
|     /* Load and check flash info. */
 | |
|     if ((ERR_FAIL == at_command_uniform_flashload(p_flash))
 | |
|         || (ERR_FAIL == at_command_uniform_flashinfo_check(p_flash)))
 | |
|     {
 | |
|         DERROR("Cannot get uniform custom flash info!");
 | |
| 
 | |
|         at_command_uniform_flashinfo_repair(p_flash);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         /* transpmode load */
 | |
|         at_command_context.transp.transpmode = p_flash->transp.transpmode;
 | |
|         iot_mac_addr_cpy(at_command_context.transp.trans_addr,
 | |
|             p_flash->transp.trans_addr);
 | |
|     }
 | |
| 
 | |
|     at_command_dump_uniform_flash(p_flash);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| uint32_t at_command_cid_convert_from_plc(iot_pkt_t* p_resp_pkt)
 | |
| {
 | |
|     plctxrx_cmd_resp_t *resp = (plctxrx_cmd_resp_t *)iot_pkt_data(p_resp_pkt);
 | |
|     uint32_t cid;
 | |
| 
 | |
|     /* TODO : THE LIST OF PLC COMMAND IDs. */
 | |
|     switch(resp->cid.cid)
 | |
|     {
 | |
|         case PLCTXRX_CID_GRAPP_REG_CONF:
 | |
|         case PLCTXRX_CID_MAC:
 | |
|             cid = AT_CID_MAC;
 | |
|             break;
 | |
|         case PLCTXRX_CID_UART:
 | |
|             cid = AT_CID_UART;
 | |
|             break;
 | |
|         case PLCTXRX_CID_TOPO:
 | |
|             cid = AT_CID_TOPO;
 | |
|             break;
 | |
|         case PLCTXRX_CID_SYSTEMINFO:
 | |
|             cid = AT_CID_SYSTEMINFO;
 | |
|             break;
 | |
|         case PLCTXRX_CID_SEND:
 | |
|             cid = AT_CID_SEND;
 | |
|             break;
 | |
|         case PLCTXRX_CID_WHITELIST:
 | |
|             cid = AT_CID_WHITELIST;
 | |
|             break;
 | |
|         case PLCTXRX_CID_TX_PWR:
 | |
|             cid = AT_CID_RFPOWER;
 | |
|             break;
 | |
|         case PLCTXRX_CID_JOIN_NETWORK:
 | |
|         case PLCTXRX_CID_LEAVE_NETWORK:
 | |
|         case PLCTXRX_CID_FIND_NETWORK:
 | |
|             cid = AT_CID_NETWORK;
 | |
|             break;
 | |
|         default:
 | |
|             cid = 0xFFFFFFFF;
 | |
|     }
 | |
| 
 | |
|     return cid;
 | |
| }
 | |
| 
 | |
| static uint8_t at_command_get_name_lenth(uint8_t *pCmd, uint16_t cmd_length)
 | |
| {
 | |
|     uint8_t i = 0, *p_ch = pCmd;
 | |
| 
 | |
|     for( i = 0; i < cmd_length; i++)
 | |
|     {
 | |
|         if (CR_OR_LF(p_ch[i]) || (p_ch[i] == CH_QUR) || (p_ch[i] == CH_SET)
 | |
|            || ((p_ch[i] >= '0') && (p_ch[i] <= '9')) || p_ch[i] == CH_EOS)
 | |
|         {
 | |
|             return i;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| at_cmd_t *at_command_get_cmd_handle_by_name(uint8_t *name, uint16_t len)
 | |
| {
 | |
|     uint8_t head_len;
 | |
|     uint16_t i = 0;
 | |
|     at_cmd_t *p_cmd_handle, *p_cmd_return = NULL;
 | |
| 
 | |
|     head_len = at_command_get_name_lenth(name, len);
 | |
| 
 | |
|     if (head_len > 0)
 | |
|     {
 | |
|         for (i = 0; i < AT_CID_MAX; i++)
 | |
|         {
 | |
|             p_cmd_handle = &(at_command_context.at_table[i]);
 | |
|             if(p_cmd_handle->head_len == head_len - 3)
 | |
|                 if (os_mem_cmp(name + 3, *(p_cmd_handle->name),   \
 | |
|                     p_cmd_handle->head_len) == 0)
 | |
|                 {
 | |
|                     p_cmd_return = p_cmd_handle;
 | |
|                     break;
 | |
|                 }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return p_cmd_return;
 | |
| }
 | |
| 
 | |
| at_cmd_t *at_command_get_cmd_handle_by_cid(uint32_t cid)
 | |
| {
 | |
|     return (cid < AT_CID_MAX) ? (&(at_command_context.at_table[cid])) : NULL;
 | |
| }
 | |
| 
 | |
| static inline uint32_t at_command_status_is_busy(void)
 | |
| {
 | |
|     at_status_t *p_status = &(at_command_context.status);
 | |
|     uint32_t busy_now = 1;
 | |
| 
 | |
|     at_sem_lock();
 | |
| 
 | |
|     if((NULL == p_status->cur_cmd)
 | |
|         || ((p_status->resp_finished)
 | |
|         && (p_status->handle_runout)))
 | |
|     {
 | |
|         busy_now = 0;
 | |
|     }
 | |
| 
 | |
|     at_sem_release();
 | |
| 
 | |
|     return busy_now;
 | |
| }
 | |
| 
 | |
| uint32_t at_command_get_opcode(uint8_t *name, uint16_t len)
 | |
| {
 | |
|     uint8_t head_len;
 | |
|     uint32_t opcode;
 | |
| 
 | |
|     head_len = at_command_get_name_lenth(name, len);
 | |
| 
 | |
|     if(CR_OR_LF(name[head_len]))
 | |
|     {
 | |
|         opcode = AT_OP_EXECUTE;
 | |
|     }
 | |
|     else if(CH_QUR == name[head_len])
 | |
|     {
 | |
|         opcode = AT_OP_QUERY;
 | |
|     }
 | |
|     else if((CH_SET == name[head_len])
 | |
|         && (CH_QUR == name[head_len + 1]))
 | |
|     {
 | |
|         opcode = AT_OP_TEST;
 | |
|     }
 | |
|     else if(CH_SET == name[head_len])
 | |
|     {
 | |
|         opcode = AT_OP_SET;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         opcode = AT_OP_INVALID;
 | |
|     }
 | |
| 
 | |
|     return opcode;
 | |
| }
 | |
| 
 | |
| /*
 | |
| 
 | |
| e.g.:
 | |
| 
 | |
| AT+EXAMPLE_PING="192.168.1.1,800",128,4,10
 | |
| 
 | |
| IP = 192.168.1.1
 | |
| PORT = 800
 | |
| SIZE = 128
 | |
| TIMEOUT = 4
 | |
| TIMES = 10
 | |
| 
 | |
| return:
 | |
| argc = 4
 | |
| 
 | |
| argv[]:
 | |
| argv[0] = "192.168.1.1,800"
 | |
| argv[1] = 128
 | |
| argv[2] = 4
 | |
| argv[3] = 10
 | |
| 
 | |
| argv[n] has type of string.
 | |
| 
 | |
| */
 | |
| uint32_t at_command_argument_process
 | |
|     (uint8_t *cmd_str, uint32_t len, uint8_t *argv[])
 | |
| {
 | |
|     uint8_t *p_search, *p_standalone = cmd_str + len;
 | |
|     uint32_t argc = 0, in_quotes = 0, i;
 | |
| 
 | |
|     p_search = cmd_str;
 | |
| 
 | |
|     /* Search the real tail of command string. */
 | |
|     while((!CR_OR_LF(*p_search)) && (p_search < p_standalone)) p_search++;
 | |
| 
 | |
|     if(p_search == p_standalone)
 | |
|     {
 | |
|         return argc;
 | |
|     }
 | |
| 
 | |
|     p_standalone = p_search;
 | |
| 
 | |
|     /* Make the tail as EOS. */
 | |
|     *p_standalone = CH_EOS;
 | |
| 
 | |
|     p_search = cmd_str;
 | |
| 
 | |
|     /* Searching the 1st argments, start with '=' or '?' */
 | |
|     while(p_search < p_standalone)
 | |
|     {
 | |
|         if((CH_QUR == *p_search) || (CH_SET == *p_search))
 | |
|         {
 | |
|             break;
 | |
|         }
 | |
|         p_search++;
 | |
|     }
 | |
| 
 | |
|     /* Check "?=" */
 | |
|     if((CH_QUR == *p_search) && (CH_SET == *(p_search + 1)))
 | |
|     {
 | |
|         p_search++;
 | |
|     }
 | |
| 
 | |
|     if(p_search >= p_standalone)
 | |
|     {
 | |
|         return argc;
 | |
|     }
 | |
| 
 | |
|     argv[argc++] = ++p_search;
 | |
| 
 | |
|     /* Searching the following argments, start with ',' */
 | |
|     do
 | |
|     {
 | |
|         if('"' == *p_search)
 | |
|         {
 | |
|             in_quotes = !in_quotes;
 | |
|         }
 | |
| 
 | |
|         if(!in_quotes)
 | |
|         {
 | |
|             if(CH_SPL == *p_search)
 | |
|             {
 | |
|                 if(argc > AT_MAX_ARGC)
 | |
|                 {
 | |
|                     break;
 | |
|                 }
 | |
| 
 | |
|                 /* Set ',' as EOS. */
 | |
|                 *p_search = CH_EOS;
 | |
| 
 | |
|                 if(p_search + 1 < p_standalone)
 | |
|                 {
 | |
|                     argv[argc++] = p_search + 1;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }while(++p_search < p_standalone);
 | |
| 
 | |
|     /* Remove pre- & post- white space chars. */
 | |
|     for(i = 0; i < argc; i++)
 | |
|     {
 | |
|         p_search = argv[i];
 | |
| 
 | |
|         /* Remove pre-chars those are white-space. */
 | |
|         while(CH_EOS != (*p_search) && ISSPACE(*p_search)) p_search++;
 | |
| 
 | |
|         argv[i] = p_search;
 | |
| 
 | |
|         /* Remove post-chars those are white-space. */
 | |
|         p_standalone = p_search;
 | |
|         while(CH_EOS != *p_standalone) p_standalone++;
 | |
| 
 | |
|         /* More than 2 chars, one is EOS and the other is p_search. */
 | |
|         if(p_standalone > p_search + 1)
 | |
|         {
 | |
|             /* One char back. */
 | |
|             p_standalone--;
 | |
| 
 | |
|             while((p_standalone > p_search) && ISSPACE(*p_standalone))
 | |
|             {
 | |
|                 p_standalone--;
 | |
|             }
 | |
| 
 | |
|             *(++p_standalone) = CH_EOS;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /* More than one white space char may case one arg exits. */
 | |
|     if((1 == argc) && (CH_EOS == *argv[0]))
 | |
|     {
 | |
|         argc = 0;
 | |
|     }
 | |
| 
 | |
|     return argc;
 | |
| }
 | |
| 
 | |
| void at_command_cmd_message_handle(iot_pkt_t *p_str_pkt, uint16_t source)
 | |
| {
 | |
|     at_cmd_t *p_at_cmd;
 | |
|     uint8_t *p_cmd_name, *argv[AT_MAX_ARGC];
 | |
|     uint32_t cmd_name_len, opcode, argc;
 | |
|     at_status_t *p_status = &(at_command_context.status);
 | |
| 
 | |
|     (void)source;
 | |
| 
 | |
|     if(NULL == p_str_pkt)
 | |
|     {
 | |
|         DERROR("Message data is NULL.");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_cmd_name = iot_pkt_data(p_str_pkt);
 | |
|     cmd_name_len = iot_pkt_data_len(p_str_pkt);
 | |
| 
 | |
|     p_at_cmd = at_command_get_cmd_handle_by_name
 | |
|         (p_cmd_name, (uint16_t)cmd_name_len);
 | |
|     opcode   = at_command_get_opcode(p_cmd_name, (uint16_t)cmd_name_len);
 | |
| 
 | |
|     /* Check command table again. */
 | |
|     if((NULL == p_at_cmd)
 | |
|         || (AT_OP_INVALID == opcode))
 | |
|     {
 | |
|         DERROR("Invalid command string : %2.64s.", p_cmd_name);
 | |
|         at_command_at_response_to_proto
 | |
|             (AT_RESP_UNKNOWN_CMD, p_cmd_name, cmd_name_len, 1);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     DINFOR("Command:%s, opcode:%d.", *(p_at_cmd->name), opcode);
 | |
| 
 | |
|     at_sem_lock();
 | |
| 
 | |
|     p_status->cur_cmd = p_at_cmd;
 | |
|     p_status->resp_index = 0;
 | |
|     p_status->resp_total = 0;
 | |
| 
 | |
|     p_status->resp_finished = 0;
 | |
|     p_status->handle_runout = 0;
 | |
| 
 | |
|     at_sem_release();
 | |
| 
 | |
|     argc = at_command_argument_process
 | |
|         (p_cmd_name + p_at_cmd->head_len, cmd_name_len - p_at_cmd->head_len,
 | |
|         argv);
 | |
| 
 | |
| #if INCLUDE_AT_COMMAND_DEBUG_PRINT
 | |
|     /* Just for debug. */
 | |
|     for(cmd_name_len = 0; cmd_name_len < argc; cmd_name_len++)
 | |
|     {
 | |
|         DINFOR("argv(%d):%s", cmd_name_len, argv[cmd_name_len]);
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     p_at_cmd->fn_send(opcode, argc, argv);
 | |
| 
 | |
|     at_sem_lock();
 | |
| 
 | |
|     p_status->handle_runout = 1;
 | |
| 
 | |
|     at_sem_release();
 | |
| 
 | |
|     if((0 != p_at_cmd->timeout)
 | |
|         && (!p_status->resp_finished))
 | |
|     {
 | |
|         os_start_timer(at_command_context.tmr, p_at_cmd->timeout * 1000);
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_command_resp_message_handle(iot_pkt_t *p_resp_pkt, uint16_t source)
 | |
| {
 | |
|     uint32_t cid;
 | |
|     at_cmd_t *p_at_cmd;
 | |
| 
 | |
|     if(AT_MSG_SOURCE_PLCTXRX == source)
 | |
|     {
 | |
|         cid = at_command_cid_convert_from_plc(p_resp_pkt);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         DERROR("Unknown message source %d.", source);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_at_cmd = at_command_get_cmd_handle_by_cid(cid);
 | |
| 
 | |
|     if(NULL == p_at_cmd)
 | |
|     {
 | |
|         DERROR("Invalid AT cid %d.", cid);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if(NULL != p_at_cmd->fn_resp)
 | |
|     {
 | |
|         p_at_cmd->fn_resp(p_resp_pkt);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         DERROR("No response handle for cid %d.", cid);
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_command_timeout_message_handle(void)
 | |
| {
 | |
|     at_command_at_response_to_proto(AT_RESP_WAIT_RESP_TIMEOUT, NULL, 0, 1);
 | |
| 
 | |
|     at_sem_lock();
 | |
|     at_command_context.status.resp_finished = 1;
 | |
|     at_sem_release();
 | |
| }
 | |
| 
 | |
| void at_command_message_handle(iot_task_h task_h, iot_task_msg_t *msg)
 | |
| {
 | |
|     at_msg_t *dm_msg = (at_msg_t *)msg;
 | |
| 
 | |
|     DINFOR("Message type=%d, id=%d.", dm_msg->msg.type, dm_msg->msg.id);
 | |
| 
 | |
|     if(AT_MSG_TYPE_COMMAND == MSG_TYPE(dm_msg->msg.type))
 | |
|     {
 | |
|         at_command_cmd_message_handle(dm_msg->data, MSG_SRC(dm_msg->msg.type));
 | |
| 
 | |
|         if(NULL != dm_msg->data)
 | |
|         {
 | |
|             iot_pkt_free(dm_msg->data);
 | |
|         }
 | |
|     }
 | |
|     else if(AT_MSG_TYPE_RESPONSE == MSG_TYPE(dm_msg->msg.type))
 | |
|     {
 | |
|         at_command_resp_message_handle(dm_msg->data, MSG_SRC(dm_msg->msg.type));
 | |
| 
 | |
|         if(NULL != dm_msg->data)
 | |
|         {
 | |
|             iot_pkt_free(dm_msg->data);
 | |
|         }
 | |
|     }
 | |
|     else if(AT_MSG_TYPE_TIMEOUT == MSG_TYPE(dm_msg->msg.type))
 | |
|     {
 | |
|         at_command_timeout_message_handle();
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         if(NULL != dm_msg->data)
 | |
|         {
 | |
|             iot_pkt_free(dm_msg->data);
 | |
|         }
 | |
|         DERROR("Invalid message type %d.", dm_msg->msg.type);
 | |
|     }
 | |
| 
 | |
|     iot_task_free_msg(task_h, &(dm_msg->msg));
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_command_message_cancel(iot_task_h task_h, iot_task_msg_t *msg)
 | |
| {
 | |
|     at_msg_t *dm_msg = (at_msg_t *)msg;
 | |
| 
 | |
|     (void)task_h;
 | |
| 
 | |
|     if(NULL == dm_msg)
 | |
|     {
 | |
|         DERROR("Null message !!");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     switch(dm_msg->msg.id)
 | |
|     {
 | |
|         case PLCTXRX_CID_SEND:
 | |
|         {
 | |
|             if(AT_MSG_SOURCE_PLCTXRX == MSG_SRC(dm_msg->msg.type))
 | |
|             {
 | |
|                 at_handle_response_send_receive(dm_msg->data);
 | |
|             }
 | |
|             break;
 | |
|         }
 | |
|         default:
 | |
|         {
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     iot_pkt_free(dm_msg->data);
 | |
| 
 | |
|     iot_task_free_msg(task_h, &(dm_msg->msg));
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_command_event_handle(iot_task_h task_h, uint32_t event)
 | |
| {
 | |
|     (void)task_h;
 | |
|     (void)event;
 | |
| 
 | |
|     /* No event implements yet. */
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_command_post_message(uint16_t m_type, uint16_t m_id, iot_pkt_t *data)
 | |
| {
 | |
|     at_msg_t *task_msg;
 | |
| 
 | |
|     task_msg = (at_msg_t*)iot_task_alloc_msg_with_reserved
 | |
|         (at_command_context.task, 0);
 | |
| 
 | |
|     if(NULL == task_msg)
 | |
|     {
 | |
|         if(NULL != data)
 | |
|         {
 | |
|             iot_pkt_free(data);
 | |
|         }
 | |
|         DERROR("Alloc message failed !!");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     task_msg->msg.type = m_type;
 | |
|     task_msg->msg.id = m_id;
 | |
|     task_msg->data = data;
 | |
| 
 | |
|     iot_task_queue_msg(at_command_context.task, &task_msg->msg, 0);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| 
 | |
| /* return 1 : found a completed AT command, 0 : AT command not completed yet */
 | |
| uint32_t at_command_at_buffer_hook(uint8_t* buffer, uint16_t buffer_len)
 | |
| {
 | |
|     uint16_t index, len = buffer_len;
 | |
|     at_buf_t *buf = &(at_command_context.at_buffer);
 | |
| 
 | |
|     iot_pkt_t *p_pkt;
 | |
|     uint8_t *rsp_data;
 | |
|     uint32_t rsp_data_len;
 | |
| 
 | |
|     if((buffer_len < 3)
 | |
|         && (('\r' == buffer[0]) || ('\n' == buffer[0]))
 | |
|         && (buf->cmd_flushed))
 | |
|     {
 | |
|         /* Loop this command. */
 | |
|         return 1;
 | |
|     }
 | |
| 
 | |
|     if(buf->cmd_flushed)
 | |
|     {
 | |
|         buf->cmd_flushed = 0;
 | |
|         buf->index = 0;
 | |
|     }
 | |
| 
 | |
|     for(index = 0; index < buffer_len; index++)
 | |
|     {
 | |
|         if (buffer[index] > 127)
 | |
|         {
 | |
|             DERROR("Input invisible character, ASCII:%d.", buffer[index]);
 | |
|             at_command_at_response_to_proto(AT_RESP_UNKNOWN_CMD,
 | |
|                 NULL, 0, true);
 | |
|             return 0;
 | |
|         }
 | |
| 
 | |
|         if(('\r' == buffer[index])
 | |
|             ||('\n' == buffer[index]))
 | |
|         {
 | |
|             len = index + 1;
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if(buf->index + len > AT_HOOK_BUFFER_LEN)
 | |
|     {
 | |
|         /* Drop this command. */
 | |
|         buf->index = 0;
 | |
|         DERROR("Command string overlength.");
 | |
|         return 0;
 | |
|     }
 | |
| 
 | |
|     os_mem_cpy(buf->c + buf->index, buffer, len);
 | |
| 
 | |
|     buf->index += len;
 | |
| 
 | |
|     if(index < buffer_len)
 | |
|     {
 | |
|         buf->cmd_flushed = 1;
 | |
|         buf->c[buf->index] = CH_EOS;
 | |
|         DINFOR("Completed command:%s", buf->c);
 | |
| 
 | |
|         /* Select the appropriate buffer size for print buffer. */
 | |
|         if(NULL == (p_pkt = iot_pkt_alloc(AT_LARGE_BUF_SIZE, AT_COMMAND_MID)))
 | |
|         {
 | |
|             DERROR("No memory!");
 | |
|             at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|             return 1;
 | |
|         }
 | |
| 
 | |
|         rsp_data = iot_pkt_data(p_pkt);
 | |
|         rsp_data_len = iot_sprintf((char *)rsp_data, "\r\n%s", buf->c);
 | |
|         at_command_at_response_to_proto(AT_RESP_FORCE_ECHO,
 | |
|             rsp_data, rsp_data_len, true);
 | |
| 
 | |
|         iot_pkt_free(p_pkt);
 | |
| 
 | |
|         return 1;
 | |
|     }
 | |
| 
 | |
|     DINFOR("Incompleted command.");
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| void at_command_at_response_to_proto
 | |
|     (uint32_t resp, uint8_t* buf, uint32_t blen, uint16_t resp_finished)
 | |
| {
 | |
|     at_status_t *p_status = &(at_command_context.status);
 | |
|     char *p_resp_str;
 | |
|     uint32_t ret_pkt_len;
 | |
|     iot_pkt_t *p_resp_pkt;
 | |
|     uint8_t *p_pkt_buf;
 | |
| 
 | |
|     if(((!resp_finished) && ((NULL == buf) || (0 == blen)))
 | |
|         || (NULL == at_command_context.fn_callback.fn_resp))
 | |
|     {
 | |
|         DINFOR("Nothing to response.");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     switch(resp)
 | |
|     {
 | |
|         case AT_RESP_OK:
 | |
|         {
 | |
|             p_resp_str = AT_RESP_STR_OK;
 | |
|             break;
 | |
|         }
 | |
|         case AT_RESP_BUSY:
 | |
|         {
 | |
|             p_resp_str = AT_RESP_STR_BUSY;
 | |
|             break;
 | |
|         }
 | |
|         case AT_RESP_UNKNOWN_CMD:
 | |
|         {
 | |
|             p_resp_str = AT_RESP_STR_UNKNOWN;
 | |
|             break;
 | |
|         }
 | |
|         case AT_RESP_INVALID_ARGUMENT:
 | |
|         {
 | |
|             p_resp_str = AT_RESP_STR_INVALID_ARG;
 | |
|             break;
 | |
|         }
 | |
|         case AT_RESP_WAIT_RESP_TIMEOUT:
 | |
|         {
 | |
|             p_resp_str = AT_RESP_STR_TIMEOUT;
 | |
|             break;
 | |
|         }
 | |
|         case AT_RESP_SET_FINISH_WITHOUT_ECHO:
 | |
|         {
 | |
|             /* We just set finish-flag if NOT_REPORT */
 | |
|             if(resp_finished)
 | |
|             {
 | |
|                 at_sem_lock();
 | |
|                 p_status->resp_finished = resp_finished;
 | |
|                 at_sem_release();
 | |
|             }
 | |
| 
 | |
|             DINFOR("AT response nothing.");
 | |
| 
 | |
|             return;
 | |
|         }
 | |
|         case AT_RESP_FORCE_ECHO:
 | |
|         case AT_RESP_ERROR:
 | |
|         default:
 | |
|         {
 | |
|             p_resp_str = AT_RESP_STR_ERROR;
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     ret_pkt_len = iot_strlen(p_resp_str) + AT_HOOK_BUFFER_LEN + blen;
 | |
| 
 | |
|     if(NULL == (p_resp_pkt = iot_pkt_alloc(ret_pkt_len, AT_COMMAND_MID)))
 | |
|     {
 | |
|         DERROR("Cannot get packet len#%d!!", ret_pkt_len);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_pkt_buf = iot_pkt_data(p_resp_pkt);
 | |
| 
 | |
|     ret_pkt_len = 0;
 | |
| 
 | |
|     if((blen > 0) && (NULL != buf))
 | |
|     {
 | |
|         os_mem_cpy(p_pkt_buf, buf, blen);
 | |
|         ret_pkt_len += blen;
 | |
|         p_pkt_buf += blen;
 | |
|     }
 | |
| 
 | |
|     if((AT_RESP_BUSY != resp)
 | |
|         && (AT_RESP_FORCE_ECHO != resp))
 | |
|     {
 | |
|         if (os_is_timer_active(at_command_context.tmr))
 | |
|         {
 | |
|             os_stop_timer(at_command_context.tmr);
 | |
|             iot_task_clean_msg(at_command_context.task,
 | |
|                 AT_MSG_TYPE_TIMEOUT | AT_MSG_SOURCE_LOCAL, 0);
 | |
|         }
 | |
| 
 | |
|         if(!resp_finished)
 | |
|         {
 | |
|             if (NULL == p_status->cur_cmd) {
 | |
|                 DERROR("p_status's field:cur_cmd is NULL");
 | |
|             } else {
 | |
|                 os_start_timer
 | |
|                     (at_command_context.tmr, p_status->cur_cmd->timeout * 1000);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if(resp_finished)
 | |
|     {
 | |
|         if(AT_RESP_FORCE_ECHO != resp)
 | |
|         {
 | |
|             if((NULL != p_status->cur_cmd)
 | |
|                 && (NULL != *(p_status->cur_cmd->name)))
 | |
|             {
 | |
|                 ret_pkt_len += iot_sprintf((char *)p_pkt_buf, p_resp_str,
 | |
|                     *(p_status->cur_cmd->name));
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 ret_pkt_len += iot_sprintf((char *)p_pkt_buf, p_resp_str, "N/A");
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         at_sem_lock();
 | |
|         p_status->resp_finished = resp_finished;
 | |
|         at_sem_release();
 | |
|     }
 | |
| 
 | |
|     DINFOR("AT response datalen=%d, string=%s.", ret_pkt_len, p_pkt_buf);
 | |
| 
 | |
|     iot_pkt_put(p_resp_pkt, ret_pkt_len);
 | |
| 
 | |
|     at_command_context.fn_callback.fn_resp(p_resp_pkt);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_command_timer_func(timer_id_t timer_id, void * arg)
 | |
| {
 | |
|     (void)timer_id;
 | |
|     (void)arg;
 | |
| 
 | |
|     at_command_post_message(AT_MSG_TYPE_TIMEOUT | AT_MSG_SOURCE_LOCAL, 0, NULL);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_command_end_pmode_timer_func(timer_id_t timer_id, void * arg)
 | |
| {
 | |
|     (void)timer_id;
 | |
|     (void)arg;
 | |
|     custom_flash_info_t *p_flash = &uniform_flashinfo_at;
 | |
|     uint8_t *p_data;
 | |
|     uint32_t data_len;
 | |
|     iot_pkt_t *p_pkt;
 | |
| 
 | |
|     DINFOR("end_pmode time out");
 | |
|     /* clean transpmode if not recv data after set end_pmode_timer */
 | |
|     if (recv_blen == 0) {
 | |
|         if(NULL == (p_pkt = iot_pkt_alloc(AT_MID_BUF_SIZE, AT_COMMAND_MID)))
 | |
|         {
 | |
|             DERROR("No memory!");
 | |
|             at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|             return;
 | |
|         }
 | |
|         p_data = iot_pkt_data(p_pkt);
 | |
| 
 | |
|         at_command_context.transp.transpmode = false;
 | |
|         os_mem_set(at_command_context.transp.trans_addr, 0, IOT_MAC_ADDR_LEN);
 | |
| 
 | |
|         data_len = iot_sprintf((char *)p_data,
 | |
|             "data recv from UART will be transparent as command\n");
 | |
|         p_flash->transp.transpmode = false;
 | |
|         /* Write flash. */
 | |
|         if (ERR_OK == at_command_uniform_flashsave(p_flash)){
 | |
|             DINFOR("Whitelist save to flash successfully!");
 | |
|         } else {
 | |
|             DERROR("Whitelist save to flash failed!");
 | |
|         }
 | |
| 
 | |
|         /* Just finish transpmode with response. */
 | |
|         at_command_at_response_to_proto(AT_RESP_FORCE_ECHO,
 | |
|             p_data, data_len, true);
 | |
|         iot_pkt_free(p_pkt);
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| int at_command_char_2_digtal(char ch)
 | |
| {
 | |
|     int ch_ret = -1;
 | |
| 
 | |
|     if('0' <= ch && '9' >= ch)
 | |
|     {
 | |
|         ch_ret = (((int)ch) & 0xFF) - '0';
 | |
|     }
 | |
|     else if('a' <= ch && 'z' >= ch)
 | |
|     {
 | |
|         ch_ret = (((int)ch) & 0xFF) - 'a' + 0xA;
 | |
|     }
 | |
|     else if('A' <= ch && 'Z' >= ch)
 | |
|     {
 | |
|         ch_ret = (((int)ch) & 0xFF) - 'A' + 0xA;
 | |
|     }
 | |
| 
 | |
|     return ch_ret;
 | |
| }
 | |
| 
 | |
| uint32_t at_command_uint32_2_digtal(uint8_t *string_ptr, uint32_t *output_ptr)
 | |
| {
 | |
|     uint32_t temp_output;
 | |
|     uint8_t *input_ptr;
 | |
|     uint32_t result = 0;
 | |
|     int ret_ch;
 | |
| 
 | |
|     input_ptr = string_ptr;
 | |
|     temp_output = 0;
 | |
| 
 | |
|     if ((NULL == input_ptr) || (NULL == input_ptr))
 | |
|     {
 | |
|         return result;
 | |
|     }
 | |
| 
 | |
|     /* Find the 1st valid char. */
 | |
|     while(*input_ptr != CH_EOS)
 | |
|     {
 | |
|         ret_ch = at_command_char_2_digtal(*input_ptr);
 | |
| 
 | |
|         if(((0 <= ret_ch) && (9 >= ret_ch)))
 | |
|         {
 | |
|             break;
 | |
|         }
 | |
| 
 | |
|         input_ptr++;
 | |
|     }
 | |
| 
 | |
|     while(true)
 | |
|     {
 | |
|         ret_ch = at_command_char_2_digtal(*input_ptr);
 | |
| 
 | |
|         if(((0 > ret_ch) || (9 < ret_ch)))
 | |
|         {
 | |
|             break;
 | |
|         }
 | |
| 
 | |
|         if(temp_output <= 429496729)
 | |
|         {
 | |
|             if(temp_output == 429496729)
 | |
|             {
 | |
|                 if(ret_ch > 5)
 | |
|                 {
 | |
|                   break;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             temp_output = temp_output * 10 + ret_ch;
 | |
| 
 | |
|             input_ptr++;
 | |
|             result++;
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|           break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     *output_ptr = temp_output;
 | |
| 
 | |
|     return result;
 | |
| }
 | |
| 
 | |
| /*
 | |
| if
 | |
| p_hex_string = "0xefef77K8" or "efef77K8"
 | |
| then
 | |
| p_hex_out = 0xefef77
 | |
| return 6
 | |
| if
 | |
| */
 | |
| uint32_t at_command_hex_2_digtal(uint8_t *p_hex_string, uint32_t *p_hex_out)
 | |
| {
 | |
|     uint8_t *p_ch = p_hex_string;
 | |
|     uint32_t chars_in_32bit = 0, value = 0;
 | |
|     int ret_ch;
 | |
| 
 | |
|     if((NULL == p_hex_string)
 | |
|         || (NULL == p_hex_out))
 | |
|     {
 | |
|         return 0;
 | |
|     }
 | |
| 
 | |
|     /* Find the 1st valid char. */
 | |
|     while((at_command_char_2_digtal(*p_ch) < 0) && ('\0' != *p_ch)) p_ch++;
 | |
| 
 | |
|     /* Check "0x" or "0X". */
 | |
|     if(('0' == *p_ch) && (('x' == *(p_ch + 1)) || ('X' == *(p_ch + 1))))
 | |
|     {
 | |
|         p_ch += 2;
 | |
|     }
 | |
| 
 | |
|     while((chars_in_32bit < 8) && '\0' != *p_ch)
 | |
|     {
 | |
|         ret_ch = at_command_char_2_digtal(*p_ch);
 | |
| 
 | |
|         /* Exit if a invalid char meets. */
 | |
|         if(ret_ch < 0)
 | |
|         {
 | |
|             break;
 | |
|         }
 | |
| 
 | |
|         value = (value << 4) | (ret_ch & 0xF);
 | |
| 
 | |
|         p_ch++;
 | |
|         chars_in_32bit++;
 | |
|     }
 | |
| 
 | |
|     *p_hex_out = value;
 | |
| 
 | |
|     return chars_in_32bit;
 | |
| }
 | |
| 
 | |
| /*
 | |
| 
 | |
| ' ' , ':' and '-' will be regard as split-chars.
 | |
| 
 | |
| if
 | |
| p_hex_in = "Fe-77:99999 ae-f 55 aa bb"
 | |
| bytes_2_get = 6
 | |
| then
 | |
| byte_out[] = {0xfe, 0x77, 0x99, 0xae, 0xf, 0x55}
 | |
| return 6
 | |
| fi
 | |
| 
 | |
| */
 | |
| uint32_t at_command_string_2_digtal
 | |
|     (uint8_t *p_hex_in, uint8_t bytes_out[], uint32_t bytes_2_get)
 | |
| {
 | |
|     uint32_t bytes_valid = 0;
 | |
|     uint8_t *p_ch = p_hex_in, byte;
 | |
|     int ret_ch;
 | |
| 
 | |
|     if((NULL == p_hex_in)
 | |
|         ||(NULL == bytes_out)
 | |
|         ||(0 >= bytes_2_get))
 | |
|     {
 | |
|         /* Nothing to output. */
 | |
|         return 0;
 | |
|     }
 | |
| 
 | |
|     /* Find the 1st valid char. */
 | |
|     while((at_command_char_2_digtal(*p_ch) < 0) && ('\0' != *p_ch)) p_ch++;
 | |
| 
 | |
|     /* Get digtal bytes start. */
 | |
|     while((bytes_valid < bytes_2_get) && ('\0' != *p_ch))
 | |
|     {
 | |
|         if((ret_ch = at_command_char_2_digtal(*p_ch)) >= 0)
 | |
|         {
 | |
|             p_ch++;
 | |
| 
 | |
|             byte = (uint8_t)(ret_ch & 0xF);
 | |
| 
 | |
|             if((ret_ch = at_command_char_2_digtal(*p_ch)) >= 0)
 | |
|             {
 | |
|                 p_ch++;
 | |
| 
 | |
|                 byte = (uint8_t)((byte << 4) | (ret_ch & 0xF));
 | |
|             }
 | |
| 
 | |
|             bytes_out[bytes_valid++] = byte;
 | |
|         }
 | |
|         else if(!CH_IS_SPLIT(*p_ch))
 | |
|         {
 | |
|             /* Stop if there is char that is not digtal or split. */
 | |
|             break;
 | |
|         }
 | |
| 
 | |
|         /* Skip the rest of valid chars. */
 | |
|         while((at_command_char_2_digtal(*p_ch) >= 0) && ('\0' != *p_ch)) p_ch++;
 | |
| 
 | |
|         /* Skip the split chars if there is more than one. */
 | |
|         while(CH_IS_SPLIT(*p_ch) && ('\0' != *p_ch)) p_ch++;
 | |
| 
 | |
|     }
 | |
| 
 | |
|     return bytes_valid;
 | |
| }
 | |
| 
 | |
| void at_command_send_to_plc(iot_pkt_t *p_pkt)
 | |
| {
 | |
| #if INCLUDE_AT_COMMAND_DEBUG_PRINT
 | |
|     plctxrx_cmd_arg_t *p_arg;
 | |
|     p_arg = (plctxrx_cmd_arg_t *)iot_pkt_data(p_pkt);
 | |
| #endif
 | |
| 
 | |
|     if(!at_is_firedup())
 | |
|     {
 | |
|         DERROR("AT module not ready.");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
| #if INCLUDE_AT_COMMAND_DEBUG_PRINT
 | |
|     DINFOR("Command to PLC : CID#0x%x, OPCODE#0x%x.", p_arg->cid.cid,
 | |
|     p_arg->cid.opcode);
 | |
| #endif
 | |
| 
 | |
|     at_command_context.fn_callback.fn_send(p_pkt);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| uint8_t iot_at_command_proto_send_to_at(uint8_t *buf, uint16_t blen)
 | |
| {
 | |
|     iot_pkt_t *p_cmd_pkt;
 | |
|     uint8_t *p_cmd_str;
 | |
|     uint16_t cmd_str_len;
 | |
|     at_cmd_t *p_at_cmd;
 | |
| 
 | |
|     if(!at_is_firedup())
 | |
|     {
 | |
|         DERROR("AT module not ready.");
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     if (at_command_context.transp.transpmode) {
 | |
|         //check TRANSPARENT_KEYWORDS
 | |
|         recv_blen += blen;
 | |
|         if (blen == TRANSPARENT_KEYWORDS_LEN &&
 | |
|             0 == os_mem_cmp((char*)buf, TRANSPARENT_KEYWORDS, blen)) {
 | |
|             /* start end transparent timer */
 | |
|             DINFOR("recv end transpmode string");
 | |
|             if (os_is_timer_active(at_command_context.end_tmode_tmr)) {
 | |
|                 os_stop_timer(at_command_context.end_tmode_tmr);
 | |
|                 iot_task_clean_msg(at_command_context.task,
 | |
|                     AT_MSG_TYPE_TIMEOUT | AT_MSG_SOURCE_LOCAL, 0);
 | |
|             }
 | |
|             os_start_timer(at_command_context.end_tmode_tmr,
 | |
|                 AT_TMR_CHECK_END_PMODE);
 | |
|             recv_blen = 0;
 | |
|             return ERR_OK;
 | |
|         }
 | |
|         if (ERR_NOMEM == at_handle_transparent_data(buf, blen)) {
 | |
|             at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|         } else {
 | |
|             at_command_at_response_to_proto(AT_RESP_SET_FINISH_WITHOUT_ECHO,
 | |
|                 NULL, 0, true);
 | |
|         }
 | |
|         return ERR_OK;
 | |
|     }
 | |
| 
 | |
|     if(!at_command_at_buffer_hook(buf, blen))
 | |
|     {
 | |
|         return ERR_OK;
 | |
|     }
 | |
| 
 | |
|     if(at_command_status_is_busy())
 | |
|     {
 | |
|         DERROR("AT module BUSY.");
 | |
|         at_command_at_response_to_proto(AT_RESP_BUSY, NULL, 0, false);
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     p_cmd_str   = at_command_context.at_buffer.c;
 | |
|     cmd_str_len = at_command_context.at_buffer.index;
 | |
| 
 | |
|     p_at_cmd = at_command_get_cmd_handle_by_name(p_cmd_str, cmd_str_len);
 | |
| 
 | |
|     if(NULL == p_at_cmd)
 | |
|     {
 | |
|         DERROR("Cannot find:%s.", p_cmd_str);
 | |
|         at_command_at_response_to_proto
 | |
|             (AT_RESP_UNKNOWN_CMD, p_cmd_str, cmd_str_len, true);
 | |
|         return ERR_OK;
 | |
|     }
 | |
| 
 | |
|     at_sem_lock();
 | |
| 
 | |
|     /*
 | |
|     Fill current executing command to announce AT has command to executing now.
 | |
|     */
 | |
|     at_command_context.status.cur_cmd = p_at_cmd;
 | |
| 
 | |
|     at_sem_release();
 | |
| 
 | |
|     if(NULL == (p_cmd_pkt = iot_pkt_alloc(cmd_str_len, AT_COMMAND_MID)))
 | |
|     {
 | |
|         DERROR("Cannot get packet length=%d.", cmd_str_len);
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     os_mem_cpy(iot_pkt_put(p_cmd_pkt, cmd_str_len), p_cmd_str, cmd_str_len);
 | |
| 
 | |
|     at_command_post_message(AT_MSG_TYPE_COMMAND | AT_MSG_SOURCE_UART,
 | |
|         0, p_cmd_pkt);
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| uint8_t iot_at_command_plc_send_response_to_at(iot_pkt_t *p_resp_pkt)
 | |
| {
 | |
|     plctxrx_cmd_resp_t *p_resp;
 | |
|     uint16_t index, total;
 | |
| 
 | |
|     at_status_t *p_status = &(at_command_context.status);
 | |
| 
 | |
|     if(NULL == p_resp_pkt)
 | |
|     {
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     if(!at_is_firedup())
 | |
|     {
 | |
|         DERROR("AT module not ready.");
 | |
|         iot_pkt_free(p_resp_pkt);
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     p_resp = (plctxrx_cmd_resp_t *)iot_pkt_data(p_resp_pkt);
 | |
| 
 | |
|     index = p_resp->index.current;
 | |
|     total = p_resp->index.total;
 | |
| 
 | |
|     /* Post before update status. */
 | |
|     at_command_post_message(AT_MSG_TYPE_RESPONSE | AT_MSG_SOURCE_PLCTXRX,
 | |
|         p_resp->cid.cid, p_resp_pkt);
 | |
| 
 | |
|     at_sem_lock();
 | |
| 
 | |
|     /* Do not care about lost response frames. */
 | |
|     p_status->resp_index = index;
 | |
|     p_status->resp_total = total;
 | |
| 
 | |
|     at_sem_release();
 | |
| 
 | |
|     DINFOR("Response from PLC : CID#0x%x, OPCODE#0x%x, INDEX#%d/%d.",
 | |
|         p_resp->cid.cid, p_resp->cid.opcode, p_resp->index.current,
 | |
|         p_resp->index.total);
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| uint8_t iot_at_command_fn_register_response_to_uart(at_fn_response_from_at_t fn)
 | |
| {
 | |
|     if(!at_is_firedup())
 | |
|     {
 | |
|         DERROR("AT module not ready.");
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     at_command_context.fn_callback.fn_resp = fn;
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| uint8_t iot_at_command_fn_register_send_to_plc(at_fn_send_from_at_t fn)
 | |
| {
 | |
|     if(!at_is_firedup())
 | |
|     {
 | |
|         DERROR("AT module not ready.");
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     at_command_context.fn_callback.fn_send = fn;
 | |
| 
 | |
|     at_command_uniform_flashinfo_init();
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| void iot_at_task_deinit(void)
 | |
| {
 | |
|     if(NULL != at_command_context.task)
 | |
|     {
 | |
|         iot_task_delete(at_command_context.task);
 | |
|         at_command_context.task = NULL;
 | |
|     }
 | |
| 
 | |
|     if(0 != at_command_context.tmr)
 | |
|     {
 | |
|         os_delete_timer(at_command_context.tmr);
 | |
|         at_command_context.tmr = 0;
 | |
|     }
 | |
| 
 | |
|     if(NULL != at_command_context.sem)
 | |
|     {
 | |
|         os_delete_mutex(at_command_context.sem);
 | |
|         at_command_context.sem = NULL;
 | |
|     }
 | |
| 
 | |
|     os_mem_set(&at_command_context, 0x0, sizeof(at_command_context));
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void iot_print_config(bool_t enable);
 | |
| 
 | |
| iot_task_h iot_at_task_init(void)
 | |
| {
 | |
|     iot_task_config_t t_cfg;
 | |
|     int cmd_index;
 | |
|     at_cmd_t *p_cmd;
 | |
| 
 | |
|     at_command_uart_cfg.port = iot_board_get_uart(UART_CUS_PORT_0);
 | |
| 
 | |
|     if(at_is_firedup())
 | |
|     {
 | |
|         DERROR("AT command module already initialized.");
 | |
|         return at_command_context.task;
 | |
|     }
 | |
| 
 | |
|     DINFOR("AT command module initializing...");
 | |
| 
 | |
|     os_mem_set(&at_command_context, 0x0, sizeof(at_command_context));
 | |
| 
 | |
|     p_cmd = &(at_command_context.at_table[0]);
 | |
| 
 | |
|     for(cmd_index = 0; cmd_index < AT_CID_MAX; cmd_index++)
 | |
|     {
 | |
|         p_cmd->head_len = (uint8_t)iot_strlen
 | |
|             (*(at_command_table[cmd_index].name));
 | |
|         p_cmd->name = at_command_table[cmd_index].name;
 | |
|         p_cmd->prio = at_command_table[cmd_index].prio;
 | |
|         p_cmd->timeout = at_command_table[cmd_index].timeout;
 | |
|         p_cmd->fn_send = at_command_table[cmd_index].fn_send;
 | |
|         p_cmd->fn_resp = at_command_table[cmd_index].fn_resp;
 | |
| 
 | |
|         DINFOR("Command Add-\r\nname:%s\r\nHead len:%d\r\nPriority:%d\r\n"\
 | |
|             "Timeout:%d\r\nfn_send:0x%08x\r\nfn_resp:0x%08x",
 | |
|             *(p_cmd->name), p_cmd->head_len, p_cmd->prio, p_cmd->timeout,
 | |
|             p_cmd->fn_send, p_cmd->fn_resp);
 | |
| 
 | |
|         p_cmd++;
 | |
|     }
 | |
| 
 | |
|     t_cfg.stack_size       = 0;
 | |
|     t_cfg.task_prio        = AT_PRIO_NOR;
 | |
|     t_cfg.msg_size         = sizeof(at_msg_t);
 | |
|     t_cfg.msg_cnt          = AT_TASK_MSG_CNT;
 | |
|     t_cfg.queue_cnt        = 1;
 | |
|     t_cfg.queue_cfg[0].quota = 0;
 | |
|     t_cfg.task_event_func  = at_command_event_handle;
 | |
|     t_cfg.msg_exe_func     = at_command_message_handle;
 | |
|     t_cfg.msg_cancel_func  = at_command_message_cancel;
 | |
| 
 | |
|     at_command_context.task = iot_task_create(AT_COMMAND_MID, &t_cfg);
 | |
| 
 | |
|     if(NULL == at_command_context.task)
 | |
|     {
 | |
|         DERROR("Create task failed.");
 | |
|         goto init_err_handle;
 | |
|     }
 | |
| 
 | |
|     at_command_context.tmr = os_create_timer
 | |
|         (AT_COMMAND_MID, 0, at_command_timer_func, 0);
 | |
| 
 | |
|     if(0 == at_command_context.tmr)
 | |
|     {
 | |
|         DERROR("Create timer failed.");
 | |
|         goto init_err_handle;
 | |
|     }
 | |
| 
 | |
|     at_command_context.end_tmode_tmr = os_create_timer(AT_COMMAND_MID, 0,
 | |
|        at_command_end_pmode_timer_func, 0);
 | |
| 
 | |
|     if (0 == at_command_context.end_tmode_tmr) {
 | |
|         DERROR("Create end_tmode_tmr timer failed.");
 | |
|         goto init_err_handle;
 | |
|     }
 | |
| 
 | |
|     at_command_context.sem = os_create_mutex(AT_COMMAND_MID);
 | |
| 
 | |
|     if(NULL == at_command_context.sem)
 | |
|     {
 | |
|         DERROR("Create semaphore failed.");
 | |
|         goto init_err_handle;
 | |
|     }
 | |
| 
 | |
| #if PLC_SUPPORT_CCO_ROLE
 | |
|     at_command_context.dev_type = IOT_PLC_DEV_ROLE_CCO;
 | |
| #else
 | |
|     at_command_context.dev_type = IOT_PLC_DEV_ROLE_STA;
 | |
| #endif
 | |
| 
 | |
|     at_fire_now();
 | |
| 
 | |
|     DINFOR("AT command module initailized seccussfully!");
 | |
| 
 | |
|     return at_command_context.task;
 | |
| 
 | |
| init_err_handle:
 | |
| 
 | |
|     iot_at_task_deinit();
 | |
| 
 | |
|     DINFOR("AT command module initailized failed!");
 | |
| 
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| at_context_t *iot_at_context_get(void)
 | |
| {
 | |
|     if(!at_is_firedup())
 | |
|     {
 | |
|         DERROR("AT module not ready.");
 | |
|         return NULL;
 | |
|     }
 | |
| 
 | |
|     return &at_command_context;
 | |
| }
 | |
| 
 | |
| void at_handle_command_help(uint32_t opcode, uint32_t argc, uint8_t *argv[])
 | |
| {
 | |
|     (void)opcode;
 | |
|     (void)argc;
 | |
|     (void)argv;
 | |
|     uint32_t i, send_len = 0;
 | |
|     iot_pkt_t *p_pkt;
 | |
|     uint8_t *r_data;
 | |
| 
 | |
|     if (NULL == (p_pkt = iot_pkt_alloc(AT_LARGE_BUF_SIZE, AT_COMMAND_MID))) {
 | |
|         DERROR("alloc memory ERR!");
 | |
|         at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0 , 1);
 | |
|         return;
 | |
|     }
 | |
|     r_data = iot_pkt_data(p_pkt);
 | |
| 
 | |
|     for (i = 0; i < AT_CID_MAX; i++) {
 | |
|         send_len += iot_sprintf((char*)r_data + send_len, "\r\n%03d:%s",
 | |
|             (int)i, *(at_command_context.at_table[i].name));
 | |
|         if (0 == (i + 1) % AT_LIST_ITEMS_PER_COMMAND ||
 | |
|             (i+1) == AT_CID_MAX) {
 | |
|             at_command_at_response_to_proto(AT_RESP_OK, r_data, send_len,
 | |
|                 ((i+1) == AT_CID_MAX) ? 1 : 0);
 | |
|             send_len = 0;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     iot_pkt_free(p_pkt);
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_handle_command_mac(uint32_t opcode, uint32_t argc, uint8_t *argv[])
 | |
| {
 | |
|     uint32_t pkt_len;
 | |
|     iot_pkt_t *p_pkt;
 | |
|     plctxrx_cmd_arg_t *p_arg;
 | |
|     at_cmd_t *p_cmd_line = at_command_get_cmd_handle_by_cid(AT_CID_MAC);
 | |
| 
 | |
|     uint8_t mac[IOT_MAC_ADDR_LEN];
 | |
|     plctxrx_handle_mac_t *p_mac_hd;
 | |
|     custom_flash_info_t *p_flash = &uniform_flashinfo_at;
 | |
| 
 | |
|     uint8_t *rsp_data;
 | |
|     uint32_t rsp_data_len;
 | |
| 
 | |
|     if(((AT_OP_QUERY != opcode) && (AT_OP_SET != opcode))
 | |
|         ||((AT_OP_SET == opcode) && ((argc != 1)
 | |
|             ||(IOT_MAC_ADDR_LEN != at_command_string_2_digtal
 | |
|                 (argv[0], mac, IOT_MAC_ADDR_LEN)))))
 | |
|     {
 | |
|         DERROR("Invalid argument!");
 | |
|         at_command_at_response_to_proto
 | |
|             (AT_RESP_INVALID_ARGUMENT, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (AT_OP_SET == opcode)
 | |
|     {
 | |
|         /* Check input MAC address is same with MAC address saved in flash. */
 | |
|         if (1 == iot_mac_addr_cmp(p_flash->local_mac, mac))
 | |
|         {
 | |
|             DINFOR("Set the same mac!");
 | |
|             at_command_at_response_to_proto(AT_RESP_OK, NULL, 0, true);
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         /* Update the AT layer local MAC address. */
 | |
|         iot_mac_addr_cpy(at_command_context.mac, mac);
 | |
| 
 | |
|         pkt_len = sizeof(*p_arg) + sizeof(*p_mac_hd);
 | |
|         if (NULL == (p_pkt = iot_pkt_alloc(pkt_len, AT_COMMAND_MID)))
 | |
|         {
 | |
|             DERROR("No memory!");
 | |
|             at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         p_arg = (plctxrx_cmd_arg_t *)iot_pkt_put(p_pkt, pkt_len);
 | |
|         p_arg->cid.cid = PLCTXRX_CID_MAC;
 | |
|         p_arg->cid.opcode = PLCTXRX_OP_CONFIG;
 | |
|         p_arg->prio = p_cmd_line->prio;
 | |
|         p_arg->dlen = sizeof(*p_mac_hd);
 | |
|         p_arg->need_ack = true;
 | |
| 
 | |
|         p_mac_hd = (plctxrx_handle_mac_t *)p_arg->arg;
 | |
|         iot_mac_addr_cpy(p_mac_hd->mac, at_command_context.mac);
 | |
|         p_mac_hd->dev_type = p_flash->local_type;
 | |
| 
 | |
|         at_command_send_to_plc(p_pkt);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         /* Select the appropriate buffer size for print buffer. */
 | |
|         if(NULL == (p_pkt = iot_pkt_alloc(AT_MID_BUF_SIZE, AT_COMMAND_MID)))
 | |
|         {
 | |
|             DERROR("No memory!");
 | |
|             at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         rsp_data = iot_pkt_data(p_pkt);
 | |
| 
 | |
|         rsp_data_len = iot_sprintf((char *)rsp_data,
 | |
|             "\r\nThe device MAC address is:[%02X:%02X:%02X:%02X:%02X:%02X]." \
 | |
|             "\r\nThe device module type is %d.",
 | |
|             p_flash->local_mac[0], p_flash->local_mac[1],
 | |
|             p_flash->local_mac[2], p_flash->local_mac[3],
 | |
|             p_flash->local_mac[4], p_flash->local_mac[5],
 | |
|             p_flash->local_type);
 | |
| 
 | |
|         at_command_at_response_to_proto(AT_RESP_OK, rsp_data, rsp_data_len, true);
 | |
| 
 | |
|         iot_pkt_free(p_pkt);
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_handle_response_mac(iot_pkt_t *p_resp_pkt)
 | |
| {
 | |
|     plctxrx_cmd_resp_t *p_resp;
 | |
|     iot_pkt_t *p_pkt;
 | |
|     uint8_t *p_data;
 | |
|     uint32_t data_len, ret;
 | |
| 
 | |
|     uint32_t pkt_len;
 | |
|     plctxrx_cmd_arg_t *p_arg;
 | |
|     at_cmd_t *p_cmd_line = at_command_get_cmd_handle_by_cid(AT_CID_MAC);
 | |
|     plctxrx_handle_mac_t *p_mac_hd;
 | |
|     iot_oem_base_cfg_t *oem_base_cfg;
 | |
|     custom_flash_info_t *p_flash = &uniform_flashinfo_at;
 | |
| 
 | |
|     if(NULL == p_resp_pkt)
 | |
|     {
 | |
|         DERROR("Invalid argument!");
 | |
|         at_command_at_response_to_proto
 | |
|             (AT_RESP_INVALID_ARGUMENT, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_resp = (plctxrx_cmd_resp_t *)iot_pkt_data(p_resp_pkt);
 | |
| 
 | |
|     if (PLCTXRX_OP_CFM == p_resp->cid.opcode)
 | |
|     {
 | |
|         /* Update MAC address saved in flash. */
 | |
|         iot_mac_addr_cpy(p_flash->local_mac, at_command_context.mac);
 | |
|         if(ERR_OK != at_command_uniform_flashsave(p_flash))
 | |
|         {
 | |
|             DERROR("Local MAC address save to flash failed!");
 | |
|             at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         /* Select the appropriate buffer size for print buffer. */
 | |
|         if(NULL == (p_pkt = iot_pkt_alloc(AT_MID_BUF_SIZE, AT_COMMAND_MID)))
 | |
|         {
 | |
|             DERROR("No memory!");
 | |
|             at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         p_data = iot_pkt_data(p_pkt);
 | |
| 
 | |
|         data_len = iot_sprintf((char *)p_data,
 | |
|             "\r\nSet the device MAC address %s!",
 | |
|             (PLCTXRX_RESP_OK != p_resp->resp) ? "failed" : "successfully");
 | |
| 
 | |
|         ret = (PLCTXRX_RESP_OK == p_resp->resp) ? AT_RESP_OK : AT_RESP_ERROR;
 | |
|         at_command_at_response_to_proto(ret, p_data, data_len, true);
 | |
| 
 | |
|         /* CCO or STA will enable whitelist if whitelist not empty when power on. */
 | |
|         if (p_flash->dev_cnt > 0)
 | |
|         {
 | |
|             /* Add/Delete whitelist to/from CVG layer.*/
 | |
|             at_command_cvg_wl_add_del(AT_WL_ACTION_ADD, NULL, false);
 | |
|             os_delay(AT_WL_OP_DELAY_MS);
 | |
|             at_command_cvg_wl_en_disable(AT_WL_ACTION_ENABLE, false);
 | |
|             /* Update the whitelist config enable/disable state. */
 | |
|             at_command_context.wl_cfg_state = AT_WL_CFG_STATE_ENABLE;
 | |
|         }
 | |
| 
 | |
|         if (at_command_context.transp.transpmode) {
 | |
|             if (iot_mac_addr_cmp(at_command_context.transp.trans_addr,
 | |
|                 IOT_AT_BROADCAST_MAC_6BYTES)) {
 | |
|                 data_len = iot_sprintf((char *)p_data,"data received from UART"
 | |
|                     " will be transparent transmitted as broadcast\n");
 | |
|             } else {
 | |
|                 data_len = iot_sprintf((char *)p_data,"data received from UART"
 | |
|                     " will be transparent transmitted to "
 | |
|                     "%02X:%02X:%02X:%02X:%02X:%02X\n",
 | |
|                     at_command_context.transp.trans_addr[0],
 | |
|                     at_command_context.transp.trans_addr[1],
 | |
|                     at_command_context.transp.trans_addr[2],
 | |
|                     at_command_context.transp.trans_addr[3],
 | |
|                     at_command_context.transp.trans_addr[4],
 | |
|                     at_command_context.transp.trans_addr[5]);
 | |
|             }
 | |
|             DERROR("%s",p_data);
 | |
|             at_command_at_response_to_proto(AT_RESP_FORCE_ECHO,
 | |
|                 p_data, data_len, true);
 | |
|         }
 | |
| 
 | |
|         iot_pkt_free(p_pkt);
 | |
|     }
 | |
|     else if (PLCTXRX_OP_INDICATION == p_resp->cid.opcode)
 | |
|     {
 | |
|         /* Get MAC address from flash firstly, need check the MAC address validity. */
 | |
|         if (mac_addr_in_flash_is_valid_addr(p_flash->local_mac))
 | |
|         {
 | |
|             DINFOR("Flash's MAC address valid!");
 | |
|             /* Update the AT layer local MAC address. */
 | |
|             iot_mac_addr_cpy(at_command_context.mac, p_flash->local_mac);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             /* If flash's MAC address invalid, get MAC address from OEM secondly. */
 | |
|             (void)iot_oem_get_base_cfg(&oem_base_cfg);
 | |
| 
 | |
|             /* Check the MAC address validity. */
 | |
|             if (!mac_addr_in_flash_is_valid_addr(oem_base_cfg->module_mac))
 | |
|             {
 | |
|                 DERROR("OEM's MAC address invalid!");
 | |
|                 return;
 | |
|             }
 | |
| 
 | |
|             /* Update the AT layer local MAC address. */
 | |
|             iot_mac_addr_cpy(at_command_context.mac, oem_base_cfg->module_mac);
 | |
|         }
 | |
| 
 | |
|         pkt_len = sizeof(*p_arg) + sizeof(*p_mac_hd);
 | |
|         if (NULL == (p_pkt = iot_pkt_alloc(pkt_len, AT_COMMAND_MID)))
 | |
|         {
 | |
|             DERROR("No memory!");
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         p_arg = (plctxrx_cmd_arg_t *)iot_pkt_put(p_pkt, pkt_len);
 | |
|         p_arg->cid.cid = PLCTXRX_CID_MAC;
 | |
|         p_arg->cid.opcode = PLCTXRX_OP_CONFIG;
 | |
|         p_arg->prio = p_cmd_line->prio;
 | |
|         p_arg->dlen = sizeof(*p_mac_hd);
 | |
|         p_arg->need_ack = true;
 | |
| 
 | |
|         p_mac_hd = (plctxrx_handle_mac_t *)p_arg->arg;
 | |
|         iot_mac_addr_cpy(p_mac_hd->mac, at_command_context.mac);
 | |
|         p_mac_hd->dev_type = p_flash->local_type;
 | |
| 
 | |
|         at_command_send_to_plc(p_pkt);
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_handle_command_time(uint32_t opcode, uint32_t argc, uint8_t *argv[])
 | |
| {
 | |
|     (void)opcode;
 | |
|     (void)argc;
 | |
|     (void)argv;
 | |
| }
 | |
| 
 | |
| void at_handle_response_time(iot_pkt_t *p_resp_pkt)
 | |
| {
 | |
|     (void)p_resp_pkt;
 | |
| }
 | |
| 
 | |
| void at_handle_command_systeminfo
 | |
|     (uint32_t opcode, uint32_t argc, uint8_t *argv[])
 | |
| {
 | |
|     iot_pkt_t *p_arg_pkt;
 | |
|     plctxrx_cmd_arg_t *p_arg;
 | |
|     at_cmd_t *p_cmd_line = at_command_get_cmd_handle_by_cid(AT_CID_SYSTEMINFO);
 | |
| 
 | |
|     (void)argv;
 | |
|     (void)argc;
 | |
|     (void)opcode;
 | |
| 
 | |
|     if(NULL == (p_arg_pkt = iot_pkt_alloc(sizeof(*p_arg), AT_COMMAND_MID)))
 | |
|     {
 | |
|         at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, 1);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_arg = (plctxrx_cmd_arg_t *)iot_pkt_put(p_arg_pkt, sizeof(*p_arg));
 | |
| 
 | |
|     p_arg->cid.opcode   = PLCTXRX_OP_QUERY;
 | |
|     p_arg->cid.cid      = PLCTXRX_CID_SYSTEMINFO;
 | |
| 
 | |
|     p_arg->prio         = p_cmd_line->prio;
 | |
|     p_arg->dlen         = 0;
 | |
|     p_arg->need_ack = true;
 | |
| 
 | |
|     at_command_send_to_plc(p_arg_pkt);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_handle_response_systeminfo(iot_pkt_t *p_resp_pkt)
 | |
| {
 | |
|     plctxrx_cmd_resp_t *p_resp;
 | |
|     plctxrx_cmd_systeminfo_t *p_sysinfo;
 | |
|     iot_pkt_t *p_finally_resp_pkt;
 | |
|     uint32_t pkt_len, version, cpu_u, ram_u;
 | |
|     uint8_t *buf;
 | |
| 
 | |
|     p_resp = (plctxrx_cmd_resp_t *)iot_pkt_data(p_resp_pkt);
 | |
|     p_sysinfo = (plctxrx_cmd_systeminfo_t *)p_resp->data;
 | |
| 
 | |
|     if(PLCTXRX_RESP_OK != p_resp->resp)
 | |
|     {
 | |
|         goto ERROR_HANDLE;
 | |
|     }
 | |
| 
 | |
|     p_finally_resp_pkt = iot_pkt_alloc(256, AT_COMMAND_MID);
 | |
| 
 | |
|     if(NULL == p_finally_resp_pkt)
 | |
|     {
 | |
|         goto ERROR_HANDLE;
 | |
|     }
 | |
| 
 | |
|     version = iot_version_hex();
 | |
| 
 | |
|     cpu_u = os_get_cpu_utilization();
 | |
| 
 | |
|     ram_u = os_get_mem_utilization();
 | |
| 
 | |
|     buf = iot_pkt_data(p_finally_resp_pkt);
 | |
| 
 | |
|     pkt_len = iot_sprintf((char *)buf,
 | |
|         "\r\nLast reboot reason:%d." \
 | |
|         "\r\nTotal reboot times:%d." \
 | |
|         "\r\nNetwork running time:%d."\
 | |
|         "\r\nAT module version:%s."\
 | |
|         "\r\nFireware version:%d.%d.%d.build-%d."\
 | |
|         "\r\nCPU utilization:%d%%."\
 | |
|         "\r\nRAM utilization:%d%%.",
 | |
|         (int)p_sysinfo->last_reboot_reason,
 | |
|         (int)p_sysinfo->total_reboot_times,
 | |
|         (int)p_sysinfo->os_running_time,
 | |
|         IOT_AT_MODULE_VERSION,
 | |
|         (version >> 27) & 0x1F, (version >> 20) & 0x7F,
 | |
|         (version >> 16) & 0xF, version & 0xFFFF,
 | |
|         cpu_u, ram_u);
 | |
| 
 | |
|     at_command_at_response_to_proto(AT_RESP_OK, buf, pkt_len, 1);
 | |
| 
 | |
|     iot_pkt_free(p_finally_resp_pkt);
 | |
| 
 | |
|     return;
 | |
| 
 | |
| ERROR_HANDLE:
 | |
|     at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, 1);
 | |
|     DERROR("AT sysinfor response error.");
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_handle_command_uart(uint32_t opcode, uint32_t argc, uint8_t *argv[])
 | |
| {
 | |
|     uint32_t pkt_len;
 | |
|     iot_pkt_t *p_pkt;
 | |
|     plctxrx_cmd_arg_t *p_arg;
 | |
|     plctxrx_handle_uart_t *p_uart;
 | |
|     at_cmd_t *p_cmd_line = at_command_get_cmd_handle_by_cid(AT_CID_UART);
 | |
| 
 | |
|     /*
 | |
|     the uart data length value range: <5-8>.
 | |
|     the uart stop bit value range: 1 -> 1 bits, 2 -> 1.5 bits, 3 -> 2 bits.
 | |
|     the uart parity value range: 0 -> none, 1 -> odd, 2 -> even.
 | |
|     */
 | |
|     uint32_t bandrate = 0, uart_data_len = 0, stop_bit = 0;
 | |
|     uint32_t parity = IOT_UART_PARITY_EVEN + 1;
 | |
|     uint8_t i;
 | |
|     char *stop_bit_symbol[3] = {"1", "1.5", "2"};
 | |
|     uint8_t stop_bit_options[3] = {
 | |
|         IOT_UART_STOP_1_BITS,
 | |
|         IOT_UART_STOP_1_5_BITS,
 | |
|         IOT_UART_STOP_2_BITS
 | |
|     };
 | |
|     char *parity_symbol[3] = {"N", "O", "E"};
 | |
|     uint8_t parity_options[3] = {
 | |
|         IOT_UART_PARITY_NONE,
 | |
|         IOT_UART_PARITY_ODD,
 | |
|         IOT_UART_PARITY_EVEN
 | |
|     };
 | |
| 
 | |
|     uint8_t *rsp_data;
 | |
|     uint32_t rsp_data_len;
 | |
| 
 | |
|     if(AT_OP_SET == opcode)
 | |
|     {
 | |
|         if ((argc < 4)
 | |
|             || (at_command_uint32_2_digtal(argv[0], &bandrate) <= 0)
 | |
|             || (at_command_uint32_2_digtal(argv[1], &uart_data_len) <= 0))
 | |
|         {
 | |
|             DERROR("Invalid argument!");
 | |
|             at_command_at_response_to_proto(AT_RESP_INVALID_ARGUMENT, NULL, 0, true);
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         for (i = 0; i < 3; i++)
 | |
|         {
 | |
|             if (!iot_strcmp((char *)argv[2], stop_bit_symbol[i]))
 | |
|             {
 | |
|                 stop_bit = stop_bit_options[i];
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         for (i = 0; i < 3; i++)
 | |
|         {
 | |
|             if (!iot_strcmp((char *)argv[3], parity_symbol[i]))
 | |
|             {
 | |
|                 parity = parity_options[i];
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if ((uart_data_len > IOT_UART_DLEN_8_BITS)
 | |
|             || (uart_data_len < IOT_UART_DLEN_5_BITS)
 | |
|             || (stop_bit > IOT_UART_STOP_2_BITS)
 | |
|             || (stop_bit < IOT_UART_STOP_1_BITS)
 | |
|             || (parity > IOT_UART_PARITY_EVEN)
 | |
|             || (parity < IOT_UART_PARITY_NONE))
 | |
|         {
 | |
|             DERROR("Invalid argument!");
 | |
|             at_command_at_response_to_proto(AT_RESP_INVALID_ARGUMENT, NULL, 0, true);
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         pkt_len = sizeof(*p_arg) + sizeof(*p_uart);
 | |
|         if (NULL == (p_pkt = iot_pkt_alloc(pkt_len, AT_COMMAND_MID)))
 | |
|         {
 | |
|             DERROR("No memory!");
 | |
|             at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         p_arg = (plctxrx_cmd_arg_t *)iot_pkt_put(p_pkt, pkt_len);
 | |
| 
 | |
|         p_arg->cid.cid  = PLCTXRX_CID_UART;
 | |
|         p_arg->cid.opcode  = PLCTXRX_OP_CONFIG;
 | |
|         p_arg->prio = p_cmd_line->prio;
 | |
|         p_arg->need_ack = true;
 | |
|         p_arg->dlen = sizeof(*p_uart) ;
 | |
| 
 | |
|         p_uart = (plctxrx_handle_uart_t *)p_arg->arg;
 | |
|         p_uart->uart_port = at_command_uart_cfg.port;
 | |
|         p_uart->bandrate = bandrate;
 | |
|         p_uart->data_len =(uint8_t)uart_data_len;
 | |
|         p_uart->stop_bit =(uint8_t)stop_bit;
 | |
|         p_uart->parity = (uint8_t)parity;
 | |
| 
 | |
|         /* save the current uart config info to the AT command layer. */
 | |
|         os_mem_set(&at_command_uart_cfg, 0 , sizeof(at_uart_cfg_t));
 | |
|         at_command_uart_cfg.port = p_uart->uart_port;
 | |
|         at_command_uart_cfg.brate = p_uart->bandrate;
 | |
|         at_command_uart_cfg.dlen = p_uart->data_len;
 | |
|         at_command_uart_cfg.stop = p_uart->stop_bit;
 | |
|         at_command_uart_cfg.parity = p_uart->parity;
 | |
| 
 | |
|         at_command_send_to_plc(p_pkt);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         /* Select the appropriate buffer size for print buffer. */
 | |
|         if(NULL == (p_pkt = iot_pkt_alloc(AT_MID_BUF_SIZE, AT_COMMAND_MID)))
 | |
|         {
 | |
|             DERROR("No memory!");
 | |
|             at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         rsp_data = iot_pkt_data(p_pkt);
 | |
| 
 | |
|         rsp_data_len = iot_sprintf((char *)rsp_data,
 | |
|             "\r\nThe uart port %d config is:" \
 | |
|             "\r\nbaudrate:%d" \
 | |
|             "\r\ndata_len:%d" \
 | |
|             "\r\nstop_bit:%s" \
 | |
|             "\r\nparity:%s",
 | |
|             at_command_uart_cfg.port,
 | |
|             at_command_uart_cfg.brate,
 | |
|             at_command_uart_cfg.dlen,
 | |
|             /* convert digital 1~3 to string "1","1.5","2", if invalid show "Unknown". */
 | |
|             ((at_command_uart_cfg.stop <= IOT_UART_STOP_2_BITS)
 | |
|                 && (at_command_uart_cfg.stop >= IOT_UART_STOP_1_BITS))
 | |
|                 ? stop_bit_symbol[at_command_uart_cfg.stop - 1] : "Unknown",
 | |
|             /* convert digital 0~2 to string "N","O","E", if invalid show "Unknown". */
 | |
|             ((at_command_uart_cfg.parity <= IOT_UART_PARITY_EVEN)
 | |
|                 && (at_command_uart_cfg.parity >= IOT_UART_PARITY_NONE))
 | |
|                 ? parity_symbol[at_command_uart_cfg.parity] : "Unknown");
 | |
| 
 | |
|         at_command_at_response_to_proto(AT_RESP_OK, rsp_data, rsp_data_len, true);
 | |
| 
 | |
|         iot_pkt_free(p_pkt);
 | |
| 
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_handle_response_uart(iot_pkt_t *p_resp_pkt)
 | |
| {
 | |
|     plctxrx_cmd_resp_t *p_resp;
 | |
|     iot_pkt_t *p_pkt;
 | |
|     uint8_t *p_data;
 | |
|     uint32_t data_len, ret;
 | |
| 
 | |
|     /* Check param validity and select the appropriate buffer size for print buffer. */
 | |
|     if ((NULL == p_resp_pkt)
 | |
|         ||(NULL == (p_pkt = iot_pkt_alloc(AT_MID_BUF_SIZE, AT_COMMAND_MID))))
 | |
|     {
 | |
|         at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_resp = (plctxrx_cmd_resp_t *)iot_pkt_data(p_resp_pkt);
 | |
|     p_data = iot_pkt_data(p_pkt);
 | |
| 
 | |
|     data_len = iot_sprintf((char *)p_data, "\r\nConfig the uart %s!",
 | |
|            (PLCTXRX_RESP_OK != p_resp->resp) ? "failed" : "successfully");
 | |
| 
 | |
|     ret = (PLCTXRX_RESP_OK != p_resp->resp) ? AT_RESP_ERROR : AT_RESP_OK;
 | |
| 
 | |
|     at_command_at_response_to_proto(ret, p_data, data_len, true);
 | |
| 
 | |
|     iot_pkt_free(p_pkt);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_handle_command_topo(uint32_t opcode, uint32_t argc, uint8_t *argv[])
 | |
| {
 | |
|     uint32_t pkt_len;
 | |
|     iot_pkt_t *p_pkt;
 | |
|     plctxrx_cmd_arg_t *p_arg;
 | |
|     plctxrx_cmd_query_topo_t *topo_cmd;
 | |
|     at_cmd_t *p_cmd_line = at_command_get_cmd_handle_by_cid(AT_CID_TOPO);
 | |
|     uint8_t *rsp_data;
 | |
|     uint32_t rsp_data_len;
 | |
| 
 | |
|     (void)opcode;
 | |
|     (void)argc;
 | |
|     (void)argv;
 | |
| 
 | |
|     pkt_len = (IOT_PLC_DEV_ROLE_STA == at_command_context.dev_type)
 | |
|         ? AT_SMALL_BUF_SIZE : sizeof(*p_arg);
 | |
| 
 | |
|     /* alloc packet for sending cmd */
 | |
|     p_pkt = iot_pkt_alloc(pkt_len, AT_COMMAND_MID);
 | |
|     if (p_pkt == NULL) {
 | |
|         DERROR("No memory!");
 | |
|         at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (IOT_PLC_DEV_ROLE_STA == at_command_context.dev_type) {
 | |
|         rsp_data = iot_pkt_data(p_pkt);
 | |
|         rsp_data_len = iot_sprintf((char *)rsp_data,
 | |
|             "\r\nSTA device query topo func is not supported!");
 | |
|         at_command_at_response_to_proto(AT_RESP_OK,
 | |
|             rsp_data, rsp_data_len, true);
 | |
|         iot_pkt_free(p_pkt);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_arg = (plctxrx_cmd_arg_t*)iot_pkt_put(cmd_pkt, pkt_len);
 | |
|     p_arg->cid.cid = PLCTXRX_CID_TOPO;
 | |
|     p_arg->cid.opcode = PLCTXRX_OP_QUERY;
 | |
|     p_arg->need_ack = true;
 | |
|     p_arg->prio = p_cmd_line->prio;
 | |
|     p_arg->dlen = sizeof(plctxrx_cmd_query_topo_t);
 | |
|     topo_cmd = (plctxrx_cmd_query_topo_t*)p_arg->arg;
 | |
|     topo_cmd->ver = IOT_PLC_CCO_TOPO_REQ_DATA_VER_V1;
 | |
|     topo_cmd->start = 1;
 | |
|     topo_cmd->cnt = STA_DEV_MAX;
 | |
| 
 | |
|     at_command_send_to_plc(p_pkt);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_handle_response_topo(iot_pkt_t *p_resp_pkt)
 | |
| {
 | |
|     plctxrx_cmd_resp_t *p_resp;
 | |
|     plctxrx_handle_topo_t *p_topo_info;
 | |
|     iot_pkt_t *p_pkt;
 | |
|     uint8_t *p_data;
 | |
|     uint32_t data_len, ret;
 | |
|     uint16_t i;
 | |
| 
 | |
|     if(NULL == p_resp_pkt)
 | |
|     {
 | |
|         at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_resp = (plctxrx_cmd_resp_t *)iot_pkt_data(p_resp_pkt);
 | |
|     p_topo_info = (plctxrx_handle_topo_t *)p_resp->data;
 | |
| 
 | |
|     if(NULL == (p_pkt = iot_pkt_alloc(128, AT_COMMAND_MID)))
 | |
|     {
 | |
|         at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_data = iot_pkt_data(p_pkt);
 | |
|     ret = (PLCTXRX_RESP_OK != p_resp->resp) ? AT_RESP_ERROR : AT_RESP_OK;
 | |
| 
 | |
|     if (p_topo_info->cnt > 0)
 | |
|     {
 | |
|         for (i = 0; i < p_topo_info->cnt; i++)
 | |
|         {
 | |
|             data_len = iot_sprintf((char *)p_data,
 | |
|                 "\r\nRemote #%02d-%02X:%02X:%02X:%02X:%02X:%02X.",
 | |
|                 i, p_topo_info->topo[i].mac[0], p_topo_info->topo[i].mac[1],
 | |
|                 p_topo_info->topo[i].mac[2], p_topo_info->topo[i].mac[3],
 | |
|                 p_topo_info->topo[i].mac[4], p_topo_info->topo[i].mac[5]);
 | |
|             at_command_at_response_to_proto(ret, p_data, data_len, false);
 | |
|         }
 | |
|         data_len = iot_sprintf((char *)p_data,
 | |
|             "\r\nTotal %d remote devices.", p_topo_info->cnt);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         data_len = iot_sprintf((char *)p_data, "\r\nCan not find remote device!");
 | |
|     }
 | |
| 
 | |
|     at_command_at_response_to_proto(ret, p_data, data_len, true);
 | |
| 
 | |
|     iot_pkt_free(p_pkt);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| uint8_t at_command_send_ping_data
 | |
|     (uint16_t type, uint16_t index, uint32_t stamp, uint8_t *p_dts_mac,
 | |
|     uint8_t * data, uint16_t dlen)
 | |
| {
 | |
|     uint16_t pkt_len;
 | |
|     iot_pkt_t *p_pkt;
 | |
|     plctxrx_cmd_arg_t *p_arg;
 | |
|     plctxrx_handle_send_t *p_send;
 | |
|     at_payload_t *p_load;
 | |
|     at_ping_t *p_ping;
 | |
| 
 | |
|     pkt_len = sizeof(*p_arg) + sizeof(*p_send) + sizeof(*p_load)
 | |
|         + sizeof(*p_ping) + dlen;
 | |
| 
 | |
|     if(NULL == (p_pkt = iot_pkt_alloc(pkt_len, AT_COMMAND_MID)))
 | |
|     {
 | |
|         DERROR("No memory!");
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     p_arg = (plctxrx_cmd_arg_t *)iot_pkt_put(p_pkt, pkt_len);
 | |
|     p_arg->cid.cid  = PLCTXRX_CID_SEND;
 | |
|     p_arg->cid.opcode  = PLCTXRX_OP_EXECUTE;
 | |
|     p_arg->prio = AT_DEF_PRIO;
 | |
|     p_arg->need_ack = true;
 | |
|     p_arg->dlen = pkt_len - sizeof(*p_arg);
 | |
| 
 | |
|     p_send = (plctxrx_handle_send_t *)p_arg->arg;
 | |
| 
 | |
|     os_mem_cpy(p_send->txinfo.dst_mac, p_dts_mac, IOT_MAC_ADDR_LEN);
 | |
|     os_mem_cpy(p_send->txinfo.org_mac, at_command_context.mac, IOT_MAC_ADDR_LEN);
 | |
|     os_mem_cpy(p_send->txinfo.src_mac, at_command_context.mac, IOT_MAC_ADDR_LEN);
 | |
| 
 | |
|     p_send->txinfo.retry_cnt = 0;
 | |
|     p_send->txinfo.need_ack = 0;
 | |
|     p_send->txinfo.retry_intvl = 0;
 | |
|     p_send->txinfo.txpwr = 0;
 | |
|     p_send->txinfo.src_module = IOT_PLCTXRX_MSDU_SRCMODULE_AT;
 | |
|     p_send->txinfo.send_type = PLCTXRX_UNICAST;
 | |
|     p_send->txinfo.sta_cnt = 1;
 | |
|     p_send->dlen =(uint8_t)(pkt_len - sizeof(*p_arg) - sizeof(*p_send));
 | |
| 
 | |
|     p_load = (at_payload_t *)p_send->data;
 | |
|     p_load->type = type;
 | |
|     p_load->dlen = sizeof(*p_ping) + dlen+sizeof(at_payload_t);
 | |
| 
 | |
|     p_ping = (at_ping_t *)p_load->data;
 | |
|     os_mem_cpy(p_ping->dst_mac, p_dts_mac, IOT_MAC_ADDR_LEN);
 | |
|     os_mem_cpy(p_ping->org_mac, at_command_context.mac, IOT_MAC_ADDR_LEN);
 | |
|     p_ping->stamp = stamp;
 | |
|     p_ping->index = index;
 | |
|     p_ping->dlen = dlen;
 | |
|     os_mem_cpy(p_ping->data, data, dlen);
 | |
| 
 | |
|     DINFOR("Ping %s send to %02x:%02x:%02x:%02x:%02x:%02x.",
 | |
|         AT_PAYLOAD_PING == type ? "packet" : "response",
 | |
|         p_dts_mac[0], p_dts_mac[1], p_dts_mac[2],
 | |
|         p_dts_mac[3], p_dts_mac[4], p_dts_mac[5]);
 | |
| 
 | |
|     at_command_send_to_plc(p_pkt);
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| /* AT+PING="xx:xx:xx:xx:xx:xx",SIZE,TIMES */
 | |
| void at_handle_command_ping(uint32_t opcode, uint32_t argc, uint8_t *argv[])
 | |
| {
 | |
|     uint8_t target_mac[IOT_MAC_ADDR_LEN], *p_resp_buf;
 | |
|     uint32_t pack_size, times_cnt, data_len, error_pkg, delta_ms, check_t, i;
 | |
|     const uint32_t check_times = 400, check_delay_ms = 5, ping_max_cnt = 0x0FFFFFFF;
 | |
|     iot_pkt_t *p_resp_buf_pkt;
 | |
|     static uint32_t index = 1;
 | |
| 
 | |
|     if((AT_OP_SET != opcode)
 | |
|         || (argc < 1)
 | |
|         || (IOT_MAC_ADDR_LEN != at_command_string_2_digtal
 | |
|             (argv[0], target_mac, IOT_MAC_ADDR_LEN)))
 | |
|     {
 | |
|         DERROR("Invalid argument!");
 | |
|         at_command_at_response_to_proto
 | |
|             (AT_RESP_INVALID_ARGUMENT, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if((argc < 2) || (at_command_uint32_2_digtal(argv[1], ×_cnt) <= 0))
 | |
|     {
 | |
|         times_cnt = AT_DEF_PING_TIMES;
 | |
|     }
 | |
|     else if(times_cnt > ping_max_cnt)
 | |
|     {
 | |
|         DERROR("Invalid argument!");
 | |
|         at_command_at_response_to_proto
 | |
|             (AT_RESP_INVALID_ARGUMENT, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if((argc < 3) || (at_command_uint32_2_digtal(argv[2], &pack_size) <= 0))
 | |
|     {
 | |
|         pack_size = AT_MAX_PING_BYTES;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         pack_size = min(pack_size, AT_MAX_PING_BYTES);
 | |
|     }
 | |
| 
 | |
|     if(NULL == (p_resp_buf_pkt = iot_pkt_alloc(128, AT_COMMAND_MID)))
 | |
|     {
 | |
|         at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_resp_buf = iot_pkt_data(p_resp_buf_pkt);
 | |
| 
 | |
|     error_pkg = 0;
 | |
| 
 | |
|     g_ping_host.started = true;
 | |
| 
 | |
|     os_mem_cpy(g_ping_host.dst_mac, target_mac, IOT_MAC_ADDR_LEN);
 | |
| 
 | |
|     for(i = index; i < times_cnt + index; i++)
 | |
|     {
 | |
|         /* Data for sent locates where p_resp_buf in RAM. Not care about data */
 | |
|         if(ERR_OK != at_command_send_ping_data
 | |
|             (AT_PAYLOAD_PING, (uint16_t)i, os_boot_time32(),
 | |
|             target_mac, p_resp_buf,(uint16_t)pack_size))
 | |
|         {
 | |
|             goto PING_LOCAL_ERROR;
 | |
|         }
 | |
| 
 | |
|         /* 0 is an invalid index. */
 | |
|         g_ping_host.reply_index = 0;
 | |
| 
 | |
|         for(check_t = 0; check_t < check_times; check_t++)
 | |
|         {
 | |
|             os_delay(check_delay_ms);
 | |
| 
 | |
|             iot_task_clean_msg(at_command_context.task,
 | |
|                 AT_MSG_TYPE_RESPONSE | AT_MSG_SOURCE_PLCTXRX, PLCTXRX_CID_SEND);
 | |
| 
 | |
|             if(g_ping_host.reply_index == i)
 | |
|             {
 | |
|                 delta_ms = os_boot_time32();
 | |
| 
 | |
|                 if(delta_ms >= g_ping_host.stamp)
 | |
|                 {
 | |
|                     delta_ms = delta_ms - g_ping_host.stamp;
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     delta_ms = delta_ms
 | |
|                         + ((uint32_t)0xFFFFFFFF - g_ping_host.stamp);
 | |
|                 }
 | |
| 
 | |
|                 /* Single path timing. */
 | |
|                 delta_ms = (delta_ms > 3) ? (delta_ms / 2) : 1;
 | |
| 
 | |
|                 goto PING_OK;
 | |
|             }
 | |
|         }
 | |
| 
 | |
| /* PING_TIMEOUT: */
 | |
|         data_len = iot_sprintf((char *)p_resp_buf,
 | |
|             "Ping#%d %02x:%02x:%02x:%02x:%02x:%02x, timeout!\r\n", i - index,
 | |
|             target_mac[0], target_mac[1], target_mac[2], target_mac[3],
 | |
|             target_mac[4], target_mac[5]);
 | |
|         error_pkg++;
 | |
|         goto PING_CONTINUE;
 | |
| 
 | |
| PING_LOCAL_ERROR:
 | |
|         data_len = iot_sprintf((char *)p_resp_buf,
 | |
|             "Ping#%d error!\r\n", i - index);
 | |
|         error_pkg++;
 | |
|         goto PING_CONTINUE;
 | |
| PING_OK:
 | |
|         /* Waite for check_delay_ms*check_times then do the next ping. */
 | |
|         os_delay(check_delay_ms * (check_times - check_t));
 | |
|         data_len = iot_sprintf((char *)p_resp_buf,
 | |
|             "Ping#%d %02x:%02x:%02x:%02x:%02x:%02x, delay %d ms.\r\n", i - index,
 | |
|             target_mac[0], target_mac[1], target_mac[2], target_mac[3],
 | |
|             target_mac[4], target_mac[5], delta_ms);
 | |
| PING_CONTINUE:
 | |
|         at_command_at_response_to_proto(AT_RESP_OK, p_resp_buf, data_len, false);
 | |
|     }
 | |
| 
 | |
|     /* Clear or increase the index. */
 | |
|     index = i > ping_max_cnt ? 1 : i;
 | |
| 
 | |
|     data_len = iot_sprintf((char *)p_resp_buf,
 | |
|         "Total %d packets, %d lost.\r\n", times_cnt, error_pkg);
 | |
| 
 | |
|     at_command_at_response_to_proto(AT_RESP_OK, p_resp_buf, data_len, true);
 | |
| 
 | |
|     iot_pkt_free(p_resp_buf_pkt);
 | |
| 
 | |
|     g_ping_host.started = false;
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| iot_pkt_t *at_command_sendpkt_prepare(uint8_t *buf, uint16_t blen, uint8_t *target_mac,
 | |
|     uint32_t retry_time)
 | |
| {
 | |
|     uint32_t pkt_len;
 | |
|     iot_pkt_t *p_pkt;
 | |
|     plctxrx_cmd_arg_t *p_arg;
 | |
|     plctxrx_handle_send_t *p_send;
 | |
|     at_payload_t *p_load;
 | |
|     at_cmd_t *p_cmd_line = at_command_get_cmd_handle_by_cid(AT_CID_SEND);
 | |
| 
 | |
|     pkt_len = sizeof(plctxrx_cmd_arg_t) + sizeof(plctxrx_handle_send_t) +
 | |
|         sizeof(at_payload_t) + AT_MAX_SEND_BYTES;
 | |
| 
 | |
|     if (NULL == (p_pkt = iot_pkt_alloc(pkt_len, AT_COMMAND_MID))) {
 | |
|         DERROR("No memory!");
 | |
|         at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|         return NULL;
 | |
|     }
 | |
| 
 | |
|     p_arg = (plctxrx_cmd_arg_t *)iot_pkt_data(p_pkt);
 | |
| 
 | |
|     p_send = (plctxrx_handle_send_t *)p_arg->arg;
 | |
| 
 | |
|     p_load = (at_payload_t *)p_send->data;
 | |
| 
 | |
|     os_mem_cpy(p_load->data, buf, blen);
 | |
| 
 | |
|     DINFOR("data_len=%d p_load->data=%p", blen, p_load->data);
 | |
| 
 | |
|     p_arg->cid.cid  = PLCTXRX_CID_SEND;
 | |
|     p_arg->cid.opcode  = PLCTXRX_OP_EXECUTE;
 | |
|     p_arg->prio = p_cmd_line->prio;
 | |
|     p_arg->need_ack = true;
 | |
|     p_arg->dlen =(uint16_t)(sizeof(plctxrx_handle_send_t) +
 | |
|         sizeof(at_payload_t) + blen);
 | |
| 
 | |
|     iot_mac_addr_cpy(p_send->txinfo.dst_mac, target_mac);
 | |
|     iot_mac_addr_cpy(p_send->txinfo.org_mac, at_command_context.mac);
 | |
|     iot_mac_addr_cpy(p_send->txinfo.src_mac, at_command_context.mac);
 | |
| 
 | |
|     if (iot_mac_addr_cmp(target_mac, IOT_AT_BROADCAST_MAC_6BYTES) &&
 | |
|         at_command_context.dev_type == IOT_PLC_DEV_ROLE_CCO) {
 | |
|         p_send->txinfo.send_type = PLCTXRX_BORADCAST;
 | |
|         p_send->txinfo.sta_cnt = 0xFF;
 | |
|     } else {
 | |
|         p_send->txinfo.send_type = PLCTXRX_UNICAST;
 | |
|         p_send->txinfo.sta_cnt = 1;
 | |
|     }
 | |
| 
 | |
|     p_send->txinfo.retry_cnt =(uint8_t)retry_time;
 | |
|     p_send->txinfo.need_ack = 0;
 | |
|     p_send->txinfo.retry_intvl = 200;
 | |
|     p_send->txinfo.txpwr = 0;
 | |
|     p_send->txinfo.src_module = IOT_PLCTXRX_MSDU_SRCMODULE_AT;
 | |
| 
 | |
|     p_send->dlen = (uint8_t)(sizeof(at_payload_t) + blen);
 | |
| 
 | |
|     p_load->type = AT_PAYLOAD_RAWDATA;
 | |
|     p_load->dlen = (uint16_t)(sizeof(at_payload_t) + blen);
 | |
|     if (at_command_context.transp.transpmode) {
 | |
|         p_load->type = SET_TRANSP_MODE(p_load->type);
 | |
|     }
 | |
| 
 | |
|     return p_pkt;
 | |
| }
 | |
| 
 | |
| 
 | |
| uint32_t at_handle_transparent_data(uint8_t *buf, uint16_t blen)
 | |
| {
 | |
|     iot_pkt_t *p_pkt;
 | |
|     uint16_t send_len = 0;
 | |
| 
 | |
|     while (blen > 0) {
 | |
|         send_len = blen > TXRX_AGGR_PKT_LEN - sizeof(at_payload_t) ?
 | |
|             TXRX_AGGR_PKT_LEN - sizeof(at_payload_t) : blen;
 | |
|         DINFOR("blen=%d send_len=%d", blen, send_len);
 | |
|         p_pkt = at_command_sendpkt_prepare(buf, send_len,
 | |
|             at_command_context.transp.trans_addr, AT_SEND_DEF_RETRY_TIME);
 | |
|         if (NULL == p_pkt) {
 | |
|             DERROR("No memory!");
 | |
|             return ERR_NOMEM;
 | |
|         }
 | |
|         at_command_send_to_plc(p_pkt);
 | |
| 
 | |
|         buf += send_len;
 | |
|         blen -= send_len;
 | |
|     }
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| /* AT+SEND="xx:xx:xx:xx:xx:xx","xx xx xx xx xx...(less than 64 bytes)"[,TRY-TIMES] */
 | |
| void at_handle_command_send(uint32_t opcode, uint32_t argc, uint8_t *argv[])
 | |
| {
 | |
|     uint8_t target_mac[IOT_MAC_ADDR_LEN];
 | |
|     iot_pkt_t *p_pkt;
 | |
|     uint32_t data_len, retry_time;
 | |
|     uint8_t data[AT_MAX_SEND_BYTES];
 | |
| 
 | |
|     if ((AT_OP_SET != opcode) || (argc < 2) || (IOT_MAC_ADDR_LEN !=
 | |
|         at_command_string_2_digtal(argv[0],target_mac, IOT_MAC_ADDR_LEN))) {
 | |
|         DERROR("Invalid argument! opcode=%d argc=%d", opcode, argc);
 | |
|         at_command_at_response_to_proto(AT_RESP_INVALID_ARGUMENT, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (0 == (data_len = at_command_string_2_digtal(argv[1],
 | |
|         data, AT_MAX_SEND_BYTES))) {
 | |
|         DERROR("Invalid argument: data_len error!");
 | |
|         at_command_at_response_to_proto(AT_RESP_INVALID_ARGUMENT, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (argc < 2 || at_command_uint32_2_digtal(argv[2], &retry_time) <= 0) {
 | |
|         retry_time = AT_SEND_DEF_RETRY_TIME;
 | |
|     }
 | |
| 
 | |
|     p_pkt = at_command_sendpkt_prepare(data, data_len, target_mac, retry_time);
 | |
| 
 | |
|     if (NULL == p_pkt) {
 | |
|         DERROR("No memory!");
 | |
|         at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|     } else {
 | |
|         at_command_send_to_plc(p_pkt);
 | |
| 
 | |
|         /* Just finish AT+SEND with out response. */
 | |
|         at_command_at_response_to_proto(AT_RESP_SET_FINISH_WITHOUT_ECHO,
 | |
|             NULL, 0, true);
 | |
|     }
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /* AT+PMODE="enable","xx:xx:xx:xx:xx:xx" */
 | |
| void at_handle_command_pmode(uint32_t opcode, uint32_t argc, uint8_t *argv[])
 | |
| {
 | |
|     custom_flash_info_t *p_flash = &uniform_flashinfo_at;
 | |
|     uint8_t *p_data;
 | |
|     iot_pkt_t *p_pkt;
 | |
|     uint32_t data_len;
 | |
|     uint8_t target_mac[IOT_MAC_ADDR_LEN];
 | |
| 
 | |
|     if ((AT_OP_SET != opcode) || argc < 1 ||
 | |
|         iot_strcmp((char*)argv[0], STRING_ENABLE)) {
 | |
|         DERROR("Invalid argument! opcode=%d argc=%d", opcode, argc);
 | |
|         at_command_at_response_to_proto(AT_RESP_INVALID_ARGUMENT,
 | |
|             NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
|     if (argc < 2) {
 | |
|         iot_mac_addr_cpy(at_command_context.transp.trans_addr,
 | |
|             (uint8_t*)IOT_AT_BROADCAST_MAC_6BYTES);
 | |
|     } else if (IOT_MAC_ADDR_LEN ==
 | |
|         at_command_string_2_digtal(argv[1], target_mac, IOT_MAC_ADDR_LEN)) {
 | |
|         /* get target_mac*/
 | |
|         if (iot_mac_addr_cmp(target_mac, INVALID_MACADDR_6BYTE)) {
 | |
|             DERROR("Invalid argument! mac invalid");
 | |
|             at_command_at_response_to_proto(AT_RESP_INVALID_ARGUMENT,
 | |
|                 NULL, 0, true);
 | |
|             return;
 | |
|         } else {
 | |
|             iot_mac_addr_cpy(at_command_context.transp.trans_addr, target_mac);
 | |
|         }
 | |
|     } else {
 | |
|         DERROR("Invalid argument!");
 | |
|         at_command_at_response_to_proto(AT_RESP_INVALID_ARGUMENT,
 | |
|             NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     at_command_context.transp.transpmode = true;
 | |
|     p_flash->transp.transpmode = true;
 | |
|     iot_mac_addr_cpy(p_flash->transp.trans_addr,
 | |
|         at_command_context.transp.trans_addr);
 | |
|     /* Write flash. */
 | |
|     if (ERR_OK != at_command_uniform_flashsave(p_flash)){
 | |
|         DERROR("save transpmode to flash failed!");
 | |
|     }
 | |
| 
 | |
|     if(NULL == (p_pkt = iot_pkt_alloc(AT_MID_BUF_SIZE, AT_COMMAND_MID))) {
 | |
|         DERROR("alloc memory ERR!");
 | |
|         at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0 , 1);
 | |
|         return;
 | |
|     }
 | |
|     p_data = iot_pkt_data(p_pkt);
 | |
| 
 | |
|     if (iot_mac_addr_cmp(at_command_context.transp.trans_addr,
 | |
|         IOT_AT_BROADCAST_MAC_6BYTES)) {
 | |
|         data_len = iot_sprintf((char *)p_data,"data received from UART will be"
 | |
|             " transparent transmitted as broadcast\n");
 | |
|     } else {
 | |
|         data_len = iot_sprintf((char *)p_data,"data received from UART will be"
 | |
|             " transparent transmitted to %02X:%02X:%02X:%02X:%02X:%02X\n",
 | |
|             at_command_context.transp.trans_addr[0],
 | |
|             at_command_context.transp.trans_addr[1],
 | |
|             at_command_context.transp.trans_addr[2],
 | |
|             at_command_context.transp.trans_addr[3],
 | |
|             at_command_context.transp.trans_addr[4],
 | |
|             at_command_context.transp.trans_addr[5]);
 | |
|     }
 | |
|     DERROR("%s",p_data);
 | |
| 
 | |
|     /* Just finish AT+PMODE with response. */
 | |
|     at_command_at_response_to_proto(AT_RESP_FORCE_ECHO,
 | |
|         p_data, data_len, true);
 | |
| 
 | |
|     iot_pkt_free(p_pkt);
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_command_send_received_data_rawdata(plctxrx_handle_recv_t *p_rcv)
 | |
| {
 | |
|     iot_pkt_t *p_pkt;
 | |
|     uint8_t *p_data;
 | |
|     uint32_t data_len, pkt_len, i, hex_data;
 | |
|     at_payload_t *p_load;
 | |
|     uint32_t appdata_len;
 | |
| 
 | |
|     p_load = (at_payload_t *)p_rcv->data;
 | |
|     appdata_len = p_load->dlen - sizeof(at_payload_t);
 | |
| 
 | |
|     if (GET_TRANSP_MODE(p_load->type)) {
 | |
| #if INCLUDE_AT_COMMAND_DEBUG_PRINT
 | |
|         DINFOR("recv appdata_len=%d", appdata_len);
 | |
| #endif
 | |
|         if (at_command_context.transp.transpmode) {
 | |
|             pkt_len = appdata_len;
 | |
|             DINFOR("recv rawdata len=%d", p_load->dlen);
 | |
| 
 | |
|             if(NULL == (p_pkt = iot_pkt_alloc(pkt_len, AT_COMMAND_MID)))
 | |
|             {
 | |
|                 DERROR("No memory!");
 | |
|                 return;
 | |
|             }
 | |
| 
 | |
|             p_data = iot_pkt_data(p_pkt);
 | |
|             os_mem_cpy(p_data, p_load->data, appdata_len);
 | |
| 
 | |
|             data_len = appdata_len;
 | |
|         } else {
 | |
|             pkt_len = AT_SMALL_BUF_SIZE;
 | |
| 
 | |
|             p_pkt = iot_pkt_alloc(pkt_len, AT_COMMAND_MID);
 | |
|             p_data = iot_pkt_data(p_pkt);
 | |
|             data_len = iot_sprintf((char *)p_data,
 | |
|                 "recv transpmode data, but local is not in transpmode\r\n");
 | |
|         }
 | |
|     } else {
 | |
|         /* A byte needs 3 chars to show. (_5E) */
 | |
|         pkt_len = AT_SMALL_BUF_SIZE + (p_load->dlen * 3);
 | |
| #if INCLUDE_AT_COMMAND_DEBUG_PRINT
 | |
|         DINFOR("recv p_load->dlen=%d", p_load->dlen);
 | |
| #endif
 | |
|         if(NULL == (p_pkt = iot_pkt_alloc(pkt_len, AT_COMMAND_MID)))
 | |
|         {
 | |
|             DERROR("No memory!");
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         p_data = iot_pkt_data(p_pkt);
 | |
| 
 | |
| 
 | |
|         data_len = iot_sprintf((char *)p_data,
 | |
|             "\r\nMessage(%d bytes) from %02x:%02x:%02x:%02x:%02x:%02x :\r\n",
 | |
|             appdata_len,
 | |
|             p_rcv->rxinfo.mac[0], p_rcv->rxinfo.mac[1],
 | |
|             p_rcv->rxinfo.mac[2], p_rcv->rxinfo.mac[3],
 | |
|             p_rcv->rxinfo.mac[4], p_rcv->rxinfo.mac[5]);
 | |
| 
 | |
|         for(i = 0; i < appdata_len; i++)
 | |
|         {
 | |
|             hex_data = ((uint32_t)p_load->data[i]) & 0xFF;
 | |
|             data_len += iot_sprintf((char *)(p_data + data_len),
 | |
|                 "%02x ", hex_data);
 | |
|         }
 | |
|         data_len += appdata_len;
 | |
|     }
 | |
| #if INCLUDE_AT_COMMAND_DEBUG_PRINT
 | |
|     DINFOR("report data_len=%d", data_len);
 | |
| #endif
 | |
|     at_command_at_response_to_proto
 | |
|         (AT_RESP_FORCE_ECHO, p_data, data_len, false);
 | |
| 
 | |
|     iot_pkt_free(p_pkt);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_command_send_received_data_ping(plctxrx_handle_recv_t *p_rcv)
 | |
| {
 | |
|     at_payload_t *p_load;
 | |
|     at_ping_t *p_ping;
 | |
| 
 | |
|     p_load = (at_payload_t *)p_rcv->data;
 | |
| 
 | |
|     p_ping = (at_ping_t *)p_load->data;
 | |
| 
 | |
|     at_command_send_ping_data(AT_PAYLOAD_PING_REPLY, p_ping->index,
 | |
|         p_ping->stamp, p_ping->org_mac, p_ping->data, p_ping->dlen);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_command_send_received_data_ping_reply(plctxrx_handle_recv_t *p_rcv)
 | |
| {
 | |
|     at_payload_t *p_load;
 | |
|     at_ping_t *p_ping;
 | |
| 
 | |
|     p_load = (at_payload_t *)p_rcv->data;
 | |
| 
 | |
|     p_ping = (at_ping_t *)p_load->data;
 | |
| 
 | |
|     if((g_ping_host.started)
 | |
|         && (0 == os_mem_cmp
 | |
|         (g_ping_host.dst_mac, p_ping->org_mac, IOT_MAC_ADDR_LEN)))
 | |
|     {
 | |
|         g_ping_host.reply_index = p_ping->index;
 | |
|         g_ping_host.stamp = p_ping->stamp;
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_handle_response_send_receive(iot_pkt_t *p_resp_pkt)
 | |
| {
 | |
|     plctxrx_cmd_resp_t *p_resp;
 | |
|     plctxrx_handle_recv_t *p_rcv;
 | |
|     at_payload_t *p_load;
 | |
| 
 | |
|     if(NULL == p_resp_pkt)
 | |
|     {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_resp = (plctxrx_cmd_resp_t *)iot_pkt_data(p_resp_pkt);
 | |
|     p_rcv = (plctxrx_handle_recv_t *)p_resp->data;
 | |
|     p_load = (at_payload_t *)p_rcv->data;
 | |
| 
 | |
|     if(PLCTXRX_OP_RECEIVE != p_resp->cid.opcode)
 | |
|     {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if(AT_PAYLOAD_RAWDATA == GET_PAYLOAD_TYPE(p_load->type))
 | |
|     {
 | |
|         at_command_send_received_data_rawdata(p_rcv);
 | |
|     }
 | |
|     else if(AT_PAYLOAD_PING == p_load->type)
 | |
|     {
 | |
|         at_command_send_received_data_ping(p_rcv);
 | |
|     }
 | |
|     else if(AT_PAYLOAD_PING_REPLY  == p_load->type)
 | |
|     {
 | |
|         at_command_send_received_data_ping_reply(p_rcv);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         /* Do nothing. */
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_handle_command_memory(uint32_t opcode, uint32_t argc, uint8_t *argv[])
 | |
| {
 | |
|     uint32_t buf_len, value, addr;
 | |
|     uint8_t buf[36];
 | |
| 
 | |
|     if(AT_OP_SET == opcode)
 | |
|     {
 | |
|         if((argc < 2)
 | |
|             || (at_command_hex_2_digtal(argv[0], &addr) <= 0)
 | |
|             || (true != iot_data_addr_legal(addr))
 | |
|             || (at_command_hex_2_digtal(argv[1], &value) <= 0))
 | |
|         {
 | |
|             at_command_at_response_to_proto(AT_RESP_INVALID_ARGUMENT,
 | |
|                 NULL, 0, true);
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         buf_len = iot_sprintf((char *)buf, "W %08x:%08x->%08x", addr,
 | |
|             *((volatile uint32_t *)addr), value);
 | |
| 
 | |
|         *((volatile uint32_t *)addr) = value;
 | |
| 
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         if((argc < 1) || (at_command_hex_2_digtal(argv[0], &addr) <= 0)
 | |
|             || (true != iot_data_addr_legal(addr)))
 | |
|         {
 | |
|             at_command_at_response_to_proto(AT_RESP_INVALID_ARGUMENT,
 | |
|                 NULL, 0, true);
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         addr &= 0xFFFFFFFC;
 | |
| 
 | |
|         buf_len = iot_sprintf((char *)buf, "R %08x:%08x", addr,
 | |
|             *((volatile uint32_t *)addr));
 | |
|     }
 | |
| 
 | |
|     at_command_at_response_to_proto(AT_RESP_OK, buf, buf_len, true);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_command_task_show(uint32_t task_id)
 | |
| {
 | |
|     task_info_t *p_tasks;
 | |
|     iot_pkt_t *p_task_info_pkt, *p_pkt_sprintf_data;
 | |
|     uint32_t task_num, i, data_len;
 | |
|     uint8_t *p_buf;
 | |
|     char *p_state[] = {"RUN", "RDY", "BLK", "SPD", "DEL", "N/A"};
 | |
| 
 | |
|     task_num = os_get_toltal_task_cnt();
 | |
| 
 | |
|     /* More than one task exists if AT running. */
 | |
|     if((0 == task_num)
 | |
|         || (NULL == (p_task_info_pkt = iot_pkt_alloc
 | |
|             (sizeof(*p_tasks) * task_num, AT_COMMAND_MID))))
 | |
|     {
 | |
|         at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_tasks = (task_info_t *)iot_pkt_data(p_task_info_pkt);
 | |
| 
 | |
|     if((0 == (task_num = os_get_task_info(p_tasks, task_num)))
 | |
|         ||(NULL == (p_pkt_sprintf_data = iot_pkt_alloc(256, AT_COMMAND_MID))))
 | |
|     {
 | |
|         iot_pkt_free(p_task_info_pkt);
 | |
|         at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_buf = iot_pkt_data(p_pkt_sprintf_data);
 | |
| 
 | |
|     for(i = 0; i < task_num; i++)
 | |
|     {
 | |
|         p_tasks->status = (p_tasks->status >= IOT_INVALID
 | |
|             || p_tasks->status < IOT_RUN) ? IOT_INVALID : p_tasks->status;
 | |
| 
 | |
|         if((0 == task_id)
 | |
|             ||(task_id == p_tasks->id))
 | |
|         {
 | |
|             data_len = iot_sprintf((char *)p_buf,
 | |
|                 "\r\n#%2d | ID:0x%08x | PRIO:%2d | STATE:%s | "\
 | |
|                 "CPU_R:%2d%% | STACK:0x%08x | LOWEST:%4d | NAME:%-40.40s",
 | |
|                 i, p_tasks->id, p_tasks->priority,
 | |
|                 (char *)p_state[p_tasks->status],
 | |
|                 p_tasks->cpu_time_ratio, p_tasks->stack_base,
 | |
|                 p_tasks->stack_warter_mask, p_tasks->name);
 | |
|             at_command_at_response_to_proto(AT_RESP_OK, p_buf, data_len, false);
 | |
|         }
 | |
| 
 | |
|         p_tasks++;
 | |
|     }
 | |
| 
 | |
|     data_len = iot_sprintf((char *)p_buf, "\r\nTotal %d tasks.", task_num);
 | |
| 
 | |
|     at_command_at_response_to_proto(AT_RESP_OK, p_buf, data_len, true);
 | |
| 
 | |
|     iot_pkt_free(p_task_info_pkt);
 | |
|     iot_pkt_free(p_pkt_sprintf_data);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_handle_command_task(uint32_t opcode, uint32_t argc, uint8_t *argv[])
 | |
| {
 | |
|     uint32_t task_id;
 | |
| 
 | |
|     (void)opcode;
 | |
| 
 | |
|     if((argc >= 1)
 | |
|         &&(at_command_hex_2_digtal(argv[0], &task_id) > 0))
 | |
|     {
 | |
|         at_command_task_show((int)task_id);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         /* Show all */
 | |
|         at_command_task_show(0);
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| 
 | |
| void at_handle_command_reboot(uint32_t opcode, uint32_t argc, uint8_t *argv[])
 | |
| {
 | |
|     uint8_t buf[64], t_mac[IOT_MAC_ADDR_LEN];
 | |
|     uint32_t data_len;
 | |
| 
 | |
|     if(AT_OP_SET != opcode)
 | |
|     {
 | |
|         DERROR("Invalid argument!");
 | |
|         at_command_at_response_to_proto
 | |
|             (AT_RESP_INVALID_ARGUMENT, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if(argc <1)
 | |
|     {
 | |
|         data_len = iot_sprintf((char *)buf,
 | |
|             "This systerm will be reboot after 5 seconds!");
 | |
| 
 | |
|         at_command_at_response_to_proto(AT_RESP_OK, buf, data_len, true);
 | |
| 
 | |
|         /* Reboot delay. */
 | |
|         os_delay(5000);
 | |
| 
 | |
|         iot_system_restart(IOT_SYS_RST_REASON_APP_REQ);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         if(IOT_MAC_ADDR_LEN != at_command_string_2_digtal
 | |
|             (argv[0], t_mac, IOT_MAC_ADDR_LEN))
 | |
|         {
 | |
|             at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         /* TODO: remote reboot. */
 | |
|         data_len = iot_sprintf((char *)buf,
 | |
|             "Cannot reboot remote device %02x:%02x:%02x:%02x:%02x:%02x!",
 | |
|             t_mac[0], t_mac[1], t_mac[2], t_mac[3], t_mac[4], t_mac[5]);
 | |
| 
 | |
|         at_command_at_response_to_proto(AT_RESP_ERROR, buf, data_len, true);
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_handle_response_reboot(iot_pkt_t *p_resp_pkt)
 | |
| {
 | |
|     (void)p_resp_pkt;
 | |
| }
 | |
| 
 | |
| void at_handle_command_who(uint32_t opcode, uint32_t argc, uint8_t *argv[])
 | |
| {
 | |
|     (void)opcode;
 | |
|     (void)argc;
 | |
|     (void)argv;
 | |
| }
 | |
| 
 | |
| void at_handle_response_who(iot_pkt_t *p_resp_pkt)
 | |
| {
 | |
|     (void)p_resp_pkt;
 | |
| }
 | |
| 
 | |
| void at_handle_command_rfpower(uint32_t opcode, uint32_t argc, uint8_t *argv[])
 | |
| {
 | |
|     uint32_t power = 0, pkt_len;
 | |
|     iot_pkt_t *p_pkt;
 | |
|     plctxrx_cmd_arg_t *p_arg;
 | |
|     plctxrx_cmd_tx_pwr_t *p_txpower;
 | |
| 
 | |
|     if(((AT_OP_SET != opcode) && (AT_OP_QUERY != opcode))
 | |
|         ||((AT_OP_SET == opcode)
 | |
|         &&((argc < 1) || (at_command_uint32_2_digtal(argv[0], &power) <= 0))))
 | |
|     {
 | |
|         DERROR("Invalid argument!");
 | |
|         at_command_at_response_to_proto
 | |
|             (AT_RESP_INVALID_ARGUMENT, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     pkt_len = sizeof(*p_arg) + sizeof(*p_txpower);
 | |
| 
 | |
|     if(NULL == (p_pkt = iot_pkt_alloc(pkt_len, AT_COMMAND_MID)))
 | |
|     {
 | |
|         DERROR("No memory!");
 | |
|         at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_arg = (plctxrx_cmd_arg_t *)iot_pkt_put(p_pkt, pkt_len);
 | |
| 
 | |
|     p_arg->cid.cid = PLCTXRX_CID_TX_PWR;
 | |
|     p_arg->prio = AT_DEF_PRIO;
 | |
|     p_arg->need_ack = true;
 | |
| 
 | |
|     if(AT_OP_SET == opcode)
 | |
|     {
 | |
|         p_arg->cid.opcode = PLCTXRX_OP_CONFIG;
 | |
|         p_arg->dlen = sizeof(*p_txpower);
 | |
|         p_txpower = (plctxrx_cmd_tx_pwr_t *)p_arg->arg;
 | |
|         p_txpower->tx_pwr = (uint8_t)(power & 0xFF);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         p_arg->cid.opcode = PLCTXRX_OP_QUERY;
 | |
|         p_arg->dlen = 0;
 | |
|     }
 | |
| 
 | |
|     at_command_send_to_plc(p_pkt);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_handle_response_rfpower(iot_pkt_t *p_resp_pkt)
 | |
| {
 | |
|     uint8_t buf[64], result;
 | |
|     uint32_t ret, data_len;
 | |
|     plctxrx_cmd_resp_t *p_resp;
 | |
| 
 | |
|     if(NULL == p_resp_pkt)
 | |
|     {
 | |
|         DERROR("Invalid argument!");
 | |
|         at_command_at_response_to_proto
 | |
|             (AT_RESP_INVALID_ARGUMENT, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_resp = (plctxrx_cmd_resp_t *)iot_pkt_data(p_resp_pkt);
 | |
| 
 | |
|     /* PLCtxrx level has no struct for this. */
 | |
|     result = p_resp->data[0];
 | |
| 
 | |
|     ret = (PLCTXRX_RESP_OK == p_resp->resp) ? AT_RESP_OK : AT_RESP_ERROR;
 | |
| 
 | |
|     if(PLCTXRX_OP_CFM == p_resp->cid.opcode)
 | |
|     {
 | |
|         data_len = iot_sprintf((char *)buf,
 | |
|             "Config rfpower %s!", result ? "failed" : "successfully");
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         data_len = iot_sprintf((char *)buf,
 | |
|             "Current rfpower is %d.", ((int)result) & 0xFF);
 | |
|     }
 | |
| 
 | |
|     at_command_at_response_to_proto(ret, buf, data_len, true);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /* Return the index of mac in the online device table if found, return -1 means not found. */
 | |
| int32_t at_command_check_online_mac_exists
 | |
|     (uint8_t *p_mac, at_dev_t *p_dev_table, uint8_t valid_cnt)
 | |
| {
 | |
|     uint8_t i;
 | |
| 
 | |
|     if (NULL == p_mac || NULL == p_dev_table)
 | |
|     {
 | |
|         DERROR("Invalid argument!");
 | |
|         return -1;
 | |
|     }
 | |
| 
 | |
|     for (i = 0; i < valid_cnt; i++)
 | |
|     {
 | |
|         if (0 == os_mem_cmp(p_dev_table[i].mac, p_mac, IOT_MAC_ADDR_LEN))
 | |
|         {
 | |
|             return i;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return -1;
 | |
| }
 | |
| 
 | |
| /* Add new device to online device list. */
 | |
| void at_command_add_dev_to_online
 | |
|     (at_dev_list_t *p_dev_list, at_dev_t *p_new_dev)
 | |
| {
 | |
|     uint8_t cnt;
 | |
| 
 | |
|     if ((NULL == p_dev_list) || (NULL == p_new_dev))
 | |
|     {
 | |
|         DERROR("Invalid argument!");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Get a free place to store. */
 | |
|     cnt = p_dev_list->valid_dev_cnt;
 | |
|     if (cnt < AT_STA_DEV_MAX)
 | |
|     {
 | |
|         os_mem_cpy(&(p_dev_list->dev[cnt]), p_new_dev, sizeof(at_dev_t));
 | |
|         p_dev_list->valid_dev_cnt++;
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   * @brief Delete existing device from online device list.
 | |
|   * @param p_dev_list: the pointer of device list.
 | |
|   * @param dev_tb_index: the index of device saved in device table that need to delete.
 | |
|   */
 | |
| void at_command_del_dev_from_online
 | |
|    (at_dev_list_t *p_dev_list, int32_t dev_tb_index)
 | |
| {
 | |
|     uint32_t cnt;
 | |
|     at_dev_t *p_dev_table;
 | |
| 
 | |
|     if ((NULL == p_dev_list)
 | |
|         || (dev_tb_index >= AT_STA_DEV_MAX)
 | |
|         || (dev_tb_index < 0))
 | |
|     {
 | |
|         DERROR("Invalid argument!");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_dev_table = p_dev_list->dev;
 | |
| 
 | |
|     /* Clear the contents of the device based on the index value. */
 | |
|     os_mem_set(&p_dev_table[dev_tb_index], 0, sizeof(at_dev_t));
 | |
|     /* Reorg the device table, move the rest device forward one by one. */
 | |
|     for(cnt = dev_tb_index + 1; cnt < p_dev_list->valid_dev_cnt; cnt++)
 | |
|     {
 | |
|         p_dev_table[cnt - 1] = p_dev_table[cnt];
 | |
| 
 | |
|         if (cnt == p_dev_list->valid_dev_cnt - 1)
 | |
|         {
 | |
|             /* Clear the contents of the last position as a result of reorg. */
 | |
|             os_mem_set(&p_dev_table[cnt], 0, sizeof(at_dev_t));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /* Reduce the total valid number. */
 | |
|     p_dev_list->valid_dev_cnt -= 1;
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /* Return the index of mac in the flash device table if found, return -1 means not found. */
 | |
| int32_t at_command_check_flash_mac_exists
 | |
|     (uint8_t *p_mac, proto_dev_t *p_dev_table, uint16_t valid_cnt)
 | |
| {
 | |
|     uint16_t i;
 | |
| 
 | |
|     if (NULL == p_mac || NULL == p_dev_table)
 | |
|     {
 | |
|         DERROR("Invalid argument!");
 | |
|         return -1;
 | |
|     }
 | |
| 
 | |
|     for (i = 0; i < valid_cnt; i++)
 | |
|     {
 | |
|         if (0 == os_mem_cmp(p_dev_table[i].mac, p_mac, IOT_MAC_ADDR_LEN))
 | |
|         {
 | |
|             return i;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return -1;
 | |
| }
 | |
| 
 | |
| /* Add new device to device list saved in flash. */
 | |
| void at_command_add_dev_to_flash(custom_flash_info_t *p_info, at_dev_t *p_new_dev)
 | |
| {
 | |
|     uint8_t cnt;
 | |
| 
 | |
|     if ((NULL == p_info) || (NULL == p_new_dev))
 | |
|     {
 | |
|         DERROR("Invalid argument!");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Get a free place to store. */
 | |
|     cnt = p_info->dev_cnt;
 | |
|     if (cnt < AT_STA_DEV_MAX)
 | |
|     {
 | |
|         p_info->dev_tbl[cnt].ip = 0;
 | |
|         p_info->dev_tbl[cnt].dev_role = p_new_dev->dev_role;
 | |
|         iot_mac_addr_cpy(p_info->dev_tbl[cnt].mac, p_new_dev->mac);
 | |
|         p_info->dev_cnt++;
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   * @brief Delete existing device from device list saved in flash.
 | |
|   * @param p_dev_list: the pointer of device list.
 | |
|   * @param dev_tb_index: the index of device saved in device table that need to delete.
 | |
|   */
 | |
| void at_command_del_dev_from_flash
 | |
|    (custom_flash_info_t *p_info, int32_t dev_tb_index)
 | |
| {
 | |
|     uint32_t cnt;
 | |
|     proto_dev_t *p_dev_table;
 | |
| 
 | |
|     if ((NULL == p_info)
 | |
|         || (dev_tb_index >= AT_STA_DEV_MAX)
 | |
|         || (dev_tb_index < 0))
 | |
|     {
 | |
|         DERROR("Invalid argument!");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_dev_table = p_info->dev_tbl;
 | |
| 
 | |
|     /* Clear the contents of the device based on the index value. */
 | |
|     os_mem_set(&p_dev_table[dev_tb_index], 0, sizeof(proto_dev_t));
 | |
|     /* Reorg the device table, move the rest device forward one by one. */
 | |
|     for(cnt = dev_tb_index + 1; cnt < p_info->dev_cnt; cnt++)
 | |
|     {
 | |
|         p_dev_table[cnt - 1] = p_dev_table[cnt];
 | |
| 
 | |
|         if (cnt == p_info->dev_cnt - 1)
 | |
|         {
 | |
|             /* Clear the contents of the last position when reorg. */
 | |
|             os_mem_set(&p_dev_table[cnt], 0, sizeof(proto_dev_t));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /* Reduce the total valid number. */
 | |
|     p_info->dev_cnt -= 1;
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief Add/Delete whitelist to/from CVG layer, based on device list saved in flash.
 | |
|  * @param action : 0 - delete; 1 - add. (same with proto layer defined)
 | |
|  * @param need_ack_cfm : true - plctxrx will ack cfm; false - No ack cfm.
 | |
|  */
 | |
| void at_command_cvg_wl_add_del(uint8_t action, uint8_t *mac, bool_t need_ack_cfm)
 | |
| {
 | |
|     uint8_t i, cnt;
 | |
|     iot_pkt_t *p_pkt;
 | |
|     uint32_t pkt_len;
 | |
|     plctxrx_cmd_arg_t *p_arg;
 | |
|     plctxrx_cmd_whitelist_t *p_wlist_set;
 | |
|     custom_flash_info_t *p_flash = &uniform_flashinfo_at;
 | |
| 
 | |
|     /* One mac op or the whole valid device table. */
 | |
|     if (mac)
 | |
|     {
 | |
|         cnt = 1;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         cnt = p_flash->dev_cnt;
 | |
|         if (0 == cnt)
 | |
|         {
 | |
|             DINFOR("No valid device to add or delete!");
 | |
|             return;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     pkt_len = sizeof(*p_arg) + sizeof(*p_wlist_set) + cnt * IOT_MAC_ADDR_LEN;
 | |
|     if (NULL == (p_pkt = iot_pkt_alloc(pkt_len, AT_COMMAND_MID)))
 | |
|     {
 | |
|         DERROR("No Memory!");
 | |
|         at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_arg = (plctxrx_cmd_arg_t *)iot_pkt_put(p_pkt, pkt_len);
 | |
|     p_arg->cid.cid = PLCTXRX_CID_WHITELIST;
 | |
|     p_arg->cid.opcode = PLCTXRX_OP_CONFIG;
 | |
|     p_arg->prio = 0;
 | |
|     p_arg->need_ack = need_ack_cfm;
 | |
|     p_arg->dlen = sizeof(*p_wlist_set) + cnt * IOT_MAC_ADDR_LEN;
 | |
| 
 | |
|     p_wlist_set = (plctxrx_cmd_whitelist_t *)p_arg->arg;
 | |
|     p_wlist_set->action = action;
 | |
| 
 | |
|     for (i = 0; i < cnt; i++)
 | |
|     {
 | |
|         iot_mac_addr_cpy(p_wlist_set->maclist[i], p_flash->dev_tbl[i].mac);
 | |
|         DINFOR("Set whitelist %02x:%02x:%02x:%02x:%02x:%02x!",
 | |
|             p_wlist_set->maclist[i][0], p_wlist_set->maclist[i][1],
 | |
|             p_wlist_set->maclist[i][2], p_wlist_set->maclist[i][3],
 | |
|             p_wlist_set->maclist[i][4], p_wlist_set->maclist[i][5]);
 | |
|     }
 | |
| 
 | |
|     p_wlist_set->listcnt = cnt;
 | |
|     at_command_send_to_plc(p_pkt);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief Enable/disable whitelist in CVG layer, based on device list saved in flash.
 | |
|  * @param action: 2 - disable; 3 - enable (same with proto layer defined)
 | |
|  * @param need_ack_cfm: true - plctxrx will ack cfm; false - No ack cfm.
 | |
|  */
 | |
| void at_command_cvg_wl_en_disable(uint8_t action, bool_t need_ack_cfm)
 | |
| {
 | |
|     iot_pkt_t *p_pkt;
 | |
|     uint32_t pkt_len;
 | |
|     plctxrx_cmd_arg_t *p_arg;
 | |
|     plctxrx_cmd_whitelist_t *p_wlist_set;
 | |
| 
 | |
|     pkt_len = sizeof(*p_arg) + sizeof(*p_wlist_set);
 | |
|     if (NULL == (p_pkt = iot_pkt_alloc(pkt_len, AT_COMMAND_MID)))
 | |
|     {
 | |
|         DERROR("No Memory!");
 | |
|         at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_arg = (plctxrx_cmd_arg_t *)iot_pkt_put(p_pkt, pkt_len);
 | |
|     p_arg->cid.cid = PLCTXRX_CID_WHITELIST;
 | |
|     p_arg->cid.opcode = PLCTXRX_OP_CONFIG;
 | |
|     p_arg->prio = AT_DEF_PRIO;
 | |
|     p_arg->need_ack = need_ack_cfm;
 | |
|     p_arg->dlen = sizeof(*p_wlist_set);
 | |
| 
 | |
|     p_wlist_set = (plctxrx_cmd_whitelist_t *)p_arg->arg;
 | |
|     p_wlist_set->action = action;
 | |
|     p_wlist_set->listcnt = 0;
 | |
| 
 | |
|     at_command_send_to_plc(p_pkt);
 | |
| }
 | |
| 
 | |
| /* Save online device list to device list saved in flash and add whitelist to CVG layer. */
 | |
| void at_command_online_dev_list_save2flash(void)
 | |
| {
 | |
|     uint8_t cnt;
 | |
|     at_dev_list_t *p_dev_list = &(at_command_context.online_dev_list);
 | |
|     custom_flash_info_t *p_flash = &uniform_flashinfo_at;
 | |
| 
 | |
|     if (p_dev_list->valid_dev_cnt <= AT_STA_DEV_MAX)
 | |
|     {
 | |
|         p_flash->dev_cnt = p_dev_list->valid_dev_cnt;
 | |
|         for (cnt = 0; cnt < p_dev_list->valid_dev_cnt; cnt++)
 | |
|         {
 | |
|             p_flash->dev_tbl[cnt].ip = 0;
 | |
|             p_flash->dev_tbl[cnt].dev_role = p_dev_list->dev[cnt].dev_role;
 | |
|             iot_mac_addr_cpy(p_flash->dev_tbl[cnt].mac, p_dev_list->dev[cnt].mac);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /* Write flash. */
 | |
|     if(ERR_OK == at_command_uniform_flashsave(p_flash))
 | |
|     {
 | |
|         DINFOR("Local device list save to flash successfully!");
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         DERROR("Local device list save to flash failed!");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Add whitelist to CVG layer.*/
 | |
|     at_command_cvg_wl_add_del(AT_WL_ACTION_ADD, NULL, false);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_handle_command_whitelist(uint32_t opcode, uint32_t argc, uint8_t *argv[])
 | |
| {
 | |
|     uint8_t target_mac[IOT_MAC_ADDR_LEN];
 | |
|     uint32_t pkt_len;
 | |
|     iot_pkt_t *p_pkt;
 | |
|     plctxrx_cmd_arg_t *p_arg;
 | |
|     plctxrx_cmd_whitelist_t *p_wl_set;
 | |
| 
 | |
|     at_dev_t signle_dev;
 | |
|     custom_flash_info_t *p_flash = &uniform_flashinfo_at;
 | |
|     int32_t dev_tb_index;
 | |
| 
 | |
|     uint8_t *rsp_data;
 | |
|     uint32_t rsp_data_len;
 | |
|     uint32_t i, wl_total_cnt;
 | |
| 
 | |
|     /* Check the validity of the parameters. */
 | |
|     if(((AT_OP_QUERY != opcode) && (AT_OP_SET != opcode))
 | |
|         ||((AT_OP_SET == opcode) && ((argc < 2)
 | |
|             ||(IOT_MAC_ADDR_LEN != at_command_string_2_digtal
 | |
|                 (argv[1], target_mac, IOT_MAC_ADDR_LEN))
 | |
|             ||((iot_strcmp((char *)argv[0], USER_INPUT_ADD_STR))
 | |
|             && (iot_strcmp((char *)argv[0], USER_INPUT_DEL_STR))))))
 | |
|     {
 | |
|         DERROR("Invalid argument!");
 | |
|         at_command_at_response_to_proto
 | |
|             (AT_RESP_INVALID_ARGUMENT, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (AT_OP_SET == opcode)
 | |
|     {
 | |
|         if (at_command_context.dev_type == IOT_PLC_DEV_ROLE_CCO)
 | |
|             signle_dev.dev_role= IOT_PLC_DEV_ROLE_STA;
 | |
|         else
 | |
|             signle_dev.dev_role= IOT_PLC_DEV_ROLE_CCO;
 | |
| 
 | |
|         os_mem_cpy(signle_dev.mac, target_mac, IOT_MAC_ADDR_LEN);
 | |
| 
 | |
|         pkt_len = sizeof(*p_arg) + sizeof(*p_wl_set) + IOT_MAC_ADDR_LEN;
 | |
|         if (NULL == (p_pkt = iot_pkt_alloc(pkt_len, AT_COMMAND_MID)))
 | |
|         {
 | |
|             DERROR("No Memory!");
 | |
|             at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         p_arg = (plctxrx_cmd_arg_t *)iot_pkt_put(p_pkt, pkt_len);
 | |
| 
 | |
|         p_arg->cid.cid = PLCTXRX_CID_WHITELIST;
 | |
|         p_arg->cid.opcode  = PLCTXRX_OP_CONFIG;
 | |
|         p_arg->prio = AT_DEF_PRIO;
 | |
|         p_arg->need_ack = true;
 | |
|         p_arg->dlen = sizeof(*p_wl_set) + IOT_MAC_ADDR_LEN;
 | |
| 
 | |
|         p_wl_set = (plctxrx_cmd_whitelist_t *)p_arg->arg;
 | |
| 
 | |
|         at_command_wl_op.latest_wl_action = AT_WL_ACTION_NONE;
 | |
| 
 | |
|         if (0 == (iot_strcmp((char *)argv[0], USER_INPUT_ADD_STR)))
 | |
|         {
 | |
|             if (p_flash->dev_cnt >= AT_STA_DEV_MAX)
 | |
|             {
 | |
|                 DERROR("No free space to store new device!");
 | |
|                 at_command_at_response_to_proto(AT_RESP_OK, NULL, 0, true);
 | |
|                 iot_pkt_free(p_pkt);
 | |
|                 return;
 | |
|             }
 | |
| 
 | |
|             if (-1 != (dev_tb_index = at_command_check_flash_mac_exists
 | |
|                     (signle_dev.mac, p_flash->dev_tbl, p_flash->dev_cnt)))
 | |
|             {
 | |
|                 DERROR("MAC Exist!");
 | |
|                 at_command_at_response_to_proto(AT_RESP_OK, NULL, 0, true);
 | |
|                 iot_pkt_free(p_pkt);
 | |
|                 return;
 | |
|             }
 | |
| 
 | |
|             p_wl_set->action = IOT_PLC_WL_ADD;
 | |
|             at_command_wl_op.latest_wl_action = AT_WL_ACTION_ADD;
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             if (-1 == (dev_tb_index = at_command_check_flash_mac_exists
 | |
|                     (signle_dev.mac, p_flash->dev_tbl, p_flash->dev_cnt)))
 | |
|             {
 | |
|                 DERROR("MAC Not Exist!");
 | |
|                 at_command_at_response_to_proto(AT_RESP_OK, NULL, 0, true);
 | |
|                 iot_pkt_free(p_pkt);
 | |
|                 return;
 | |
|             }
 | |
| 
 | |
|             p_wl_set->action = IOT_PLC_WL_DEL;
 | |
|             at_command_wl_op.latest_wl_action = AT_WL_ACTION_DEL;
 | |
|         }
 | |
| 
 | |
|         os_mem_cpy(&(at_command_wl_op.signle_dev), &signle_dev, sizeof(at_dev_t));
 | |
| 
 | |
|         /* Sync new device mac to CVG layer whitelist. */
 | |
|         p_wl_set->listcnt = 1;
 | |
|         os_mem_cpy(p_wl_set->maclist[0], signle_dev.mac, IOT_MAC_ADDR_LEN);
 | |
|         at_command_send_to_plc(p_pkt);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         /* Select the appropriate buffer size, ensure it is enough for print buffer. */
 | |
|         if(NULL == (p_pkt = iot_pkt_alloc(AT_MID_BUF_SIZE, AT_COMMAND_MID)))
 | |
|         {
 | |
|             DERROR("No memory!");
 | |
|             at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         rsp_data = iot_pkt_data(p_pkt);
 | |
| 
 | |
|         wl_total_cnt = p_flash->dev_cnt;
 | |
|         for (i = 0; i < wl_total_cnt; i++)
 | |
|         {
 | |
|             rsp_data_len = iot_sprintf((char *)rsp_data,
 | |
|                 "\r\n#%2d | MAC:%02X:%02X:%02X:%02X:%02X:%02X.", i,
 | |
|                 p_flash->dev_tbl[i].mac[0], p_flash->dev_tbl[i].mac[1],
 | |
|                 p_flash->dev_tbl[i].mac[2], p_flash->dev_tbl[i].mac[3],
 | |
|                 p_flash->dev_tbl[i].mac[4], p_flash->dev_tbl[i].mac[5]);
 | |
| 
 | |
|             at_command_at_response_to_proto(AT_RESP_OK, rsp_data, rsp_data_len, false);
 | |
|         }
 | |
| 
 | |
|         rsp_data_len = iot_sprintf((char *)rsp_data,
 | |
|             "\r\nCurrent device role is %s, its whitelist entries total count = %d.",
 | |
|             (1 == PLC_SUPPORT_CCO_ROLE) ? "CCO" : "STA", wl_total_cnt);
 | |
| 
 | |
|         at_command_at_response_to_proto(AT_RESP_OK, rsp_data, rsp_data_len, true);
 | |
| 
 | |
|         iot_pkt_free(p_pkt);
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_handle_response_whitelist(iot_pkt_t *p_resp_pkt)
 | |
| {
 | |
|     uint32_t data_len, ret;
 | |
|     uint8_t *p_data;
 | |
|     iot_pkt_t *p_pkt;
 | |
|     plctxrx_cmd_resp_t *p_resp;
 | |
| 
 | |
|     custom_flash_info_t *p_flash = &uniform_flashinfo_at;
 | |
|     int32_t dev_tb_index;
 | |
| 
 | |
|     if(NULL == p_resp_pkt)
 | |
|     {
 | |
|         DERROR("Invalid argument!");
 | |
|         at_command_at_response_to_proto
 | |
|             (AT_RESP_INVALID_ARGUMENT, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Select the appropriate buffer size, ensure it is enough for print buffer. */
 | |
|     if(NULL == (p_pkt = iot_pkt_alloc(AT_MID_BUF_SIZE, AT_COMMAND_MID)))
 | |
|     {
 | |
|         DERROR("No memory!");
 | |
|         at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_data = iot_pkt_data(p_pkt);
 | |
| 
 | |
|     p_resp = (plctxrx_cmd_resp_t *)iot_pkt_data(p_resp_pkt);
 | |
| 
 | |
|     ret = (PLCTXRX_RESP_OK == p_resp->resp) ? AT_RESP_OK : AT_RESP_ERROR;
 | |
| 
 | |
|     if(PLCTXRX_OP_CFM == p_resp->cid.opcode)
 | |
|     {
 | |
|         if (PLCTXRX_RESP_OK == p_resp->resp)
 | |
|         {
 | |
|             if (AT_WL_ACTION_ADD == at_command_wl_op.latest_wl_action)
 | |
|             {
 | |
|                 if (-1 == (dev_tb_index = at_command_check_flash_mac_exists
 | |
|                     (at_command_wl_op.signle_dev.mac, p_flash->dev_tbl,
 | |
|                      p_flash->dev_cnt)))
 | |
|                 {
 | |
|                     /* Update device list saved in flash, add recorded signle dev info. */
 | |
|                     at_command_add_dev_to_flash(p_flash,
 | |
|                         &at_command_wl_op.signle_dev);
 | |
|                     if (ERR_OK != at_command_uniform_flashsave(p_flash))
 | |
|                     {
 | |
|                         DERROR("Update device list saved in flash failed!");
 | |
|                     }
 | |
| 
 | |
|                     data_len = iot_sprintf((char *)p_data,
 | |
|                         "\r\nConfig whitelist successfully!");
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     data_len = iot_sprintf((char *)p_data,
 | |
|                         "\r\nMAC Exist!Config whitelist failed!");
 | |
|                     at_command_at_response_to_proto(AT_RESP_ERROR,
 | |
|                         p_data, data_len, true);
 | |
|                     iot_pkt_free(p_pkt);
 | |
| 
 | |
|                     at_command_wl_op.latest_wl_action = AT_WL_ACTION_NONE;
 | |
| 
 | |
|                     return;
 | |
|                 }
 | |
|             }
 | |
|             else if (AT_WL_ACTION_DEL == at_command_wl_op.latest_wl_action)
 | |
|             {
 | |
|                 if (-1 == (dev_tb_index = at_command_check_flash_mac_exists
 | |
|                     (at_command_wl_op.signle_dev.mac, p_flash->dev_tbl,
 | |
|                      p_flash->dev_cnt)))
 | |
|                 {
 | |
|                     data_len = iot_sprintf((char *)p_data,
 | |
|                         "\r\nMAC Not Exist!Config whitelist failed!");
 | |
|                     at_command_at_response_to_proto(AT_RESP_ERROR,
 | |
|                         p_data, data_len, true);
 | |
|                     iot_pkt_free(p_pkt);
 | |
| 
 | |
|                     at_command_wl_op.latest_wl_action = AT_WL_ACTION_NONE;
 | |
| 
 | |
|                     return;
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     /* Update device list saved in flash. */
 | |
|                     at_command_del_dev_from_flash(p_flash, dev_tb_index);
 | |
|                     if (ERR_OK != at_command_uniform_flashsave(p_flash))
 | |
|                     {
 | |
|                         DERROR("Update device list saved in flash failed!");
 | |
|                     }
 | |
| 
 | |
|                     data_len = iot_sprintf((char *)p_data,
 | |
|                         "\r\nConfig whitelist successfully!");
 | |
|                 }
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 data_len = iot_sprintf((char *)p_data, "\r\nConfig whitelist failed!");
 | |
|             }
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             data_len = iot_sprintf((char *)p_data, "\r\nConfig whitelist failed!");
 | |
|         }
 | |
| 
 | |
|         at_command_at_response_to_proto(ret, p_data, data_len, true);
 | |
|     }
 | |
| 
 | |
|     iot_pkt_free(p_pkt);
 | |
| 
 | |
|     at_command_wl_op.latest_wl_action = AT_WL_ACTION_NONE;
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_handle_command_network(uint32_t opcode, uint32_t argc, uint8_t *argv[])
 | |
| {
 | |
|     uint8_t target_mac[IOT_MAC_ADDR_LEN];
 | |
|     iot_pkt_t *p_pkt;
 | |
|     uint32_t pkt_len;
 | |
|     plctxrx_cmd_arg_t *p_arg;
 | |
|     plctxrx_cmd_join_network_t *p_join;
 | |
|     plctxrx_cmd_leave_net_t *p_leave;
 | |
| 
 | |
|     at_dev_t new_dev_info;
 | |
|     custom_flash_info_t *p_flash = &uniform_flashinfo_at;
 | |
|     int32_t dev_tb_index;
 | |
| 
 | |
|     (void)argc;
 | |
|     (void)argv;
 | |
| 
 | |
|     if(((AT_OP_QUERY != opcode) && (AT_OP_SET != opcode))
 | |
|         ||((AT_OP_SET == opcode) && ((argc < 2)
 | |
|             ||(IOT_MAC_ADDR_LEN != at_command_string_2_digtal
 | |
|                 (argv[1], target_mac, IOT_MAC_ADDR_LEN))
 | |
|             ||((iot_strcmp((char *)argv[0], USER_INPUT_ADD_STR))
 | |
|             && (iot_strcmp((char *)argv[0], USER_INPUT_DEL_STR))))))
 | |
|     {
 | |
|         DERROR("Invalid argument!");
 | |
|         at_command_at_response_to_proto
 | |
|             (AT_RESP_INVALID_ARGUMENT, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Alloc a bigger buffer for all issues. */
 | |
|     pkt_len = sizeof(*p_arg) +
 | |
|         max(sizeof(*p_join), sizeof(*p_leave) + IOT_MAC_ADDR_LEN);
 | |
| 
 | |
|     if(NULL == (p_pkt = iot_pkt_alloc(pkt_len, AT_COMMAND_MID)))
 | |
|     {
 | |
|         DERROR("No memory!");
 | |
|         at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_arg = (plctxrx_cmd_arg_t *)iot_pkt_data(p_pkt);
 | |
| 
 | |
|     if(AT_OP_QUERY == opcode)
 | |
|     {
 | |
|         p_arg->cid.cid = PLCTXRX_CID_FIND_NETWORK;
 | |
|         p_arg->cid.opcode = PLCTXRX_OP_QUERY;
 | |
|         p_arg->dlen = 0;
 | |
|         pkt_len = sizeof(*p_arg);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         /* Store new dev info. STA update device list saved in flash and CVG whitelist. */
 | |
|         new_dev_info.dev_role= IOT_PLC_DEV_ROLE_CCO;
 | |
|         iot_mac_addr_cpy(new_dev_info.mac, target_mac);
 | |
| 
 | |
|         p_arg->cid.opcode = PLCTXRX_OP_CONFIG;
 | |
| 
 | |
|         if(0 == iot_strcmp((char *)argv[0], USER_INPUT_ADD_STR))
 | |
|         {
 | |
|             if (-1 != (dev_tb_index = at_command_check_flash_mac_exists
 | |
|                 (new_dev_info.mac, p_flash->dev_tbl, p_flash->dev_cnt)))
 | |
|             {
 | |
|                 DERROR("MAC Exist!");
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 if (p_flash->dev_cnt < AT_STA_DEV_MAX)
 | |
|                 {
 | |
|                     /* STA update device list saved in flash. */
 | |
|                     at_command_add_dev_to_flash(p_flash, &new_dev_info);
 | |
|                     if (ERR_OK != at_command_uniform_flashsave(p_flash))
 | |
|                     {
 | |
|                         DERROR("Update device list saved in flash failed!");
 | |
|                     }
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     DERROR("No free space to store new device!");
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             p_arg->cid.cid = PLCTXRX_CID_JOIN_NETWORK;
 | |
|             p_arg->dlen = sizeof(*p_join);
 | |
| 
 | |
|             pkt_len = sizeof(*p_arg) + sizeof(*p_join);
 | |
| 
 | |
|             p_join = (plctxrx_cmd_join_network_t *)p_arg->arg;
 | |
| 
 | |
|             /* Clear nid, they are not used. */
 | |
|             p_join->nid = 0;
 | |
| 
 | |
|             os_mem_cpy(p_join->mac, target_mac, IOT_MAC_ADDR_LEN);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             if (-1 == (dev_tb_index = at_command_check_flash_mac_exists
 | |
|                 (new_dev_info.mac, p_flash->dev_tbl, p_flash->dev_cnt)))
 | |
|             {
 | |
|                 DERROR("MAC Not Exist!");
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 /* STA update device list saved in flash. */
 | |
|                 at_command_del_dev_from_flash(p_flash, dev_tb_index);
 | |
|                 if (ERR_OK != at_command_uniform_flashsave(p_flash))
 | |
|                 {
 | |
|                     DERROR("Update device list saved in flash failed!");
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             p_arg->cid.cid = PLCTXRX_CID_LEAVE_NETWORK;
 | |
|             p_arg->dlen = sizeof(*p_leave);
 | |
| 
 | |
|             pkt_len = sizeof(*p_arg) + sizeof(*p_leave) + IOT_MAC_ADDR_LEN;
 | |
| 
 | |
|             p_leave = (plctxrx_cmd_leave_net_t *)p_arg->arg;
 | |
| 
 | |
|             p_leave->cnt = 1;
 | |
| 
 | |
|             os_mem_cpy(p_leave->mac[0], target_mac, IOT_MAC_ADDR_LEN);
 | |
| 
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     p_arg->need_ack = true;
 | |
|     p_arg->prio = AT_DEF_PRIO;
 | |
| 
 | |
|     iot_pkt_put(p_pkt, pkt_len);
 | |
| 
 | |
|     at_command_send_to_plc(p_pkt);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_handle_response_network(iot_pkt_t *p_resp_pkt)
 | |
| {
 | |
|     uint32_t i, total, data_len, ret;
 | |
|     uint8_t *p_buf;
 | |
|     iot_pkt_t *p_pkt;
 | |
|     plctxrx_cmd_resp_t *p_resp;
 | |
|     plctxrx_cmd_network_t *p_net;
 | |
|     plctxrx_cmd_joined_network_t *p_join;
 | |
|     plctxrx_cmd_leave_net_t *p_leave;
 | |
| 
 | |
|     at_dev_t new_dev_info;
 | |
|     at_dev_list_t *p_dev_list = &(at_command_context.online_dev_list);
 | |
|     int32_t dev_tb_index;
 | |
| 
 | |
|     if (NULL == p_resp_pkt) {
 | |
|         DERROR("Invalid argument!");
 | |
|         at_command_at_response_to_proto
 | |
|             (AT_RESP_INVALID_ARGUMENT, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* 128 bytes is enough for print buffer. */
 | |
|     if (NULL == (p_pkt = iot_pkt_alloc(128, AT_COMMAND_MID))) {
 | |
|         DERROR("No memory!");
 | |
|         at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     p_buf = iot_pkt_data(p_pkt);
 | |
| 
 | |
|     p_resp = (plctxrx_cmd_resp_t *)iot_pkt_data(p_resp_pkt);
 | |
| 
 | |
|     if (PLCTXRX_OP_INDICATION == p_resp->cid.opcode) {
 | |
|         if (PLCTXRX_CID_FIND_NETWORK == p_resp->cid.cid) {
 | |
|             p_net = (plctxrx_cmd_network_t *)p_resp->data;
 | |
| 
 | |
|             total = p_net->count;
 | |
| 
 | |
|             for (i = 0; i < total; i++) {
 | |
|                 data_len = iot_sprintf((char *)p_buf,
 | |
|                     "\r\n#%2d | NID:0x%08x | MAC:%02x:%02x:%02x:%02x:%02x:%02x"\
 | |
|                     " | SNR:%d",
 | |
|                     i, p_net->node[i].nid, p_net->node[i].mac[0],
 | |
|                     p_net->node[i].mac[1], p_net->node[i].mac[2],
 | |
|                     p_net->node[i].mac[3], p_net->node[i].mac[4],
 | |
|                     p_net->node[i].mac[5], (int)p_net->node[i].snr);
 | |
| 
 | |
|                 at_command_at_response_to_proto(AT_RESP_OK, p_buf,
 | |
|                     data_len, false);
 | |
|             }
 | |
| 
 | |
|             data_len = iot_sprintf((char *)p_buf,
 | |
|                 "\r\nTotal %d network found!", total);
 | |
|         } else if(PLCTXRX_CID_JOIN_NETWORK == p_resp->cid.cid) {
 | |
|             /* PLCTXRX_CID_JOIN_NETWORK */
 | |
|             p_join = (plctxrx_cmd_joined_network_t *)p_resp->data;
 | |
|             if (at_command_context.dev_type == IOT_PLC_DEV_ROLE_CCO) {
 | |
|                 data_len = iot_sprintf((char *)p_buf,
 | |
|                     "\r\nRemote MAC:%02x:%02x:%02x:%02x:%02x:%02x join network!",
 | |
|                     p_join->mac[0], p_join->mac[1], p_join->mac[2],
 | |
|                     p_join->mac[3], p_join->mac[4], p_join->mac[5]);
 | |
|             } else {
 | |
|                 data_len = iot_sprintf((char *)p_buf,
 | |
|                     "\r\nJoin network NID:0x%08x "
 | |
|                     "MAC:%02x:%02x:%02x:%02x:%02x:%02x!",
 | |
|                     p_join->nid, p_join->mac[0], p_join->mac[1], p_join->mac[2],
 | |
|                     p_join->mac[3], p_join->mac[4], p_join->mac[5]);
 | |
|             }
 | |
| 
 | |
|             /* Store new device info. CCO and STA update online device list only. */
 | |
|             if (at_command_context.dev_type == IOT_PLC_DEV_ROLE_CCO)
 | |
|             {
 | |
|                 new_dev_info.dev_role= IOT_PLC_DEV_ROLE_STA;
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 new_dev_info.dev_role= IOT_PLC_DEV_ROLE_CCO;
 | |
|             }
 | |
|             iot_mac_addr_cpy(new_dev_info.mac, p_join->mac);
 | |
| 
 | |
|             if (-1 != (dev_tb_index = at_command_check_online_mac_exists
 | |
|                         (new_dev_info.mac, p_dev_list->dev, p_dev_list->valid_dev_cnt)))
 | |
|             {
 | |
|                 DERROR("MAC Exist!");
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 if (p_dev_list->valid_dev_cnt < AT_STA_DEV_MAX)
 | |
|                 {
 | |
|                     /* CCO and STA update online device list only. */
 | |
|                     at_command_add_dev_to_online(p_dev_list, &new_dev_info);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     DERROR("No free space to store new device!");
 | |
|                 }
 | |
|             }
 | |
|         } else {
 | |
|             /* PLCTXRX_CID_LEAVE_NETWORK */
 | |
|             p_leave = (plctxrx_cmd_leave_net_t *)p_resp->data;
 | |
|             if (at_command_context.dev_type == IOT_PLC_DEV_ROLE_CCO) {
 | |
|                 total = p_leave->cnt;
 | |
|                 for (i = 0; i < total; i++) {
 | |
|                     data_len = iot_sprintf((char *)p_buf,
 | |
|                         "\r\n#%2d MAC:%02x:%02x:%02x:%02x:%02x:%02x",
 | |
|                         i, p_leave->mac[i][0], p_leave->mac[i][1],
 | |
|                         p_leave->mac[i][2], p_leave->mac[i][3],
 | |
|                         p_leave->mac[i][4], p_leave->mac[i][5]);
 | |
| 
 | |
|                     at_command_at_response_to_proto(AT_RESP_OK, p_buf,
 | |
|                         data_len, false);
 | |
|                 }
 | |
| 
 | |
|                 data_len = iot_sprintf((char *)p_buf,
 | |
|                     "\r\nTotal %d network leave!", total);
 | |
|             } else {
 | |
|                 data_len = iot_sprintf((char *)p_buf,
 | |
|                     "\r\nLeave network MAC:%02x:%02x:%02x:%02x:%02x:%02x!",
 | |
|                     p_leave->mac[0][0], p_leave->mac[0][1], p_leave->mac[0][2],
 | |
|                     p_leave->mac[0][3], p_leave->mac[0][4], p_leave->mac[0][5]);
 | |
|             }
 | |
| 
 | |
|             /* Store new temp device info. CCO and STA update online device list only. */
 | |
|             if (at_command_context.dev_type == IOT_PLC_DEV_ROLE_CCO)
 | |
|             {
 | |
|                 total = p_leave->cnt;
 | |
|                 for (i = 0; i < total; i++)
 | |
|                 {
 | |
|                     new_dev_info.dev_role= IOT_PLC_DEV_ROLE_STA;
 | |
|                     iot_mac_addr_cpy(new_dev_info.mac, p_leave->mac[i]);
 | |
| 
 | |
|                     if (-1 == (dev_tb_index = at_command_check_online_mac_exists
 | |
|                         (new_dev_info.mac, p_dev_list->dev, p_dev_list->valid_dev_cnt)))
 | |
|                     {
 | |
|                         DERROR("MAC Not Exist!");
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
|                         /* CCO update online device list only. */
 | |
|                         at_command_del_dev_from_online(p_dev_list, dev_tb_index);
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 new_dev_info.dev_role= IOT_PLC_DEV_ROLE_CCO;
 | |
|                 iot_mac_addr_cpy(new_dev_info.mac, p_leave->mac[0]);
 | |
|                 if (-1 == (dev_tb_index = at_command_check_online_mac_exists
 | |
|                         (new_dev_info.mac, p_dev_list->dev, p_dev_list->valid_dev_cnt)))
 | |
|                 {
 | |
|                     DERROR("MAC Not Exist!");
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     /* STA update online device list only. */
 | |
|                     at_command_del_dev_from_online(p_dev_list, dev_tb_index);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     } else {
 | |
|         data_len = iot_sprintf((char *)p_buf,
 | |
|             "\r\nConifg %s network %s!",
 | |
|             (PLCTXRX_CID_JOIN_NETWORK == p_resp->cid.cid) ? "join" : "leave",
 | |
|             (PLCTXRX_RESP_OK == p_resp->resp) ? "successfully" : "failed");
 | |
|     }
 | |
| 
 | |
|     ret = (PLCTXRX_RESP_OK == p_resp->resp) ? AT_RESP_OK : AT_RESP_ERROR;
 | |
| 
 | |
|     at_command_at_response_to_proto(ret, p_buf, data_len, true);
 | |
| 
 | |
|     iot_pkt_free(p_pkt);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /* Operating the customer flash info saved in the AT layer. */
 | |
| void at_handle_command_flash(uint32_t opcode, uint32_t argc, uint8_t *argv[])
 | |
| {
 | |
|     iot_pkt_t *p_pkt, *p_resp_pkt;
 | |
|     uint32_t i, data_offset, data_len;
 | |
|     uint8_t *op_data;
 | |
|     uint32_t op_ret;
 | |
|     uint8_t *rsp_data;
 | |
|     uint32_t rsp_data_len;
 | |
| 
 | |
|     /* Select the appropriate buffer size for print buffer. */
 | |
|     if((NULL == (p_resp_pkt = iot_pkt_alloc(AT_SMALL_BUF_SIZE, AT_COMMAND_MID)))
 | |
|         || (NULL == (p_pkt = iot_pkt_alloc(AT_CUST_FLASH_MAX_OP_BUF_SIZE,
 | |
|             AT_COMMAND_MID))))
 | |
|     {
 | |
|         DERROR("No memory!");
 | |
|         at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     op_data = iot_pkt_data(p_pkt);
 | |
|     rsp_data = iot_pkt_data(p_resp_pkt);
 | |
| 
 | |
|     /* Check the validity of the parameters. */
 | |
|     if ((AT_OP_QUERY != opcode) && (AT_OP_SET != opcode))
 | |
|     {
 | |
|         goto ERROR_INVALID_ARG;
 | |
|     }
 | |
| 
 | |
|     if(AT_OP_SET == opcode)
 | |
|     {
 | |
|         if (0 == iot_strcmp((char *)argv[0], USER_INPUT_READ_STR))
 | |
|         {
 | |
|             if ((argc != 3)
 | |
|                 || (at_command_uint32_2_digtal(argv[1], &data_offset) <= 0)
 | |
|                 || (at_command_uint32_2_digtal(argv[2], &data_len) <= 0)
 | |
|                 || (data_len < 1)
 | |
|                 || (data_len > AT_CUST_FLASH_MAX_RD_WR_BYTES)
 | |
|                 || (data_offset + data_len > AT_CUST_FLASH_USER_OP_MAX_SIZE))
 | |
|             {
 | |
|                 goto ERROR_INVALID_ARG;
 | |
|             }
 | |
| 
 | |
|             op_ret = at_command_flash_read(
 | |
|                 AT_CUST_FLASH_USER_OP_START_OFFSET + data_offset,
 | |
|                 data_len, op_data);
 | |
| 
 | |
|             if (ERR_OK == op_ret)
 | |
|             {
 | |
|                 rsp_data_len = 0;
 | |
|                 rsp_data_len += iot_sprintf ((char *)(rsp_data + rsp_data_len), "\r\n");
 | |
|                 for(i = 0; i < data_len ; i++)
 | |
|                 {
 | |
|                     /* Reset print cache every 8byte, linefeed added for readability. */
 | |
|                     if ((0 == (i % AT_FLASH_DIS_ON_SAME_ROW_DATA_NUM))
 | |
|                         && (i > 0))
 | |
|                     {
 | |
|                         at_command_at_response_to_proto
 | |
|                             (AT_RESP_OK, rsp_data, rsp_data_len, false);
 | |
|                         rsp_data_len = 0;
 | |
|                         rsp_data_len += iot_sprintf
 | |
|                             ((char *)(rsp_data + rsp_data_len), "\r\n");
 | |
|                     }
 | |
| 
 | |
|                     rsp_data_len += iot_sprintf((char *)(rsp_data + rsp_data_len),
 | |
|                         "%02X ", op_data[i]);
 | |
|                 }
 | |
| 
 | |
|                 at_command_at_response_to_proto
 | |
|                     (AT_RESP_OK, rsp_data, rsp_data_len, true);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 rsp_data_len = iot_sprintf((char *)rsp_data, "\r\nRead failed!");
 | |
|                 at_command_at_response_to_proto
 | |
|                     ( AT_RESP_ERROR, rsp_data, rsp_data_len, true);
 | |
|             }
 | |
|         }
 | |
|         else if (0 == iot_strcmp((char *)argv[0], USER_INPUT_WRITE_STR))
 | |
|         {
 | |
|             if ((argc != 3)
 | |
|                 || (at_command_uint32_2_digtal(argv[1], &data_offset) <= 0)
 | |
|                 || (0 == (data_len = at_command_string_2_digtal
 | |
|                         (argv[2], op_data, AT_CUST_FLASH_MAX_OP_BUF_SIZE)))
 | |
|                 || (data_len > AT_CUST_FLASH_MAX_RD_WR_BYTES)
 | |
|                 || (data_offset + data_len > AT_CUST_FLASH_USER_OP_MAX_SIZE))
 | |
|             {
 | |
|                 goto ERROR_INVALID_ARG;
 | |
|             }
 | |
| 
 | |
|             op_ret = at_command_flash_write(
 | |
|                 AT_CUST_FLASH_USER_OP_START_OFFSET + data_offset,
 | |
|                 data_len, op_data);
 | |
|             rsp_data_len = iot_sprintf((char *)rsp_data,
 | |
|                 "\r\nWrite %s!", (ERR_OK == op_ret) ? "successfully" : "failed");
 | |
| 
 | |
|             at_command_at_response_to_proto
 | |
|                 ((ERR_OK == op_ret) ? AT_RESP_OK : AT_RESP_ERROR,
 | |
|                  rsp_data, rsp_data_len, true);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             goto ERROR_INVALID_ARG;
 | |
|         }
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         rsp_data_len = iot_sprintf((char *)rsp_data,
 | |
|             "\r\nMax size of customer flash that user can use is %d bytes.",
 | |
|             AT_CUST_FLASH_USER_OP_MAX_SIZE);
 | |
| 
 | |
|         at_command_at_response_to_proto(AT_RESP_OK, rsp_data, rsp_data_len, true);
 | |
|     }
 | |
| 
 | |
|     iot_pkt_free(p_pkt);
 | |
|     iot_pkt_free(p_resp_pkt);
 | |
|     return;
 | |
| 
 | |
| ERROR_INVALID_ARG:
 | |
|     DERROR("Invalid argument!");
 | |
|     at_command_at_response_to_proto
 | |
|         (AT_RESP_INVALID_ARGUMENT, NULL, 0, true);
 | |
|     iot_pkt_free(p_pkt);
 | |
|     iot_pkt_free(p_resp_pkt);
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_handle_command_spi(uint32_t opcode, uint32_t argc, uint8_t *argv[])
 | |
| {
 | |
|     iot_pkt_t *p_pkt;
 | |
| 
 | |
|     at_spi_cfg_t curr_spi_cfg;
 | |
|     iot_spi_cfg_t spi_gpio;
 | |
|     uint32_t port, clk_pin, cs_pin, miso_pin, mosi_pin;
 | |
|     uint32_t spi_cfg_hex, tm_cfg_hex;
 | |
|     uint8_t dev_type, trs_mode, frm_fmt, dfrm_sz, cs_en;
 | |
|     uint32_t frq, rx_thd, tx_thd;
 | |
|     uint8_t scpol, scph, scph_tgl, sste;
 | |
| 
 | |
|     uint32_t i;
 | |
|     uint32_t op_data_len, op_ret;
 | |
|     char rx_buf[AT_SPI_MAX_RD_WR_BYTES];
 | |
|     uint8_t tx_buf[AT_SPI_MAX_WR_BUF_SIZE];
 | |
| 
 | |
|     uint8_t *rsp_data;
 | |
|     uint32_t rsp_data_len;
 | |
| 
 | |
|     /*
 | |
|     Select the appropriate buffer size for print buffer, when spi read no more than 64 bytes,
 | |
|     one byte needs 3 chars to show (eg. _5E), so need choose the large buf size (256).
 | |
|     */
 | |
|     if(NULL == (p_pkt = iot_pkt_alloc(AT_LARGE_BUF_SIZE, AT_COMMAND_MID)))
 | |
|     {
 | |
|         DERROR("No memory!");
 | |
|         at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     rsp_data = iot_pkt_data(p_pkt);
 | |
| 
 | |
|     os_mem_set(rx_buf, 0, sizeof(char) * AT_SPI_MAX_RD_WR_BYTES);
 | |
|     os_mem_set(tx_buf, 0, sizeof(uint8_t) * AT_SPI_MAX_WR_BUF_SIZE);
 | |
| 
 | |
|     if(AT_OP_SET == opcode)
 | |
|     {
 | |
|         if (0 == iot_strcmp((char *)argv[0], USER_INPUT_READ_STR))
 | |
|         {
 | |
|             if (AT_SPI_INIT_COMPLETED == at_command_spi_cfg.inited)
 | |
|             {
 | |
|                 if ((argc != 2)
 | |
|                     || (at_command_uint32_2_digtal(argv[1], &op_data_len) <= 0)
 | |
|                     || (op_data_len > AT_SPI_MAX_RD_WR_BYTES))
 | |
|                 {
 | |
|                     goto ERROR_INVALID_ARG;
 | |
|                 }
 | |
| 
 | |
|                 op_ret = at_command_spi_read_data(rx_buf, (uint16_t)op_data_len);
 | |
| 
 | |
|                 if (ERR_OK == op_ret)
 | |
|                 {
 | |
|                     rsp_data_len = 0;
 | |
|                     for(i = 0; i < op_data_len ; i++)
 | |
|                     {
 | |
|                         rsp_data_len += iot_sprintf((char *)(rsp_data + rsp_data_len),
 | |
|                             "%02X ", rx_buf[i]);
 | |
|                     }
 | |
| 
 | |
|                     at_command_at_response_to_proto(AT_RESP_OK,
 | |
|                         rsp_data, rsp_data_len, true);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     rsp_data_len = iot_sprintf((char *)rsp_data, "\r\nSPI Read failed!");
 | |
|                     at_command_at_response_to_proto(AT_RESP_ERROR,
 | |
|                         rsp_data, rsp_data_len, true);
 | |
|                 }
 | |
| 
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 rsp_data_len = iot_sprintf((char *)rsp_data, "\r\nSPI init uncompleted!");
 | |
|                 at_command_at_response_to_proto(AT_RESP_OK,
 | |
|                     rsp_data, rsp_data_len, true);
 | |
|             }
 | |
|         }
 | |
|         else if (0 == iot_strcmp((char *)argv[0], USER_INPUT_WRITE_STR))
 | |
|         {
 | |
|             if (AT_SPI_INIT_COMPLETED == at_command_spi_cfg.inited)
 | |
|             {
 | |
|                 if ((argc != 2)
 | |
|                     || (0 == (op_data_len = at_command_string_2_digtal
 | |
|                             (argv[1], tx_buf, AT_SPI_MAX_WR_BUF_SIZE)))
 | |
|                     || (op_data_len > AT_SPI_MAX_RD_WR_BYTES))
 | |
|                 {
 | |
|                     goto ERROR_INVALID_ARG;
 | |
|                 }
 | |
| 
 | |
|                 op_ret = at_command_spi_write_data((char *)tx_buf,
 | |
|                     (uint16_t)op_data_len);
 | |
| 
 | |
|                 rsp_data_len = iot_sprintf((char *)rsp_data, "\r\nSPI Write %s!",
 | |
|                      (ERR_OK == op_ret) ? "successfully" : "failed");
 | |
| 
 | |
|                 at_command_at_response_to_proto((ERR_OK == op_ret)
 | |
|                     ? AT_RESP_OK : AT_RESP_ERROR, rsp_data, rsp_data_len, true);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 rsp_data_len = iot_sprintf((char *)rsp_data, "\r\nSPI init uncompleted!");
 | |
|                 at_command_at_response_to_proto(AT_RESP_OK,
 | |
|                     rsp_data, rsp_data_len, true);
 | |
|             }
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             if((argc < 10)
 | |
|                 || (at_command_uint32_2_digtal(argv[0], &port) <= 0)
 | |
|                 || (at_command_uint32_2_digtal(argv[1], &clk_pin) <= 0)
 | |
|                 || (at_command_uint32_2_digtal(argv[2], &cs_pin) <= 0)
 | |
|                 || (at_command_uint32_2_digtal(argv[3], &miso_pin) <= 0)
 | |
|                 || (at_command_uint32_2_digtal(argv[4], &mosi_pin) <= 0))
 | |
|             {
 | |
|                 goto ERROR_INVALID_ARG;
 | |
|             }
 | |
| 
 | |
|             if ((at_command_hex_2_digtal(argv[5], &spi_cfg_hex) <= 0)
 | |
|                 || (at_command_uint32_2_digtal(argv[6], &frq) <= 0)
 | |
|                 || (at_command_uint32_2_digtal(argv[7], &rx_thd) <= 0)
 | |
|                 || (at_command_uint32_2_digtal(argv[8], &tx_thd) <= 0)
 | |
|                 || (at_command_hex_2_digtal(argv[9], &tm_cfg_hex) <= 0))
 | |
|             {
 | |
|                 goto ERROR_INVALID_ARG;
 | |
|             }
 | |
| 
 | |
|             /* parse the combine spi config and timing hex string.*/
 | |
|             dev_type = spi_cfg_hex & 0x3;
 | |
|             trs_mode = (spi_cfg_hex >> 2) & 0x3;
 | |
|             frm_fmt = (spi_cfg_hex >> 4) & 0x3;
 | |
|             dfrm_sz = (spi_cfg_hex >> 6) & 0x1F;
 | |
|             cs_en = (spi_cfg_hex >> 11) & 0x1;
 | |
| 
 | |
|             scpol = tm_cfg_hex & 0x1;
 | |
|             scph = (tm_cfg_hex >> 1) & 0x1;
 | |
|             scph_tgl = (tm_cfg_hex >> 2) & 0x1;
 | |
|             sste = (tm_cfg_hex >> 3) & 0x1;
 | |
| 
 | |
|             if ((DEVICE_SPI0_MASTER != port) && (DEVICE_SPI1_MASTER != port)
 | |
|                 && (DEVICE_SPI0_SLAVER != port))
 | |
|             {
 | |
|                 goto ERROR_INVALID_ARG;
 | |
|             }
 | |
| 
 | |
|             if (((SPI_SLAVER != dev_type) && (SPI_MASTER != dev_type))
 | |
|                 || (trs_mode > TMOD_RECIEVER)
 | |
|                 || (trs_mode < TMOD_TRANCIEVER)
 | |
|                 || (FRM_STD != frm_fmt)
 | |
|                 || ((SPI_DFRAME_SIZE_8 != dfrm_sz)
 | |
|                     && (SPI_DFRAME_SIZE_16 != dfrm_sz)
 | |
|                     &&  (SPI_DFRAME_SIZE_32 != dfrm_sz)))
 | |
|             {
 | |
|                 goto ERROR_INVALID_ARG;
 | |
|             }
 | |
| 
 | |
|             curr_spi_cfg.inited = AT_SPI_INIT_COMPLETED;
 | |
|             curr_spi_cfg.port = port;
 | |
|             curr_spi_cfg.gpio.clk= clk_pin;
 | |
|             curr_spi_cfg.gpio.cs = cs_pin;
 | |
|             curr_spi_cfg.gpio.miso = miso_pin;
 | |
|             curr_spi_cfg.gpio.mosi = mosi_pin;
 | |
| 
 | |
|             curr_spi_cfg.cfg.dev_type = dev_type;
 | |
|             curr_spi_cfg.cfg.trs_mode = trs_mode;
 | |
|             curr_spi_cfg.cfg.frm_fmt = frm_fmt;
 | |
|             curr_spi_cfg.cfg.dfrm_sz = dfrm_sz;
 | |
|             curr_spi_cfg.cfg.cs_en= cs_en;
 | |
|             curr_spi_cfg.cfg.frq = (int)frq;
 | |
|             curr_spi_cfg.cfg.rx_thd = (int)rx_thd;
 | |
|             curr_spi_cfg.cfg.tx_thd = (int)tx_thd;
 | |
| 
 | |
|             curr_spi_cfg.tm.scpol = scpol;
 | |
|             curr_spi_cfg.tm.scph = scph;
 | |
|             curr_spi_cfg.tm.scph_tgl = scph_tgl;
 | |
|             curr_spi_cfg.tm.sste = sste;
 | |
| 
 | |
|             if (0 ==
 | |
|                 os_mem_cmp(&at_command_spi_cfg, &curr_spi_cfg, sizeof(spi_cfg)))
 | |
|             {
 | |
|                 iot_pkt_free(p_pkt);
 | |
|                 DINFOR("Set the same config!");
 | |
|                 at_command_at_response_to_proto(AT_RESP_OK, NULL, 0, true);
 | |
|                 return;
 | |
|             }
 | |
| 
 | |
|             os_mem_cpy(&at_command_spi_cfg, &curr_spi_cfg, sizeof(spi_cfg));
 | |
| 
 | |
|             os_mem_cpy(&(spi_gpio.gpio), &(at_command_spi_cfg.gpio),
 | |
|                 sizeof(iot_spi_gpio_sel_t));
 | |
| 
 | |
|             iot_gpio_open_as_output(at_command_spi_cfg.gpio.clk);
 | |
|             iot_gpio_open_as_output(at_command_spi_cfg.gpio.cs);
 | |
|             iot_gpio_open_as_input(at_command_spi_cfg.gpio.miso);
 | |
|             iot_gpio_open_as_output(at_command_spi_cfg.gpio.mosi);
 | |
|             spi_gpio.port = 0;
 | |
|             (void)iot_spi_module_init(&spi_gpio);
 | |
|             (void)iot_spi_dev_register_detail
 | |
|                 (at_command_spi_cfg.port, &(at_command_spi_cfg.cfg), \
 | |
|                  &(at_command_spi_cfg.tm), NULL, NULL, 0x0);
 | |
| 
 | |
|             rsp_data = iot_pkt_data(p_pkt);
 | |
|             rsp_data_len = iot_sprintf((char *)rsp_data,
 | |
|                 "\r\nSet spi is OK, spi port %d config is:" \
 | |
|                 "\r\nclk_pin:%d, cs_pin:%d, miso_pin:%d, mosi_pin:%d" \
 | |
|                 "\r\ndev type:%s, trans mode:%d"
 | |
|                 "\r\nframe format:%d, data frame size:%d, cs_en:%d" \
 | |
|                 "\r\nfrq:%d, rx thd:%d, tx thd:%d" \
 | |
|                 "\r\nscpol:%d, scph:%d, scph_tgl:%d, sste:%d",
 | |
|                 at_command_spi_cfg.port,
 | |
|                 at_command_spi_cfg.gpio.clk, at_command_spi_cfg.gpio.cs,
 | |
|                 at_command_spi_cfg.gpio.miso, at_command_spi_cfg.gpio.mosi,
 | |
|                 at_command_spi_cfg.cfg.dev_type ? "Slaver" : "Master",
 | |
|                 at_command_spi_cfg.cfg.trs_mode, at_command_spi_cfg.cfg.frm_fmt,
 | |
|                 at_command_spi_cfg.cfg.dfrm_sz, at_command_spi_cfg.cfg.cs_en & 0x1,
 | |
|                 at_command_spi_cfg.cfg.frq, at_command_spi_cfg.cfg.rx_thd,
 | |
|                 at_command_spi_cfg.cfg.tx_thd, (at_command_spi_cfg.tm.scpol & 0x1),
 | |
|                 (at_command_spi_cfg.tm.scph & 0x1),
 | |
|                 (at_command_spi_cfg.tm.scph_tgl & 0x1),
 | |
|                 (at_command_spi_cfg.tm.sste & 0x1));
 | |
| 
 | |
|             at_command_at_response_to_proto(AT_RESP_OK,
 | |
|                 rsp_data, rsp_data_len, true);
 | |
|         }
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         if (AT_SPI_INIT_COMPLETED == at_command_spi_cfg.inited)
 | |
|         {
 | |
|             rsp_data_len = iot_sprintf((char *)rsp_data,
 | |
|                 "\r\nSPI port %d config is:" \
 | |
|                 "\r\nclk_pin:%d, cs_pin:%d, miso_pin:%d, mosi_pin:%d" \
 | |
|                 "\r\ndev type:%s, trans mode:%d"
 | |
|                 "\r\nframe format:%d, data frame size:%d, cs_en:%d" \
 | |
|                 "\r\nfrq:%d, rx thd:%d, tx thd:%d" \
 | |
|                 "\r\nscpol:%d, scph:%d, scph_tgl:%d, sste:%d",
 | |
|                 at_command_spi_cfg.port,
 | |
|                 at_command_spi_cfg.gpio.clk, at_command_spi_cfg.gpio.cs,
 | |
|                 at_command_spi_cfg.gpio.miso, at_command_spi_cfg.gpio.mosi,
 | |
|                 at_command_spi_cfg.cfg.dev_type ? "Slaver" : "Master",
 | |
|                 at_command_spi_cfg.cfg.trs_mode, at_command_spi_cfg.cfg.frm_fmt,
 | |
|                 at_command_spi_cfg.cfg.dfrm_sz, at_command_spi_cfg.cfg.cs_en & 0x1,
 | |
|                 at_command_spi_cfg.cfg.frq, at_command_spi_cfg.cfg.rx_thd,
 | |
|                 at_command_spi_cfg.cfg.tx_thd, (at_command_spi_cfg.tm.scpol & 0x1),
 | |
|                 (at_command_spi_cfg.tm.scph & 0x1),
 | |
|                 (at_command_spi_cfg.tm.scph_tgl & 0x1),
 | |
|                 (at_command_spi_cfg.tm.sste & 0x1));
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             rsp_data_len = iot_sprintf((char *)rsp_data, "\r\nSPI init uncompleted!");
 | |
|         }
 | |
| 
 | |
|         at_command_at_response_to_proto(AT_RESP_OK, rsp_data, rsp_data_len, true);
 | |
|     }
 | |
| 
 | |
|     iot_pkt_free(p_pkt);
 | |
| 
 | |
|     return;
 | |
| 
 | |
| ERROR_INVALID_ARG:
 | |
|     iot_pkt_free(p_pkt);
 | |
|     DERROR("Invalid argument!");
 | |
|     at_command_at_response_to_proto(AT_RESP_INVALID_ARGUMENT, NULL, 0, true);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| uint32_t at_command_iic_write_8bit_reg(uint8_t addr, uint8_t reg, uint8_t val)
 | |
| {
 | |
|     char buf[2];
 | |
| 
 | |
|     buf[0] = reg;
 | |
|     buf[1] = val;
 | |
| 
 | |
|     if(ERR_OK != iot_i2c_write(at_command_iic_cfg.port, addr, buf, 2))
 | |
|     {
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     os_delay(10);
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| uint32_t at_command_iic_write_16bit_reg(uint8_t addr, uint16_t reg, uint16_t val)
 | |
| {
 | |
|     char buf[4];
 | |
| 
 | |
|     buf[0] = (reg >> 8) & 0xFF;
 | |
|     buf[1] = reg & 0xFF;
 | |
|     buf[2] = (val >> 8) & 0xFF;
 | |
|     buf[3] = val & 0xFF;
 | |
| 
 | |
|     if(ERR_OK != iot_i2c_write(at_command_iic_cfg.port, addr, buf, 4))
 | |
|     {
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     os_delay(10);
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| uint32_t at_command_iic_read_8bit_reg(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len)
 | |
| {
 | |
|     char buf[1];
 | |
| 
 | |
|     buf[0] = reg;
 | |
| 
 | |
|     if(ERR_OK != iot_i2c_write(at_command_iic_cfg.port, addr, buf, 1))
 | |
|     {
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     os_delay(10);
 | |
| 
 | |
|     if(ERR_OK != iot_i2c_read(at_command_iic_cfg.port, addr, (char *)data, len))
 | |
|     {
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| uint32_t at_command_iic_read_16bit_reg(uint8_t addr, uint16_t reg, uint8_t *data, uint8_t len)
 | |
| {
 | |
|     char buf[2];
 | |
| 
 | |
|     buf[0] = (reg >> 8) & 0xFF;
 | |
|     buf[1] = reg & 0xFF;
 | |
| 
 | |
|     if(ERR_OK != iot_i2c_write(at_command_iic_cfg.port, addr, buf, 2))
 | |
|     {
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     os_delay(10);
 | |
| 
 | |
|     if(ERR_OK != iot_i2c_read(at_command_iic_cfg.port, addr, (char *)data, len))
 | |
|     {
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| uint32_t at_command_iic_init(at_iic_cfg_t *cfg)
 | |
| {
 | |
|     if (NULL == cfg)
 | |
|     {
 | |
|         DERROR("Invalid argument!");
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     iot_i2c_module_cfg_t iic_cfg;
 | |
| 
 | |
|     iic_cfg.baud = cfg->baud;
 | |
|     iic_cfg.gpio.scl = cfg->gpio.scl;
 | |
|     iic_cfg.gpio.sda = cfg->gpio.sda;
 | |
|     iic_cfg.nack_wait_num = cfg->nack_wait_num;
 | |
|     iic_cfg.port = cfg->port;
 | |
| 
 | |
|     // iot_gpio_open_as_output can cancel the function bound on the GPIO.
 | |
|     // This is not necessary if those GPIOs are not multiplex.
 | |
|     if((ERR_OK != iot_gpio_open_as_output(iic_cfg.gpio.scl))
 | |
|         || (ERR_OK != iot_gpio_open_as_output(iic_cfg.gpio.sda)))
 | |
|     {
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     if(ERR_OK != iot_i2c_module_init(&iic_cfg))
 | |
|     {
 | |
|         return ERR_FAIL;
 | |
|     }
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| /* Operating the IIC. */
 | |
| void at_handle_command_iic(uint32_t opcode, uint32_t argc, uint8_t *argv[])
 | |
| {
 | |
|     iot_pkt_t *p_pkt;
 | |
| 
 | |
|     at_iic_cfg_t new_iic_cfg;
 | |
|     uint32_t port, speed, nack_wait_num;
 | |
|     uint32_t scl_pin, sda_pin, reg_addr_len;
 | |
| 
 | |
|     uint32_t slave_addr, reg_addr;
 | |
|     uint32_t read_data_len, write_val;
 | |
|     uint8_t read_data_buf[AT_IIC_MAX_RD_WR_BYTES];
 | |
|     uint32_t op_ret = ERR_OK;
 | |
|     uint32_t i;
 | |
|     uint8_t *rsp_data;
 | |
|     uint32_t rsp_data_len;
 | |
| 
 | |
|     os_mem_set(read_data_buf, 0, AT_IIC_MAX_RD_WR_BYTES);
 | |
| 
 | |
|     /*
 | |
|     Select the appropriate buffer size for print buffer, when spi read no more than 64 bytes,
 | |
|     one byte needs 3 chars to show (eg. _5E), so need choose the large buf size (256).
 | |
|     */
 | |
|     if(NULL == (p_pkt = iot_pkt_alloc(AT_LARGE_BUF_SIZE, AT_COMMAND_MID)))
 | |
|     {
 | |
|         DERROR("No memory!");
 | |
|         at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     rsp_data = iot_pkt_data(p_pkt);
 | |
| 
 | |
|     /* Check the validity of the parameters. */
 | |
|     if ((AT_OP_QUERY != opcode) && (AT_OP_SET != opcode))
 | |
|     {
 | |
|         goto ERROR_INVALID_ARG;
 | |
|     }
 | |
| 
 | |
|     if(AT_OP_SET == opcode)
 | |
|     {
 | |
|         if (0 == iot_strcmp((char *)argv[0], USER_INPUT_READ_STR))
 | |
|         {
 | |
|             if (AT_IIC_INIT_COMPLETED == at_command_iic_cfg.inited)
 | |
|             {
 | |
|                 if ((argc != 4)
 | |
|                     || (at_command_hex_2_digtal(argv[1], &slave_addr) <= 0)
 | |
|                     || (at_command_hex_2_digtal(argv[2], ®_addr) <= 0)
 | |
|                     || (at_command_uint32_2_digtal(argv[3], &read_data_len) <= 0)
 | |
|                     || (read_data_len > AT_IIC_MAX_RD_WR_BYTES))
 | |
|                 {
 | |
|                     goto ERROR_INVALID_ARG;
 | |
|                 }
 | |
| 
 | |
|                 DINFOR("reg_addr:%X, read_data_len:%d", reg_addr, read_data_len);
 | |
|                 if (AT_IIC_OP_COMMON_LEN_1BYTE == at_command_iic_cfg.reg_addr_len)
 | |
|                 {
 | |
|                     /* 1BYTE reg addr should no more than max val. */
 | |
|                     if (reg_addr > AT_IIC_OP_MAX_VAL_1BYTE)
 | |
|                     {
 | |
|                         goto ERROR_INVALID_ARG;
 | |
|                     }
 | |
| 
 | |
|                     op_ret = at_command_iic_read_8bit_reg(slave_addr,
 | |
|                         (uint8_t)reg_addr, read_data_buf, read_data_len);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     /* 2BYTE reg addr should no more than max val. */
 | |
|                     if (reg_addr > AT_IIC_OP_MAX_VAL_2BYTE)
 | |
|                     {
 | |
|                         goto ERROR_INVALID_ARG;
 | |
|                     }
 | |
| 
 | |
|                     op_ret = at_command_iic_read_16bit_reg(slave_addr,
 | |
|                         (uint16_t)reg_addr, read_data_buf, read_data_len);
 | |
|                 }
 | |
| 
 | |
|                 if (ERR_OK == op_ret)
 | |
|                 {
 | |
|                     rsp_data_len = 0;
 | |
|                     for(i = 0; i < read_data_len ; i++)
 | |
|                     {
 | |
|                         rsp_data_len += iot_sprintf((char *)(rsp_data + rsp_data_len),
 | |
|                             "%02X ", read_data_buf[i]);
 | |
|                     }
 | |
| 
 | |
|                     at_command_at_response_to_proto(AT_RESP_OK,
 | |
|                         rsp_data, rsp_data_len, true);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     rsp_data_len = iot_sprintf((char *)rsp_data, "\r\nIIC Read failed!");
 | |
|                     at_command_at_response_to_proto(AT_RESP_ERROR,
 | |
|                         rsp_data, rsp_data_len, true);
 | |
|                 }
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 rsp_data_len = iot_sprintf((char *)rsp_data, "\r\nIIC init uncompleted!");
 | |
|                 at_command_at_response_to_proto(AT_RESP_OK,
 | |
|                     rsp_data, rsp_data_len, true);
 | |
|             }
 | |
|         }
 | |
|         else if (0 == iot_strcmp((char *)argv[0], USER_INPUT_WRITE_STR))
 | |
|         {
 | |
|             if (AT_IIC_INIT_COMPLETED == at_command_iic_cfg.inited)
 | |
|             {
 | |
|                 if ((argc != 4)
 | |
|                     || (at_command_hex_2_digtal(argv[1], &slave_addr) <= 0)
 | |
|                     || (at_command_hex_2_digtal(argv[2], ®_addr) <= 0)
 | |
|                     || (at_command_hex_2_digtal(argv[3], &write_val) <= 0))
 | |
|                 {
 | |
|                     goto ERROR_INVALID_ARG;
 | |
|                 }
 | |
| 
 | |
|                 if (AT_IIC_OP_COMMON_LEN_1BYTE == at_command_iic_cfg.reg_addr_len)
 | |
|                 {
 | |
|                     /* 1BYTE reg addr and write value should no more than max val. */
 | |
|                     if ((reg_addr > AT_IIC_OP_MAX_VAL_1BYTE)
 | |
|                         || (write_val > AT_IIC_OP_MAX_VAL_1BYTE))
 | |
|                     {
 | |
|                         goto ERROR_INVALID_ARG;
 | |
|                     }
 | |
| 
 | |
|                     op_ret = at_command_iic_write_8bit_reg(slave_addr,
 | |
|                         (uint8_t)reg_addr, (uint8_t)write_val);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     /* 2BYTE reg addr and write value should no more than max val. */
 | |
|                     if ((reg_addr > AT_IIC_OP_MAX_VAL_2BYTE)
 | |
|                         || (write_val > AT_IIC_OP_MAX_VAL_2BYTE))
 | |
|                     {
 | |
|                         goto ERROR_INVALID_ARG;
 | |
|                     }
 | |
| 
 | |
|                     op_ret = at_command_iic_write_16bit_reg(slave_addr,
 | |
|                         (uint16_t)reg_addr, (uint16_t)write_val);
 | |
|                 }
 | |
| 
 | |
|                 rsp_data_len = iot_sprintf((char *)rsp_data, "\r\nIIC Write %s!",
 | |
|                      (ERR_OK == op_ret) ? "successfully" : "failed");
 | |
| 
 | |
|                 at_command_at_response_to_proto((ERR_OK == op_ret)
 | |
|                     ? AT_RESP_OK : AT_RESP_ERROR, rsp_data, rsp_data_len, true);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 rsp_data_len = iot_sprintf((char *)rsp_data, "\r\nIIC init uncompleted!");
 | |
|                 at_command_at_response_to_proto(AT_RESP_OK,
 | |
|                     rsp_data, rsp_data_len, true);
 | |
|             }
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             if ((argc != 6)
 | |
|                 || (at_command_uint32_2_digtal(argv[0], &port) <= 0)
 | |
|                 || (at_command_uint32_2_digtal(argv[1], &speed) <= 0)
 | |
|                 || (at_command_uint32_2_digtal(argv[2], &nack_wait_num) <= 0)
 | |
|                 || (at_command_uint32_2_digtal(argv[3], &scl_pin) <= 0)
 | |
|                 || (at_command_uint32_2_digtal(argv[4], &sda_pin) <= 0))
 | |
|             {
 | |
|                 goto ERROR_INVALID_ARG;
 | |
|             }
 | |
| 
 | |
|             if ((at_command_uint32_2_digtal(argv[5], ®_addr_len) <= 0)
 | |
|                 ||((AT_IIC_OP_COMMON_LEN_1BYTE!= reg_addr_len)
 | |
|                     && (AT_IIC_OP_COMMON_LEN_2BYTE != reg_addr_len)))
 | |
|             {
 | |
|                 goto ERROR_INVALID_ARG;
 | |
|             }
 | |
| 
 | |
|             new_iic_cfg.inited = AT_IIC_INIT_UNCOMPLETED;
 | |
|             new_iic_cfg.port = port;
 | |
|             new_iic_cfg.baud= speed;
 | |
|             new_iic_cfg.nack_wait_num= nack_wait_num;
 | |
|             new_iic_cfg.gpio.scl= scl_pin;
 | |
|             new_iic_cfg.gpio.sda= sda_pin;
 | |
|             new_iic_cfg.reg_addr_len = reg_addr_len;
 | |
| 
 | |
|             op_ret = at_command_iic_init(&new_iic_cfg);
 | |
| 
 | |
|             if (ERR_OK == op_ret)
 | |
|             {
 | |
|                 new_iic_cfg.inited = AT_IIC_INIT_COMPLETED;
 | |
|                 /* save the current iic config info to the AT command layer. */
 | |
|                 os_mem_cpy(&at_command_iic_cfg, &new_iic_cfg, sizeof(at_iic_cfg_t));
 | |
| 
 | |
|                 rsp_data_len = iot_sprintf((char *)rsp_data,
 | |
|                     "\r\nConfig IIC port %d successfully!" \
 | |
|                     "\r\nbaudrate:%d kb, wait nack number:%d" \
 | |
|                     "\r\nscl_pin:%d, sda_pin:%d, reg_addr_len:%dbyte.",
 | |
|                     at_command_iic_cfg.port, at_command_iic_cfg.baud,
 | |
|                     at_command_iic_cfg.nack_wait_num, at_command_iic_cfg.gpio.scl,
 | |
|                     at_command_iic_cfg.gpio.sda, at_command_iic_cfg.reg_addr_len);
 | |
| 
 | |
|                 at_command_at_response_to_proto(AT_RESP_OK,
 | |
|                     rsp_data, rsp_data_len, true);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 rsp_data_len = iot_sprintf((char *)rsp_data,
 | |
|                     "\r\nConfig IIC port %d failed!", new_iic_cfg.port);
 | |
| 
 | |
|                 at_command_at_response_to_proto(AT_RESP_ERROR,
 | |
|                     rsp_data, rsp_data_len, true);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         if (AT_IIC_INIT_COMPLETED == at_command_iic_cfg.inited)
 | |
|         {
 | |
|             rsp_data_len = iot_sprintf((char *)rsp_data,
 | |
|                 "\r\nThe IIC port %d config is:" \
 | |
|                 "\r\nbaudrate:%d kb, wait nack number:%d" \
 | |
|                 "\r\nscl_pin:%d, sda_pin:%d, reg_addr_len:%dbyte.",
 | |
|                 at_command_iic_cfg.port, at_command_iic_cfg.baud,
 | |
|                 at_command_iic_cfg.nack_wait_num, at_command_iic_cfg.gpio.scl,
 | |
|                 at_command_iic_cfg.gpio.sda, at_command_iic_cfg.reg_addr_len);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             rsp_data_len = iot_sprintf((char *)rsp_data, "\r\nIIC init uncompleted!");
 | |
|         }
 | |
| 
 | |
|         at_command_at_response_to_proto(AT_RESP_OK, rsp_data, rsp_data_len, true);
 | |
|     }
 | |
| 
 | |
|     iot_pkt_free(p_pkt);
 | |
|     return;
 | |
| 
 | |
| ERROR_INVALID_ARG:
 | |
|     DERROR("Invalid argument!");
 | |
|     at_command_at_response_to_proto(AT_RESP_INVALID_ARGUMENT, NULL, 0, true);
 | |
|     iot_pkt_free(p_pkt);
 | |
|     return;
 | |
| }
 | |
| 
 | |
| 
 | |
| void at_handle_command_gpiocfg(uint32_t opcode, uint32_t argc, uint8_t *argv[])
 | |
| {
 | |
|     iot_pkt_t *p_pkt;
 | |
|     uint32_t gpio_x;
 | |
|     uint32_t op_ret = ERR_OK;
 | |
|     uint8_t *rsp_data;
 | |
|     uint32_t rsp_data_len;
 | |
| 
 | |
|     /* Select the appropriate buffer size for print buffer. */
 | |
|     if(NULL == (p_pkt = iot_pkt_alloc(AT_SMALL_BUF_SIZE, AT_COMMAND_MID)))
 | |
|     {
 | |
|         DERROR("No memory!");
 | |
|         at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     rsp_data = iot_pkt_data(p_pkt);
 | |
| 
 | |
|     if(AT_OP_SET == opcode)
 | |
|     {
 | |
|         if((argc < 3)
 | |
|             || (at_command_uint32_2_digtal(argv[0], &gpio_x) <= 0))
 | |
|         {
 | |
|             goto ERROR_INVALID_ARG;
 | |
|         }
 | |
| 
 | |
|         if ((0 != iot_strcmp((char *)argv[1], USER_INPUT_GPIOCFG_INPUT_STR))
 | |
|             && (0 != iot_strcmp((char *)argv[1], USER_INPUT_GPIOCFG_OUTPUT_STR)))
 | |
|         {
 | |
|             goto ERROR_INVALID_ARG;
 | |
|         }
 | |
| 
 | |
|         if ((0 != iot_strcmp((char *)argv[2], USER_INPUT_GPIOCFG_PULLUP_STR))
 | |
|             && (0 != iot_strcmp((char *)argv[2], USER_INPUT_GPIOCFG_PULLDOWN_STR)))
 | |
|         {
 | |
|             goto ERROR_INVALID_ARG;
 | |
|         }
 | |
| 
 | |
|         if (0 == iot_strcmp((char *)argv[1], USER_INPUT_GPIOCFG_INPUT_STR))
 | |
|         {
 | |
|             op_ret |= iot_gpio_open_as_input(gpio_x);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             op_ret |= iot_gpio_open_as_output(gpio_x);
 | |
|         }
 | |
| 
 | |
|         if (0 != iot_strcmp((char *)argv[2], USER_INPUT_GPIOCFG_PULLUP_STR))
 | |
|         {
 | |
|             op_ret |= iot_gpio_set_pull_mode(gpio_x, GPIO_PULL_UP);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             op_ret |= iot_gpio_set_pull_mode(gpio_x, GPIO_PULL_DOWN);
 | |
|         }
 | |
| 
 | |
|         rsp_data_len = iot_sprintf((char *)rsp_data,"\r\nConfig gpio:%d is %s!",
 | |
|             gpio_x, (ERR_OK != op_ret) ? "failed" : "successfully");
 | |
| 
 | |
|         at_command_at_response_to_proto(AT_RESP_OK, rsp_data, rsp_data_len, true);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         goto ERROR_INVALID_ARG;
 | |
|     }
 | |
| 
 | |
|     iot_pkt_free(p_pkt);
 | |
| 
 | |
|     return;
 | |
| 
 | |
| ERROR_INVALID_ARG:
 | |
|     iot_pkt_free(p_pkt);
 | |
|     DERROR("Invalid argument!");
 | |
|     at_command_at_response_to_proto(AT_RESP_INVALID_ARGUMENT, NULL, 0, true);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void at_handle_command_gpioval(uint32_t opcode, uint32_t argc, uint8_t *argv[])
 | |
| {
 | |
|     iot_pkt_t *p_pkt;
 | |
|     uint32_t gpio_x, gpio_val;
 | |
|     uint32_t op_ret = ERR_OK;
 | |
|     uint8_t *rsp_data;
 | |
|     uint32_t rsp_data_len;
 | |
| 
 | |
|     /* Select the appropriate buffer size for print buffer. */
 | |
|     if(NULL == (p_pkt = iot_pkt_alloc(AT_SMALL_BUF_SIZE, AT_COMMAND_MID)))
 | |
|     {
 | |
|         DERROR("No memory!");
 | |
|         at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     rsp_data = iot_pkt_data(p_pkt);
 | |
| 
 | |
|     if(AT_OP_SET == opcode)
 | |
|     {
 | |
|         if((argc < 2)
 | |
|             || (at_command_uint32_2_digtal(argv[0], &gpio_x) <= 0)
 | |
|             || (at_command_uint32_2_digtal(argv[1], &gpio_val) <= 0))
 | |
|         {
 | |
|             goto ERROR_INVALID_ARG;
 | |
|         }
 | |
| 
 | |
|         op_ret = iot_gpio_value_set(gpio_x, gpio_val);
 | |
| 
 | |
|         rsp_data_len = iot_sprintf((char *)rsp_data, "\r\nSet gpio:%d, value:%d is %s!",
 | |
|             gpio_x, gpio_val, (ERR_OK != op_ret) ? "failed" : "successfully");
 | |
| 
 | |
|         at_command_at_response_to_proto(AT_RESP_OK, rsp_data, rsp_data_len, true);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         if((argc < 1)
 | |
|             || (at_command_uint32_2_digtal(argv[0], &gpio_x) <= 0))
 | |
|         {
 | |
|             goto ERROR_INVALID_ARG;
 | |
|         }
 | |
| 
 | |
|         gpio_val = iot_gpio_value_get(gpio_x);
 | |
| 
 | |
|         rsp_data_len = iot_sprintf((char *)rsp_data,
 | |
|             "\r\nAT+GPIOVAL=%d, %d.", gpio_x, gpio_val);
 | |
| 
 | |
|         at_command_at_response_to_proto(AT_RESP_OK, rsp_data, rsp_data_len, true);
 | |
|     }
 | |
| 
 | |
|     iot_pkt_free(p_pkt);
 | |
| 
 | |
|     return;
 | |
| 
 | |
| ERROR_INVALID_ARG:
 | |
|     iot_pkt_free(p_pkt);
 | |
|     DERROR("Invalid argument!");
 | |
|     at_command_at_response_to_proto(AT_RESP_INVALID_ARGUMENT, NULL, 0, true);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| #if (IOT_FLASH_SIZE >=2 )
 | |
| void at_handle_cmd_sw_uartmode(uint32_t opcode, uint32_t argc, uint8_t *argv[])
 | |
| {
 | |
|     uint8_t *p_data;
 | |
|     uint32_t data_len;
 | |
|     iot_oem_base_cfg_t *oem_base_cfg;
 | |
|     iot_pkt_t *p_pkt;
 | |
| 
 | |
|     if ((AT_OP_SET != opcode) || argc < 1 ||
 | |
|         iot_strcmp((char*)argv[0], STRING_ENABLE)) {
 | |
|         DERROR("Invalid argument! opcode=%d argc=%d", opcode, argc);
 | |
|         at_command_at_response_to_proto(AT_RESP_INVALID_ARGUMENT,
 | |
|             NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* save uart mode to GR_MCU_OP_MODE oem */
 | |
|     iot_oem_get_base_cfg(&oem_base_cfg);
 | |
| 
 | |
|     DINFOR("get iotapp_mode=%d", oem_base_cfg->iotapp_mode);
 | |
| 
 | |
|     oem_base_cfg->iotapp_mode = GR_MCU_OP_MODE;
 | |
|     if(iot_oem_set_base_cfg(oem_base_cfg))
 | |
|     {
 | |
|         DERROR("Set OEM UART mode Faild!");
 | |
|         at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|         return;
 | |
|     } else {
 | |
|         if(NULL == (p_pkt = iot_pkt_alloc(AT_MID_BUF_SIZE, AT_COMMAND_MID)))
 | |
|         {
 | |
|             DERROR("No memory!");
 | |
|             at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|             return;
 | |
|         }
 | |
|         p_data = iot_pkt_data(p_pkt);
 | |
|         data_len = iot_sprintf((char *)p_data,"system will reboot after "
 | |
|             "three seconds,and then uart will switch to GE mode\n");
 | |
|         DERROR("%s",p_data);
 | |
|         /* Just finish AT+PMODE with response. */
 | |
|         at_command_at_response_to_proto(AT_RESP_FORCE_ECHO,
 | |
|             p_data, data_len, true);
 | |
|         iot_pkt_free(p_pkt);
 | |
|         /* delay three seconds and then reboot system*/
 | |
|         os_delay(3000);
 | |
| 
 | |
|         iot_system_restart(IOT_SYS_RST_REASON_APP_REQ);
 | |
|         return;
 | |
|     }
 | |
| }
 | |
| #else
 | |
| void at_handle_cmd_sw_uartmode(uint32_t opcode, uint32_t argc, uint8_t *argv[])
 | |
| {
 | |
|     uint8_t *p_data;
 | |
|     uint32_t data_len;
 | |
|     iot_pkt_t *p_pkt;
 | |
| 
 | |
|     if(NULL == (p_pkt = iot_pkt_alloc(AT_MID_BUF_SIZE, AT_COMMAND_MID)))
 | |
|     {
 | |
|         DERROR("No memory!");
 | |
|         at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
|     p_data = iot_pkt_data(p_pkt);
 | |
|     data_len = iot_sprintf((char *)p_data,
 | |
|         "system not support switch to GE mode\n");
 | |
|     DERROR("%s",p_data);
 | |
| 
 | |
|     at_command_at_response_to_proto(AT_RESP_FORCE_ECHO,
 | |
|         p_data, data_len, true);
 | |
| 
 | |
|     iot_pkt_free(p_pkt);
 | |
|     return;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #if PLC_SUPPORT_CCO_ROLE
 | |
| /* Start/End group network. */
 | |
| void at_handle_command_netgroup(uint32_t opcode, uint32_t argc, uint8_t *argv[])
 | |
| {
 | |
|     iot_pkt_t *p_rsp_pkt;
 | |
|     uint8_t *rsp_data;
 | |
|     uint32_t rsp_data_len;
 | |
|     custom_flash_info_t *p_flash = &uniform_flashinfo_at;
 | |
| 
 | |
|     /* Check the validity of the parameters. */
 | |
|     if((AT_OP_SET != opcode)
 | |
|         || (argc != 1)
 | |
|         || (iot_strcmp((char *)argv[0], USER_INPUT_NETGROUP_START_STR)
 | |
|             && iot_strcmp((char *)argv[0], USER_INPUT_NETGROUP_END_STR)))
 | |
|     {
 | |
|         DERROR("Invalid argument!");
 | |
|         at_command_at_response_to_proto
 | |
|             (AT_RESP_INVALID_ARGUMENT, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Select the appropriate buffer size for print buffer. */
 | |
|     if(NULL == (p_rsp_pkt = iot_pkt_alloc(AT_SMALL_BUF_SIZE,
 | |
|         AT_COMMAND_MID)))
 | |
|     {
 | |
|         DERROR("No memory!");
 | |
|         at_command_at_response_to_proto(AT_RESP_ERROR,
 | |
|             NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
|     rsp_data = iot_pkt_data(p_rsp_pkt);
 | |
| 
 | |
|     if (0 == iot_strcmp((char *)argv[0], USER_INPUT_NETGROUP_START_STR))
 | |
|     {
 | |
|         if (AT_WL_CFG_STATE_ENABLE == at_command_context.wl_cfg_state)
 | |
|         {
 | |
|             /* 1st: empty whitelist in CVG layer. */
 | |
|             at_command_cvg_wl_add_del(AT_WL_ACTION_DEL, NULL, false);
 | |
|             /* 2nd: empty device list saved in flash. */
 | |
|             p_flash->dev_cnt = 0;
 | |
|             os_mem_set(&(p_flash->dev_tbl), 0, AT_STA_DEV_MAX * sizeof(proto_dev_t));
 | |
|             if (ERR_OK != at_command_uniform_flashsave(p_flash))
 | |
|             {
 | |
|                 DERROR("Update device list saved in flash failed!");
 | |
|             }
 | |
|             /* 3rd: disable whitelist, do not need to handle cmd confirm. */
 | |
|             at_command_cvg_wl_en_disable(AT_WL_ACTION_DISABLE, false);
 | |
|             /* Update the whitelist config enable/disable state. */
 | |
|             at_command_context.wl_cfg_state = AT_WL_CFG_STATE_DISABLE;
 | |
|         }
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         /* 1st: save online device list to flash whitelist and set to CVG layer. */
 | |
|         at_command_online_dev_list_save2flash();
 | |
|         os_delay(AT_WL_OP_DELAY_MS);
 | |
|         /* 2nd: enable whitelist, do not need to handle cmd confirm. */
 | |
|         at_command_cvg_wl_en_disable(AT_WL_ACTION_ENABLE, false);
 | |
|         /* Update the whitelist config enable/disable state. */
 | |
|         at_command_context.wl_cfg_state = AT_WL_CFG_STATE_ENABLE;
 | |
|     }
 | |
| 
 | |
|     rsp_data_len = iot_sprintf((char *)rsp_data,
 | |
|         "\r\nGroup network, whitelist operation state is ok!");
 | |
| 
 | |
|     at_command_at_response_to_proto(AT_RESP_OK,
 | |
|         rsp_data, rsp_data_len, true);
 | |
| 
 | |
|     iot_pkt_free(p_rsp_pkt);
 | |
|     return;
 | |
| }
 | |
| 
 | |
| #else
 | |
| /* Start/End group network. */
 | |
| void at_handle_command_netgroup(uint32_t opcode, uint32_t argc, uint8_t *argv[])
 | |
| {
 | |
|     iot_pkt_t *p_rsp_pkt;
 | |
|     uint8_t *rsp_data;
 | |
|     uint32_t rsp_data_len;
 | |
| 
 | |
|     (void)opcode;
 | |
|     (void)argc;
 | |
|     (void)argv;
 | |
| 
 | |
|     /* Select the appropriate buffer size for print buffer. */
 | |
|     if(NULL == (p_rsp_pkt = iot_pkt_alloc(AT_SMALL_BUF_SIZE,
 | |
|         AT_COMMAND_MID)))
 | |
|     {
 | |
|         DERROR("No memory!");
 | |
|         at_command_at_response_to_proto(AT_RESP_ERROR,
 | |
|             NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     rsp_data = iot_pkt_data(p_rsp_pkt);
 | |
|     rsp_data_len = iot_sprintf((char *)rsp_data,
 | |
|         "\r\nAT+NETGROUP, only for CCO, not supported on STA!");
 | |
| 
 | |
|     at_command_at_response_to_proto(AT_RESP_OK, rsp_data, rsp_data_len, true);
 | |
| 
 | |
|     iot_pkt_free(p_rsp_pkt);
 | |
|     return;
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| #if SUPPORT_HOST_PORT_ETH
 | |
| 
 | |
| void at_handle_command_host_port(uint32_t opcode, uint32_t argc, uint8_t *argv[])
 | |
| {
 | |
|     iot_pkt_t *p_rsp_pkt;
 | |
|     uint8_t *rsp_data;
 | |
|     uint32_t rsp_data_len;
 | |
|     uint8_t input_host_port;
 | |
|     iot_oem_base_cfg_t *oem_base_cfg;
 | |
| 
 | |
|     /* Select the appropriate buffer size for print buffer. */
 | |
|     if(NULL == (p_rsp_pkt = iot_pkt_alloc(AT_SMALL_BUF_SIZE, AT_COMMAND_MID)))
 | |
|     {
 | |
|         DERROR("No memory!");
 | |
|         at_command_at_response_to_proto(AT_RESP_ERROR, NULL, 0, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     rsp_data = iot_pkt_data(p_rsp_pkt);
 | |
| 
 | |
|     /* Check the validity of the parameters. */
 | |
|     if ((AT_OP_QUERY != opcode) && (AT_OP_SET != opcode))
 | |
|     {
 | |
|         goto ERROR_INVALID_ARG;
 | |
|     }
 | |
| 
 | |
|     iot_oem_get_base_cfg(&oem_base_cfg);
 | |
| 
 | |
|     if(AT_OP_SET == opcode)
 | |
|     {
 | |
|         if((argc != 1)
 | |
|             || (iot_strcmp((char *)argv[0], USER_INPUT_HOST_PORT_UART_STR)
 | |
|                 && iot_strcmp((char *)argv[0], USER_INPUT_HOST_PORT_ETH_STR)))
 | |
|         {
 | |
|             goto ERROR_INVALID_ARG;
 | |
|         }
 | |
| 
 | |
|         if (0 == iot_strcmp((char *)argv[0], USER_INPUT_HOST_PORT_UART_STR))
 | |
|         {
 | |
|             input_host_port = HOST_PORT_UART;
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             input_host_port = HOST_PORT_ETH;
 | |
|         }
 | |
| 
 | |
|         if (oem_base_cfg->host_port == input_host_port)
 | |
|         {
 | |
|             DINFOR("Set the same config!");
 | |
|             at_command_at_response_to_proto(AT_RESP_OK, NULL, 0, true);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             /* Save host port to oem. */
 | |
|             oem_base_cfg->host_port = input_host_port;
 | |
| 
 | |
|             if (ERR_OK != iot_oem_set_base_cfg(oem_base_cfg))
 | |
|             {
 | |
|                 DERROR("set oem cfg host port error\n");
 | |
|                 rsp_data_len = iot_sprintf((char *)rsp_data,
 | |
|                     "\r\nSet host port failed!");
 | |
|                 at_command_at_response_to_proto(AT_RESP_ERROR,
 | |
|                     rsp_data, rsp_data_len, true);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 rsp_data_len = iot_sprintf((char *)rsp_data,
 | |
|                     "\r\nSet host port successfully!" \
 | |
|                     "\r\nSystem will reboot after 3s, host port will use %s.",
 | |
|                     (input_host_port == HOST_PORT_ETH) ? "ETH" : "UART");
 | |
|                 /* Just finish AT+HOSTPORT with response. */
 | |
|                 at_command_at_response_to_proto(AT_RESP_FORCE_ECHO,
 | |
|                     rsp_data, rsp_data_len, true);
 | |
|                 iot_pkt_free(p_rsp_pkt);
 | |
| 
 | |
|                 /* Delay three seconds and then reboot system */
 | |
|                 os_delay(3000);
 | |
|                 iot_system_restart(IOT_SYS_RST_REASON_APP_REQ);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         rsp_data_len = iot_sprintf((char *)rsp_data,
 | |
|             "\r\nCurrent host port is %s!",
 | |
|             (oem_base_cfg->host_port == HOST_PORT_ETH)
 | |
|             ? "ETH" : "UART");
 | |
| 
 | |
|         at_command_at_response_to_proto(AT_RESP_OK,
 | |
|             rsp_data, rsp_data_len, true);
 | |
|     }
 | |
| 
 | |
|     iot_pkt_free(p_rsp_pkt);
 | |
|     return;
 | |
| 
 | |
| ERROR_INVALID_ARG:
 | |
|     DERROR("Invalid argument!");
 | |
|     at_command_at_response_to_proto(AT_RESP_INVALID_ARGUMENT, NULL, 0, true);
 | |
|     iot_pkt_free(p_rsp_pkt);
 | |
|     return;
 | |
| }
 | |
| 
 | |
| #endif /* end SUPPORT_HOST_PORT_ETH */
 | |
| 
 | |
| #else /* INCLUDE_AT_COMMAND_MODULE */
 | |
| 
 | |
| uint8_t iot_at_command_plc_send_response_to_at(iot_pkt_t *p_resp_pkt)
 | |
| {
 | |
|     iot_pkt_free(p_resp_pkt);
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| uint8_t iot_at_command_proto_send_to_at(uint8_t *buf, uint16_t blen)
 | |
| {
 | |
|     (void)buf;
 | |
|     (void)blen;
 | |
| 
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| 
 | |
| #endif
 | |
| 
 | |
| #endif
 |