void ICACHE_FLASH_ATTR pando_subdevice_recv(uint8_t * buffer, uint16_t length) { if(NULL == buffer) { return; } PRINTF("subdevive receive a package: \n"); show_package(buffer, length); struct sub_device_buffer *device_buffer = (struct sub_device_buffer *)pd_malloc(sizeof(struct sub_device_buffer)); device_buffer->buffer_length = length; device_buffer->buffer = (uint8 *)pd_malloc(length); pd_memcpy(device_buffer->buffer, buffer, length); uint16 payload_type = get_sub_device_payloadtype(device_buffer); switch (payload_type) { case PAYLOAD_TYPE_DATA: decode_data(device_buffer); break; case PAYLOAD_TYPE_COMMAND: decode_command(device_buffer); break; default: PRINTF("unsuported paload type : %d", payload_type); break; } delete_device_package(device_buffer); }
struct sub_device_buffer *create_feedback_package() { struct sub_device_buffer *device_buffer = NULL; struct pando_event *event = NULL; struct device_header *header; uint16_t payload_length; uint16_t payload_type = PAYLOAD_TYPE_EVENT; device_buffer = (struct sub_device_buffer *)pd_malloc(sizeof(struct sub_device_buffer)); payload_length = 0; device_buffer->buffer = (uint8_t *)pd_malloc(DEV_HEADER_LEN); pd_memset(device_buffer->buffer, 0, DEV_HEADER_LEN); device_buffer->buffer_length = DEV_HEADER_LEN; header = (struct device_header *)device_buffer->buffer; base_params.event_sequence++; header->magic = MAGIC_HEAD_SUB_DEVICE; header->crc = 0x11; header->frame_seq = host32_to_net(base_params.command_sequence); header->flags = host16_to_net(0xaabb); header->payload_len = host16_to_net(payload_length); header->payload_type = host16_to_net(payload_type); return device_buffer; }
void load_data_from_flash() { pd_printf("loading config data from flash...\n"); int32 cnt, i; int32 magic = 0; pd_printf("loading config data from flash...\n"); //TODO: add system data storage interface. //STMFLASH_Read(PANDO_CONFIG_ADDRESS, (uint16 *)&magic, sizeof(int32)); pd_printf("read magic : %x\n", magic); if(magic != PANDO_CONFIG_MAGIC) { pd_printf("flash config data not initialized!\n"); return; } ////TODO: add system data storage interface. //STMFLASH_Read(PANDO_CONFIG_ADDRESS + sizeof(int32), (uint16 *)&cnt, sizeof(int32)); pd_printf("reading config from flash , key count : %d...\n", cnt); for(i=0; i<cnt; i++) { struct data_pair * p = (struct data_pair * )pd_malloc(sizeof(struct data_pair)); STMFLASH_Read(PANDO_CONFIG_ADDRESS + sizeof(int32) + sizeof(int32) + sizeof(struct data_pair)*i, (uint16 *)p, sizeof(struct data_pair)); p->next = head; head = p; } pd_printf("done...\n"); }
pando_objects_iterator* FUNCTION_ATTRIBUTE create_pando_objects_iterator() { pando_objects_iterator* it = (pando_objects_iterator*)pd_malloc(sizeof(pando_objects_iterator)); it->cur = 0; return it; }
struct TLVs * FUNCTION_ATTRIBUTE create_params_block(uint16_t first_type, uint16_t first_length, void *first_value) { struct TLVs *tlv_block = NULL; uint8_t need_length; current_tlv_block_size = 0; //确保每次新建tlv信息区时,信息区大小的计数都是正确的 need_length = is_tlv_need_length(first_type); //计算合适的初始信息区大小 if ((first_length + sizeof(struct TLV) - need_length * sizeof(first_length)) <= (DEFAULT_TLV_BLOCK_SIZE - sizeof(uint16_t))) { tlv_block_buffer_size = DEFAULT_TLV_BLOCK_SIZE; } else { tlv_block_buffer_size = DEFAULT_TLV_BLOCK_SIZE + first_length + sizeof(struct TLV) - need_length * sizeof(first_length); } tlv_block = (struct TLVs *)pd_malloc(tlv_block_buffer_size); if (tlv_block == NULL) { return NULL; } tlv_block->count = 0; //初始化个数为0 current_tlv_block_size = sizeof(struct TLVs); //没有添加param时,block的内存占用大小仅仅是个数 add_next_param(tlv_block, first_type, first_length, first_value); return tlv_block; }
/* malloc a new block to save old buffer and new property, and update the package length */ int FUNCTION_ATTRIBUTE add_next_property(struct sub_device_buffer *data_package, uint16_t property_num, struct TLVs *next_data_params) { uint8_t *old_buffer = NULL; uint8_t *position = NULL; uint16_t old_len = 0; uint16_t subdevice_id; if (data_package == NULL) { return -1; } old_buffer = data_package->buffer; old_len = data_package->buffer_length; /* append payload length */ data_package->buffer_length += (sizeof(struct pando_property) + current_tlv_block_size - sizeof(struct TLVs)); data_package->buffer = (uint8_t *)pd_malloc(data_package->buffer_length); pd_memset(data_package->buffer, 0, data_package->buffer_length); /* copy old content and new property */ position = copy_return_next(data_package->buffer, old_buffer, old_len); subdevice_id = 0; position = copy_return_next(position, &subdevice_id, sizeof(subdevice_id)); property_num = host16_to_net(property_num); position = copy_return_next(position, &property_num, sizeof(property_num)); pd_memcpy(position, next_data_params, current_tlv_block_size); pd_free(old_buffer); return 0; }
/* event exactly the same as command */ void FUNCTION_ATTRIBUTE decode_command(struct pando_buffer *buf, uint16_t payload_type) { // 网关解包 pando_protocol_decode(buf, payload_type); // 网关向子设备传递数据包,如果是向子设备发包,请用对应的设备send函数 struct sub_device_buffer *device_buffer = pd_malloc(sizeof(struct sub_device_buffer)); device_buffer->buffer_length = pando_get_package_length(buf); device_buffer->buffer = pd_malloc(device_buffer->buffer_length); // 从网关数据包中获取子设备数据包 pd_memcpy(device_buffer->buffer, pando_get_package_begin(buf), device_buffer->buffer_length); // 获取数据完成,释放网关缓冲区 pando_buffer_delete(buf); /* 以下是子设备解析代码 */ struct pando_command cmd_body; // 1.子设备解命令包, 返回参数区的起始位置 struct TLVs *cmd_params_block = get_sub_device_command(device_buffer, &cmd_body); pd_printf("sub id %02x, cmd num %02x, pri %02x, count: %d\n", cmd_body.sub_device_id, cmd_body.command_num, cmd_body.priority, cmd_body.params->count); // 2.子设备获取命令参数 uint16_t tlv_length; uint8_t *value = pd_malloc(100); uint8_t param1 = get_next_uint8(cmd_params_block); show_package(¶m1, sizeof(param1)); uint32_t param2 = get_next_uint32(cmd_params_block); show_package(¶m2, sizeof(param2)); char *param_bytes = get_next_bytes(cmd_params_block, &tlv_length); pd_memcpy(value, param_bytes, tlv_length); show_package(value, tlv_length); pd_free(value); // 3. 删除子设备缓冲区 delete_device_package(device_buffer); }
struct sub_device_buffer *create_command_package(uint16_t cmd_num, uint16_t flags, uint16_t priority, struct TLVs *cmd_params) { struct sub_device_buffer *device_buffer = NULL; struct pando_event *event = NULL; struct device_header *header; uint16_t payload_length; uint16_t payload_type = PAYLOAD_TYPE_COMMAND; device_buffer = (struct sub_device_buffer *)pd_malloc(sizeof(struct sub_device_buffer)); if (cmd_params != NULL) { payload_length = sizeof(struct pando_event) + current_tlv_block_size - sizeof(struct TLVs); //由于pando_event已包含一个tlvs的长度,需要减掉 device_buffer->buffer = (uint8_t *)pd_malloc(DEV_HEADER_LEN + payload_length); pd_memset(device_buffer->buffer, 0, DEV_HEADER_LEN + payload_length); pd_memcpy(device_buffer->buffer + DEV_HEADER_LEN + sizeof(struct pando_event) - sizeof(struct TLVs) , cmd_params, current_tlv_block_size); } else { payload_length = sizeof(struct pando_event); device_buffer->buffer = (uint8_t *)pd_malloc(DEV_HEADER_LEN + payload_length); pd_memset(device_buffer->buffer, 0, DEV_HEADER_LEN + payload_length); } device_buffer->buffer_length = DEV_HEADER_LEN + payload_length; header = (struct device_header *)device_buffer->buffer; event = (struct pando_event *)(device_buffer->buffer + DEV_HEADER_LEN); base_params.event_sequence++; header->magic = MAGIC_HEAD_SUB_DEVICE; header->crc = 0x11; header->frame_seq = host32_to_net(base_params.event_sequence); header->flags = host16_to_net(flags); header->payload_len = host16_to_net(payload_length); header->payload_type = host16_to_net(payload_type); event->event_num = host16_to_net(cmd_num); event->priority = host16_to_net(priority); return device_buffer; }
/****************************************************************************** * FunctionName : zero_device_data_process. * Description : process the received data of zero device(zero device is the gateway itself). * Parameters : uint. * Returns : none. *******************************************************************************/ static void FUNCTION_ATTRIBUTE zero_device_data_process(uint8_t * buffer, uint16_t length) { struct pando_command cmd_body; uint16_t type = 0; uint16_t len = 0; struct sub_device_buffer * device_buffer = (struct sub_device_buffer *)pd_malloc(sizeof(struct sub_device_buffer)); if(device_buffer == NULL) { pd_printf("%s:malloc error!\n", __func__); return; } device_buffer->buffer = (uint8_t*)pd_malloc(length); if(device_buffer->buffer == NULL) { pd_printf("%s:malloc error!\n", __func__); pd_free(device_buffer); return; } pd_memcpy(device_buffer->buffer, buffer, length); device_buffer->buffer_length = length; struct TLVs *cmd_param = get_sub_device_command(device_buffer, &cmd_body); if(COMMON_COMMAND_SYN_TIME == cmd_body.command_num ) { pd_printf("PANDO: synchronize time\n"); uint64_t time = get_next_uint64(cmd_param); show_package((uint8_t*)(&time), sizeof(time)); // pando_set_system_time(time); } if( device_buffer->buffer != NULL) { pd_free( device_buffer->buffer); device_buffer->buffer = NULL; } if(device_buffer != NULL) { pd_free(device_buffer); device_buffer = NULL; } }
/** * @brief MQTT initialization mqtt client function * @param client: MQTT_Client reference * @param clientid: MQTT client id * @param client_user:MQTT client user * @param client_pass:MQTT client password * @param client_pass:MQTT keep alive timer, in second * @retval None */ void FUNCTION_ATTRIBUTE MQTT_InitClient(MQTT_Client *mqttClient, uint8_t* client_id, uint8_t* client_user, uint8_t* client_pass, uint32_t keepAliveTime, uint8_t cleanSession) { uint32_t temp; INFO("MQTT_InitClient\r\n"); pd_memset(&mqttClient->connect_info, 0, sizeof(mqtt_connect_info_t)); temp = pd_strlen(client_id); mqttClient->connect_info.client_id = (uint8_t*)pd_malloc(temp + 1); pd_memset(mqttClient->connect_info.client_id, 0, temp + 1); pd_strcpy(mqttClient->connect_info.client_id, client_id); mqttClient->connect_info.client_id[temp] = 0; temp = pd_strlen(client_user); mqttClient->connect_info.username = (uint8_t*)pd_malloc(temp + 1); pd_memset(mqttClient->connect_info.username, 0, temp + 1); pd_strcpy(mqttClient->connect_info.username, client_user); mqttClient->connect_info.username[temp] = 0; temp = pd_strlen(client_pass); mqttClient->connect_info.password = (uint8_t*)pd_malloc(temp + 1); pd_memset(mqttClient->connect_info.password, 0, temp + 1); pd_strcpy(mqttClient->connect_info.password, client_pass); mqttClient->connect_info.password[temp] = 0; mqttClient->connect_info.keepalive = keepAliveTime; mqttClient->connect_info.clean_session = cleanSession; mqttClient->mqtt_state.in_buffer = (uint8_t *)pd_malloc(MQTT_BUF_SIZE); pd_memset(mqttClient->mqtt_state.in_buffer, 0, MQTT_BUF_SIZE); mqttClient->mqtt_state.in_buffer_length = MQTT_BUF_SIZE; mqttClient->mqtt_state.out_buffer = (uint8_t *)pd_malloc(MQTT_BUF_SIZE); pd_memset(mqttClient->mqtt_state.out_buffer, 0, MQTT_BUF_SIZE); mqttClient->mqtt_state.out_buffer_length = MQTT_BUF_SIZE; mqttClient->mqtt_state.connect_info = &mqttClient->connect_info; mqttClient->mqtt_state.message_length_read = 0; mqtt_msg_init(&mqttClient->mqtt_state.mqtt_connection, mqttClient->mqtt_state.out_buffer, mqttClient->mqtt_state.out_buffer_length); QUEUE_Init(&mqttClient->msgQueue, QUEUE_BUFFER_SIZE); //MQTT_Task(mqttClient); }
void FUNCTION_ATTRIBUTE MQTT_InitLWT(MQTT_Client *mqttClient, uint8_t* will_topic, uint8_t* will_msg, uint8_t will_qos, uint8_t will_retain) { uint32_t temp; temp = pd_strlen(will_topic); mqttClient->connect_info.will_topic = (uint8_t*)pd_malloc(temp + 1); pd_memset(mqttClient->connect_info.will_topic, 0, temp + 1); pd_strcpy(mqttClient->connect_info.will_topic, will_topic); mqttClient->connect_info.will_topic[temp] = 0; temp = pd_strlen(will_msg); mqttClient->connect_info.will_message = (uint8_t*)pd_malloc(temp + 1); pd_memset(mqttClient->connect_info.will_message, 0, temp + 1); pd_strcpy(mqttClient->connect_info.will_message, will_msg); mqttClient->connect_info.will_message[temp] = 0; mqttClient->connect_info.will_qos = will_qos; mqttClient->connect_info.will_retain = will_retain; }
struct pando_buffer * FUNCTION_ATTRIBUTE pando_buffer_create(int length, int offset) { struct pando_buffer *protocol_buffer = (struct pando_buffer *)pd_malloc(sizeof(struct pando_buffer)); if (protocol_buffer == NULL) { return NULL; } protocol_buffer->buff_len = length; protocol_buffer->offset = offset; protocol_buffer->buffer = (uint8_t *)pd_malloc(protocol_buffer->buff_len); if (protocol_buffer->buffer == NULL) { pd_free(protocol_buffer); return NULL; } pd_memset(protocol_buffer->buffer, 0, protocol_buffer->buff_len); return protocol_buffer; }
struct sub_device_buffer * FUNCTION_ATTRIBUTE create_data_package(uint16_t property_num, uint16_t flags, struct TLVs *data_params) { struct sub_device_buffer *data_buffer = NULL; struct pando_property *single_property = NULL; struct device_header *header = NULL; uint16_t payload_length; uint16_t payload_type = PAYLOAD_TYPE_DATA; if (data_params == NULL) { pd_printf("Must create data package with params.\n"); return NULL; } data_buffer = (struct sub_device_buffer *)pd_malloc(sizeof(struct sub_device_buffer)); payload_length = sizeof(struct pando_property) + current_tlv_block_size - sizeof(struct TLVs); //count 被重复包含了 data_buffer->buffer_length = payload_length + DEV_HEADER_LEN; data_buffer->buffer = (uint8_t *)pd_malloc(data_buffer->buffer_length); pd_memset(data_buffer->buffer, 0, data_buffer->buffer_length); header = (struct device_header *)data_buffer->buffer; single_property = (struct pando_property *)(data_buffer->buffer + DEV_HEADER_LEN); base_params.data_sequence++; header->crc = 0x11; header->flags = host16_to_net(flags); header->frame_seq = host32_to_net(base_params.data_sequence); header->magic = MAGIC_HEAD_SUB_DEVICE; header->payload_len = host16_to_net(payload_length); header->payload_type = host16_to_net(payload_type); single_property->property_num = host16_to_net(property_num); pd_memcpy(single_property->params, data_params, current_tlv_block_size); return data_buffer; }
/****************************************************************************** * FunctionName : pando_device_login * Description : try login device using pando cloud device register api. * Parameters : the specify login callback function * Returns : *******************************************************************************/ void FUNCTION_ATTRIBUTE pando_device_login(gateway_callback callback) { pd_printf("begin login device...\n"); if(callback != NULL) { device_login_callback = callback; } char * str_device_id = NULL; char * str_device_secret = NULL; str_device_id = pando_data_get(DATANAME_DEVICE_ID); str_device_secret = pando_data_get(DATANAME_DEVICE_SECRET); if(str_device_id == NULL || str_device_secret == NULL) { // has not registered pd_printf("login failed ! device has not been registerd...\n"); device_login_callback(PANDO_NOT_REGISTERED); return; } int device_id = atol(str_device_id); // try login via HTTP struct jsontree_int json_device_id = JSONTREE_INT(device_id); struct jsontree_string json_device_secret = JSONTREE_STRING(str_device_secret); struct jsontree_string json_protocol = JSONTREE_STRING("mqtt"); JSONTREE_OBJECT_EXT(device_info, JSONTREE_PAIR("device_id", &json_device_id), JSONTREE_PAIR("device_secret", &json_device_secret), JSONTREE_PAIR("protocol", &json_protocol)); request = (char *)pd_malloc(MAX_BUF_LEN); int ret = pando_json_print((struct jsontree_value*)(&device_info), request, MAX_BUF_LEN); pd_printf("device login request:::\n%s\n(end)\n", request); net_http_post(PANDO_API_URL "/v1/devices/authentication", request, http_callback_login); if(request != NULL) { pd_free(request); request = NULL; } }
static struct sub_device_buffer * FUNCTION_ATTRIBUTE create_package( uint16_t flags, uint16_t payload_type) { struct sub_device_buffer *data_buffer = NULL; struct device_header *header = NULL; data_buffer = (struct sub_device_buffer *)pd_malloc(sizeof(struct sub_device_buffer)); pd_memset(data_buffer, 0, sizeof(struct sub_device_buffer)); //only create header data_buffer->buffer_length = DEV_HEADER_LEN; data_buffer->buffer = (uint8_t *)pd_malloc(data_buffer->buffer_length); pd_memset(data_buffer->buffer, 0, data_buffer->buffer_length); header = (struct device_header *)data_buffer->buffer; if (payload_type == PAYLOAD_TYPE_COMMAND) { base_params.command_sequence++; header->frame_seq = host32_to_net(base_params.command_sequence); } else if (payload_type == PAYLOAD_TYPE_EVENT) { base_params.event_sequence++; header->frame_seq = host32_to_net(base_params.event_sequence); }if (payload_type == PAYLOAD_TYPE_DATA) { base_params.data_sequence++; header->frame_seq = host32_to_net(base_params.data_sequence); } header->flags = host16_to_net(flags); header->magic = MAGIC_HEAD_SUB_DEVICE; header->payload_type = host16_to_net(payload_type); return data_buffer; }
/** * @brief MQTT initialization connection function * @param client: MQTT_Client reference * @param host: Domain or IP string * @param port: Port to connect * @param security: 1 for ssl, 0 for none * @retval None */ void FUNCTION_ATTRIBUTE MQTT_InitConnection(MQTT_Client *mqttClient, uint8_t* host, uint32_t port, uint8_t security) { uint32_t temp; INFO("MQTT_InitConnection\r\n"); pd_memset(mqttClient, 0, sizeof(MQTT_Client)); temp = pd_strlen(host); mqttClient->host = (uint8_t*)pd_malloc(temp + 1); pd_memset(mqttClient->host, 0, temp + 1); pd_strcpy(mqttClient->host, host); mqttClient->host[temp] = 0; mqttClient->port = port; mqttClient->security = security; }
struct TLVs * FUNCTION_ATTRIBUTE create_params_block() { struct TLVs *tlv_block = NULL; uint8_t need_length; current_tlv_block_size = 0; tlv_block_buffer_size = DEFAULT_TLV_BLOCK_SIZE; tlv_block = (struct TLVs *)pd_malloc(tlv_block_buffer_size); if (tlv_block == NULL) { return NULL; } tlv_block->count = 0; //初始化个数为0 current_tlv_block_size = sizeof(struct TLVs); //没有添加param时,block的内存占用大小仅仅是个数 return tlv_block; }
/****************************************************************************** * FunctionName : pando_data_set * Description : set the vale of the parameter stored, if the parameter is existing. Else creat the parameter, and save it. * Parameters : key -- the parameter; value -- the value of the parameter. * Returns : the save result *******************************************************************************/ SET_RESULT pando_data_set(char* key, char* value) { struct data_pair * p; p = find_pair_by_key(key); if(p != NULL) { // key exist, update value. pd_strncpy(p->val, value, DATAPAIR_VALUE_LEN); pd_printf("key %s updated...\n", key, p->val); } else { // key not exist, create a new pair. struct data_pair * p = (struct data_pair * )pd_malloc(sizeof(struct data_pair)); pd_strncpy(p->key, key, DATAPAIR_KEY_LEN); pd_strncpy(p->val, value, DATAPAIR_VALUE_LEN); p->next = head; head = p; pd_printf("key %s created..., value %s \n", key, p->val); } save_data_to_flash(); }
int add_next_property(struct sub_device_buffer *data_package, uint16_t property_num, struct TLVs *next_data_params) { uint8_t *new_buffer = NULL; uint8_t *position = NULL; struct device_header *hdr = (struct device_header *)data_package->buffer; uint16_t payload_len = 0; uint16_t append_len = sizeof(struct pando_property) + current_tlv_block_size - sizeof(struct TLVs); if (data_package == NULL) { return -1; } /* append payload length */ payload_len = net16_to_host(hdr->payload_len); data_package->buffer_length += append_len; payload_len += append_len; hdr->payload_len = host16_to_net(payload_len); new_buffer = (uint8_t *)pd_malloc(data_package->buffer_length); pd_memset(new_buffer, 0, data_package->buffer_length); /* copy buffer content, skip subdev id, copy property num and tlv params */ position = new_buffer + data_package->buffer_length - append_len; pd_memcpy(new_buffer, data_package->buffer, data_package->buffer_length); position += 2; //sub device id property_num = host16_to_net(property_num); pd_memcpy(position, &property_num, sizeof(property_num)); position += sizeof(property_num); pd_memcpy(position, next_data_params, current_tlv_block_size); pd_free(data_package->buffer); data_package->buffer = new_buffer; return 0; }
/** * @brief Begin connect to MQTT broker * @param client: MQTT_Client reference * @retval None */ void FUNCTION_ATTRIBUTE MQTT_Connect(MQTT_Client *mqttClient) { MQTT_Disconnect(mqttClient); mqttClient->pCon = (struct pando_tcp_conn *)pd_malloc(sizeof(struct pando_tcp_conn)); pd_memset(mqttClient->pCon, 0, sizeof(struct pando_tcp_conn)); (mqttClient->pCon)->reverse = mqttClient; mqttClient->pCon->secure = mqttClient->security; net_tcp_register_connected_callback(mqttClient->pCon, mqtt_tcpclient_connect_cb); //no reconnection call back. TODO mqttClient->keepAliveTick = 0; mqttClient->reconnectTick = 0; mqttClient->connectTick = 0; mqttClient->heart_beat_flag = 1; mqttClient->mqttTimer.interval = 1000; mqttClient->mqttTimer.timer_no = 1; mqttClient->mqttTimer.repeated = 1; mqttClient->mqttTimer.arg = mqttClient; mqttClient->mqttTimer.timer_cb = mqtt_timer; pando_timer_init(&(mqttClient->mqttTimer)); pando_timer_stop(&(mqttClient->mqttTimer)); pando_timer_start(&(mqttClient->mqttTimer)); (mqttClient->pCon)->remote_port = mqttClient->port; if(UTILS_StrToIP(mqttClient->host, &mqttClient->pCon->remote_ip)) { INFO("TCP: Connect to ip %s:%d\r\n", mqttClient->host, mqttClient->port); net_tcp_connect(mqttClient->pCon, mqttClient->sendTimeout); } else { INFO("TCP: Connect to domain %s:%d\r\n", mqttClient->host, mqttClient->port); //need a host name function. TODO //espconn_gethostbyname(mqttClient->pCon, mqttClient->host, &mqttClient->ip, mqtt_dns_found); } mqttClient->connState = TCP_CONNECTING; }
static void FUNCTION_ATTRIBUTE http_callback_login(char * response) { if(request != NULL) { pd_free(request); request = NULL; } if(response == NULL) { device_login_callback(PANDO_LOGIN_FAIL); return; } pd_printf("response=%s\n(end)\n", response); uint16_t response_len = pd_strlen(response) + 1; char* login_response = (char*)pd_malloc(response_len); pd_memset(login_response, 0, response_len); pd_memcpy(login_response, response, response_len); struct jsonparse_state json_state; jsonparse_setup(&json_state, login_response, pd_strlen(login_response)); int code; char message[MSG_BUF_LEN]; char access_token[ACCESS_TOKEN_LEN*2 + 16]; char access_addr[KEY_BUF_LEN]; access_token[ACCESS_TOKEN_LEN*2] = '\0'; int type; while ((type = jsonparse_next(&json_state)) != 0) { if (type == JSON_TYPE_PAIR_NAME) { if(jsonparse_strcmp_value(&json_state, "code") == 0) { jsonparse_next(&json_state); jsonparse_next(&json_state); code = jsonparse_get_value_as_int(&json_state); } else if(jsonparse_strcmp_value(&json_state, "message") == 0) { jsonparse_next(&json_state); jsonparse_next(&json_state); jsonparse_copy_value(&json_state, message, MSG_BUF_LEN); } else if(jsonparse_strcmp_value(&json_state, "data") == 0) { while((type = jsonparse_next(&json_state)) != 0 && json_state.depth > 1) { if(type == JSON_TYPE_PAIR_NAME) { if(jsonparse_strcmp_value(&json_state, "access_token") == 0) { jsonparse_next(&json_state); jsonparse_next(&json_state); jsonparse_copy_value(&json_state, access_token, ACCESS_TOKEN_LEN*2 + 16); } else if(jsonparse_strcmp_value(&json_state, "access_addr") == 0) { jsonparse_next(&json_state); jsonparse_next(&json_state); jsonparse_copy_value(&json_state, access_addr, KEY_BUF_LEN); } } } } } } if(login_response != NULL) { pd_free(login_response); } if(code != 0) { pd_printf("device login failed: %s\n", message); if(device_login_callback != NULL) { device_login_callback(PANDO_LOGIN_FAIL); } return; } hex2bin(pando_device_token, access_token); pd_printf("device login success, access_addr : %s\n", access_addr); pando_data_set(DATANAME_ACCESS_ADDR, access_addr); pando_data_set(DATANAME_ACCESS_TOKEN, access_token); if(device_login_callback != NULL) { device_login_callback(PANDO_LOGIN_OK); } }
int FUNCTION_ATTRIBUTE add_next_param(struct TLVs *params_block, uint16_t next_type, uint16_t next_length, void *next_value) { uint16_t type; uint16_t conver_length; uint8_t need_length; uint8_t tlv_length; uint8_t tmp_value[8]; uint8_t *tlv_position; struct TLVs *new_property_block = NULL; uint16_t current_count = net16_to_host(params_block->count); //由于create的时候就对该值进行了端转换,因此需要回转 need_length = is_tlv_need_length(next_type); if (1 == need_length) { } else if (0 == need_length) { if(next_length != get_type_length(next_type)) { printf("Param type dismatch with the input length\n"); return -1; } } else { return -1; } //信息区扩容 if (current_tlv_block_size + next_length + sizeof(struct TLV) - (!need_length) * sizeof(next_length) > tlv_block_buffer_size) { tlv_block_buffer_size = tlv_block_buffer_size + DEFAULT_TLV_BLOCK_SIZE + next_length; new_property_block = (struct TLVs *)pd_malloc(tlv_block_buffer_size); pd_memcpy(new_property_block, params_block, current_tlv_block_size); pd_free(params_block); params_block = new_property_block; } current_count++; tlv_position = (uint8_t *)params_block + current_tlv_block_size; //将count保存为网络字节序,便于创建事件或数据包时直接赋值 params_block->count = host16_to_net(current_count); //复制tlv内容,并大小端转换,修正tlv长度和type的设置方式,解决跨字错误 type = host16_to_net(next_type); pd_memcpy(tlv_position, &type, sizeof(type)); tlv_position += sizeof(type); if (need_length) { conver_length = host16_to_net(next_length); pd_memcpy(tlv_position, &conver_length, sizeof(conver_length)); tlv_position += sizeof(conver_length); } switch(next_type) { case TLV_TYPE_FLOAT64 : *((double *)tmp_value) = host64f_to_net(*((uint64_t *)next_value)); pd_memcpy(tlv_position, tmp_value, next_length); break; case TLV_TYPE_FLOAT32 : *((float *)tmp_value) = host32f_to_net(*((float *)next_value)); pd_memcpy(tlv_position, tmp_value, next_length); break; case TLV_TYPE_INT16: *((int16_t *)tmp_value) = host16_to_net(*((int16_t *)next_value)); pd_memcpy(tlv_position, tmp_value, next_length); break; case TLV_TYPE_UINT16: *((uint16_t *)tmp_value) = host16_to_net(*((uint16_t *)next_value)); pd_memcpy(tlv_position, tmp_value, next_length); break; case TLV_TYPE_INT32: *((int32_t *)tmp_value) = host32_to_net(*((int32_t *)next_value)); pd_memcpy(tlv_position, tmp_value, next_length); break; case TLV_TYPE_UINT32: *((uint32_t *)tmp_value) = host32_to_net(*((uint32_t *)next_value)); pd_memcpy(tlv_position, tmp_value, next_length); break; case TLV_TYPE_UINT64: *((uint64_t *)tmp_value) = host64_to_net(*((uint64_t *)next_value)); pd_memcpy(tlv_position, tmp_value, next_length); break; case TLV_TYPE_INT64: *((int64_t *)tmp_value) = host64_to_net(*((int64_t *)next_value)); pd_memcpy(tlv_position, tmp_value, next_length); break; default: pd_memcpy(tlv_position, next_value, next_length); break; } current_tlv_block_size = current_tlv_block_size + next_length + sizeof(struct TLV) - (!need_length) * sizeof(next_length); return 0; }
void FUNCTION_ATTRIBUTE decode_data(struct pando_buffer *buf, uint16_t payload_type) { // 网关解包 pando_protocol_decode(buf, payload_type); // 网关向子设备传递数据包,如果是向子设备发包,请用对应的设备send函数 struct sub_device_buffer *device_buffer = pd_malloc(sizeof(struct sub_device_buffer)); device_buffer->buffer_length = pando_get_package_length(buf); device_buffer->buffer = pd_malloc(device_buffer->buffer_length); // 从网关数据包中获取子设备数据包 pd_memcpy(device_buffer->buffer, pando_get_package_begin(buf), device_buffer->buffer_length); // 获取数据完成,释放网关缓冲区 pando_buffer_delete(buf); show_package(device_buffer->buffer, device_buffer->buffer_length); /* 以下是子设备解析代码 */ struct pando_property data_body; uint8_t *buf_end = device_buffer->buffer + device_buffer->buffer_length; int i = 0; uint16_t tlv_type, tlv_length; uint8_t *value = pd_malloc(100); struct TLV *param = NULL; struct TLVs *property_block; // 2.子设备获取命令参数 uint32_t param1 = 0; uint8_t param2 = 0; char *param_bytes = NULL; while(1) { property_block = get_sub_device_property(device_buffer, &data_body); if (property_block == NULL) { pd_printf("reach end of buffer\n"); break; } pd_printf("count: %d\n", data_body.params->count); if (data_body.params->count == 3) { param1 = get_next_uint32(property_block); show_package(¶m1, sizeof(param1)); param2 = get_next_uint8(property_block); show_package(¶m2, sizeof(param2)); param_bytes = get_next_bytes(property_block, &tlv_length); pd_memcpy(value, param_bytes, tlv_length); show_package(value, tlv_length); } else if (data_body.params->count == 2) { param2 = get_next_uint8(property_block); show_package(¶m2, sizeof(param2)); param_bytes = get_next_bytes(property_block, &tlv_length); pd_memcpy(value, param_bytes, tlv_length); show_package(value, tlv_length); } } pd_free(value); // 3. 删除子设备缓冲区 delete_device_package(device_buffer); }
/*! * Common mode filter algorithm for all port drivers * * @param call_back * @param in_list * @param out_list * @param dvo_info * @param display_info * * @return PD_SUCCESS on success * @return PD_ERR_NULL_PTR or PD_ERR_NOMEM on failure */ int pd_filter_timings( void *callback_context, pd_timing_t *in_list, pd_timing_t **out_list, pd_dvo_info_t *dvo_info, pd_display_info_t *display_info) { igd_display_port_t *port = (igd_display_port_t *)callback_context; pd_timing_t *timing = NULL, *native_dtd = NULL; int j; int count = 0; unsigned short fp_refresh = 60; pd_timing_t *olist = NULL; unsigned long fixed_timing = 0; int i, ret; if (!port || !in_list || !out_list) { return PD_ERR_NULL_PTR; } /* Start with fixed_res = 0 */ display_info->fixed_res = 0; /* DisplayID FP width are specified */ if (port->firmware_type == PI_FIRMWARE_DISPLAYID) { display_info->width = port->displayid->display_params.horz_pixels; display_info->height = port->displayid->display_params.vert_pixels; fixed_timing = port->displayid->display_params.fixed_timing; display_info->fixed_res = port->displayid->display_params.fixed_res; } /* Overwrite DisplayID FP values with config fpinfo, later * these will be overwritten by native DTD width, height */ if (port->fp_info) { /* This is done for backward compatibility: * Set width, height from display port fp_info * This also required dropping fp_info width and height attributes * from all port drivers */ display_info->width = (unsigned short) port->fp_info->fp_width; display_info->height = (unsigned short) port->fp_info->fp_height; /* Backward compatibility: If width and height are specified, * that means it is a fixed resolution panel */ if (port->fp_info->fp_width && port->fp_info->fp_height) { display_info->fixed_res = 1; fp_refresh = 60; } } /* If fixed timing also comes from user attributes then override DisplayID * fixed timing and fpinfo values */ ret = pi_get_port_init_attr(port, PD_ATTR_ID_FIXED_TIMING, &fixed_timing); if (fixed_timing) { display_info->fixed_res = 1; fp_refresh = 60; } /* Do gmch filtering: * There is no way to get the mode context inorder to reach the * gmch filtering function */ /* First find the native resolution */ get_native_dtd(in_list, PI_SUPPORTED_TIMINGS, &display_info->native_dtd, PD_MODE_DTD_FP_NATIVE); /* If no FP Native DTD provided, then get the native DTD * either user DTD or edid DTD */ if (!display_info->native_dtd) { get_native_dtd(in_list, PI_SUPPORTED_TIMINGS, &display_info->native_dtd, PD_MODE_DTD_USER); } if (!display_info->native_dtd) { get_native_dtd(in_list, PI_SUPPORTED_TIMINGS, &display_info->native_dtd, PD_MODE_DTD); } /* Set up the fp width, height and refresh for the comparison */ if (display_info->native_dtd) { #ifndef CONFIG_MICRO /* If fp width, height doesn' match with native width and height, * Configuration isn't correct */ if ((display_info->width && (display_info->width != display_info->native_dtd->width)) && (display_info->height && (display_info->height != display_info->native_dtd->height))) { EMGD_DEBUG("FP Width Height doesn't match with Native DTD."); } #endif /* Overwrite native width height as panel width and height */ display_info->width = display_info->native_dtd->width; display_info->height = display_info->native_dtd->height; fp_refresh = display_info->native_dtd->refresh; } else if (ret && port->firmware_type != PI_FIRMWARE_DISPLAYID && dvo_info->upscale) { /* TODO: * For time being this function has to assume all upscaling encoders * are connected to a fixed timing panel if no fixed_timing is * specified. * * Once fixed_timing init-time attribute becomes mandatory, below check * can be removed. * * If customer uses old config system and didn't specified init time * fixed_timing attribute, then driver assumes it is a fixed-resolution * panel. If user do specifies fixed_timing attribute, then above check * will fail, and algorithm continues with whatever value set to * fixed_res attr. * * ret != 0 means no fixed_timing user attribute * firmware_type == DISPLAYID means firmware provided fixed_timing, * so don't change it. */ display_info->fixed_res = 1; } /* Check native_dtd for fixed_res display */ if (display_info->fixed_res && !display_info->native_dtd) { /* This happens if user provides fp_width, fp_height and didn't set * fixed res parameter. In this case native_dtd will be set as part * of the while loop while filtering the modes */ EMGD_DEBUG("pd_filter_timings: No native dtd for fixed_resolution"); } if (!display_info->width && !display_info->height) { /* If fp width and height isn't known, then enable all modes as * non-fixed res display */ display_info->fixed_res = 0; } EMGD_DEBUG("fixed_res = %u fixed_timing = %lu", display_info->fixed_res, fixed_timing); EMGD_DEBUG("fp_width = %u, fp_height = %u, fp_refresh = %u", display_info->width, display_info->height, fp_refresh); EMGD_DEBUG("min_dclk = %lu, max_dclk = %lu", dvo_info->min_dclk, dvo_info->max_dclk); /* This function can be called with following * --------------------------------------------------------------- * DVO device PanelFit Display AvailableModes * DOWN UP Fixed? * -------------------------------------------------------- * 0 0 0 0 All supported modes * 1 0 0 0 All supported modes * 0 1 0 0 All supported modes * 1 1 0 0 All supported modes * 0 0 1 0 All supported modes * 1 0 1 0 All supported modes * 0 1 1 0 All supported modes * 1 1 1 0 All supported modes * * 0 0 0 Y Only one mode * 1 0 0 Y Only one mode * 0 1 0 Y Only one mode * 1 1 0 Y Only one mode * 0 0 1 Y Only one mode * * 0 1 1 Y All upscalable modes * 1 0 1 Y All downscalable modes * * 1 1 1 Y All UP & DOWN scalable modes * ------------------------------------------------------------------------- */ for (i = 0; i < 2; ++i) { j = 0; timing = in_list; while(timing->width != PD_TIMING_LIST_END) { /* If mode supported and dclk is within the range */ if ((timing->mode_info_flags & PD_MODE_SUPPORTED) && ((!dvo_info->max_dclk || (timing->dclk <= dvo_info->max_dclk))&& (!dvo_info->min_dclk || (timing->dclk >= dvo_info->min_dclk)))){ if ( /* fixed_res = 0 */ !display_info->fixed_res || /* no panel fit */ (!display_info->panel_fit && timing->refresh == fp_refresh && timing->width == display_info->width && timing->height == display_info->height) || /* panel fit and upscale or downscale */ (display_info->panel_fit && timing->refresh == fp_refresh && ((dvo_info->upscale && timing->width <= display_info->width && timing->height <= display_info->height && (!dvo_info->upscale_min_width || timing->width >= dvo_info->upscale_min_width) && (!dvo_info->upscale_min_height || timing->height >= dvo_info->upscale_min_height)) #if 0 || (dvo_info->downscale && timing->width >= display_info->width && timing->height >= display_info->height && (!dvo_info->downscale_max_width || timing->width <= dvo_info->downscale_max_width) && (!dvo_info->downscale_max_height || timing->height >= dvo_info->downscale_max_height)) #endif ))) { if(!i){ count++; } else { /* copy timing */ olist[j] = *timing; /* save the native_dtd timing */ if ((timing->width == display_info->width) && (timing->height == display_info->height) && (timing->refresh == fp_refresh)) { native_dtd = &(olist[j]); } /* The native DTD pointer is pointing in the in_list, * reset this pointer to point in the out_list */ if (timing == display_info->native_dtd) { display_info->native_dtd = &olist[j]; } j++; } } } timing++; if ((timing->width == PD_TIMING_LIST_END) && timing->extn_ptr) { timing = timing->extn_ptr; } } if(!i) { count++; olist = (pd_timing_t *) pd_malloc(count * sizeof(pd_timing_t)); if(!olist) { return PD_ERR_NOMEM; } } else { /* Copy the END of LIST entry */ olist[j] = *timing; } } /* If there is no native_dtd, then use the first matching * resolution with fp width and height as native dtd */ if (!display_info->native_dtd) { display_info->native_dtd = native_dtd; } if (display_info->native_dtd) { EMGD_DEBUG("pd_filter_timings: NativeDTD: %ux%u@%u", display_info->native_dtd->width, display_info->native_dtd->height, display_info->native_dtd->refresh); display_info->native_dtd->mode_info_flags |= PD_MODE_DTD_FP_NATIVE; } *out_list = olist; return PD_SUCCESS; }