482 lines
16 KiB
C
482 lines
16 KiB
C
/****************************************************************************
|
|
|
|
Copyright(c) 2016-2018 by WuQi Technologies. ALL RIGHTS RESERVED.
|
|
|
|
This Information is proprietary to WuQi Technologies and MAY NOT
|
|
be copied by any method or incorporated into another program without
|
|
the express written consent of WuQi. This Information or any portion
|
|
thereof remains the property of WuQi. The Information contained herein
|
|
is believed to be accurate and WuQi 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 inringement.
|
|
|
|
****************************************************************************/
|
|
#include "proto_69845_vendor.h"
|
|
|
|
/* os_shim header files */
|
|
#include "os_utils_api.h"
|
|
|
|
/* iot common header files */
|
|
#include "iot_app_api.h"
|
|
#include "iot_utils_api.h"
|
|
#include "iot_upgrade_api.h"
|
|
#include "iot_oem_api.h"
|
|
#include "iot_board_api.h"
|
|
#include "iot_bitmap_api.h"
|
|
#include "iot_io_api.h"
|
|
#include "iot_system_api.h"
|
|
#include "iot_plc_hw_topo_api.h"
|
|
#include "iot_adc_api.h"
|
|
#include "iot_version_api.h"
|
|
|
|
/* smart grid internal header files */
|
|
#include "iot_sg.h"
|
|
#include "iot_sg_sta.h"
|
|
#include "proto_69845.h"
|
|
#include "iot_oem_api.h"
|
|
|
|
#if IOT_SMART_GRID_ENABLE
|
|
|
|
static uint8_t proto_69845_apdu_set_rf_param(uint8_t *data, uint16_t len)
|
|
{
|
|
uint8_t dar = PROTO_69845_APP_DAR_SUCCESS;
|
|
proto_69845_app_ele_data_t *ele_data = NULL;
|
|
proto_69845_ext_rf_param_t *param = NULL;
|
|
|
|
if (data == NULL || len < sizeof(*ele_data) + sizeof(*param)) {
|
|
dar = PROTO_69845_APP_DAR_DATA_BLOCK_DAMAGE;
|
|
goto out;
|
|
}
|
|
ele_data = (proto_69845_app_ele_data_t *)data;
|
|
if (ele_data->data_type != PROTO_69845_APP_DATA_OCTET_STRING) {
|
|
dar = PROTO_69845_APP_DAR_TYPE_MISMATCH;
|
|
goto out;
|
|
}
|
|
param = (proto_69845_ext_rf_param_t *)(ele_data->data);
|
|
if (ele_data->num_of_data != sizeof(*param)) {
|
|
dar = PROTO_69845_APP_DAR_DATA_BLOCK_DAMAGE;
|
|
goto out;
|
|
}
|
|
if ((param->option == IOT_PLC_RF_OPTION_1 &&
|
|
param->channel < IOT_PLC_OPTION1_CHANNEL_ID_MAX) ||
|
|
(param->option == IOT_PLC_RF_OPTION_2 &&
|
|
param->channel < IOT_PLC_OPTION2_CHANNEL_ID_MAX) ||
|
|
(param->option == IOT_PLC_RF_OPTION_3 &&
|
|
param->channel < IOT_PLC_OPTION3_CHANNEL_ID_MAX)) {
|
|
/* set rf option and channel */
|
|
iot_plc_set_rf_channel(p_sg_glb->plc_app_h,
|
|
IOT_PLC_API_REQ_ID_DEFAULT, param->option, param->channel, 0);
|
|
iot_sg_printf("%s %lu %lu\n", __FUNCTION__, param->option,
|
|
param->channel);
|
|
} else {
|
|
dar = PROTO_69845_APP_DAR_OVERFLOW;
|
|
goto out;
|
|
}
|
|
out:
|
|
return dar;
|
|
}
|
|
|
|
static uint8_t proto_69845_apdu_set_hrf_mode(uint8_t *data, uint16_t len)
|
|
{
|
|
uint8_t dar = PROTO_69845_APP_DAR_SUCCESS;
|
|
proto_69845_app_ele_data_t *ele_data = NULL;
|
|
proto_69845_ext_work_mode_t *mode = NULL;
|
|
|
|
if (len < (sizeof(*ele_data) + sizeof(*mode))) {
|
|
dar = PROTO_69845_APP_DAR_DATA_BLOCK_DAMAGE;
|
|
goto out;
|
|
}
|
|
ele_data = (proto_69845_app_ele_data_t *)data;
|
|
if (ele_data->data_type != PROTO_69845_APP_DATA_OCTET_STRING) {
|
|
dar = PROTO_69845_APP_DAR_TYPE_MISMATCH;
|
|
goto out;
|
|
}
|
|
if (ele_data->num_of_data != sizeof(*mode)) {
|
|
dar = PROTO_69845_APP_DAR_DATA_BLOCK_DAMAGE;
|
|
goto out;
|
|
}
|
|
mode = (proto_69845_ext_work_mode_t *)(ele_data->data);
|
|
if (mode->mode != PROTO_69845_CONTROLLER_MODE_HPLC &&
|
|
mode->mode != PROTO_69845_CONTROLLER_MODE_RF) {
|
|
dar = PROTO_69845_APP_DAR_OVERFLOW;
|
|
goto out;
|
|
}
|
|
iot_sg_printf("%s %lu\n", __FUNCTION__, mode->mode);
|
|
out:
|
|
return dar;
|
|
}
|
|
|
|
static iot_pkt_t *proto_69845_apdu_set_req_normal_handle(
|
|
proto_69845_frame_head_info_t *header, uint8_t *data, uint32_t len,
|
|
uint32_t *handle)
|
|
{
|
|
iot_pkt_t *pkt = NULL;
|
|
uint32_t oad = 0;
|
|
uint8_t dar = 0;
|
|
proto_69845_app_set_req_normal_t *normal = NULL;
|
|
addr_info_t addr_info = {0};
|
|
proto_69845_app_oad_t app_oad = {0};
|
|
|
|
if (len < sizeof(*normal)) {
|
|
goto out;
|
|
}
|
|
normal = (proto_69845_app_set_req_normal_t *)data;
|
|
len -= sizeof(*normal);
|
|
oad = iot_bytes_to_uint32((uint8_t *)&normal->oad.oi, 1);
|
|
switch (oad) {
|
|
case PROTO_69845_EXT_APP_OAD_BROADCAST_RF_PARAM:
|
|
{
|
|
dar = proto_69845_apdu_set_rf_param(
|
|
(uint8_t *)&normal->data, (uint16_t)len);
|
|
*handle = 1;
|
|
/* set rf param is broadcast, no response */
|
|
goto out;
|
|
}
|
|
case PROTO_69845_EXT_APP_OAD_HRF_MODE:
|
|
{
|
|
dar = proto_69845_apdu_set_hrf_mode(
|
|
(uint8_t *)&normal->data, (uint16_t)len);
|
|
*handle = 1;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
goto out;
|
|
}
|
|
}
|
|
proto_69845_get_addr_info(header, &addr_info);
|
|
app_oad.oi = iot_bytes_to_uint16((uint8_t *)&normal->oad.oi, 1);
|
|
app_oad.attribute_id = normal->oad.attribute_id;
|
|
app_oad.attribute_char = normal->oad.attribute_char;
|
|
app_oad.element_index = normal->oad.element_index;
|
|
pkt = proto_69845_set_normal_ack(&addr_info, &normal->piid,
|
|
&app_oad, dar);
|
|
|
|
out:
|
|
if(*handle) {
|
|
iot_sg_printf("%s %04X-%lu\n", __FUNCTION__, oad, dar);
|
|
}
|
|
return pkt;
|
|
}
|
|
|
|
static iot_pkt_t *proto_69845_apdu_set_request_handle(
|
|
proto_69845_frame_head_info_t *hdr, uint8_t *data, uint32_t len,
|
|
uint32_t *handle)
|
|
{
|
|
uint32_t length = 0;
|
|
iot_pkt_t *pkt = NULL;
|
|
proto_69845_app_set_req_t *set_req = NULL;
|
|
|
|
set_req = (proto_69845_app_set_req_t *)data;
|
|
length = len - sizeof(*set_req);
|
|
switch (set_req->data_type) {
|
|
case PROTO_69845_APP_SET_NORMAL:
|
|
{
|
|
pkt = proto_69845_apdu_set_req_normal_handle(hdr, set_req->data,
|
|
length, handle);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return pkt;
|
|
}
|
|
|
|
static iot_pkt_t *proto_69845_ext_build_get_resp(
|
|
proto_69845_frame_head_info_t *req_hdr,
|
|
proto_69845_app_get_req_normal_t *get_normal, uint8_t result_type,
|
|
uint8_t *data, uint32_t result_len)
|
|
{
|
|
iot_pkt_t *pkt = NULL;
|
|
uint8_t addr_len = 0, *point;
|
|
uint16_t head_len = 0;
|
|
uint32_t pkt_len = 0;
|
|
addr_info_t addr_info = {0};
|
|
proto_69845_frame_head_info_t *resp_hdr = NULL;
|
|
proto_69845_apdu_t *resp_apdu = NULL;
|
|
proto_69845_app_get_resp_t *resp_get = NULL;
|
|
proto_69845_app_get_resp_normal_t *resp_normal = NULL;
|
|
|
|
addr_len = proto_69845_get_addr_info(req_hdr, &addr_info);
|
|
pkt_len = sizeof(*resp_hdr) + addr_len + PROTO_69845_CHECKSUM_LEN +
|
|
sizeof(*resp_apdu) + sizeof(*resp_get) + sizeof(*resp_normal) +
|
|
result_len + PROTO_69845_NO_FLW_DATA_LEN +
|
|
PROTO_69845_NO_TIME_TAG_LEN + sizeof(proto_69845_tailer_t);
|
|
|
|
pkt = iot_pkt_alloc(pkt_len, IOT_SMART_GRID_MID);
|
|
if (pkt == NULL) {
|
|
goto out;
|
|
}
|
|
point = iot_pkt_put(pkt, pkt_len);
|
|
resp_hdr = (proto_69845_frame_head_info_t *)point;
|
|
head_len = sizeof(*resp_hdr) + addr_len + PROTO_69845_CHECKSUM_LEN;
|
|
proto_69845_head_fill(
|
|
resp_hdr, head_len, (uint16_t)pkt_len, &addr_info,
|
|
PROTO_69845_FN_USER_DATA, PROTO_69845_APDU_WHOLE,
|
|
PROTO_69845_D_P_SERVER_RESPONSE);
|
|
point += head_len;
|
|
|
|
resp_apdu = (proto_69845_apdu_t *)point;
|
|
resp_apdu->type = PROTO_69845_S_APP_GET_RESP;
|
|
|
|
resp_get = (proto_69845_app_get_resp_t *)resp_apdu->data;
|
|
resp_get->data_type = PROTO_69845_APP_GET_NORMAL;
|
|
|
|
resp_normal = (proto_69845_app_get_resp_normal_t *)resp_get->data;
|
|
resp_normal->piid_acd.sn = get_normal->piid.sn;
|
|
resp_normal->piid_acd.priority = get_normal->piid.priority;
|
|
resp_normal->piid_acd.acd = 0;
|
|
resp_normal->oad.oi = get_normal->oad.oi;
|
|
resp_normal->oad.attribute_id = get_normal->oad.attribute_id;
|
|
resp_normal->oad.attribute_char = get_normal->oad.attribute_char;
|
|
resp_normal->oad.element_index = get_normal->oad.element_index;
|
|
|
|
resp_normal->result_type = result_type;
|
|
os_mem_cpy(resp_normal->result, data, result_len);
|
|
|
|
proto_69845_tail_fill_without_ts_fl(resp_hdr,
|
|
resp_normal->result + result_len, sizeof(proto_69845_tailer_t) +
|
|
PROTO_69845_NO_TIME_TAG_LEN + PROTO_69845_NO_FLW_DATA_LEN);
|
|
out:
|
|
return pkt;
|
|
}
|
|
|
|
static iot_pkt_t *proto_69845_get_chip_id(
|
|
proto_69845_frame_head_info_t *header,
|
|
proto_69845_app_get_req_normal_t *get_normal)
|
|
{
|
|
iot_pkt_t *pkt = NULL;
|
|
uint8_t dar = PROTO_69845_APP_DAR_SUCCESS;
|
|
proto_69845_app_ele_data_t *data = NULL;
|
|
uint8_t chip_id[sizeof(*data) + PROTO_69845_EXT_CHIP_ID_LEN];
|
|
|
|
data = (proto_69845_app_ele_data_t *)chip_id;
|
|
data->data_type = PROTO_69845_APP_DATA_OCTET_STRING;
|
|
data->num_of_data = PROTO_69845_EXT_CHIP_ID_LEN;
|
|
if (iot_oem_get_chip_mmid(data->data, PROTO_69845_EXT_CHIP_ID_LEN) == 0) {
|
|
dar = PROTO_69845_APP_DAR_OTHER;
|
|
}
|
|
if (dar) {
|
|
pkt = proto_69845_ext_build_get_resp(
|
|
header, get_normal, PROTO_69845_APP_GET_RESULT_DAR, &dar,
|
|
sizeof(dar));
|
|
} else {
|
|
pkt = proto_69845_ext_build_get_resp(
|
|
header, get_normal, PROTO_69845_APP_GET_RESULT_DATA, chip_id,
|
|
PROTO_69845_EXT_CHIP_ID_LEN + sizeof(*data));
|
|
}
|
|
return pkt;
|
|
}
|
|
|
|
static iot_pkt_t *proto_69845_get_simulate_ept_pos(
|
|
proto_69845_frame_head_info_t *header,
|
|
proto_69845_app_get_req_normal_t *get_normal)
|
|
{
|
|
static uint8_t read_cnt = 1;
|
|
iot_pkt_t *pkt = NULL, *temp_pkt = NULL;
|
|
uint8_t dar = PROTO_69845_APP_DAR_SUCCESS, i;
|
|
uint32_t pos = read_cnt;
|
|
uint32_t length = 0;
|
|
proto_69845_app_ele_data_t *data = NULL;
|
|
proto_69845_app_data_t *pos_item = NULL;
|
|
|
|
length = sizeof(*data) + (sizeof(*pos_item) +
|
|
sizeof(pos)) * PROTO_69845_ENERGY_DATA_ARRAY_COUNT;
|
|
temp_pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
|
|
if (temp_pkt == NULL) {
|
|
dar = PROTO_69845_APP_DAR_OTHER;
|
|
goto out;
|
|
}
|
|
iot_pkt_put(temp_pkt, length);
|
|
data = (proto_69845_app_ele_data_t *)iot_pkt_data(temp_pkt);
|
|
data->data_type = PROTO_69845_APP_DATA_ARRAY;
|
|
data->num_of_data = PROTO_69845_ENERGY_DATA_ARRAY_COUNT;
|
|
|
|
pos_item = (proto_69845_app_data_t *)data->data;
|
|
pos_item->data_type = PROTO_69845_APP_DATA_DOUBLE_LONG_UNSIGNED;
|
|
iot_uint32_to_bytes(pos * PROTO_69845_ENERGY_DATA_ARRAY_COUNT - 1,
|
|
pos_item->data, 1);
|
|
pos_item = (proto_69845_app_data_t *)(pos_item->data + sizeof(pos));
|
|
|
|
for (i = 0; i < PROTO_69845_ENERGY_DATA_ARRAY_COUNT - 1; i++) {
|
|
pos_item->data_type = PROTO_69845_APP_DATA_DOUBLE_LONG_UNSIGNED;
|
|
iot_uint32_to_bytes(pos, pos_item->data, 1);
|
|
pos_item = (proto_69845_app_data_t *)(pos_item->data + sizeof(pos));
|
|
}
|
|
read_cnt += 1;
|
|
|
|
out:
|
|
if (dar) {
|
|
pkt = proto_69845_ext_build_get_resp(header, get_normal,
|
|
PROTO_69845_APP_GET_RESULT_DAR, &dar, sizeof(dar));
|
|
} else {
|
|
pkt = proto_69845_ext_build_get_resp(header, get_normal,
|
|
PROTO_69845_APP_GET_RESULT_DATA, iot_pkt_data(temp_pkt),
|
|
iot_pkt_data_len(temp_pkt));
|
|
}
|
|
if (temp_pkt) {
|
|
iot_pkt_free(temp_pkt);
|
|
}
|
|
return pkt;
|
|
}
|
|
|
|
static iot_pkt_t *proto_69845_apdu_get_req_normal_handle(
|
|
proto_69845_frame_head_info_t *header, uint8_t *data, uint32_t len,
|
|
uint32_t *handle)
|
|
{
|
|
uint32_t oad = 0;
|
|
iot_pkt_t *pkt = NULL;
|
|
proto_69845_app_get_req_normal_t *normal = NULL;
|
|
|
|
IOT_ASSERT(header && data);
|
|
if (len < sizeof(*normal)) {
|
|
iot_sg_printf("69845 vendor get: undersize\n");
|
|
goto out;
|
|
}
|
|
normal = (proto_69845_app_get_req_normal_t *)data;
|
|
oad = iot_bytes_to_uint32((uint8_t *)&normal->oad.oi, 1);
|
|
switch (oad)
|
|
{
|
|
case PROTO_69845_EXT_APP_OAD_READ_CHIP_ID:
|
|
{
|
|
pkt = proto_69845_get_chip_id(header, normal);
|
|
*handle = 1;
|
|
break;
|
|
}
|
|
case PROTO_69845_APP_OAD_EPT_POS:
|
|
{
|
|
if (IOT_DEV_TEST_CCO_MODE) {
|
|
pkt = proto_69845_get_simulate_ept_pos(header, normal);
|
|
*handle = 1;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
if (*handle) {
|
|
iot_sg_printf("69845 vendor get oad: %08X\n", oad);
|
|
}
|
|
|
|
out:
|
|
return pkt;
|
|
}
|
|
|
|
static iot_pkt_t *proto_69845_apdu_get_request_handle(
|
|
proto_69845_frame_head_info_t *header, uint8_t *data, uint32_t len,
|
|
uint32_t *handle)
|
|
{
|
|
uint32_t length = 0;
|
|
iot_pkt_t *pkt = NULL;
|
|
proto_69845_app_get_req_t *get_req = NULL;
|
|
|
|
get_req = (proto_69845_app_get_req_t *)data;
|
|
length = len - sizeof(*get_req);
|
|
switch (get_req->data_type) {
|
|
case PROTO_69845_APP_GET_NORMAL:
|
|
{
|
|
pkt = proto_69845_apdu_get_req_normal_handle(
|
|
header, get_req->data, length, handle);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return pkt;
|
|
}
|
|
|
|
uint32_t proto_69845_handle_vendor_proto(
|
|
uint8_t *data, uint32_t len, int8_t snr, int8_t rssi)
|
|
{
|
|
uint8_t pm_addr[IOT_MAC_ADDR_LEN] = {0};
|
|
uint32_t handle = 0, length = 0;
|
|
iot_pkt_t *pkt = NULL;
|
|
apdu_info_t apdu_info = {0};
|
|
proto_69845_apdu_t *apdu = NULL;
|
|
proto_69845_frame_head_info_t *hdr;
|
|
addr_info_t addr_info = {0};
|
|
|
|
(void)snr;
|
|
(void)rssi;
|
|
|
|
if (iot_sg_sta_get_user_type() != USER_TYPE_STATE_GRID_LIAONING) {
|
|
goto out;
|
|
}
|
|
hdr = proto_69845_sanity_check(data, (uint16_t)len);
|
|
if (!hdr) {
|
|
goto out;
|
|
}
|
|
proto_69845_get_addr_info(hdr, &addr_info);
|
|
if (addr_info.ser_info.type == PROTO_69845_SA_TYPE_BROADCAST) {
|
|
if (addr_info.ser_info.addr[0] != PROTO_69845_SA_BROADCAST_ADD) {
|
|
goto out;
|
|
}
|
|
} else if (addr_info.ser_info.type == PROTO_69845_SA_TYPE_SIG) {
|
|
if (p_sg_glb->desc.sta->drv) {
|
|
p_sg_glb->desc.sta->drv->get_login_addr(pm_addr);
|
|
if (!iot_mac_addr_cmp(pm_addr, addr_info.ser_info.addr)){
|
|
goto out;
|
|
}
|
|
}
|
|
} else {
|
|
goto out;
|
|
}
|
|
if (hdr->ctrl.fn != PROTO_69845_FN_USER_DATA ||
|
|
hdr->ctrl.fragment != PROTO_69845_APDU_WHOLE) {
|
|
goto out;
|
|
}
|
|
if (hdr->ctrl.dir_prm != PROTO_69845_D_P_CLIENT_RESPONSE &&
|
|
hdr->ctrl.dir_prm != PROTO_69845_D_P_CLIENT_REQUEST) {
|
|
goto out;
|
|
}
|
|
if (proto_69845_get_apdu(hdr, hdr->len + PROTO_69845_START_END_LEN,
|
|
&apdu_info) != ERR_OK) {
|
|
goto out;
|
|
}
|
|
if (hdr->ctrl.flag_scramble) {
|
|
proto_69845_sub33_handle(apdu_info.ptr, apdu_info.len);
|
|
}
|
|
apdu = (proto_69845_apdu_t *)apdu_info.ptr;
|
|
length = apdu_info.len - sizeof(*apdu);
|
|
switch (apdu->type)
|
|
{
|
|
case PROTO_69845_C_APP_GET_REQ:
|
|
{
|
|
pkt = proto_69845_apdu_get_request_handle(
|
|
hdr, apdu->data, length, &handle);
|
|
break;
|
|
}
|
|
case PROTO_69845_C_APP_SET_REQ:
|
|
{
|
|
pkt = proto_69845_apdu_set_request_handle(
|
|
hdr, apdu->data, length, &handle);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
out:
|
|
if (handle) {
|
|
iot_sg_sta_meter_read_done_framework(
|
|
(uint8_t)p_sg_glb->desc.sta->mr.data_type, pkt);
|
|
} else if (pkt) {
|
|
IOT_ASSERT(0);
|
|
}
|
|
return handle;
|
|
}
|
|
|
|
#else
|
|
|
|
uint32_t proto_69845_handle_vendor_proto(
|
|
uint8_t *data, uint32_t len, int8_t snr, int8_t rssi)
|
|
{
|
|
(void)data;
|
|
(void)len;
|
|
(void)snr;
|
|
(void)rssi;
|
|
return 0;
|
|
}
|
|
|
|
#endif
|