在逗猫棒的基础上实现蓝牙转USB功能,目前功能已经实现,还需裁剪掉之前逗猫棒的业务程序

This commit is contained in:
2026-07-24 11:41:08 +08:00
commit b3f06697a6
1569 changed files with 515355 additions and 0 deletions
@@ -0,0 +1,405 @@
/**
* \file tuya_ble_api.h
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#ifndef TUYA_BLE_API_H__
#define TUYA_BLE_API_H__
#include "tuya_ble_type.h"
#include "tuya_ble_internal_config.h"
#include "tuya_ble_port.h"
#if (TUYA_BLE_USE_OS==0)
/**
* @brief Function for executing all enqueued tasks.
*
* @note This function must be called from within the main loop. It will
* execute all events scheduled since the last time it was called.
* */
void tuya_ble_main_tasks_exec(void);
#endif
/**
* @brief Function for transmit ble data from peer devices to tuya sdk.
*
* @note This function must be called from where the ble data is received.
*.
* */
tuya_ble_status_t tuya_ble_gatt_receive_data(uint8_t *p_data, uint16_t len);
/**
* @brief Function for transmit uart data to tuya sdk.
*
* @note This function must be called from where the uart data is received.
*.
* */
tuya_ble_status_t tuya_ble_common_uart_receive_data(uint8_t *p_data, uint16_t len);
/**
* @brief Function for send the full instruction received from uart to the sdk.
*
* @param
* [in]p_data : pointer to full instruction data(Complete instruction,include0x55 or 0x66 0xaa and checksum.)
* [in]len : Number of bytes of pdata.
*
* @note If the application uses a custom uart parsing algorithm to obtain the full uart instruction,then call this function to send the full instruction.
*
* */
tuya_ble_status_t tuya_ble_common_uart_send_full_instruction_received(uint8_t *p_data, uint16_t len);
/**
* @brief Function for update the device id to tuya sdk.
*
* @note the following id of the device must be update immediately when changed.
*.
* */
tuya_ble_status_t tuya_ble_device_update_product_id(tuya_ble_product_id_type_t type, uint8_t len, uint8_t *p_buf);
tuya_ble_status_t tuya_ble_device_update_login_key(uint8_t *p_buf, uint8_t len);
#if ((TUYA_BLE_PROTOCOL_VERSION_HIGN==4) && (TUYA_BLE_BEACON_KEY_ENABLE))
tuya_ble_status_t tuya_ble_device_update_beacon_key(uint8_t *p_buf, uint8_t len);
#endif
tuya_ble_status_t tuya_ble_device_update_bound_state(uint8_t state);
tuya_ble_status_t tuya_ble_device_update_mcu_version(uint32_t mcu_firmware_version, uint32_t mcu_hardware_version);
/**
* @brief Function for initialize the tuya sdk.
*
* @note appliction should call this after all platform init complete.
*.
* */
tuya_ble_status_t tuya_ble_sdk_init(tuya_ble_device_param_t *param_data);
#if (TUYA_BLE_PROTOCOL_VERSION_HIGN==4)
/**
* @brief Function for send the dp point data.
*
* @param [in]sn: The sending sequence number of the application definition management.
* [in]type : DP_SEND_TYPE_ACTIVE- The device actively sends dp data;DP_SEND_TYPE_PASSIVE- The device passively sends dp data. For example, in order to answer the dp query command of the mobile app. Currently only applicable to WIFI+BLE combo devices.
* [in]mode : See the description in the 'tuya_ble_type.h' file for details.
* [in]ack : See the description in the 'tuya_ble_type.h' file for details.
* [in]p_dp_data : The pointer of dp data .
* [in]dp_data_len : The length of dp data .
* @note new api, The length of each dp data sent through this function must be 2 bytes. DTLD->'L' must be 2 bytes.
*.
* */
tuya_ble_status_t tuya_ble_dp_data_send(uint32_t sn, tuya_ble_dp_data_send_type_t type, tuya_ble_dp_data_send_mode_t mode, tuya_ble_dp_data_send_ack_t ack, uint8_t *p_dp_data, uint32_t dp_data_len);
/**
* @brief Function for send the dp data with time.
*
* @param [in]sn: The sending sequence number of the application definition management.
* [in]mode : See the description in the 'tuya_ble_type.h' file for details.
* [in]time_type : DP_TIME_TYPE_MS_STRING - Indicates that the following 'p_time_data' is a string of milliseconds that must be 13 bytes in length.
* E.g, 'p_time_data' points to the string "1600777955000";
* DP_TIME_TYPE_UNIX_TIMESTAMP - Indicates that the following 'p_time_data' points to the four-byte unix timestamp data.
* E.g, unix timestamp is 1600777955 = 0x5F69EEE3, then 'p_time_data' is {0x5F,0x69,0xEE,0xE3} ;
* [in]p_time_data : time data pointer.
* [in]p_dp_data : The pointer of dp data .
* [in]dp_data_len : The length of dp data .
* @note new api, The length of each dp data sent through this function must be 2 bytes. DTLD->'L' must be 2 bytes.
*. The default type of this function is 'DP_SEND_TYPE_ACTIVE', and the default ack is 'DP_SEND_WITH_RESPONSE', which cannot be changed.
* */
tuya_ble_status_t tuya_ble_dp_data_with_time_send(uint32_t sn, tuya_ble_dp_data_send_mode_t mode, tuya_ble_dp_data_send_time_type_t time_type, uint8_t *p_time_data, uint8_t *p_dp_data, uint32_t dp_data_len);
#else
/**
* @brief Function for report the dp point data.
*
* @note
*.
* */
tuya_ble_status_t tuya_ble_dp_data_report(uint8_t *p_data, uint32_t len);
/**
* @brief Function for report the dp point data with time.
*
* @note
*.
* */
tuya_ble_status_t tuya_ble_dp_data_with_time_report(uint32_t timestamp, uint8_t *p_data, uint32_t len);
/**
* @brief Function for report the dp point data with time.
*
* @note time_string: 13-byte millisecond string ,for example ,"0000000123456";
*.
* */
tuya_ble_status_t tuya_ble_dp_data_with_time_ms_string_report(uint8_t *time_string, uint8_t *p_data, uint32_t len);
/**
* @brief Function for report the dp point data with flag.
*
* @note
*.
* */
tuya_ble_status_t tuya_ble_dp_data_with_flag_report(uint16_t sn, tuya_ble_dp_data_send_mode_t mode, uint8_t *p_data, uint32_t len);
/**
* @brief Function for report the dp point data with flag and time.
*
* @note
*.
* */
tuya_ble_status_t tuya_ble_dp_data_with_flag_and_time_report(uint16_t sn, tuya_ble_dp_data_send_mode_t mode, uint32_t timestamp, uint8_t *p_data, uint32_t len);
/**
* @brief Function for report the dp point data with flag and time.
*
* @note time_string: 13-byte millisecond string ,for example ,"0000000123456";
*.
* */
tuya_ble_status_t tuya_ble_dp_data_with_flag_and_time_ms_string_report(uint16_t sn, tuya_ble_dp_data_send_mode_t mode, uint8_t *time_string, uint8_t *p_data, uint32_t len);
#endif
/**
* @brief Function for process the internal state of tuya sdk, application should call this in connect handler.
*
* @note
*.
* */
void tuya_ble_connected_handler(void);
/**
* @brief Function for process the internal state of tuya sdk, application should call this in disconnect handler.
*
* @note
*.
* */
void tuya_ble_disconnected_handler(void);
#if TUYA_BLE_LINK_LAYER_ENCRYPTION_SUPPORT_ENABLE
/**
*@brief Function for update the link encrypted status to sdk, application should call this function when the link layer encryption is successful.
*@note
*
* */
void tuya_ble_link_encrypted_handler(void);
#endif
#if (TUYA_BLE_PROTOCOL_VERSION_HIGN >= 3)
/**
* @brief Function for process the internal state of tuya sdk, application should call this in disconnect handler.
* @param [in]on_off: 0-off ,1 - on.
* @note
*.
* */
tuya_ble_status_t tuya_ble_adv_data_connecting_request_set(uint8_t on_off);
#endif
/**
* @brief Function for data passthrough.
*
* @note The tuya sdk will forwards the data to the app.
*.
* */
tuya_ble_status_t tuya_ble_data_passthrough(uint8_t *p_data, uint32_t len);
/**
* @brief Function for response the production test instruction asynchronous.
*
* @param [in]channel: 0-uart ,1 - ble.
* [in]pdata : pointer to production test cmd data(Complete instruction,include0x66 0xaa and checksum.)
* [in]len : Number of bytes of pdata.
* @note The tuya sdk will forwards the data to the app.
*.
* */
tuya_ble_status_t tuya_ble_production_test_asynchronous_response(uint8_t channel, uint8_t *p_data, uint32_t len);
/**
* @brief Function for response for the net config req.
*
* @note
*.
* */
tuya_ble_status_t tuya_ble_net_config_response(int16_t result_code);
#if (!TUYA_BLE_DEVICE_REGISTER_FROM_BLE)
/**
* @brief Function for response for ubound req.
*
* @note
*.
* */
tuya_ble_status_t tuya_ble_ubound_response(uint8_t result_code);
/**
* @brief Function for response for anomaly ubound req.
*
* @note
*.
* */
tuya_ble_status_t tuya_ble_anomaly_ubound_response(uint8_t result_code);
/**
* @brief Function for response for device reset req.
*
* @note
*.
* */
tuya_ble_status_t tuya_ble_device_reset_response(uint8_t result_code);
#endif
/**
* @brief Function for get the ble connet status.
*
* @note
*.
* */
tuya_ble_connect_status_t tuya_ble_connect_status_get(void);
/**
* @brief Function for notify the sdk the device has unbind.
*
* @note
*.
* */
tuya_ble_status_t tuya_ble_device_unbind(void);
/**
* @brief Function for notify the sdk the device has resumes factory Settings.
*
* @note When the device resumes factory Settings,shoule notify the sdk.
*.
* */
tuya_ble_status_t tuya_ble_device_factory_reset(void);
/**
* @brief Function for Request update time.
*
* @param time_type: 0-13-byte millisecond string [from cloud],1 - normal time format [from cloud] , 2 - normal time format[from app local]
* @note
*.
* */
tuya_ble_status_t tuya_ble_time_req(uint8_t time_type);
/**
* @brief Function for response the ota req.
*
* @note response the ota data req from call back event.
*.
* */
tuya_ble_status_t tuya_ble_ota_response(tuya_ble_ota_response_t *p_data);
/**
* @brief Function for send custom event to main process of ble sdk.
*
* @note
*.
* */
uint8_t tuya_ble_custom_event_send(tuya_ble_custom_evt_t evt);
#if TUYA_BLE_USE_OS
/**
* @brief Function for registe queue to receive call back evt when use os
*
* @note
*
* */
tuya_ble_status_t tuya_ble_callback_queue_register(void *cb_queue);
/**
* @brief Function for response the event.
*
* @note if use os,must be sure to call this function after process one event in queue.
*
* */
tuya_ble_status_t tuya_ble_event_response(tuya_ble_cb_evt_param_t *param);
#else
/**
* @brief Function for registe call back functions.
*
* @note appliction should receive the message from the call back registed by this function.
*
* */
tuya_ble_status_t tuya_ble_callback_queue_register(tuya_ble_callback_t cb);
/**
* @brief Function for get scheduler queue size.
*
* @note If it returns 0, it means that the queue has not been initialized.
*
* */
uint16_t tuya_ble_scheduler_queue_size_get(void);
/**
* @brief Function for get queue free space.
*
* @note
*
* */
uint16_t tuya_ble_scheduler_queue_space_get(void);
/**
* @brief Function for get the number of current events in the queue.
*
* @note
*
* */
uint16_t tuya_ble_scheduler_queue_events_get(void);
#endif
/**
* @brief Function for check if sleep is allowed.
*
* @note If it returns true, it means that sleep is allowed.
*
* */
bool tuya_ble_sleep_allowed_check(void);
#endif
@@ -0,0 +1,92 @@
/**
* \file tuya_ble_bulkdata.h
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#ifndef TUYA_BLE_BULK_DATA_H_
#define TUYA_BLE_BULK_DATA_H_
#ifdef __cplusplus
extern "C" {
#endif
/*********************************************************************
* INCLUDE
*/
#include "tuya_ble_stdlib.h"
#include "tuya_ble_type.h"
/**@brief Macro for defining bulk data transfer protocol. */
#define FRM_BULK_DATA_READ_INFO_REQ 0x0007 //APP->BLE
#define FRM_BULK_DATA_READ_INFO_RESP 0x0007 //BLE->APP
#define FRM_BULK_DATA_READ_DATA_REQ 0x0008 //APP->BLE
#define FRM_BULK_DATA_READ_DATA_RESP 0x0008 //BLE->APP
#define FRM_BULK_DATA_SEND_DATA 0x0009 //BLE->APP
#define FRM_BULK_DATA_ERASE_DATA_REQ 0x000A //APP->BLE
#define FRM_BULK_DATA_ERASE_DATA_RESP 0x000A //BLE->APP
/**@brief Function for get the block size used for bulk data reading.
*
*
* @param[out] block size used for bulk data reading.
* @note The block size depends on the mtu value negotiated after the BLE connection is established.
* If the return value is 0, stop the current bulk data transmission.
*/
uint32_t tuya_ble_bulk_data_read_block_size_get(void);
/**@brief Function for handling the bulk data request.
*
*
* @param[in] cmd Request command.
* @param[in] p_recv_data Pointer to the buffer with received data.
* @param[in] recv_data_len Length of received data.
*/
void tuya_ble_handle_bulk_data_req(uint16_t cmd, uint8_t *p_recv_data, uint32_t recv_data_len);
/**@brief Function for respond to app requests.
*
*
* @param[in] p_data The pointer to the response data.
*/
tuya_ble_status_t tuya_ble_bulk_data_response(tuya_ble_bulk_data_response_t *p_data);
/**@brief Function for handling the bulk data events.
*
*
* @param[in] p_evt Event received from the application.
*/
void tuya_ble_handle_bulk_data_evt(tuya_ble_evt_param_t *p_evt);
#ifdef __cplusplus
}
#endif
#endif //TUYA_BLE_BULKDATA_H_
@@ -0,0 +1,194 @@
/**
* \file tuya_ble_data_handler.h
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#ifndef TUYA_BLE_DATA_HANDLER_H_
#define TUYA_BLE_DATA_HANDLER_H_
#include "tuya_ble_stdlib.h"
#include "tuya_ble_internal_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#define FRM_QRY_DEV_INFO_REQ 0x0000 //APP->BLE
#define FRM_QRY_DEV_INFO_RESP 0x0000 //BLE->APP
#define PAIR_REQ 0x0001 //APP->BLE
#define PAIR_RESP 0x0001 //BLE->APP
#define FRM_CMD_SEND 0x0002 //APP->BLE
#define FRM_CMD_RESP 0x0002 //BLE->APP
#define FRM_STATE_QUERY 0x0003 //APP->BLE
#define FRM_STATE_QUERY_RESP 0x0003 //BLE->APP
#define FRM_LOGIN_KEY_REQ 0x0004 //APP->BLE
#define FRM_LOGIN_KEY_RESP 0x0004 //BLE->APP
#define FRM_UNBONDING_REQ 0x0005 //APP->BLE
#define FRM_UNBONDING_RESP 0x0005 //BLE->APP
#define FRM_DEVICE_RESET 0x0006 //APP->BLE
#define FRM_DEVICE_RESET_RESP 0x0006 //BLE->APP
#define FRM_OTA_START_REQ 0x000C //APP->BLE
#define FRM_OTA_START_RESP 0x000C //BLE->APP
#define FRM_OTA_FILE_INFOR_REQ 0x000D //APP->BLE
#define FRM_OTA_FILE_INFOR_RESP 0x000D //BLE->APP
#define FRM_OTA_FILE_OFFSET_REQ 0x000E //APP->BLE
#define FRM_OTA_FILE_OFFSET_RESP 0x000E //BLE->APP
#define FRM_OTA_DATA_REQ 0x000F //APP->BLE
#define FRM_OTA_DATA_RESP 0x000F //BLE->APP
#define FRM_OTA_END_REQ 0x0010 //APP->BLE
#define FRM_OTA_END_RESP 0x0010 //BLE->APP
#define FRM_FACTORY_TEST_CMD 0x0012 //APP->BLE
#define FRM_FACTORY_TEST_RESP 0x0012 //BLE->APP
#define FRM_ANOMALY_UNBONDING_REQ 0x0014 //APP->BLE
#define FRM_ANOMALY_UNBONDING_RESP 0x0014 //BLE->APP
#define FRM_AUTHENTICATE_PHASE_1_REQ 0x0015 //APP->BLE
#define FRM_AUTHENTICATE_PHASE_1_RESP 0x0015 //BLE->APP
#define FRM_AUTHENTICATE_PHASE_2_REQ 0x0016 //APP->BLE
#define FRM_AUTHENTICATE_PHASE_2_RESP 0x0016 //BLE->APP
#define FRM_AUTHENTICATE_PHASE_3_REQ 0x0017 //APP->BLE
#define FRM_AUTHENTICATE_PHASE_3_RESP 0x0017 //BLE->APP
#define FRM_ANOMALY_UNBONDING_REQ 0x0014 //APP->BLE
#define FRM_ANOMALY_UNBONDING_RESP 0x0014 //BLE->APP
#define FRM_NET_CONFIG_INFO_REQ 0x0021 //APP->BLE
#define FRM_NET_CONFIG_INFO_RESP 0x0021 //BLE->APP
#define FRM_NET_CONFIG_RESPONSE_REPORT_REQ 0x0022 //APP->BLE
#define FRM_NET_CONFIG_RESPONSE_REPORT_RESP 0x0022 //BLE->APP
#define FRM_DATA_PASSTHROUGH_REQ 0x0023 //APP<->BLE
#define FRM_DP_DATA_WRITE_REQ 0x0027 //APP->BLE
#define FRM_DP_DATA_WRITE_RESP 0x0027 //BLE->APP
#define FRM_STAT_REPORT 0x8001 //BLE->APP
#define FRM_STAT_REPORT_RESP 0x8001 //APP->BLE
#define FRM_STAT_WITH_TIME_REPORT 0x8003 //BLE->APP
#define FRM_STAT_WITH_TIME_REPORT_RESP 0x8003 //APP->BLE
#define FRM_DATA_WITH_FLAG_REPORT 0x8004 //BLE->APP
#define FRM_DATA_WITH_FLAG_REPORT_RESP 0x8004 //APP->BLE
#define FRM_DATA_WITH_FLAG_AND_TIME_REPORT 0x8005 //BLE->APP
#define FRM_DATA_WITH_FLAG_AND_TIME_REPORT_RESP 0x8005 //APP->BLE
#define FRM_DP_DATA_SEND_REQ 0x8006 //BLE->APP
#define FRM_DP_DATA_SEND_RESP 0x8006 //APP->BLE
#define FRM_DP_DATA_WITH_TIME_SEND_REQ 0x8007 //BLE->APP
#define FRM_DP_DATA_WITH_TIME_SEND_RESP 0x8007 //APP->BLE
#define FRM_WEATHER_DATA_REQUEST 0x8017 //BLE->APP
#define FRM_WEATHER_DATA_REQUEST_RESP 0x8017 //APP->BLE
#define FRM_WEATHER_DATA_RECEIVED 0x8018 //APP->BLE
#define FRM_WEATHER_DATA_RECEIVED_RESP 0x8018 //BLE->APP
#define FRM_GET_UNIX_TIME_MS_REQ 0x8010 //BLE->APP
#define FRM_GET_UNIX_TIME_MS_RESP 0x8010 //APP->BLE
#define FRM_GET_UNIX_TIME_CHAR_MS_REQ 0x8011 //BLE->APP
#define FRM_GET_UNIX_TIME_CHAR_MS_RESP 0x8011 //APP->BLE
#define FRM_GET_UNIX_TIME_CHAR_DATE_REQ 0x8012 //BLE->APP
#define FRM_GET_UNIX_TIME_CHAR_DATE_RESP 0x8012 //APP->BLE
#define FRM_GET_APP_LOCAL_TIME_REQ 0x8013 //BLE->APP
#define FRM_GET_APP_LOCAL_TIME_RESP 0x8013 //APP->BLE
#define FRM_GET_UNIX_TIME_WITH_DST_REQ 0x8014 //BLE->APP [timestamp + timezone + daylight saving time]
#define FRM_GET_UNIX_TIME_WITH_DST_RESP 0x8014 //APP->BLE [timestamp + timezone + daylight saving time]
typedef enum {
TUYA_BLE_OTA_STATUS_NONE,
TUYA_BLE_OTA_STATUS_START,
TUYA_BLE_OTA_STATUS_FILE_INFO,
TUYA_BLE_OTA_STATUS_FILE_OFFSET,
TUYA_BLE_OTA_STATUS_FILE_DATA,
TUYA_BLE_OTA_STATUS_FILE_END,
TUYA_BLE_OTA_STATUS_MAX,
} tuya_ble_ota_status_t;
typedef struct {
uint32_t send_len;
uint8_t *send_data;
uint32_t encrypt_data_buf_len;
uint8_t *encrypt_data_buf;
} tuya_ble_r_air_send_packet;
typedef struct {
uint32_t recv_len;
uint32_t recv_len_max;
uint8_t *recv_data;
uint32_t decrypt_buf_len;
uint8_t *de_encrypt_buf;
} tuya_ble_r_air_recv_packet;
void tuya_ble_air_recv_packet_free(void);
void tuya_ble_set_device_version(uint32_t firmware_version, uint32_t hardware_version);
void tuya_ble_set_external_mcu_version(uint32_t firmware_version, uint32_t hardware_version);
uint8_t tuya_ble_commData_send(uint16_t cmd, uint32_t ack_sn, uint8_t *data, uint16_t len, uint8_t encryption_mode);
uint8_t tuya_ble_send(uint16_t cmd, uint32_t ack_sn, uint8_t *data, uint16_t len);
void tuya_ble_evt_process(uint16_t cmd, uint8_t *recv_data, uint32_t recv_len);
void tuya_ble_reset_ble_sn(void);
void tuya_ble_commonData_rx_proc(uint8_t *buf, uint16_t len);
void tuya_ble_pair_rand_clear(void);
uint8_t tuya_ble_pair_rand_valid_get(void);
uint32_t tuya_ble_send_packet_data_length_get(void);
void tuya_ble_device_unbond(void);
#if (TUYA_BLE_SECURE_CONNECTION_TYPE==TUYA_BLE_SECURE_CONNECTION_WITH_AUTH_KEY_ADVANCED_ENCRYPTION)
void tuya_ble_auth_data_reset(void);
#endif
#ifdef __cplusplus
}
#endif
#endif // TUYA_BLE_COMMDATA_HANDLER_H_
@@ -0,0 +1,159 @@
/**
* \file tuya_ble_event.h
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#ifndef TUYA_BLE_EVENT_H_
#define TUYA_BLE_EVENT_H_
#include "tuya_ble_stdlib.h"
#include "tuya_ble_type.h"
#ifdef __cplusplus
extern "C" {
#endif
#if (!TUYA_BLE_USE_OS)
#define TUYA_BLE_EVT_MAX_NUM MAX_NUMBER_OF_TUYA_MESSAGE
#define TUYA_BLE_EVT_SIZE 52 //64
enum {
TUYA_BLE_EVT_SEND_SUCCESS = 0,
TUYA_BLE_EVT_SEND_NO_MEMORY = 1,
TUYA_BLE_EVT_SEND_FAIL = 2,
};
#define TUYA_BLE_ERROR_HANDLER(ERR_CODE)
#define TUYA_BLE_ERROR_CHECK(ERR_CODE)
#define TUYA_BLE_ERROR_CHECK_BOOL(BOOLEAN_VALUE)
#define CEIL_DIV(A, B) \
(((A) + (B) - 1) / (B))
/**@brief Compute number of bytes required to hold the scheduler buffer.
*
* @param[in] EVENT_SIZE Maximum size of events to be passed through the scheduler.
* @param[in] QUEUE_SIZE Number of entries in scheduler queue (i.e. the maximum number of events
* that can be scheduled for execution).
*
* @return Required scheduler buffer size (in bytes).
*/
#define TUYA_BLE_SCHED_BUF_SIZE(EVENT_SIZE, QUEUE_SIZE) \
((EVENT_SIZE) * ((QUEUE_SIZE) + 1))
/**@brief Macro for initializing the event scheduler.
*
* @details It will also handle dimensioning and allocation of the memory buffer required by the
* scheduler, making sure the buffer is correctly aligned.
*
* @param[in] EVENT_SIZE Maximum size of events to be passed through the scheduler.
* @param[in] QUEUE_SIZE Number of entries in scheduler queue (i.e. the maximum number of events
* that can be scheduled for execution).
*
* @note Since this macro allocates a buffer, it must only be called once (it is OK to call it
* several times as long as it is from the same location, e.g. to do a reinitialization).
*/
#define TUYA_BLE_SCHED_INIT(EVENT_SIZE, QUEUE_SIZE) \
do \
{ \
static uint32_t TUYA_BLE_SCHED_BUF[CEIL_DIV(TUYA_BLE_SCHED_BUF_SIZE((EVENT_SIZE), (QUEUE_SIZE)), \
sizeof(uint32_t))]; \
uint32_t ERR_CODE = tuya_ble_sched_init((EVENT_SIZE), (QUEUE_SIZE), TUYA_BLE_SCHED_BUF); \
TUYA_BLE_ERROR_CHECK(ERR_CODE); \
} while (0)
/**@brief Function for initializing the Scheduler.
*
* @details It must be called before entering the main loop.
*
* @param[in] max_event_size Maximum size of events to be passed through the scheduler.
* @param[in] queue_size Number of entries in scheduler queue (i.e. the maximum number of
* events that can be scheduled for execution).
* @param[in] p_evt_buffer Pointer to memory buffer for holding the scheduler queue. It must
* be dimensioned using the APP_SCHED_BUFFER_SIZE() macro. The buffer
* must be aligned to a 4 byte boundary.
*
* @note Normally initialization should be done using the TUYA_SCHED_INIT() macro, as that will both
* allocate the scheduler buffer, and also align the buffer correctly.
*
* @retval NRF_SUCCESS Successful initialization.
* @retval NRF_ERROR_INVALID_PARAM Invalid parameter (buffer not aligned to a 4 byte
* boundary).
*/
//uint32_t tuya_ble_sched_init(uint16_t max_event_size, uint16_t queue_size, void * p_evt_buffer);
/**@brief Function for executing all scheduled events.
*
* @details This function must be called from within the main loop. It will execute all events
* scheduled since the last time it was called.
*/
void tuya_sched_execute(void);
/**@brief Function for scheduling an event.
*
* @details Puts an event into the event queue.
*
* @param[in] p_event_data Pointer to event data to be scheduled.
* @param[in] event_size Size of event data to be scheduled.
* @param[in] handler Event handler to receive the event.
*
* @return NRF_SUCCESS on success, otherwise an error code.
*/
//tuya_ble_status_t tuya_ble_sched_event_put(void const * p_event_data, uint16_t event_data_size);
/**@brief Function for getting the current amount of free space in the queue.
*
* @details The real amount of free space may be less if entries are being added from an interrupt.
* To get the sxact value, this function should be called from the critical section.
*
* @return Amount of free space in the queue.
*/
uint16_t tuya_ble_sched_queue_size_get(void);
uint16_t tuya_ble_sched_queue_space_get(void);
uint16_t tuya_ble_sched_queue_events_get(void);
void tuya_ble_event_queue_init(void);
tuya_ble_status_t tuya_ble_message_send(tuya_ble_evt_param_t *evt);
#endif
#ifdef __cplusplus
}
#endif
#endif //
@@ -0,0 +1,221 @@
/**
* \file tuya_ble_feature_weather.h
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#ifndef TUYA_BLE_FEATURE_WEATHER_H_
#define TUYA_BLE_FEATURE_WEATHER_H_
#include "tuya_ble_stdlib.h"
#include "tuya_ble_type.h"
/**@brief Total number of weather parameters currently supported. */
#define SUPPORT_WEATHER_KEY_TYPE_MAX_NUMS ( 25 )
/**@brief Weather key type. */
typedef enum {
WKT_TEMP = (1 << 0), /**< temperature. */
WKT_THIHG = (1 << 1), /**< high temperature. */
WKT_TLOW = (1 << 2), /**< low temperature. */
WKT_HUMIDITY = (1 << 3), /**< humidity. */
WKT_CONDITION = (1 << 4), /**< weather condition. */
WKT_PRESSURE = (1 << 5), /**< pressure. */
WKT_REALFEEL = (1 << 6), /**< sendible temperature. */
WKT_UVI = (1 << 7), /**< uvi. */
WKT_SUNRISE = (1 << 8), /**< sunrise. */
WKT_SUNSET = (1 << 9), /**< sunset. */
WKT_UNIX = (1 << 10), /**< unix time, Use with sunrise and sunset. */
WKT_LOCAL = (1 << 11), /**< local time, Use with sunrise and sunset. */
WKT_WINDSPEED = (1 << 12), /**< wind speed. */
WKT_WINDDIR = (1 << 13), /**< wind direction. */
WKT_WINDLEVEL = (1 << 14), /**< wind speed scale/level. */
WKT_AQI = (1 << 15), /**< aqi. */
WKT_TIPS = (1 << 16), /**< tips. */
WKT_RANK = (1 << 17), /**< Detailed AQI status and national ranking. */
WKT_PM10 = (1 << 18), /**< pm10. */
WKT_PM25 = (1 << 19), /**< pm2.5. */
WKT_O3 = (1 << 20), /**< o3. */
WKT_NO2 = (1 << 21), /**< no2. */
WKT_CO = (1 << 22), /**< co. */
WKT_SO2 = (1 << 23), /**< so2. */
WKT_CONDITIONNUM = (1 << 24), /**< weather condition mapping id. */
WKT_COMBINE_BITMAP_MAXVAL = (1 << SUPPORT_WEATHER_KEY_TYPE_MAX_NUMS),
} tuya_ble_weather_key_type_t;
/**@brief Weather value type. */
typedef enum {
WVT_INTEGER = 0,
WVT_STRING,
} tuya_ble_weather_value_type_t;
/**@brief Weather location type. */
typedef enum {
WLT_PAIR_NETWORK_LOCATION = 1, /**< Pair network location. */
WLT_APP_CURRENT_LOCATION, /**< Mobile phone current location. */
WLT_CUSTOM_LOCATION, /**< The current sdk version unsupport. */
WLT_MAX,
} tuya_ble_weather_location_type_t;
/**@brief Weather data object structure.
*
*/
typedef struct {
uint8_t n_day; /**< which day. */
tuya_ble_weather_key_type_t key_type; /**< weather key type. */
tuya_ble_weather_value_type_t val_type; /**< weather value type. */
uint8_t value_len; /**< weather value length. */
char vaule[]; /**< weather values. */
} tuya_ble_wd_object_t;
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Function for request weather data. Default request current location of mobile phone
*
* @note Example1: request temperatur & humidity and two days, called: tuya_ble_feature_weather_data_request((WKT_TEMP | WKT_HUMIDITY), 2);
* Example2: request sunrise data&time and ont day, called: tuya_ble_feature_weather_data_request((WKT_SUNRISE | WKT_LOCAL), 1);
* Example3: request highest temperature and seven days, called: tuya_ble_feature_weather_data_request((WKT_THIHG), 7);
* In addition, request sunrise/sunset must be matched with WKT_UNIX/WKT_LOCAL, otherwise the received data is unix time
*
* @param[in] combine_type Request combine types. For details, see the enum of tuya_ble_weather_key_type_t
* @param[in] n_days Request forecast days, rang from [1-7]; 1-means only today, 2-means today+tomorrow ...
*
* @retval TUYA_BLE_ERR_INVALID_PARAM The provided Parameters are not valid.
* @retval TUYA_BLE_ERR_NO_MEM If no memory is available to accept the operation.
* @retval TUYA_BLE_ERR_INTERNAL If weather request message send failed.
* @retval TUYA_BLE_SUCCESS Successful.
*
* */
extern tuya_ble_status_t tuya_ble_feature_weather_data_request(uint32_t combine_type, uint8_t n_days);
/**
* @brief Function for request weather data with appoint location.
*
* @param[in] location_type Request location types. For details, see the enum of tuya_ble_weather_location_type_t.
* @param[in] combine_type Request combine types. For details, see the enum of tuya_ble_weather_key_type_t
* @param[in] n_days Request forecast days, rang from [1-7]; 1-means only today, 2-means today+tomorrow ...
*
* @retval TUYA_BLE_ERR_INVALID_PARAM The provided Parameters are not valid.
* @retval TUYA_BLE_ERR_NO_MEM If no memory is available to accept the operation.
* @retval TUYA_BLE_ERR_INTERNAL If weather request message send failed.
* @retval TUYA_BLE_SUCCESS Successful.
*
* */
extern tuya_ble_status_t tuya_ble_feature_weather_data_request_with_location(tuya_ble_weather_location_type_t location_type, uint32_t combine_type, uint8_t n_days);
/**
* @brief Function for application parse received weather datas, In tuya_cb_handler() function
* add TUYA_BLE_CB_EVT_WEATHER_DATA_REQ_RESPONSE and TUYA_BLE_CB_EVT_WEATHER_DATA_RECEIVED callback
* event and process it. For example:
*
case TUYA_BLE_CB_EVT_WEATHER_DATA_REQ_RESPONSE:
TUYA_APP_LOG_INFO("received weather data request response result code =%d",event->weather_req_response_data.status);
break;
case TUYA_BLE_CB_EVT_WEATHER_DATA_RECEIVED:
tuya_ble_wd_object_t *object;
uint16_t object_len = 0;
for (;;) {
object = (tuya_ble_wd_object_t *)(event->weather_received_data.p_data + object_len);
TUYA_APP_LOG_DEBUG("recvived weather data, n_days=[%d] key=[0x%08x] val_type=[%d] val_len=[%d]", \
object->n_day, object->key_type, object->val_type, object->value_len);
TUYA_APP_LOG_HEXDUMP_DEBUG("vaule :", (uint8_t *)object->vaule, object->value_len);
// TODO .. YOUR JOBS
object_len += (sizeof(tuya_ble_wd_object_t) + object->value_len);
if (object_len >= event->weather_received_data.data_len)
break;
}
break;
* */
/**
* @brief Function for convert weather enum type to string
*
* @note For example input convert type=WKT_TEMP, output key "w.temp"
*
* @param[in] type Convert type
* @param[out] key The ponit of weather key string
*
* @retval TUYA_BLE_ERR_INVALID_PARAM The provided Parameters are not valid.
* @retval TUYA_BLE_ERR_NOT_FOUND No corresponding type was found.
* @retval TUYA_BLE_SUCCESS Successful.
*
* */
extern tuya_ble_status_t tuya_ble_feature_weather_key_enum_type_to_string(tuya_ble_weather_key_type_t type, char *key);
/**
* @brief Function for handler weather data request event
*
* @details Internal use of tuya ble sdk
*
* @param[in] evt For details, see the struct of tuya_ble_evt_param_t
*
* */
extern void tuya_ble_handle_weather_data_request_evt(tuya_ble_evt_param_t *evt);
/**
* @brief Function for handler weather data request response/ack
*
* @details Internal use of tuya ble sdk
*
* @param[in] recv_data The point of recvived response data
* @param[in] recv_len The numbers of data
*
* */
extern void tuya_ble_handle_weather_data_request_response(uint8_t *recv_data, uint16_t recv_len);
/**
* @brief Function for handler weather data received
*
* @details Internal use of tuya ble sdk
*
* @param[in] recv_data The point of recvived weather data
* @param[in] recv_len The numbers of data
*
* */
extern void tuya_ble_handle_weather_data_received(uint8_t *recv_data, uint16_t recv_len);
#ifdef __cplusplus
}
#endif
#endif /* TUYA_BLE_FEATURE_WEATHER_H_ */
@@ -0,0 +1,49 @@
/**
* \file tuya_ble_gatt_send_queue.h
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#ifndef TUYA_BLE_GATT_SEND_QUEUE_H_
#define TUYA_BLE_GATT_SEND_QUEUE_H_
#include "tuya_ble_stdlib.h"
#include "tuya_ble_type.h"
#include "tuya_ble_queue.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
uint8_t *buf;
uint8_t size;
} tuya_ble_gatt_send_data_t;
void tuya_ble_gatt_send_queue_init(void);
void tuya_ble_gatt_send_data_handle(void *evt);
tuya_ble_status_t tuya_ble_gatt_send_data_enqueue(uint8_t *p_data, uint8_t data_len);
#ifdef __cplusplus
}
#endif
#endif //TUYA_BLE_GATT_SEND_QUEUE_H_
@@ -0,0 +1,114 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef TUYA_HEAP_H__
#define TUYA_HEAP_H__
#include "tuya_ble_stdlib.h"
#ifdef __cplusplus
extern "C" {
#endif
#if (TUYA_BLE_USE_PLATFORM_MEMORY_HEAP==0)
#define portBYTE_ALIGNMENT 4
#if portBYTE_ALIGNMENT == 32
#define portBYTE_ALIGNMENT_MASK ( 0x001f )
#endif
#if portBYTE_ALIGNMENT == 16
#define portBYTE_ALIGNMENT_MASK ( 0x000f )
#endif
#if portBYTE_ALIGNMENT == 8
#define portBYTE_ALIGNMENT_MASK ( 0x0007 )
#endif
#if portBYTE_ALIGNMENT == 4
#define portBYTE_ALIGNMENT_MASK ( 0x0003 )
#endif
#if portBYTE_ALIGNMENT == 2
#define portBYTE_ALIGNMENT_MASK ( 0x0001 )
#endif
#if portBYTE_ALIGNMENT == 1
#define portBYTE_ALIGNMENT_MASK ( 0x0000 )
#endif
#ifndef portBYTE_ALIGNMENT_MASK
#error "Invalid portBYTE_ALIGNMENT definition"
#endif
#ifndef tuyaASSERT
#define tuyaASSERT( x )
#define tuyaASSERT_DEFINED 0
#else
#define tuyaASSERT_DEFINED 1
#endif
#ifndef tuyaCOVERAGE_TEST_MARKER
#define tuyaCOVERAGE_TEST_MARKER()
#endif
#ifndef tuya_traceMALLOC
#define tuya_traceMALLOC( pvAddress, uiSize )
#endif
#ifndef tuya_traceFREE
#define tuya_traceFREE( pvAddress, uiSize )
#endif
void *pvTuyaPortMalloc(uint32_t xWantedSize);
void vTuyaPortFree(void *pv);
uint32_t xTuyaPortGetFreeHeapSize(void);
uint32_t xTuyaPortGetMinimumEverFreeHeapSize(void);
#endif
#ifdef __cplusplus
}
#endif
#endif //TUYA_HEAP_H__
/** @} */
@@ -0,0 +1,150 @@
/**
* \file tuya_ble_internal_config.h
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#ifndef TUYA_BLE_INTERNAL_CONFIG_H__
#define TUYA_BLE_INTERNAL_CONFIG_H__
#include "tuya_ble_config.h"
#include "tuya_ble_port.h"
#define MAX_NUMBER_OF_TUYA_MESSAGE 16 //!< tuya ble message queue size
//BLE Communication protocol version v4.2
#define TUYA_BLE_PROTOCOL_VERSION_HIGN 0x04
#define TUYA_BLE_PROTOCOL_VERSION_LOW 0x02
#define TUYA_BLE_DP_WRITE_CURRENT_VERSION 0
#if (TUYA_BLE_PROTOCOL_VERSION_HIGN>=4)
#define TUYA_BLE_AIR_FRAME_MAX 1536
#define TUYA_UART_RECEIVE_MAX_DP_DATA_LEN (512+4)
#define TUYA_UART_RECEIVE_MAX_DP_BUFFER_DATA_LEN (512+4)
#define TUYA_BLE_RECEIVE_MAX_DP_DATA_LEN (512+4)
#define TUYA_BLE_SEND_MAX_DP_DATA_LEN TUYA_BLE_RECEIVE_MAX_DP_DATA_LEN
#define TUYA_BLE_SEND_MAX_DATA_LEN (((TUYA_BLE_AIR_FRAME_MAX-17)/16)*16-14)
#define TUYA_BLE_RECEIVE_MAX_DATA_LEN TUYA_BLE_SEND_MAX_DATA_LEN
#else
#define TUYA_BLE_ADVANCED_ENCRYPTION_DEVICE 0
#define TUYA_BLE_AIR_FRAME_MAX 1024
#define TUYA_UART_RECEIVE_MAX_DP_DATA_LEN (255+4)
#define TUYA_UART_RECEIVE_MAX_DP_BUFFER_DATA_LEN (255+4)
#define TUYA_BLE_RECEIVE_MAX_DP_DATA_LEN (255+3)
#define TUYA_BLE_SEND_MAX_DP_DATA_LEN TUYA_BLE_RECEIVE_MAX_DP_DATA_LEN
#define TUYA_BLE_REPORT_MAX_DP_DATA_LEN TUYA_BLE_RECEIVE_MAX_DP_DATA_LEN
#define TUYA_BLE_TRANSMISSION_MAX_DATA_LEN (TUYA_BLE_AIR_FRAME_MAX-29)
#define TUYA_BLE_SEND_MAX_DATA_LEN TUYA_BLE_TRANSMISSION_MAX_DATA_LEN
#define TUYA_BLE_RECEIVE_MAX_DATA_LEN TUYA_BLE_SEND_MAX_DATA_LEN
#endif
#define TUYA_BLE_GATT_SEND_DATA_QUEUE_SIZE (MAX_NUMBER_OF_TUYA_MESSAGE*3)
#if (TUYA_BLE_USE_PLATFORM_MEMORY_HEAP==0)
/**
* MACRO for memory management
*/
#define TUYA_BLE_TOTAL_HEAP_SIZE 5120
#if (TUYA_BLE_TOTAL_HEAP_SIZE<5120)
#define TUYA_BLE_BULK_DATA_MAX_READ_BLOCK_SIZE 512
#else
#define TUYA_BLE_BULK_DATA_MAX_READ_BLOCK_SIZE 1024
#endif
#else
#define TUYA_BLE_BULK_DATA_MAX_READ_BLOCK_SIZE 512
#endif
#ifndef TUYA_BLE_MAX_CALLBACKS
#define TUYA_BLE_MAX_CALLBACKS 1
#endif
#define TUYA_BLE_AUTH_FLASH_ADDR (TUYA_NV_START_ADDR)
#define TUYA_BLE_AUTH_FLASH_BACKUP_ADDR (TUYA_NV_START_ADDR+TUYA_NV_ERASE_MIN_SIZE)
#define TUYA_BLE_SYS_FLASH_ADDR (TUYA_NV_START_ADDR+TUYA_NV_ERASE_MIN_SIZE*2)
#define TUYA_BLE_SYS_FLASH_BACKUP_ADDR (TUYA_NV_START_ADDR+TUYA_NV_ERASE_MIN_SIZE*3)
/**
* 1 - device register from ble 0 - from others
* @note:
*/
#define TUYA_BLE_DEVICE_REGISTER_FROM_BLE (TUYA_BLE_DEVICE_COMMUNICATION_ABILITY&TUYA_BLE_DEVICE_COMMUNICATION_ABILITY_REGISTER_FROM_BLE)
#define TUYA_BLE_DEVICE_AUTH_DATA_STORE TUYA_BLE_DEVICE_AUTH_SELF_MANAGEMENT
/**
* if 1 ,tuya ble sdk authorization storage into extern medium, For example security chip
*/
#define TUYA_BLE_DEVICE_AUTH_DATA_STORE_EXT_MEDIUM 0
/**
* if 1 ,used ble dongle for product test, the transmit datas will encryption
*/
#define TUYA_BLE_PROD_TEST_SUPPORT_ENCRYPTION 0
/**
* if >=1, the product support oem, when execute prod test will write in pid and json config file
*
* Noticed!!! if enable the macro, need to realization 'tuya_ble_status_t tuya_ble_prod_storage_oem_info(uint8_t *para,uint16_t len)'
* function yourself at the custom_app_product_test.c
*/
#define TUYA_BLE_PROD_SUPPORT_OEM_TYPE TUYA_BLE_PROD_OEM_TYPE_NONE
#if (TUYA_BLE_SYS_FLASH_BACKUP_ADDR>=(TUYA_NV_AREA_SIZE+TUYA_NV_START_ADDR))
#error "Storage Memory overflow!"
#endif
#endif
@@ -0,0 +1,142 @@
/**
* \file tuya_ble_log.h
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#ifndef TUYA_BLE_LOG_H__
#define TUYA_BLE_LOG_H__
#include "tuya_ble_stdlib.h"
#include "tuya_ble_internal_config.h"
#include "tuya_ble_log_internal.h"
#if TUYA_BLE_LOG_ENABLE
#ifndef TUYA_BLE_LOG_LEVEL
#define TUYA_BLE_LOG_LEVEL TUYA_BLE_LOG_LEVEL_DEBUG
#endif
#ifndef TUYA_BLE_LOG_COLORS_ENABLE
#define TUYA_BLE_LOG_COLORS_ENABLE 0
#endif
#define TUYA_BLE_LOG_ERROR(...) TUYA_BLE_LOG_INTERNAL_ERROR(__VA_ARGS__)
#define TUYA_BLE_LOG_WARNING(...) TUYA_BLE_LOG_INTERNAL_WARNING( __VA_ARGS__)
#define TUYA_BLE_LOG_INFO(...) TUYA_BLE_LOG_INTERNAL_INFO( __VA_ARGS__)
#define TUYA_BLE_LOG_DEBUG(...) TUYA_BLE_LOG_INTERNAL_DEBUG( __VA_ARGS__)
#define TUYA_BLE_LOG_HEXDUMP_ERROR(...) TUYA_BLE_LOG_INTERNAL_HEXDUMP_ERROR(__VA_ARGS__)
#define TUYA_BLE_LOG_HEXDUMP_WARNING(...) TUYA_BLE_LOG_INTERNAL_HEXDUMP_WARNING( __VA_ARGS__)
#define TUYA_BLE_LOG_HEXDUMP_INFO(...) TUYA_BLE_LOG_INTERNAL_HEXDUMP_INFO( __VA_ARGS__)
#define TUYA_BLE_LOG_HEXDUMP_DEBUG(...) TUYA_BLE_LOG_INTERNAL_HEXDUMP_DEBUG( __VA_ARGS__)
#else
#define TUYA_BLE_LOG_ERROR(...)
#define TUYA_BLE_LOG_WARNING(...)
#define TUYA_BLE_LOG_INFO(...)
#define TUYA_BLE_LOG_DEBUG(...)
#define TUYA_BLE_LOG_HEXDUMP_ERROR(...)
#define TUYA_BLE_LOG_HEXDUMP_WARNING(...)
#define TUYA_BLE_LOG_HEXDUMP_INFO(...)
#define TUYA_BLE_LOG_HEXDUMP_DEBUG(...)
#endif //
#if TUYA_APP_LOG_ENABLE
#ifndef TUYA_APP_LOG_LEVEL
#define TUYA_APP_LOG_LEVEL TUYA_APP_LOG_LEVEL_DEBUG
#endif
#ifndef TUYA_APP_LOG_COLORS_ENABLE
#define TUYA_APP_LOG_COLORS_ENABLE 0
#endif
#define TUYA_APP_LOG_ERROR(...) TUYA_APP_LOG_INTERNAL_ERROR(__VA_ARGS__)
#define TUYA_APP_LOG_WARNING(...) TUYA_APP_LOG_INTERNAL_WARNING( __VA_ARGS__)
#define TUYA_APP_LOG_INFO(...) TUYA_APP_LOG_INTERNAL_INFO( __VA_ARGS__)
#define TUYA_APP_LOG_DEBUG(...) TUYA_APP_LOG_INTERNAL_DEBUG( __VA_ARGS__)
#define TUYA_APP_LOG_HEXDUMP_ERROR(...) TUYA_APP_LOG_INTERNAL_HEXDUMP_ERROR(__VA_ARGS__)
#define TUYA_APP_LOG_HEXDUMP_WARNING(...) TUYA_APP_LOG_INTERNAL_HEXDUMP_WARNING( __VA_ARGS__)
#define TUYA_APP_LOG_HEXDUMP_INFO(...) TUYA_APP_LOG_INTERNAL_HEXDUMP_INFO( __VA_ARGS__)
#define TUYA_APP_LOG_HEXDUMP_DEBUG(...) TUYA_APP_LOG_INTERNAL_HEXDUMP_DEBUG( __VA_ARGS__)
#else
#define TUYA_APP_LOG_ERROR(...)
#define TUYA_APP_LOG_WARNING(...)
#define TUYA_APP_LOG_INFO(...)
#define TUYA_APP_LOG_DEBUG(...)
#define TUYA_APP_LOG_HEXDUMP_ERROR(...)
#define TUYA_APP_LOG_HEXDUMP_WARNING(...)
#define TUYA_APP_LOG_HEXDUMP_INFO(...)
#define TUYA_APP_LOG_HEXDUMP_DEBUG(...)
#endif //
#ifdef TUYA_BLE_ASSERT
#define TUYA_BLE_ERR_HANDLER(ERR_CODE) \
do \
{ \
TUYA_BLE_LOG_ERROR("Error code 0x%04X <%d>. %s:%d\n", ERR_CODE, ERR_CODE, (uint32_t)__FILE__, __LINE__); \
} while (0)
#define TUYA_BLE_ERR_CHECK(ERR_CODE) \
do \
{ \
const uint32_t LOCAL_ERR_CODE = (ERR_CODE); \
if (LOCAL_ERR_CODE != 0) \
{ \
TUYA_BLE_ERR_HANDLER(LOCAL_ERR_CODE); \
} \
} while (0)
#define TUYA_BLE_ERR_TEST(ERR_CODE, EXPECT) \
do \
{ \
const uint32_t LOCAL_ERR_CODE = (ERR_CODE); \
if (LOCAL_ERR_CODE != (EXPECT)) \
{ \
TUYA_BLE_ERR_HANDLER(LOCAL_ERR_CODE); \
} \
} while (0)
#else //
#define TUYA_BLE_ERR_CHECK(ERR_CODE)
#define TUYA_BLE_ERR_TEST(ERR_CODE, EXPECT)
#endif //
#endif // TUYA_BLE_LOG_H__
@@ -0,0 +1,288 @@
/**
* \file tuya_ble_log_internal.h
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#ifndef TUYA_BLE_LOG_INTERNAL__H__
#define TUYA_BLE_LOG_INTERNAL__H__
#include "tuya_ble_port.h"
#include "tuya_ble_internal_config.h"
#if !defined(TUYA_BLE_PRINTF)
#error "Not defined printf function."
#elif !defined(TUYA_BLE_HEXDUMP)
#error "Not defined hexdump function."
#endif
#ifndef TUYA_BLE_LOG_COLORS_ENABLE
#define TUYA_BLE_LOG_COLORS_ENABLE 0
#endif
#ifndef TUYA_BLE_LOG_MODULE_NAME
#define TUYA_BLE_LOG_MODULE_NAME "TUYA_BLE"
#endif
#if TUYA_BLE_LOG_COLORS_ENABLE
#define TUYA_BLE_LOG_COLOR_DEFAULT "\x1B[0m"
#define TUYA_BLE_LOG_COLOR_BLACK "\x1B[1;30m"
#define TUYA_BLE_LOG_COLOR_RED "\x1B[1;31m"
#define TUYA_BLE_LOG_COLOR_GREEN "\x1B[1;32m"
#define TUYA_BLE_LOG_COLOR_YELLOW "\x1B[1;33m"
#define TUYA_BLE_LOG_COLOR_BLUE "\x1B[1;34m"
#define TUYA_BLE_LOG_COLOR_MAGENTA "\x1B[1;35m"
#define TUYA_BLE_LOG_COLOR_CYAN "\x1B[1;36m"
#define TUYA_BLE_LOG_COLOR_WHITE "\x1B[1;37m"
#else
#define TUYA_BLE_LOG_COLOR_DEFAULT
#define TUYA_BLE_LOG_COLOR_BLACK
#define TUYA_BLE_LOG_COLOR_RED
#define TUYA_BLE_LOG_COLOR_GREEN
#define TUYA_BLE_LOG_COLOR_YELLOW
#define TUYA_BLE_LOG_COLOR_BLUE
#define TUYA_BLE_LOG_COLOR_MAGENTA
#define TUYA_BLE_LOG_COLOR_CYAN
#define TUYA_BLE_LOG_COLOR_WHITE
#endif
#define TUYA_BLE_LOG_ERROR_COLOR TUYA_BLE_LOG_COLOR_RED
#define TUYA_BLE_LOG_WARNING_COLOR TUYA_BLE_LOG_COLOR_YELLOW
#define TUYA_BLE_LOG_INFO_COLOR TUYA_BLE_LOG_COLOR_DEFAULT
#define TUYA_BLE_LOG_DEBUG_COLOR TUYA_BLE_LOG_COLOR_GREEN
#define TUYA_BLE_LOG_DEFAULT_COLOR TUYA_BLE_LOG_COLOR_DEFAULT
#define TUYA_BLE_LOG_BREAK ": "
//#define TUYA_BLE_LOG_CRLF "\r\n"
#define TUYA_BLE_LOG_CRLF ""
#define TUYA_BLE_ERROR_PREFIX TUYA_BLE_LOG_ERROR_COLOR "[E] " TUYA_BLE_LOG_MODULE_NAME TUYA_BLE_LOG_BREAK
#define TUYA_BLE_WARNING_PREFIX TUYA_BLE_LOG_WARNING_COLOR "[W] " TUYA_BLE_LOG_MODULE_NAME TUYA_BLE_LOG_BREAK
#define TUYA_BLE_INFO_PREFIX TUYA_BLE_LOG_INFO_COLOR "[I] " TUYA_BLE_LOG_MODULE_NAME TUYA_BLE_LOG_BREAK
#define TUYA_BLE_DEBUG_PREFIX TUYA_BLE_LOG_DEBUG_COLOR "[D] " TUYA_BLE_LOG_MODULE_NAME TUYA_BLE_LOG_BREAK
#define TUYA_BLE_LOG_INTERNAL_ERROR(_fmt_, ...) \
do { \
if (TUYA_BLE_LOG_LEVEL >= TUYA_BLE_LOG_LEVEL_ERROR) \
{ \
TUYA_BLE_PRINTF(TUYA_BLE_ERROR_PREFIX _fmt_ TUYA_BLE_LOG_DEFAULT_COLOR TUYA_BLE_LOG_CRLF, ##__VA_ARGS__); \
} \
} while(0)
#define TUYA_BLE_LOG_INTERNAL_WARNING(_fmt_, ...) \
do { \
if (TUYA_BLE_LOG_LEVEL >= TUYA_BLE_LOG_LEVEL_WARNING) \
{ \
TUYA_BLE_PRINTF(TUYA_BLE_WARNING_PREFIX _fmt_ TUYA_BLE_LOG_DEFAULT_COLOR TUYA_BLE_LOG_CRLF, ##__VA_ARGS__); \
} \
} while(0)
#define TUYA_BLE_LOG_INTERNAL_INFO(_fmt_, ...) \
do { \
if (TUYA_BLE_LOG_LEVEL >= TUYA_BLE_LOG_LEVEL_INFO) \
{ \
TUYA_BLE_PRINTF(TUYA_BLE_INFO_PREFIX _fmt_ TUYA_BLE_LOG_DEFAULT_COLOR TUYA_BLE_LOG_CRLF, ##__VA_ARGS__); \
} \
} while(0)
#define TUYA_BLE_LOG_INTERNAL_DEBUG(_fmt_, ...) \
do { \
if (TUYA_BLE_LOG_LEVEL >= TUYA_BLE_LOG_LEVEL_DEBUG) \
{ \
TUYA_BLE_PRINTF(TUYA_BLE_DEBUG_PREFIX _fmt_ TUYA_BLE_LOG_DEFAULT_COLOR TUYA_BLE_LOG_CRLF, ##__VA_ARGS__); \
} \
} while(0)
#define TUYA_BLE_LOG_INTERNAL_HEXDUMP_ERROR(_fmt_, p_data, len) \
do { \
if (TUYA_BLE_LOG_LEVEL >= TUYA_BLE_LOG_LEVEL_ERROR) \
{ \
TUYA_BLE_PRINTF(TUYA_BLE_ERROR_PREFIX _fmt_ TUYA_BLE_LOG_DEFAULT_COLOR " [len=%d] :" TUYA_BLE_LOG_CRLF,len ); \
TUYA_BLE_HEXDUMP(p_data, len); \
TUYA_BLE_PRINTF(TUYA_BLE_LOG_CRLF); \
} \
} while(0)
#define TUYA_BLE_LOG_INTERNAL_HEXDUMP_WARNING(_fmt_, p_data, len) \
do { \
if (TUYA_BLE_LOG_LEVEL >= TUYA_BLE_LOG_LEVEL_WARNING) \
{ \
TUYA_BLE_PRINTF(TUYA_BLE_WARNING_PREFIX _fmt_ TUYA_BLE_LOG_DEFAULT_COLOR " [len=%d] :" TUYA_BLE_LOG_CRLF,len); \
TUYA_BLE_HEXDUMP(p_data, len); \
TUYA_BLE_PRINTF(TUYA_BLE_LOG_CRLF); \
} \
} while(0)
#define TUYA_BLE_LOG_INTERNAL_HEXDUMP_INFO(_fmt_, p_data, len) \
do { \
if (TUYA_BLE_LOG_LEVEL >= TUYA_BLE_LOG_LEVEL_INFO) \
{ \
TUYA_BLE_PRINTF(TUYA_BLE_INFO_PREFIX _fmt_ TUYA_BLE_LOG_DEFAULT_COLOR " [len=%d] :" TUYA_BLE_LOG_CRLF,len); \
TUYA_BLE_HEXDUMP(p_data, len); \
TUYA_BLE_PRINTF(TUYA_BLE_LOG_CRLF); \
} \
} while(0)
#define TUYA_BLE_LOG_INTERNAL_HEXDUMP_DEBUG(_fmt_, p_data, len) \
do { \
if (TUYA_BLE_LOG_LEVEL >= TUYA_BLE_LOG_LEVEL_DEBUG) \
{ \
TUYA_BLE_PRINTF(TUYA_BLE_DEBUG_PREFIX _fmt_ TUYA_BLE_LOG_DEFAULT_COLOR " [len=%d] :" TUYA_BLE_LOG_CRLF,len); \
TUYA_BLE_HEXDUMP(p_data, len); \
TUYA_BLE_PRINTF(TUYA_BLE_LOG_CRLF); \
} \
} while(0)
/* TUYA APP LOG */
#ifndef TUYA_APP_LOG_COLORS_ENABLE
#define TUYA_APP_LOG_COLORS_ENABLE 0
#endif
#ifndef TUYA_APP_LOG_MODULE_NAME
#define TUYA_APP_LOG_MODULE_NAME "TUYA_APP"
#endif
#if TUYA_APP_LOG_COLORS_ENABLE
#define TUYA_APP_LOG_COLOR_DEFAULT "\x1B[0m"
#define TUYA_APP_LOG_COLOR_BLACK "\x1B[1;30m"
#define TUYA_APP_LOG_COLOR_RED "\x1B[1;31m"
#define TUYA_APP_LOG_COLOR_GREEN "\x1B[1;32m"
#define TUYA_APP_LOG_COLOR_YELLOW "\x1B[1;33m"
#define TUYA_APP_LOG_COLOR_BLUE "\x1B[1;34m"
#define TUYA_APP_LOG_COLOR_MAGENTA "\x1B[1;35m"
#define TUYA_APP_LOG_COLOR_CYAN "\x1B[1;36m"
#define TUYA_APP_LOG_COLOR_WHITE "\x1B[1;37m"
#else
#define TUYA_APP_LOG_COLOR_DEFAULT
#define TUYA_APP_LOG_COLOR_BLACK
#define TUYA_APP_LOG_COLOR_RED
#define TUYA_APP_LOG_COLOR_GREEN
#define TUYA_APP_LOG_COLOR_YELLOW
#define TUYA_APP_LOG_COLOR_BLUE
#define TUYA_APP_LOG_COLOR_MAGENTA
#define TUYA_APP_LOG_COLOR_CYAN
#define TUYA_APP_LOG_COLOR_WHITE
#endif
#define TUYA_APP_LOG_ERROR_COLOR TUYA_APP_LOG_COLOR_RED
#define TUYA_APP_LOG_WARNING_COLOR TUYA_APP_LOG_COLOR_YELLOW
#define TUYA_APP_LOG_INFO_COLOR TUYA_APP_LOG_COLOR_DEFAULT
#define TUYA_APP_LOG_DEBUG_COLOR TUYA_APP_LOG_COLOR_GREEN
#define TUYA_APP_LOG_DEFAULT_COLOR TUYA_APP_LOG_COLOR_DEFAULT
#define TUYA_APP_LOG_BREAK ": "
//#define TUYA_APP_LOG_CRLF "\r\n"
#define TUYA_APP_LOG_CRLF ""
#define TUYA_APP_ERROR_PREFIX TUYA_APP_LOG_ERROR_COLOR "[E] " TUYA_APP_LOG_MODULE_NAME TUYA_APP_LOG_BREAK
#define TUYA_APP_WARNING_PREFIX TUYA_APP_LOG_WARNING_COLOR "[W] " TUYA_APP_LOG_MODULE_NAME TUYA_APP_LOG_BREAK
#define TUYA_APP_INFO_PREFIX TUYA_APP_LOG_INFO_COLOR "[I] " TUYA_APP_LOG_MODULE_NAME TUYA_APP_LOG_BREAK
#define TUYA_APP_DEBUG_PREFIX TUYA_APP_LOG_DEBUG_COLOR "[D] " TUYA_APP_LOG_MODULE_NAME TUYA_APP_LOG_BREAK
#define TUYA_APP_LOG_INTERNAL_ERROR(_fmt_, ...) \
do { \
if (TUYA_APP_LOG_LEVEL >= TUYA_APP_LOG_LEVEL_ERROR) \
{ \
TUYA_BLE_PRINTF(TUYA_APP_ERROR_PREFIX _fmt_ TUYA_APP_LOG_DEFAULT_COLOR TUYA_APP_LOG_CRLF, ##__VA_ARGS__); \
} \
} while(0)
#define TUYA_APP_LOG_INTERNAL_WARNING(_fmt_, ...) \
do { \
if (TUYA_APP_LOG_LEVEL >= TUYA_APP_LOG_LEVEL_WARNING) \
{ \
TUYA_BLE_PRINTF(TUYA_APP_WARNING_PREFIX _fmt_ TUYA_APP_LOG_DEFAULT_COLOR TUYA_APP_LOG_CRLF, ##__VA_ARGS__); \
} \
} while(0)
#define TUYA_APP_LOG_INTERNAL_INFO(_fmt_, ...) \
do { \
if (TUYA_APP_LOG_LEVEL >= TUYA_APP_LOG_LEVEL_INFO) \
{ \
TUYA_BLE_PRINTF(TUYA_APP_INFO_PREFIX _fmt_ TUYA_APP_LOG_DEFAULT_COLOR TUYA_APP_LOG_CRLF, ##__VA_ARGS__); \
} \
} while(0)
#define TUYA_APP_LOG_INTERNAL_DEBUG(_fmt_, ...) \
do { \
if (TUYA_APP_LOG_LEVEL >= TUYA_APP_LOG_LEVEL_DEBUG) \
{ \
TUYA_BLE_PRINTF(TUYA_APP_DEBUG_PREFIX _fmt_ TUYA_APP_LOG_DEFAULT_COLOR TUYA_APP_LOG_CRLF, ##__VA_ARGS__); \
} \
} while(0)
#define TUYA_APP_LOG_INTERNAL_HEXDUMP_ERROR(_fmt_, p_data, len) \
do { \
if (TUYA_APP_LOG_LEVEL >= TUYA_APP_LOG_LEVEL_ERROR) \
{ \
TUYA_BLE_PRINTF(TUYA_APP_ERROR_PREFIX _fmt_ TUYA_APP_LOG_DEFAULT_COLOR " [len=%d] :" TUYA_APP_LOG_CRLF,len ); \
TUYA_BLE_HEXDUMP(p_data, len); \
TUYA_BLE_PRINTF(TUYA_APP_LOG_CRLF); \
} \
} while(0)
#define TUYA_APP_LOG_INTERNAL_HEXDUMP_WARNING(_fmt_, p_data, len) \
do { \
if (TUYA_APP_LOG_LEVEL >= TUYA_APP_LOG_LEVEL_WARNING) \
{ \
TUYA_BLE_PRINTF(TUYA_APP_WARNING_PREFIX _fmt_ TUYA_APP_LOG_DEFAULT_COLOR " [len=%d] :" TUYA_APP_LOG_CRLF,len); \
TUYA_BLE_HEXDUMP(p_data, len); \
TUYA_BLE_PRINTF(TUYA_APP_LOG_CRLF); \
} \
} while(0)
#define TUYA_APP_LOG_INTERNAL_HEXDUMP_INFO(_fmt_, p_data, len) \
do { \
if (TUYA_APP_LOG_LEVEL >= TUYA_APP_LOG_LEVEL_INFO) \
{ \
TUYA_BLE_PRINTF(TUYA_APP_INFO_PREFIX _fmt_ TUYA_APP_LOG_DEFAULT_COLOR " [len=%d] :" TUYA_APP_LOG_CRLF,len); \
TUYA_BLE_HEXDUMP(p_data, len); \
TUYA_BLE_PRINTF(TUYA_APP_LOG_CRLF); \
} \
} while(0)
#define TUYA_APP_LOG_INTERNAL_HEXDUMP_DEBUG(_fmt_, p_data, len) \
do { \
if (TUYA_APP_LOG_LEVEL >= TUYA_APP_LOG_LEVEL_DEBUG) \
{ \
TUYA_BLE_PRINTF(TUYA_APP_DEBUG_PREFIX _fmt_ TUYA_APP_LOG_DEFAULT_COLOR " [len=%d] :" TUYA_APP_LOG_CRLF,len); \
TUYA_BLE_HEXDUMP(p_data, len); \
TUYA_BLE_PRINTF(TUYA_APP_LOG_CRLF); \
} \
} while(0)
#endif // TUYA_BLE_LOG_INTERNAL__H__
@@ -0,0 +1,78 @@
/**
* \file tuya_ble_main.h
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#ifndef TUYA_BLE_MAIN_H__
#define TUYA_BLE_MAIN_H__
#include "tuya_ble_type.h"
#include "tuya_ble_internal_config.h"
#ifdef __cplusplus
extern "C" {
#endif
extern tuya_ble_parameters_settings_t tuya_ble_current_para;
void tuya_ble_connect_status_set(tuya_ble_connect_status_t status);
tuya_ble_connect_status_t tuya_ble_connect_status_get(void);
#if TUYA_BLE_LINK_LAYER_ENCRYPTION_SUPPORT_ENABLE
void tuya_ble_link_status_set(tuya_ble_link_status_t status);
tuya_ble_link_status_t tuya_ble_link_status_get(void);
#endif
void tuya_ble_event_init(void);
uint8_t tuya_ble_event_send(tuya_ble_evt_param_t *evt);
uint8_t tuya_ble_cb_event_send(tuya_ble_cb_evt_param_t *evt);
uint8_t tuya_ble_get_adv_connect_request_bit_status(void);
void tuya_ble_adv_change(void);
#if (TUYA_BLE_PROTOCOL_VERSION_HIGN >= 3)
void tuya_ble_adv_change_with_connecting_request(void);
#endif
tuya_ble_status_t tuya_ble_inter_event_response(tuya_ble_cb_evt_param_t *param);
void tuya_ble_connect_monitor_timer_init(void);
void tuya_ble_connect_monitor_timer_start(void);
void tuya_ble_connect_monitor_timer_stop(void);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,54 @@
/**
* \file tuya_ble_mem.h
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#ifndef TUYA_BLE_MEM_H__
#define TUYA_BLE_MEM_H__
#include "tuya_ble_type.h"
#ifdef __cplusplus
extern "C" {
#endif
void *tuya_ble_malloc(uint16_t size);
tuya_ble_status_t tuya_ble_free(uint8_t *ptr);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,316 @@
/**
* \file tuya_ble_mutli_tsf_protocol.h
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#ifndef _TUYA_BLE_MUTLI_TSF_PROTOCOL_H
#define _TUYA_BLE_MUTLI_TSF_PROTOCOL_H
#include "tuya_ble_stdlib.h"
#include "tuya_ble_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __MUTLI_TSF_PROTOCOL_GLOBALS
#define __MUTLI_TSF_PROTOCOL_EXT
#else
#define __MUTLI_TSF_PROTOCOL_EXT extern
#endif
/***********************************************************
*************************micro define***********************
***********************************************************/
#define SNGL_PKG_TRSFR_LMT TUYA_BLE_DATA_MTU_MAX // single package transfer limit
//#define FRM_TYPE_OFFSET (0x0f << 4)
#define FRM_VERSION_OFFSET (0x0f << 4)
#define FRM_SEQ_OFFSET (0x0f << 0)
// frame total len
typedef uint32_t frame_total_t;
// frame subpackage num
typedef uint32_t frame_subpkg_num_t;
// frame sequence
typedef uint8_t frame_seq_t;
#define FRAME_SEQ_LMT 16
// frame subpackage len
typedef uint16_t frame_subpkg_len_t;
// frame package description
typedef uint8_t frm_pkg_desc_t;
#define FRM_PKG_INIT 0 // frame package init
#define FRM_PKG_FIRST 1 // frame package first
#define FRM_PKG_MIDDLE 2 // frame package middle
#define FRM_PKG_END 3 // frame package end
// mutil tsf ret code
typedef int32_t mtp_ret;
#define MTP_OK 0
#define MTP_INVALID_PARAM 1
#define MTP_COM_ERROR 2
#define MTP_TRSMITR_CONTINUE 3
#define MTP_TRSMITR_ERROR 4
#define MTP_MALLOC_ERR 5
// frame transmitter process
typedef struct {
frame_total_t total; //4 bytes, total length of data, not including header
uint8_t version; //1 byte, protocol major version number
frame_seq_t seq; //1 byte
frm_pkg_desc_t pkg_desc; //1 byte, Current packet frame type (init/first/middle/end)
frame_subpkg_num_t subpkg_num;//4 bytes, current sub-packet number
uint32_t pkg_trsmitr_cnt; // package process count ,Number of bytes sent
frame_subpkg_len_t subpkg_len;//1 byte, the data length in the current sub-packet
uint8_t subpkg[SNGL_PKG_TRSFR_LMT];
} frm_trsmitr_proc_s;
// dp type description,please refer to the relevant help documents of Tuya iot platform for the usage of various types of dp points.
typedef uint8_t dp_type;
#define DT_RAW 0
#define DT_BOOL 1
#define DT_VALUE 2
#define DT_INT DT_VALUE
#define DT_STRING 3
#define DT_ENUM 4
#define DT_BITMAP 5
#define DT_CHAR 7 //Not currently supported
#define DT_UCHAR 8 //Not currently supported
#define DT_SHORT 9 //Not currently supported
#define DT_USHORT 10 //Not currently supported
#define DT_LMT DT_USHORT
#define DT_VALUE_LEN 4 // int
#define DT_BOOL_LEN 1
#define DT_ENUM_LEN 1
#define DT_BITMAP_MAX 4 // 1/2/4
#define DT_STR_MAX 255
#define DT_RAW_MAX 255
#define DT_INT_LEN DT_VALUE_LEN
typedef struct s_klv_node {
struct s_klv_node *next;
uint8_t id;
dp_type type;
uint16_t len;
uint8_t *data;
} klv_node_s;
/***********************************************************
*************************variable define********************
***********************************************************/
/***********************************************************
*************************function define********************
***********************************************************/
/***********************************************************
* Function: make_klv_list
* description:
* Input:
* Output:
* Return:
***********************************************************/
__MUTLI_TSF_PROTOCOL_EXT \
klv_node_s *make_klv_list(klv_node_s *list, uint8_t id, dp_type type, \
void *data, uint16_t len);
/***********************************************************
* Function: free_klv_list
* description:
* Input: list
* Output:
* Return:
***********************************************************/
__MUTLI_TSF_PROTOCOL_EXT \
void free_klv_list(klv_node_s *list);
/***********************************************************
* Function: klvlist_2_data
* description:
* Input: list
* Output: data len
* Return:
* Note:data need free.
***********************************************************/
__MUTLI_TSF_PROTOCOL_EXT \
mtp_ret klvlist_2_data(klv_node_s *list, uint8_t **data, uint32_t *len, uint8_t type);
/***********************************************************
* Function: data_2_klvlist
* description:
* Input: data len
* Output: list
* Return:
* Note: list need to call free_klv_list to free.
***********************************************************/
__MUTLI_TSF_PROTOCOL_EXT \
mtp_ret data_2_klvlist(uint8_t *data, uint32_t len, klv_node_s **list, uint8_t type);
/***********************************************************
* Function: create_trsmitr_init
* description: create a transmitter and initialize
* Input: none
* Output:
* Return: transmitter handle
***********************************************************/
__MUTLI_TSF_PROTOCOL_EXT \
frm_trsmitr_proc_s *create_trsmitr_init(void);
/***********************************************************
* Function: trsmitr_init
* description: init a transmitter
* Input: transmitter handle
* Output:
* Return:
***********************************************************/
__MUTLI_TSF_PROTOCOL_EXT \
void trsmitr_init(frm_trsmitr_proc_s *frm_trsmitr);
/***********************************************************
* Function: delete_trsmitr
* description: delete transmitter
* Input: transmitter handle
* Output:
* Return:
***********************************************************/
__MUTLI_TSF_PROTOCOL_EXT \
void delete_trsmitr(frm_trsmitr_proc_s *frm_trsmitr);
/***********************************************************
* Function: get_trsmitr_frame_total_len
* description: get a transmitter total data len
* Input: transmitter handle
* Output:
* Return: frame_total_t
***********************************************************/
__MUTLI_TSF_PROTOCOL_EXT \
frame_total_t get_trsmitr_frame_total_len(frm_trsmitr_proc_s *frm_trsmitr);
/***********************************************************
* Function: get_trsmitr_frame_type
* description:
* Input: transmitter handle
* Output:
* Return: frame_type_t
***********************************************************/
__MUTLI_TSF_PROTOCOL_EXT \
uint8_t get_trsmitr_frame_version(frm_trsmitr_proc_s *frm_trsmitr);
/***********************************************************
* Function: get_trsmitr_frame_seq
* description:
* Input: transmitter handle
* Output:
* Return: frame_seq_t
***********************************************************/
__MUTLI_TSF_PROTOCOL_EXT \
frame_seq_t get_trsmitr_frame_seq(frm_trsmitr_proc_s *frm_trsmitr);
/***********************************************************
* Function: get_trsmitr_subpkg_len
* description:
* Input: transmitter handle
* Output:
* Return: frame_subpkg_len_t
***********************************************************/
__MUTLI_TSF_PROTOCOL_EXT \
frame_subpkg_len_t get_trsmitr_subpkg_len(frm_trsmitr_proc_s *frm_trsmitr);
/***********************************************************
* Function: get_trsmitr_subpkg
* description:
* Input: transmitter handle
* Output:
* Return: subpackage buf
***********************************************************/
__MUTLI_TSF_PROTOCOL_EXT \
uint8_t *get_trsmitr_subpkg(frm_trsmitr_proc_s *frm_trsmitr);
/***********************************************************
* Function: trsmitr_send_pkg_encode
* description: frm_trsmitr->transmitter handle
* type->frame type
* buf->data buf
* len->data len
* Input:
* Output:
* Return: MTP_OK->buf send up
* MTP_TRSMITR_CONTINUE->need call again to be continue
* other->error
* Note: could get from encode data len and encode data by calling method
get_trsmitr_subpkg_len() and get_trsmitr_subpkg()
***********************************************************/
__MUTLI_TSF_PROTOCOL_EXT \
mtp_ret trsmitr_send_pkg_encode(frm_trsmitr_proc_s *frm_trsmitr, uint8_t version, uint8_t *buf, uint32_t len);
/***********************************************************
* Function: trsmitr_send_pkg_encode_with_packet_length
* description: Encoding function for specifying sub-packet length
*
*
*
* Input:
* Output:
* Return: MTP_OK->buf send up
* MTP_TRSMITR_CONTINUE->need call again to be continue
* other->error
* Note: could get from encode data len and encode data by calling method
get_trsmitr_subpkg_len() and get_trsmitr_subpkg()
***********************************************************/
__MUTLI_TSF_PROTOCOL_EXT \
mtp_ret trsmitr_send_pkg_encode_with_packet_length(frm_trsmitr_proc_s *frm_trsmitr, uint32_t pkg_len_max, uint8_t version, uint8_t *buf, uint32_t len);
/***********************************************************
* Function: trsmitr_recv_pkg_decode
* description: frm_trsmitr->transmitter handle
* raw_data->raw encode data
* raw_data_len->raw encode data len
* Input:
* Output:
* Return: MTP_OK->buf receive up
* MTP_TRSMITR_CONTINUE->need call again to be continue
* other->error
* Note: could get from decode data len and decode data by calling method
get_trsmitr_subpkg_len() and get_trsmitr_subpkg()
***********************************************************/
__MUTLI_TSF_PROTOCOL_EXT \
mtp_ret trsmitr_recv_pkg_decode(frm_trsmitr_proc_s *frm_trsmitr, uint8_t *raw_data, uint16_t raw_data_len);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,56 @@
/**
* \file tuya_ble_queue.h
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#ifndef TUYA_BLE_QUEUE_H_
#define TUYA_BLE_QUEUE_H_
#include "tuya_ble_stdlib.h"
#include "tuya_ble_type.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
void *buf;
volatile uint8_t size;
volatile uint8_t offset;
volatile uint8_t rd_ptr;
volatile uint8_t wr_ptr;
volatile uint8_t used;
} tuya_ble_queue_t;
tuya_ble_status_t tuya_ble_queue_init(tuya_ble_queue_t *q, void *buf, uint8_t size, uint8_t elem_size);
tuya_ble_status_t tuya_ble_enqueue(tuya_ble_queue_t *q, void *in);
tuya_ble_status_t tuya_ble_queue_get(tuya_ble_queue_t *q, void *out);
tuya_ble_status_t tuya_ble_dequeue(tuya_ble_queue_t *q, void *out);
void tuya_ble_queue_decrease(tuya_ble_queue_t *q);
void tuya_ble_queue_flush(tuya_ble_queue_t *q);
uint8_t tuya_ble_get_queue_used(tuya_ble_queue_t *q);
#ifdef __cplusplus
}
#endif
#endif //TUYA_BLE_QUEUE_H_
@@ -0,0 +1,53 @@
/**
* \file tuya_ble_storage.h
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#ifndef TUYA_BLE_STORAGE_H_
#define TUYA_BLE_STORAGE_H_
#include "tuya_ble_type.h"
#include "tuya_ble_internal_config.h"
uint32_t tuya_ble_storage_save_sys_settings(void);
uint32_t tuya_ble_storage_save_auth_settings(void);
uint32_t tuya_ble_storage_init(void);
#if (TUYA_BLE_DEVICE_AUTH_DATA_STORE)
tuya_ble_status_t tuya_ble_storage_write_pid(tuya_ble_product_id_type_t pid_type, uint8_t pid_len, uint8_t *pid);
tuya_ble_status_t tuya_ble_storage_write_hid(uint8_t *hid, uint8_t len);
tuya_ble_status_t tuya_ble_storage_read_id_info(tuya_ble_factory_id_data_t *id);
tuya_ble_status_t tuya_ble_storage_write_auth_key_device_id_mac(uint8_t *auth_key, uint8_t auth_key_len, uint8_t *device_id, uint8_t device_id_len,
uint8_t *mac, uint8_t mac_len, uint8_t *mac_string, uint8_t mac_string_len, uint8_t *pid, uint8_t pid_len);
#endif
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,51 @@
/**
* \file tuya_ble_unix_time.h
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#ifndef TUYA_BLE_UNIX_TIME_H_
#define TUYA_BLE_UNIX_TIME_H_
#include "tuya_ble_stdlib.h"
/* time struct */
typedef struct {
uint16_t nYear;
uint8_t nMonth;
uint8_t nDay;
uint8_t nHour;
uint8_t nMin;
uint8_t nSec;
uint8_t DayIndex; /* 0 = Sunday */
} tuya_ble_time_struct_data_t;
void tuya_ble_utc_sec_2_mytime(uint32_t utc_sec, tuya_ble_time_struct_data_t *result, bool daylightSaving);
void tuya_ble_utc_sec_2_mytime_string(uint32_t utc_sec, bool daylightSaving, char *s);
uint32_t tuya_ble_mytime_2_utc_sec(tuya_ble_time_struct_data_t *currTime, bool daylightSaving);
#endif
@@ -0,0 +1,123 @@
/**
* \file tuya_ble_utils.h
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#ifndef TUYA_BLE_UTILS_H_
#define TUYA_BLE_UTILS_H_
#include "tuya_ble_stdlib.h"
#define BSWAP_16(x) \
(uint16_t)((((uint16_t)(x) & 0x00ff) << 8) | \
(((uint16_t)(x) & 0xff00) >> 8) )
#define BSWAP_32(x) \
(uint32_t)((((uint32_t)(x) & 0xff000000) >> 24) | \
(((uint32_t)(x) & 0x00ff0000) >> 8) | \
(((uint32_t)(x) & 0x0000ff00) << 8) | \
(((uint32_t)(x) & 0x000000ff) << 24))
int32_t tuya_ble_rand_number(int32_t min, int32_t max);
int32_t tuya_ble_count_bits(uint32_t data);
void tuya_ble_inverted_array(uint8_t *array, uint16_t length);
bool tuya_ble_buffer_value_is_all_x(uint8_t *buffer, uint16_t len, uint8_t value);
uint8_t tuya_ble_check_sum(uint8_t *pbuf, uint16_t len);
uint8_t tuya_ble_check_num(uint8_t *buf, uint8_t num);
void tuya_ble_hextoascii(uint8_t *hexbuf, uint8_t len, uint8_t *ascbuf);
void tuya_ble_hextostr(uint8_t *hexbuf, uint8_t len, uint8_t *strbuf);
void tuya_ble_asciitohex(uint8_t *ascbuf, uint8_t *hexbuf);
uint8_t tuya_ble_char_2_ascii(uint8_t data);
void tuya_ble_str_to_hex(uint8_t *str_buf, uint8_t str_len, uint8_t *hex_buf);
bool tuya_ble_is_word_aligned_tuya(void const *p);
uint16_t tuya_ble_crc16_compute(uint8_t *p_data, uint16_t size, uint16_t *p_crc);
uint32_t tuya_ble_crc32_compute(uint8_t const *p_data, uint32_t size, uint32_t const *p_crc);
void tuya_ble_device_id_20_to_16(uint8_t *in, uint8_t *out);
void tuya_ble_device_id_16_to_20(uint8_t *in, uint8_t *out);
char tuya_ble_hexstr2hex(uint8_t *hexstr, int32_t len, uint8_t *hex);
/**
* @brief Function for search character/symbol index from input string
*
* @param
* [in]data : pointer to input data
* [in]data : Number of bytes of data
* [in]symbol : Search symbol or character, Such as ':' or ','
* [out]index[] : Array of indexs
*
* @return The number of matched character/symbol
*
* @note
*
* */
int32_t tuya_ble_search_symbol_index(char *data, uint16_t len, char symbol, uint8_t index[]);
int32_t tuya_ble_ascii_to_int(char *ascii, uint16_t len);
/**
* @brief Function for pem format ecc key to hex foramt
*
* @param
* [in]pem : pointer to pem data
* [out]key : pointer to output data, hex format ecc key
* [out]key_len: Number of bytes of key.
*
* @return 0 - failed, 1 - success
*
* @note developer could use tuya_ble_ecc_key_pem2hex_example() function to test
*
* */
int32_t tuya_ble_ecc_key_pem2hex(const char *pem, uint8_t *key, uint16_t *key_len);
/**
* @brief Function for extract r+s from der from ecdsa sign
*
* @param
* [in]der : pointer to der data
* [out]raw_rs : pointer to output data, the raw data[r+s] of der
*
* @return 0 - failed, 1 - success
*
* @note
*
* */
int32_t tuya_ble_ecc_sign_secp256r1_extract_raw_from_der(const char *der, uint8_t *raw_rs);
#endif /* TUYA_UTILS_H_ */
@@ -0,0 +1,99 @@
/**
* \file tuya_ble_event_handler.h
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#ifndef TUYA_BLE_EVENT_HANDLER_H__
#define TUYA_BLE_EVENT_HANDLER_H__
#include "tuya_ble_type.h"
#ifdef __cplusplus
extern "C" {
#endif
void tuya_ble_handle_device_info_update_evt(tuya_ble_evt_param_t *evt);
void tuya_ble_handle_dp_data_reported_evt(tuya_ble_evt_param_t *evt);
void tuya_ble_handle_dp_data_with_time_reported_evt(tuya_ble_evt_param_t *evt);
void tuya_ble_handle_dp_data_with_time_string_reported_evt(tuya_ble_evt_param_t *evt);
void tuya_ble_handle_dp_data_with_flag_reported_evt(tuya_ble_evt_param_t *evt);
void tuya_ble_handle_dp_data_with_flag_and_time_reported_evt(tuya_ble_evt_param_t *evt);
void tuya_ble_handle_dp_data_with_flag_and_time_string_reported_evt(tuya_ble_evt_param_t *evt);
void tuya_ble_handle_dp_data_send_evt(tuya_ble_evt_param_t *evt);
void tuya_ble_handle_dp_data_with_time_send_evt(tuya_ble_evt_param_t *evt);
void tuya_ble_handle_device_unbind_evt(tuya_ble_evt_param_t *evt);
void tuya_ble_handle_factory_reset_evt(tuya_ble_evt_param_t *evt);
void tuya_ble_handle_ota_response_evt(tuya_ble_evt_param_t *evt);
void tuya_ble_handle_bulk_data_evt(tuya_ble_evt_param_t *p_evt);
void tuya_ble_handle_data_passthrough_evt(tuya_ble_evt_param_t *evt);
void tuya_ble_handle_data_prod_test_response_evt(tuya_ble_evt_param_t *evt);
void tuya_ble_handle_uart_cmd_evt(tuya_ble_evt_param_t *evt);
void tuya_ble_handle_ble_cmd_evt(tuya_ble_evt_param_t *evt);
void tuya_ble_handle_net_config_response_evt(tuya_ble_evt_param_t *evt);
void tuya_ble_handle_time_request_evt(tuya_ble_evt_param_t *evt);
void tuya_ble_handle_extend_time_request_evt(tuya_ble_evt_param_t *evt);
void tuya_ble_handle_unbound_response_evt(tuya_ble_evt_param_t *evt);
void tuya_ble_handle_anomaly_unbound_response_evt(tuya_ble_evt_param_t *evt);
void tuya_ble_handle_device_reset_response_evt(tuya_ble_evt_param_t *evt);
void tuya_ble_handle_connect_change_evt(tuya_ble_evt_param_t *evt);
void tuya_ble_handle_ble_data_evt(uint8_t *buf, uint16_t len);
void tuya_ble_handle_connecting_request_evt(tuya_ble_evt_param_t *evt);
void tuya_ble_handle_link_update_evt(tuya_ble_evt_param_t *evt);
void tuya_ble_handle_weather_data_request_evt(tuya_ble_evt_param_t *evt);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,74 @@
/**
* \file tuya_ble_secure.h
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#ifndef TUYA_BLE_SECURE_H_
#define TUYA_BLE_SECURE_H_
#include "tuya_ble_type.h"
#ifdef __cplusplus
extern "C" {
#endif
enum {
ENCRYPTION_MODE_NONE,
ENCRYPTION_MODE_KEY_1,
ENCRYPTION_MODE_KEY_2,
ENCRYPTION_MODE_KEY_3,
ENCRYPTION_MODE_KEY_4,
ENCRYPTION_MODE_SESSION_KEY,
ENCRYPTION_MODE_ECDH_KEY,
ENCRYPTION_MODE_FTM_KEY,
ENCRYPTION_MODE_MAX,
};
bool tuya_ble_register_key_generate(uint8_t *output, tuya_ble_parameters_settings_t *current_para);
uint8_t tuya_ble_encryption(uint16_t protocol_version, uint8_t encryption_mode, uint8_t *iv, uint8_t *in_buf, uint32_t in_len, uint32_t *out_len, uint8_t *out_buf, tuya_ble_parameters_settings_t *current_para_data, uint8_t *dev_rand);
uint8_t tuya_ble_encrypt_old_with_key(uint8_t *key, uint8_t *in_buf, uint8_t in_len, uint8_t *out_buf);
bool tuya_ble_device_id_encrypt(uint8_t *key_in, uint16_t key_len, uint8_t *input, uint16_t input_len, uint8_t *output);
bool tuya_ble_device_id_decrypt(uint8_t *key_in, uint16_t key_len, uint8_t *input, uint16_t input_len, uint8_t *output);
bool tuya_ble_device_id_encrypt_v4(uint8_t *key_in, uint16_t key_len, uint8_t *input, uint16_t input_len, uint8_t *output);
uint8_t tuya_ble_decryption(uint16_t protocol_version, uint8_t const *in_buf, uint32_t in_len, uint32_t *out_len, uint8_t *out_buf, tuya_ble_parameters_settings_t *current_para_data, uint8_t *dev_rand);
bool tuya_ble_server_cert_data_verify(const uint8_t *p_data, uint16_t data_len, const uint8_t *p_sig);
bool tuya_ble_sig_data_verify(const uint8_t *p_pk, const uint8_t *p_data, uint16_t data_len, const uint8_t *p_sig);
void tuya_ble_event_process(tuya_ble_evt_param_t *tuya_ble_evt);
#ifdef __cplusplus
}
#endif
#endif // TUYA_BLE_SECURE_H_
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,278 @@
/**
* \file tuya_ble_bulkdata.c
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#include "tuya_ble_bulk_data.h"
#include "tuya_ble_stdlib.h"
#include "tuya_ble_type.h"
#include "tuya_ble_heap.h"
#include "tuya_ble_mem.h"
#include "tuya_ble_api.h"
#include "tuya_ble_port.h"
#include "tuya_ble_main.h"
#include "tuya_ble_internal_config.h"
#include "tuya_ble_data_handler.h"
#include "tuya_ble_mutli_tsf_protocol.h"
#include "tuya_ble_utils.h"
#include "tuya_ble_secure.h"
#include "tuya_ble_main.h"
#include "tuya_ble_storage.h"
#include "tuya_ble_unix_time.h"
#include "tuya_ble_log.h"
#include "tuya_ble_gatt_send_queue.h"
uint32_t tuya_ble_bulk_data_read_block_size_get(void)
{
uint32_t mtu_length = 0;
uint32_t read_block_size = 0;
if (tuya_ble_connect_status_get() != BONDING_CONN) {
read_block_size = 0;
} else {
mtu_length = tuya_ble_send_packet_data_length_get();
if (mtu_length < 100) {
read_block_size = 256;
} else if ((mtu_length >= 100) && (mtu_length < 150)) {
read_block_size = 512;
} else {
read_block_size = TUYA_BLE_BULK_DATA_MAX_READ_BLOCK_SIZE;
}
}
return read_block_size;
}
void tuya_ble_handle_bulk_data_req(uint16_t cmd, uint8_t *p_recv_data, uint32_t recv_data_len)
{
uint16_t data_len;
tuya_ble_cb_evt_param_t event;
uint8_t err_code = 0;
data_len = (p_recv_data[11] << 8) + p_recv_data[12];
if (data_len == 0) {
return;
} else if (p_recv_data[13] != 0) { /*Currently only supports version 0*/
return;
} else {
}
event.evt = TUYA_BLE_CB_EVT_BULK_DATA;
switch (cmd) {
case FRM_BULK_DATA_READ_INFO_REQ:
event.bulk_req_data.evt = TUYA_BLE_BULK_DATA_EVT_READ_INFO;
event.bulk_req_data.bulk_type = p_recv_data[14];
break;
case FRM_BULK_DATA_READ_DATA_REQ:
event.bulk_req_data.evt = TUYA_BLE_BULK_DATA_EVT_READ_BLOCK;
event.bulk_req_data.bulk_type = p_recv_data[14];
event.bulk_req_data.params.block_data_req_data.block_number = (p_recv_data[15] << 8) + p_recv_data[16];
break;
case FRM_BULK_DATA_ERASE_DATA_REQ:
event.bulk_req_data.evt = TUYA_BLE_BULK_DATA_EVT_ERASE;
event.bulk_req_data.bulk_type = p_recv_data[14];
break;
default:
err_code = 1;
break;
}
if (err_code == 0) {
if (tuya_ble_cb_event_send(&event) != 0) {
TUYA_BLE_LOG_ERROR("tuya_ble_handle_bulk_data_req-tuya ble send cb event failed.");
}
}
}
tuya_ble_status_t tuya_ble_bulk_data_response(tuya_ble_bulk_data_response_t *p_data)
{
tuya_ble_evt_param_t evt;
if (tuya_ble_connect_status_get() != BONDING_CONN) {
return TUYA_BLE_ERR_INVALID_STATE;
}
if ((p_data->evt == TUYA_BLE_BULK_DATA_EVT_SEND_DATA) && (p_data->params.send_res_data.current_block_length > (TUYA_BLE_SEND_MAX_DATA_LEN - 8))) {
return TUYA_BLE_ERR_INVALID_LENGTH;
}
evt.hdr.event = TUYA_BLE_EVT_BULK_DATA_RESPONSE;
memcpy(&evt.bulk_res_data, p_data, sizeof(tuya_ble_bulk_data_response_t));
if (p_data->evt == TUYA_BLE_BULK_DATA_EVT_SEND_DATA) {
evt.bulk_res_data.params.send_res_data.p_current_block_data = NULL;
evt.bulk_res_data.params.send_res_data.p_current_block_data = (uint8_t *)tuya_ble_malloc(p_data->params.send_res_data.current_block_length);
if (evt.bulk_res_data.params.send_res_data.p_current_block_data == NULL) {
return TUYA_BLE_ERR_NO_MEM;
}
memcpy(evt.bulk_res_data.params.send_res_data.p_current_block_data, p_data->params.send_res_data.p_current_block_data, p_data->params.send_res_data.current_block_length);
}
if (tuya_ble_event_send(&evt) != 0) {
if (p_data->evt == TUYA_BLE_BULK_DATA_EVT_SEND_DATA) {
tuya_ble_free(evt.bulk_res_data.params.send_res_data.p_current_block_data);
}
return TUYA_BLE_ERR_NO_EVENT;
}
return TUYA_BLE_SUCCESS;
}
void tuya_ble_handle_bulk_data_evt(tuya_ble_evt_param_t *evt)
{
uint16_t bulk_data_cmd = 0;
uint8_t buffer[14];
uint8_t *p_buf = NULL;
uint16_t data_length = 0;
uint8_t encry_mode = 0;
tuya_ble_cb_evt_param_t event;
uint8_t err_code = 0;
if (tuya_ble_pair_rand_valid_get() == 1) {
encry_mode = ENCRYPTION_MODE_SESSION_KEY;
} else {
encry_mode = ENCRYPTION_MODE_KEY_4;
}
buffer[0] = 0;
buffer[1] = evt->bulk_res_data.bulk_type;
switch (evt->bulk_res_data.evt) {
case TUYA_BLE_BULK_DATA_EVT_READ_INFO:
bulk_data_cmd = FRM_BULK_DATA_READ_INFO_RESP;
buffer[2] = evt->bulk_res_data.params.bulk_info_res_data.status;
buffer[3] = evt->bulk_res_data.params.bulk_info_res_data.flag;
buffer[4] = evt->bulk_res_data.params.bulk_info_res_data.bulk_data_length >> 24;
buffer[5] = evt->bulk_res_data.params.bulk_info_res_data.bulk_data_length >> 16;
buffer[6] = evt->bulk_res_data.params.bulk_info_res_data.bulk_data_length >> 8;
buffer[7] = evt->bulk_res_data.params.bulk_info_res_data.bulk_data_length;
buffer[8] = evt->bulk_res_data.params.bulk_info_res_data.bulk_data_crc >> 24;
buffer[9] = evt->bulk_res_data.params.bulk_info_res_data.bulk_data_crc >> 16;
buffer[10] = evt->bulk_res_data.params.bulk_info_res_data.bulk_data_crc >> 8;
buffer[11] = evt->bulk_res_data.params.bulk_info_res_data.bulk_data_crc;
buffer[12] = evt->bulk_res_data.params.bulk_info_res_data.block_data_length >> 8;
buffer[13] = evt->bulk_res_data.params.bulk_info_res_data.block_data_length;
data_length = 14;
break;
case TUYA_BLE_BULK_DATA_EVT_READ_BLOCK:
bulk_data_cmd = FRM_BULK_DATA_READ_DATA_RESP;
buffer[2] = evt->bulk_res_data.params.block_res_data.status;
buffer[3] = evt->bulk_res_data.params.block_res_data.block_number >> 8;
buffer[4] = evt->bulk_res_data.params.block_res_data.block_number;
buffer[5] = evt->bulk_res_data.params.block_res_data.block_data_length >> 8;
buffer[6] = evt->bulk_res_data.params.block_res_data.block_data_length;
buffer[7] = evt->bulk_res_data.params.block_res_data.max_packet_data_length >> 8;
buffer[8] = evt->bulk_res_data.params.block_res_data.max_packet_data_length;
buffer[9] = evt->bulk_res_data.params.block_res_data.block_data_crc16 >> 8;
buffer[10] = evt->bulk_res_data.params.block_res_data.block_data_crc16;
data_length = 11;
break;
case TUYA_BLE_BULK_DATA_EVT_SEND_DATA :
bulk_data_cmd = FRM_BULK_DATA_SEND_DATA;
p_buf = (uint8_t *)tuya_ble_malloc(evt->bulk_res_data.params.send_res_data.current_block_length + 8);
if (p_buf) {
p_buf[0] = 0;
p_buf[1] = evt->bulk_res_data.bulk_type;
p_buf[2] = evt->bulk_res_data.params.send_res_data.current_block_number >> 8;
p_buf[3] = evt->bulk_res_data.params.send_res_data.current_block_number;
p_buf[4] = 0;
p_buf[5] = 0;
p_buf[6] = evt->bulk_res_data.params.send_res_data.current_block_length >> 8;
p_buf[7] = evt->bulk_res_data.params.send_res_data.current_block_length;
memcpy(&p_buf[8], evt->bulk_res_data.params.send_res_data.p_current_block_data, evt->bulk_res_data.params.send_res_data.current_block_length);
data_length = evt->bulk_res_data.params.send_res_data.current_block_length + 8;
}
tuya_ble_free(evt->bulk_res_data.params.send_res_data.p_current_block_data);
break;
case TUYA_BLE_BULK_DATA_EVT_ERASE :
bulk_data_cmd = FRM_BULK_DATA_ERASE_DATA_RESP;
buffer[2] = evt->bulk_res_data.params.erase_res_data.status;
data_length = 3;
break;
default:
break;
}
if (data_length > 0) {
if (evt->bulk_res_data.evt == TUYA_BLE_BULK_DATA_EVT_READ_BLOCK) {
err_code = tuya_ble_commData_send(bulk_data_cmd, 0, buffer, data_length, encry_mode);
if (evt->bulk_res_data.params.block_res_data.status == 0) {
event.evt = TUYA_BLE_CB_EVT_BULK_DATA;
event.bulk_req_data.evt = TUYA_BLE_BULK_DATA_EVT_SEND_DATA;
event.bulk_req_data.bulk_type = evt->bulk_res_data.bulk_type;
event.bulk_req_data.params.send_data_req_data.block_number = evt->bulk_res_data.params.block_res_data.block_number;
if (!err_code) {
if (tuya_ble_cb_event_send(&event) != 0) {
TUYA_BLE_LOG_ERROR("tuya_ble_handle_bulk_data_evt-tuya ble send cb event failed.");
}
} else {
TUYA_BLE_LOG_ERROR("tuya_ble_handle_bulk_data_evt-response read bulk data error.");
}
}
} else if (evt->bulk_res_data.evt == TUYA_BLE_BULK_DATA_EVT_SEND_DATA) {
err_code = tuya_ble_commData_send(bulk_data_cmd, 0, p_buf, data_length, encry_mode);
tuya_ble_free(p_buf);
} else {
tuya_ble_commData_send(bulk_data_cmd, 0, buffer, data_length, encry_mode);
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,225 @@
/**
* \file tuya_ble_event.c
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#include "tuya_ble_stdlib.h"
#include "tuya_ble_type.h"
#include "tuya_ble_heap.h"
#include "tuya_ble_mem.h"
#include "tuya_ble_api.h"
#include "tuya_ble_port.h"
#include "tuya_ble_main.h"
#include "tuya_ble_secure.h"
#include "tuya_ble_data_handler.h"
#include "tuya_ble_storage.h"
#include "tuya_ble_sdk_version.h"
#include "tuya_ble_utils.h"
#include "tuya_ble_event.h"
#include "tuya_ble_log.h"
#if (!TUYA_BLE_USE_OS)
static uint8_t *m_queue_event_data; /**< Array for holding the queue event data. */
static volatile uint8_t m_queue_start_index; /**< Index of queue entry at the start of the queue. */
static volatile uint8_t m_queue_end_index; /**< Index of queue entry at the end of the queue. */
static uint16_t m_queue_event_size; /**< Maximum event size in queue. */
static uint16_t m_queue_size; /**< Number of queue entries. */
/**@brief Function for incrementing a queue index, and handle wrap-around.
*
* @param[in] index Old index.
*
* @return New (incremented) index.
*/
static __TUYA_BLE_INLINE uint8_t next_index(uint8_t index)
{
return (index < m_queue_size) ? (index + 1) : 0;
}
static __TUYA_BLE_INLINE uint8_t tuya_sched_queue_full(void)
{
uint8_t tmp = m_queue_start_index;
return next_index(m_queue_end_index) == tmp;
}
/**@brief Macro for checking if a queue is full. */
#define TUYA_BLE_SCHED_QUEUE_FULL() tuya_sched_queue_full()
static __TUYA_BLE_INLINE uint8_t tuya_sched_queue_empty(void)
{
uint8_t tmp = m_queue_start_index;
return m_queue_end_index == tmp;
}
/**@brief Macro for checking if a queue is empty. */
#define TUYA_BLE_SCHED_QUEUE_EMPTY() tuya_sched_queue_empty()
uint32_t tuya_ble_sched_init(uint16_t event_size, uint16_t queue_size, void *p_event_buffer)
{
// Check that buffer is correctly aligned
if (!tuya_ble_is_word_aligned_tuya(p_event_buffer)) {
TUYA_BLE_LOG_ERROR("tuya_ble_sched_init error");
return 1;
}
// Initialize event scheduler
m_queue_event_data = &((uint8_t *)p_event_buffer)[0];
m_queue_end_index = 0;
m_queue_start_index = 0;
m_queue_event_size = event_size;
m_queue_size = queue_size;
return 0;
}
uint16_t tuya_ble_sched_queue_size_get(void)
{
return m_queue_size;
}
uint16_t tuya_ble_sched_queue_space_get(void)
{
uint16_t start = m_queue_start_index;
uint16_t end = m_queue_end_index;
uint16_t free_space = m_queue_size - ((end >= start) ?
(end - start) : (m_queue_size + 1 - start + end));
return free_space;
}
uint16_t tuya_ble_sched_queue_events_get(void)
{
uint16_t start = m_queue_start_index;
uint16_t end = m_queue_end_index;
uint16_t number_of_events;
if (m_queue_size == 0) {
number_of_events = 0;
} else {
number_of_events = ((end >= start) ? (end - start) : (m_queue_size + 1 - start + end));
}
return number_of_events;
}
static tuya_ble_status_t tuya_ble_sched_event_put(void const *p_event_data, uint16_t event_data_size)
{
tuya_ble_status_t err_code;
if (event_data_size <= m_queue_event_size) {
uint16_t event_index = 0xFFFF;
tuya_ble_device_enter_critical();
if (!TUYA_BLE_SCHED_QUEUE_FULL()) {
event_index = m_queue_end_index;
m_queue_end_index = next_index(m_queue_end_index);
}
tuya_ble_device_exit_critical();
if (event_index != 0xFFFF) {
// NOTE: This can be done outside the critical region since the event consumer will
// always be called from the main loop, and will thus never interrupt this code.
if ((p_event_data != NULL) && (event_data_size > 0)) {
memcpy(&m_queue_event_data[event_index * m_queue_event_size],
p_event_data,
event_data_size);
} else {
}
err_code = TUYA_BLE_SUCCESS;
} else {
err_code = TUYA_BLE_ERR_NO_MEM;
}
} else {
err_code = TUYA_BLE_ERR_INVALID_LENGTH;
}
return err_code;
}
void tuya_sched_execute(void)
{
static tuya_ble_evt_param_t tuya_ble_evt;
tuya_ble_evt_param_t *evt;
evt = &tuya_ble_evt;
uint8_t end_ix = m_queue_end_index;
while (m_queue_start_index != end_ix) { //(!TUYA_BLE_SCHED_QUEUE_EMPTY())
// Since this function is only called from the main loop, there is no
// need for a critical region here, however a special care must be taken
// regarding update of the queue start index (see the end of the loop).
uint16_t event_index = m_queue_start_index;
void *p_event_data;
p_event_data = &(m_queue_event_data[event_index * m_queue_event_size]);
memcpy(evt, p_event_data, sizeof(tuya_ble_evt_param_t));
//TUYA_BLE_LOG_DEBUG("TUYA_RECEIVE_EVT-0x%04x,start index-0x%04x,end index-0x%04x\n",evt->hdr.event,m_queue_start_index,m_queue_end_index);
tuya_ble_event_process(evt);
// Event processed, now it is safe to move the queue start index,
// so the queue entry occupied by this event can be used to store
// a next one.
m_queue_start_index = next_index(m_queue_start_index);
}
}
void tuya_ble_event_queue_init(void)
{
if ((sizeof(tuya_ble_evt_param_t)) > TUYA_BLE_EVT_SIZE) {
TUYA_BLE_LOG_ERROR("ERROR!!TUYA_BLE_EVT_SIZE is not enough!");
return;
}
TUYA_BLE_SCHED_INIT(TUYA_BLE_EVT_SIZE, TUYA_BLE_EVT_MAX_NUM);
}
tuya_ble_status_t tuya_ble_message_send(tuya_ble_evt_param_t *evt)
{
return tuya_ble_sched_event_put(evt, m_queue_event_size);
}
#endif
@@ -0,0 +1,779 @@
/**
* \file tuya_ble_event_handler.c
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#include "tuya_ble_stdlib.h"
#include "tuya_ble_type.h"
#include "tuya_ble_heap.h"
#include "tuya_ble_mem.h"
#include "tuya_ble_api.h"
#include "tuya_ble_port.h"
#include "tuya_ble_main.h"
#include "tuya_ble_secure.h"
#include "tuya_ble_data_handler.h"
#include "tuya_ble_storage.h"
#include "tuya_ble_sdk_version.h"
#include "tuya_ble_event.h"
#include "tuya_ble_utils.h"
#include "tuya_ble_app_uart_common_handler.h"
#include "tuya_ble_app_production_test.h"
#include "tuya_ble_log.h"
#include "tuya_ble_event_handler.h"
void tuya_ble_handle_device_info_update_evt(tuya_ble_evt_param_t *evt)
{
#if (!TUYA_BLE_DEVICE_REGISTER_FROM_BLE)
tuya_ble_cb_evt_param_t event;
tuya_ble_connect_status_t current_connect_status;
#endif
switch (evt->device_info_data.type) {
case DEVICE_INFO_TYPE_PID:
tuya_ble_current_para.pid_type = TUYA_BLE_PRODUCT_ID_TYPE_PID;
tuya_ble_current_para.pid_len = evt->device_info_data.len;
memcpy(tuya_ble_current_para.pid, evt->device_info_data.data, tuya_ble_current_para.pid_len);
tuya_ble_adv_change();
break;
case DEVICE_INFO_TYPE_PRODUCT_KEY:
tuya_ble_current_para.pid_type = TUYA_BLE_PRODUCT_ID_TYPE_PRODUCT_KEY;
tuya_ble_current_para.pid_len = evt->device_info_data.len;
memcpy(tuya_ble_current_para.pid, evt->device_info_data.data, tuya_ble_current_para.pid_len);
tuya_ble_adv_change();
break;
case DEVICE_INFO_TYPE_LOGIN_KEY:
#if (!TUYA_BLE_DEVICE_REGISTER_FROM_BLE)
if (memcmp(tuya_ble_current_para.sys_settings.login_key, evt->device_info_data.data, LOGIN_KEY_LEN)) {
memcpy(tuya_ble_current_para.sys_settings.login_key, evt->device_info_data.data, LOGIN_KEY_LEN);
}
#endif
break;
case DEVICE_INFO_TYPE_BOUND:
#if (!TUYA_BLE_DEVICE_REGISTER_FROM_BLE)
if (tuya_ble_current_para.sys_settings.bound_flag != evt->device_info_data.data[0]) {
tuya_ble_current_para.sys_settings.bound_flag = evt->device_info_data.data[0];
tuya_ble_adv_change();
current_connect_status = tuya_ble_connect_status_get();
if (tuya_ble_current_para.sys_settings.bound_flag == 1) { //0->1
if (current_connect_status == UNBONDING_CONN) {
tuya_ble_connect_status_set(BONDING_CONN);
} else if (current_connect_status == UNBONDING_UNAUTH_CONN) {
tuya_ble_connect_status_set(BONDING_UNAUTH_CONN);
} else if (current_connect_status == UNBONDING_UNCONN) {
tuya_ble_connect_status_set(BONDING_UNCONN);
} else {
}
} else { //1->0
if (current_connect_status == BONDING_CONN) {
tuya_ble_connect_status_set(UNBONDING_CONN);
} else if (current_connect_status == BONDING_UNAUTH_CONN) {
tuya_ble_connect_status_set(UNBONDING_UNAUTH_CONN);
} else if (current_connect_status == BONDING_UNCONN) {
tuya_ble_connect_status_set(UNBONDING_UNCONN);
} else {
}
}
event.evt = TUYA_BLE_CB_EVT_CONNECTE_STATUS;
event.connect_status = tuya_ble_connect_status_get();
if (tuya_ble_cb_event_send(&event) != 0) {
TUYA_BLE_LOG_ERROR("tuya ble send cb event failed.");
} else {
TUYA_BLE_LOG_ERROR("tuya ble send cb event succeed.");
}
}
#endif
break;
default:
break;
}
}
void tuya_ble_handle_dp_data_reported_evt(tuya_ble_evt_param_t *evt)
{
uint8_t encry_mode = 0;
if (tuya_ble_pair_rand_valid_get() == 1) {
encry_mode = ENCRYPTION_MODE_SESSION_KEY;
} else {
encry_mode = ENCRYPTION_MODE_KEY_4;
}
tuya_ble_commData_send(FRM_STAT_REPORT, 0, evt->reported_data.p_data, evt->reported_data.data_len, encry_mode);
if (evt->reported_data.p_data) {
tuya_ble_free(evt->reported_data.p_data);
}
}
void tuya_ble_handle_dp_data_with_flag_reported_evt(tuya_ble_evt_param_t *evt)
{
uint8_t encry_mode = 0;
if (tuya_ble_pair_rand_valid_get() == 1) {
encry_mode = ENCRYPTION_MODE_SESSION_KEY;
} else {
encry_mode = ENCRYPTION_MODE_KEY_4;
}
tuya_ble_commData_send(FRM_DATA_WITH_FLAG_REPORT, 0, evt->flag_reported_data.p_data, evt->flag_reported_data.data_len, encry_mode);
if (evt->flag_reported_data.p_data) {
tuya_ble_free(evt->flag_reported_data.p_data);
}
}
void tuya_ble_handle_dp_data_with_time_reported_evt(tuya_ble_evt_param_t *evt)
{
uint8_t *data_buffer = NULL;
uint16_t data_len;
uint8_t encry_mode = 0;
data_len = 5 + evt->reported_with_time_data.data_len;
data_buffer = (uint8_t *)tuya_ble_malloc(data_len);
if (data_buffer == NULL) {
TUYA_BLE_LOG_ERROR("tuya_ble_handle_dp_data_with_time_reported_evt malloc failed.");
if (evt->reported_with_time_data.p_data) {
tuya_ble_free(evt->reported_with_time_data.p_data);
}
return;
} else {
memset(data_buffer, 0, data_len);
}
if (tuya_ble_pair_rand_valid_get() == 1) {
encry_mode = ENCRYPTION_MODE_SESSION_KEY;
} else {
encry_mode = ENCRYPTION_MODE_KEY_4;
}
data_buffer[0] = 1;
data_buffer[1] = evt->reported_with_time_data.timestamp >> 24;
data_buffer[2] = evt->reported_with_time_data.timestamp >> 16;
data_buffer[3] = evt->reported_with_time_data.timestamp >> 8;
data_buffer[4] = evt->reported_with_time_data.timestamp;
memcpy(&data_buffer[5], evt->reported_with_time_data.p_data, evt->reported_with_time_data.data_len);
tuya_ble_commData_send(FRM_STAT_WITH_TIME_REPORT, 0, data_buffer, data_len, encry_mode);
tuya_ble_free(data_buffer);
if (evt->reported_with_time_data.p_data) {
tuya_ble_free(evt->reported_with_time_data.p_data);
}
}
void tuya_ble_handle_dp_data_with_flag_and_time_reported_evt(tuya_ble_evt_param_t *evt)
{
uint8_t *data_buffer = NULL;
uint16_t data_len;
uint8_t encry_mode = 0;
data_len = 8 + evt->flag_reported_with_time_data.data_len;
data_buffer = (uint8_t *)tuya_ble_malloc(data_len);
if (data_buffer == NULL) {
TUYA_BLE_LOG_ERROR("tuya_ble_handle_dp_data_with_flag_and_time_reported_evt malloc failed.");
if (evt->flag_reported_with_time_data.p_data) {
tuya_ble_free(evt->flag_reported_with_time_data.p_data);
}
return;
} else {
memset(data_buffer, 0, data_len);
}
if (tuya_ble_pair_rand_valid_get() == 1) {
encry_mode = ENCRYPTION_MODE_SESSION_KEY;
} else {
encry_mode = ENCRYPTION_MODE_KEY_4;
}
data_buffer[0] = evt->flag_reported_with_time_data.sn >> 8;
data_buffer[1] = evt->flag_reported_with_time_data.sn;
data_buffer[2] = evt->flag_reported_with_time_data.mode;
data_buffer[3] = 1;
data_buffer[4] = evt->flag_reported_with_time_data.timestamp >> 24;
data_buffer[5] = evt->flag_reported_with_time_data.timestamp >> 16;
data_buffer[6] = evt->flag_reported_with_time_data.timestamp >> 8;
data_buffer[7] = evt->flag_reported_with_time_data.timestamp;
memcpy(&data_buffer[8], evt->flag_reported_with_time_data.p_data, evt->flag_reported_with_time_data.data_len);
tuya_ble_commData_send(FRM_DATA_WITH_FLAG_AND_TIME_REPORT, 0, data_buffer, data_len, encry_mode);
tuya_ble_free(data_buffer);
if (evt->flag_reported_with_time_data.p_data) {
tuya_ble_free(evt->flag_reported_with_time_data.p_data);
}
}
void tuya_ble_handle_dp_data_with_time_string_reported_evt(tuya_ble_evt_param_t *evt)
{
uint8_t *data_buffer = NULL;
uint16_t data_len;
uint8_t encry_mode = 0;
data_len = 14 + evt->reported_with_time_string_data.data_len;
data_buffer = (uint8_t *)tuya_ble_malloc(data_len);
if (data_buffer == NULL) {
TUYA_BLE_LOG_ERROR("tuya_ble_handle_dp_data_with_time_string_reported_evt malloc failed.");
if (evt->reported_with_time_string_data.p_data) {
tuya_ble_free(evt->reported_with_time_string_data.p_data);
}
return;
} else {
memset(data_buffer, 0, data_len);
}
if (tuya_ble_pair_rand_valid_get() == 1) {
encry_mode = ENCRYPTION_MODE_SESSION_KEY;
} else {
encry_mode = ENCRYPTION_MODE_KEY_4;
}
data_buffer[0] = 0;
memcpy(&data_buffer[1], evt->reported_with_time_string_data.time_string, 13);
memcpy(&data_buffer[14], evt->reported_with_time_string_data.p_data, evt->reported_with_time_string_data.data_len);
tuya_ble_commData_send(FRM_STAT_WITH_TIME_REPORT, 0, data_buffer, data_len, encry_mode);
tuya_ble_free(data_buffer);
if (evt->reported_with_time_string_data.p_data) {
tuya_ble_free(evt->reported_with_time_string_data.p_data);
}
}
void tuya_ble_handle_dp_data_with_flag_and_time_string_reported_evt(tuya_ble_evt_param_t *evt)
{
uint8_t *data_buffer = NULL;
uint16_t data_len;
uint8_t encry_mode = 0;
data_len = 17 + evt->flag_reported_with_time_string_data.data_len;
data_buffer = (uint8_t *)tuya_ble_malloc(data_len);
if (data_buffer == NULL) {
TUYA_BLE_LOG_ERROR("tuya_ble_handle_dp_data_with_flag_and_time_string_reported_evt malloc failed.");
if (evt->flag_reported_with_time_string_data.p_data) {
tuya_ble_free(evt->flag_reported_with_time_string_data.p_data);
}
return;
} else {
memset(data_buffer, 0, data_len);
}
if (tuya_ble_pair_rand_valid_get() == 1) {
encry_mode = ENCRYPTION_MODE_SESSION_KEY;
} else {
encry_mode = ENCRYPTION_MODE_KEY_4;
}
data_buffer[0] = evt->flag_reported_with_time_string_data.sn >> 8;
data_buffer[1] = evt->flag_reported_with_time_string_data.sn;
data_buffer[2] = evt->flag_reported_with_time_string_data.mode;
data_buffer[3] = 0;
memcpy(&data_buffer[4], evt->flag_reported_with_time_string_data.time_string, 13);
memcpy(&data_buffer[17], evt->flag_reported_with_time_string_data.p_data, evt->flag_reported_with_time_string_data.data_len);
tuya_ble_commData_send(FRM_DATA_WITH_FLAG_AND_TIME_REPORT, 0, data_buffer, data_len, encry_mode);
tuya_ble_free(data_buffer);
if (evt->flag_reported_with_time_string_data.p_data) {
tuya_ble_free(evt->flag_reported_with_time_string_data.p_data);
}
}
void tuya_ble_handle_dp_data_send_evt(tuya_ble_evt_param_t *evt)
{
uint8_t encry_mode = 0;
if (tuya_ble_pair_rand_valid_get() == 1) {
encry_mode = ENCRYPTION_MODE_SESSION_KEY;
} else {
encry_mode = ENCRYPTION_MODE_KEY_4;
}
tuya_ble_commData_send(FRM_DP_DATA_SEND_REQ, 0, evt->dp_send_data.p_data, evt->dp_send_data.data_len, encry_mode);
if (evt->dp_send_data.p_data) {
tuya_ble_free(evt->dp_send_data.p_data);
}
}
void tuya_ble_handle_dp_data_with_time_send_evt(tuya_ble_evt_param_t *evt)
{
uint8_t encry_mode = 0;
if (tuya_ble_pair_rand_valid_get() == 1) {
encry_mode = ENCRYPTION_MODE_SESSION_KEY;
} else {
encry_mode = ENCRYPTION_MODE_KEY_4;
}
tuya_ble_commData_send(FRM_DP_DATA_WITH_TIME_SEND_REQ, 0, evt->dp_with_time_send_data.p_data, evt->dp_with_time_send_data.data_len, encry_mode);
if (evt->dp_with_time_send_data.p_data) {
tuya_ble_free(evt->dp_with_time_send_data.p_data);
}
}
void tuya_ble_handle_device_unbind_evt(tuya_ble_evt_param_t *evt)
{
tuya_ble_cb_evt_param_t event;
tuya_ble_device_unbond();
event.evt = TUYA_BLE_CB_EVT_CONNECTE_STATUS;
event.connect_status = tuya_ble_connect_status_get();
if (tuya_ble_cb_event_send(&event) != 0) {
TUYA_BLE_LOG_ERROR("tuya_ble_handle_factory_reset_evt-tuya ble send cb event (connect status update) failed.");
} else {
}
event.evt = TUYA_BLE_CB_EVT_UNBIND_RESET_RESPONSE;
event.reset_response_data.type = RESET_TYPE_UNBIND;
event.reset_response_data.status = 0;
if (tuya_ble_cb_event_send(&event) != 0) {
TUYA_BLE_LOG_ERROR("tuya_ble_handle_device_unbind_evt-tuya ble send cb event (TUYA_BLE_CB_EVT_UNBIND_RESET_RESPONSE) failed.");
} else {
}
}
void tuya_ble_handle_factory_reset_evt(tuya_ble_evt_param_t *evt)
{
tuya_ble_cb_evt_param_t event;
memset(tuya_ble_current_para.sys_settings.device_virtual_id, 0, DEVICE_VIRTUAL_ID_LEN);
tuya_ble_device_unbond();
event.evt = TUYA_BLE_CB_EVT_CONNECTE_STATUS;
event.connect_status = tuya_ble_connect_status_get();
if (tuya_ble_cb_event_send(&event) != 0) {
TUYA_BLE_LOG_ERROR("tuya_ble_handle_factory_reset_evt-tuya ble send cb event (connect status update) failed.");
} else {
}
event.evt = TUYA_BLE_CB_EVT_UNBIND_RESET_RESPONSE;
event.reset_response_data.type = RESET_TYPE_FACTORY_RESET;
event.reset_response_data.status = 0;
if (tuya_ble_cb_event_send(&event) != 0) {
TUYA_BLE_LOG_ERROR("tuya_ble_handle_factory_reset_evt-tuya ble send cb event (TUYA_BLE_CB_EVT_UNBIND_RESET_RESPONSE) failed.");
} else {
}
}
void tuya_ble_handle_ota_response_evt(tuya_ble_evt_param_t *evt)
{
uint16_t ota_cmd_type = 0;
uint8_t encry_mode = 0;
if (tuya_ble_pair_rand_valid_get() == 1) {
encry_mode = ENCRYPTION_MODE_SESSION_KEY;
} else {
encry_mode = ENCRYPTION_MODE_KEY_4;
}
switch (evt->ota_response_data.type) {
case TUYA_BLE_OTA_REQ:
ota_cmd_type = FRM_OTA_START_REQ;
break;
case TUYA_BLE_OTA_FILE_INFO:
ota_cmd_type = FRM_OTA_FILE_INFOR_REQ;
break;
case TUYA_BLE_OTA_FILE_OFFSET_REQ :
ota_cmd_type = FRM_OTA_FILE_OFFSET_REQ;
break;
case TUYA_BLE_OTA_DATA :
ota_cmd_type = FRM_OTA_DATA_REQ;
break;
case TUYA_BLE_OTA_END :
ota_cmd_type = FRM_OTA_END_REQ;
break;
default:
break;
}
if (ota_cmd_type != 0) {
tuya_ble_commData_send(ota_cmd_type, 0, evt->ota_response_data.p_data, evt->ota_response_data.data_len, encry_mode);
}
if (evt->ota_response_data.p_data) {
tuya_ble_free(evt->ota_response_data.p_data);
}
}
void tuya_ble_handle_data_passthrough_evt(tuya_ble_evt_param_t *evt)
{
uint8_t encry_mode = 0;
if (tuya_ble_current_para.sys_settings.bound_flag) {
if (tuya_ble_pair_rand_valid_get() == 1) {
encry_mode = ENCRYPTION_MODE_SESSION_KEY;
} else {
encry_mode = ENCRYPTION_MODE_KEY_4;
}
} else {
encry_mode = ENCRYPTION_MODE_KEY_2;
}
tuya_ble_commData_send(FRM_DATA_PASSTHROUGH_REQ, 0, evt->passthrough_data.p_data, evt->passthrough_data.data_len, encry_mode);
if (evt->passthrough_data.p_data) {
tuya_ble_free(evt->passthrough_data.p_data);
}
}
void tuya_ble_handle_data_prod_test_response_evt(tuya_ble_evt_param_t *evt)
{
uint8_t encry_mode = 0;
tuya_ble_connect_status_t connect_status;
if (evt->prod_test_res_data.channel == 0) {
tuya_ble_common_uart_send_data(evt->prod_test_res_data.p_data, evt->prod_test_res_data.data_len);
} else if (evt->prod_test_res_data.channel == 1) {
connect_status = tuya_ble_connect_status_get();
if (connect_status == BONDING_CONN) {
encry_mode = ENCRYPTION_MODE_SESSION_KEY;
} else {
#if (TUYA_BLE_PROD_TEST_SUPPORT_ENCRYPTION != 0)
encry_mode = ENCRYPTION_MODE_FTM_KEY;
#else
encry_mode = ENCRYPTION_MODE_NONE;
#endif
}
tuya_ble_commData_send(FRM_FACTORY_TEST_RESP, 0, evt->prod_test_res_data.p_data, evt->prod_test_res_data.data_len, encry_mode);
}
if (evt->prod_test_res_data.p_data) {
tuya_ble_free(evt->prod_test_res_data.p_data);
}
}
void tuya_ble_handle_uart_cmd_evt(tuya_ble_evt_param_t *evt)
{
uint8_t sum;
uint8_t *uart_send_buffer;
uint16_t uart_send_len;
TUYA_BLE_LOG_HEXDUMP_DEBUG("received uart cmd data", (uint8_t *)evt->uart_cmd_data.p_data, evt->uart_cmd_data.data_len); //
#if (TUYA_BLE_DEVICE_REGISTER_FROM_BLE)
if (evt->uart_cmd_data.data_len > 0) {
sum = tuya_ble_check_sum(evt->uart_cmd_data.p_data, evt->uart_cmd_data.data_len - 1);
if (sum == evt->uart_cmd_data.p_data[evt->uart_cmd_data.data_len - 1]) {
switch (evt->uart_cmd_data.p_data[0]) {
case 0x55:
tuya_ble_uart_common_process(evt->uart_cmd_data.p_data, evt->uart_cmd_data.data_len);
break;
case 0x66:
tuya_ble_app_production_test_process(0, evt->uart_cmd_data.p_data, evt->uart_cmd_data.data_len);
break;
default:
break;
};
} else {
TUYA_BLE_LOG_ERROR("uart receive data check_sum error , receive sum = 0x%02x ; cal sum = 0x%02x", evt->uart_cmd_data.p_data[evt->uart_cmd_data.data_len - 1], sum);
}
}
#endif
if (evt->uart_cmd_data.p_data) {
tuya_ble_free(evt->uart_cmd_data.p_data);
}
}
void tuya_ble_handle_ble_cmd_evt(tuya_ble_evt_param_t *evt)
{
tuya_ble_evt_process(evt->ble_cmd_data.cmd, evt->ble_cmd_data.p_data, evt->ble_cmd_data.data_len);
if (evt->ble_cmd_data.p_data) {
tuya_ble_free(evt->ble_cmd_data.p_data);
}
}
void tuya_ble_handle_net_config_response_evt(tuya_ble_evt_param_t *evt)
{
uint8_t encry_mode = 0;
uint8_t data[2];
if (tuya_ble_pair_rand_valid_get() == 1) {
encry_mode = ENCRYPTION_MODE_KEY_2;
} else {
encry_mode = ENCRYPTION_MODE_KEY_1;
}
data[0] = ((int16_t)(evt->net_config_response_data.result_code)) >> 8;
data[1] = (int16_t)(evt->net_config_response_data.result_code);
tuya_ble_commData_send(FRM_NET_CONFIG_RESPONSE_REPORT_REQ, 0, data, 2, encry_mode);
}
void tuya_ble_handle_time_request_evt(tuya_ble_evt_param_t *evt)
{
uint8_t encry_mode = 0;
uint16_t cmd;
if (tuya_ble_pair_rand_valid_get() == 1) {
encry_mode = ENCRYPTION_MODE_SESSION_KEY;
} else {
encry_mode = ENCRYPTION_MODE_KEY_4;
}
if (evt->time_req_data.time_type == 0) {
cmd = FRM_GET_UNIX_TIME_CHAR_MS_REQ;
} else if (evt->time_req_data.time_type == 1) {
cmd = FRM_GET_UNIX_TIME_CHAR_DATE_REQ;
} else if (evt->time_req_data.time_type == 2) {
cmd = FRM_GET_APP_LOCAL_TIME_REQ;
} else {
return;
}
tuya_ble_commData_send(cmd, 0, NULL, 0, encry_mode);
}
void tuya_ble_handle_extend_time_request_evt(tuya_ble_evt_param_t *evt)
{
uint8_t encry_mode = 0;
uint8_t data[1];
if (tuya_ble_pair_rand_valid_get() == 1) {
encry_mode = ENCRYPTION_MODE_SESSION_KEY;
} else {
encry_mode = ENCRYPTION_MODE_KEY_4;
}
data[0] = evt->extend_time_req_data.n_years_dst;
tuya_ble_commData_send(FRM_GET_UNIX_TIME_WITH_DST_REQ, 0, data, 1, encry_mode);
}
void tuya_ble_handle_unbound_response_evt(tuya_ble_evt_param_t *evt)
{
#if (!TUYA_BLE_DEVICE_REGISTER_FROM_BLE)
uint8_t encry_mode = 0;
uint8_t result;
encry_mode = ENCRYPTION_MODE_SESSION_KEY;
result = evt->ubound_res_data.result_code;
tuya_ble_commData_send(FRM_UNBONDING_RESP, 0, &result, 1, encry_mode);
#else
return;
#endif
}
void tuya_ble_handle_anomaly_unbound_response_evt(tuya_ble_evt_param_t *evt)
{
#if (!TUYA_BLE_DEVICE_REGISTER_FROM_BLE)
uint8_t encry_mode = 0;
uint8_t result;
encry_mode = ENCRYPTION_MODE_SESSION_KEY;
result = evt->anomaly_ubound_res_data.result_code;
tuya_ble_commData_send(FRM_ANOMALY_UNBONDING_RESP, 0, &result, 1, encry_mode);
#else
return;
#endif
}
void tuya_ble_handle_device_reset_response_evt(tuya_ble_evt_param_t *evt)
{
#if (!TUYA_BLE_DEVICE_REGISTER_FROM_BLE)
uint8_t encry_mode = 0;
uint8_t result;
encry_mode = ENCRYPTION_MODE_SESSION_KEY;
result = evt->device_reset_res_data.result_code;
tuya_ble_commData_send(FRM_DEVICE_RESET_RESP, 0, &result, 1, encry_mode);
#else
return;
#endif
}
#if (TUYA_BLE_PROTOCOL_VERSION_HIGN >= 3)
void tuya_ble_handle_connecting_request_evt(tuya_ble_evt_param_t *evt)
{
tuya_ble_connect_status_t currnet_connect_status;
currnet_connect_status = tuya_ble_connect_status_get();
if ((currnet_connect_status != BONDING_UNCONN) && (currnet_connect_status != UNBONDING_UNCONN)) {
return;
}
if (evt->connecting_request_data.cmd == 0) {
tuya_ble_adv_change();
} else {
tuya_ble_adv_change_with_connecting_request();
}
}
#endif
extern void tuya_ble_connect_monitor_timer_start(void);
void tuya_ble_handle_connect_change_evt(tuya_ble_evt_param_t *evt)
{
tuya_ble_cb_evt_param_t event;
uint8_t send_cb_flag = 1;
if (evt->connect_change_evt == TUYA_BLE_CONNECTED) {
TUYA_BLE_LOG_INFO("Connected!");
tuya_ble_reset_ble_sn();
if (tuya_ble_current_para.sys_settings.bound_flag != 1) {
tuya_ble_connect_status_set(UNBONDING_UNAUTH_CONN);
} else {
tuya_ble_connect_status_set(BONDING_UNAUTH_CONN);
}
tuya_ble_connect_monitor_timer_start();
#if (TUYA_BLE_DEVICE_REGISTER_FROM_BLE&&TUYA_BLE_DEVICE_AUTH_DATA_STORE)
tuya_ble_internal_production_test_with_ble_flag_clear();
#endif
#if (TUYA_BLE_SECURE_CONNECTION_TYPE==TUYA_BLE_SECURE_CONNECTION_WITH_AUTH_KEY_ADVANCED_ENCRYPTION)
tuya_ble_auth_data_reset();
#endif
#if TUYA_BLE_LINK_LAYER_ENCRYPTION_SUPPORT_ENABLE
tuya_ble_link_status_set(LINK_CONNECTED);
#endif
} else if (evt->connect_change_evt == TUYA_BLE_DISCONNECTED) {
TUYA_BLE_LOG_INFO("Disonnected");
tuya_ble_reset_ble_sn();
tuya_ble_pair_rand_clear();
tuya_ble_air_recv_packet_free();
if (tuya_ble_current_para.sys_settings.bound_flag == 1) {
tuya_ble_connect_status_set(BONDING_UNCONN);
} else {
tuya_ble_connect_status_set(UNBONDING_UNCONN);
}
#if TUYA_BLE_LINK_LAYER_ENCRYPTION_SUPPORT_ENABLE
tuya_ble_link_status_set(LINK_DISCONNECTED);
#endif
} else {
TUYA_BLE_LOG_WARNING("unknown connect_change_evt!");
}
if (send_cb_flag) {
event.evt = TUYA_BLE_CB_EVT_CONNECTE_STATUS;
event.connect_status = tuya_ble_connect_status_get();
if (tuya_ble_cb_event_send(&event) != 0) {
TUYA_BLE_LOG_ERROR("tuya ble send cb event failed.");
} else {
TUYA_BLE_LOG_DEBUG("tuya ble send cb event succeed.");
}
}
}
void tuya_ble_handle_link_update_evt(tuya_ble_evt_param_t *evt)
{
#if TUYA_BLE_LINK_LAYER_ENCRYPTION_SUPPORT_ENABLE
if (evt->link_update_data.link_app_status == 1) {
tuya_ble_link_status_set(LINK_ENCRYPTED);
if (tuya_ble_connect_status_get() != BONDING_CONN) {
tuya_ble_connect_monitor_timer_stop();
}
TUYA_BLE_LOG_DEBUG("link encrypted.");
}
#endif
}
void tuya_ble_handle_ble_data_evt(uint8_t *buf, uint16_t len)
{
tuya_ble_commonData_rx_proc(buf, len);
if (len > 20) {
tuya_ble_free(buf);
}
}
@@ -0,0 +1,193 @@
/**
* \file tuya_ble_event_handler_weak.c
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#include "tuya_ble_stdlib.h"
#include "tuya_ble_type.h"
#include "tuya_ble_event_handler.h"
__TUYA_BLE_WEAK void tuya_ble_handle_device_info_update_evt(tuya_ble_evt_param_t *evt)
{
}
__TUYA_BLE_WEAK void tuya_ble_handle_dp_data_reported_evt(tuya_ble_evt_param_t *evt)
{
}
__TUYA_BLE_WEAK void tuya_ble_handle_dp_data_with_time_reported_evt(tuya_ble_evt_param_t *evt)
{
}
__TUYA_BLE_WEAK void tuya_ble_handle_dp_data_with_time_string_reported_evt(tuya_ble_evt_param_t *evt)
{
}
__TUYA_BLE_WEAK void tuya_ble_handle_dp_data_with_flag_reported_evt(tuya_ble_evt_param_t *evt)
{
}
__TUYA_BLE_WEAK void tuya_ble_handle_dp_data_with_flag_and_time_reported_evt(tuya_ble_evt_param_t *evt)
{
}
__TUYA_BLE_WEAK void tuya_ble_handle_dp_data_with_flag_and_time_string_reported_evt(tuya_ble_evt_param_t *evt)
{
}
__TUYA_BLE_WEAK void tuya_ble_handle_dp_data_send_evt(tuya_ble_evt_param_t *evt)
{
}
__TUYA_BLE_WEAK void tuya_ble_handle_dp_data_with_time_send_evt(tuya_ble_evt_param_t *evt)
{
}
__TUYA_BLE_WEAK void tuya_ble_handle_device_unbind_evt(tuya_ble_evt_param_t *evt)
{
}
__TUYA_BLE_WEAK void tuya_ble_handle_factory_reset_evt(tuya_ble_evt_param_t *evt)
{
}
__TUYA_BLE_WEAK void tuya_ble_handle_ota_response_evt(tuya_ble_evt_param_t *evt)
{
}
__TUYA_BLE_WEAK void tuya_ble_handle_bulk_data_evt(tuya_ble_evt_param_t *evt)
{
}
__TUYA_BLE_WEAK void tuya_ble_handle_data_passthrough_evt(tuya_ble_evt_param_t *evt)
{
}
__TUYA_BLE_WEAK void tuya_ble_handle_data_prod_test_response_evt(tuya_ble_evt_param_t *evt)
{
}
__TUYA_BLE_WEAK void tuya_ble_handle_uart_cmd_evt(tuya_ble_evt_param_t *evt)
{
}
__TUYA_BLE_WEAK void tuya_ble_handle_ble_cmd_evt(tuya_ble_evt_param_t *evt)
{
}
__TUYA_BLE_WEAK void tuya_ble_handle_net_config_response_evt(tuya_ble_evt_param_t *evt)
{
}
__TUYA_BLE_WEAK void tuya_ble_handle_time_request_evt(tuya_ble_evt_param_t *evt)
{
}
__TUYA_BLE_WEAK void tuya_ble_handle_extend_time_request_evt(tuya_ble_evt_param_t *evt)
{
}
__TUYA_BLE_WEAK void tuya_ble_handle_unbound_response_evt(tuya_ble_evt_param_t *evt)
{
}
__TUYA_BLE_WEAK void tuya_ble_handle_anomaly_unbound_response_evt(tuya_ble_evt_param_t *evt)
{
}
__TUYA_BLE_WEAK void tuya_ble_handle_device_reset_response_evt(tuya_ble_evt_param_t *evt)
{
}
__TUYA_BLE_WEAK void tuya_ble_handle_connect_change_evt(tuya_ble_evt_param_t *evt)
{
}
__TUYA_BLE_WEAK void tuya_ble_handle_connecting_request_evt(tuya_ble_evt_param_t *evt)
{
}
__TUYA_BLE_WEAK void tuya_ble_handle_ble_data_evt(uint8_t *buf, uint16_t len)
{
}
__TUYA_BLE_WEAK void tuya_ble_handle_link_update_evt(tuya_ble_evt_param_t *evt)
{
}
__TUYA_BLE_WEAK void tuya_ble_handle_weather_data_request_evt(tuya_ble_evt_param_t *evt)
{
}
@@ -0,0 +1,447 @@
/**
* \file tuya_ble_feature_weather.c
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#include "tuya_ble_stdlib.h"
#include "tuya_ble_type.h"
#include "tuya_ble_heap.h"
#include "tuya_ble_mem.h"
#include "tuya_ble_api.h"
#include "tuya_ble_port.h"
#include "tuya_ble_main.h"
#include "tuya_ble_internal_config.h"
#include "tuya_ble_feature_weather.h"
#include "tuya_ble_data_handler.h"
#include "tuya_ble_mutli_tsf_protocol.h"
#include "tuya_ble_utils.h"
#include "tuya_ble_secure.h"
#include "tuya_ble_main.h"
#include "tuya_ble_storage.h"
#include "tuya_ble_unix_time.h"
#include "tuya_ble_log.h"
#include "tuya_ble_gatt_send_queue.h"
#if ( (TUYA_BLE_PROTOCOL_VERSION_HIGN==4) && (TUYA_BLE_FEATURE_WEATHER_ENABLE != 0) )
/**@brief Weather key string. */
const char *weather_key[] = {
"w.temp",
"w.thigh",
"w.tlow",
"w.humidity",
"w.condition",
"w.pressure",
"w.realFeel",
"w.uvi",
"w.sunRise",
"w.sunSet",
"t.unix",
"t.local",
"w.windSpeed",
"w.windDir",
"w.windLevel",
"w.aqi",
"w.tips",
"w.rank",
"w.pm10",
"w.pm25",
"w.o3",
"w.no2",
"w.co",
"w.so2",
"w.conditionNum",
"w.data.", //**< w.data.n, n rang from [1-7]
};
static tuya_ble_weather_location_type_t cur_req_weather_location_type;
/**
* @brief Function for calculate weather key max string length
*
* @return The max string len
*
* */
static uint16_t calc_weather_key_max_string_len(void)
{
int i, string_array_element = sizeof(weather_key) / sizeof(weather_key[0]);
uint16_t string_len = 0, tmp;
for (i = 0; i < string_array_element; i++) {
tmp = strlen(weather_key[i]);
if (tmp > string_len) {
string_len = tmp;
}
}
return string_len;
}
/**
* @brief Function for convert weather key to enum type
*
* @note For example input key "w.temp.0", convert type=WKT_TEMP day=1
*
* @param[in] key The ponit of input weather key string
* @param[out] type Convert type
* @param[out] day The day of weather data, rang from [1-7], 1-means today
*
* @retval TUYA_BLE_ERR_INVALID_PARAM The provided Parameters are not valid.
* @retval TUYA_BLE_ERR_NOT_FOUND No corresponding key was found.
* @retval TUYA_BLE_SUCCESS Successful.
*
* */
static tuya_ble_status_t weather_key_string_to_enum_type(char *key, uint8_t key_str_len, tuya_ble_weather_key_type_t *type, uint8_t *day)
{
int i, string_array_element;
if (key == NULL) {
return TUYA_BLE_ERR_INVALID_PARAM;
}
string_array_element = sizeof(weather_key) / sizeof(weather_key[0]);
for (i = 0; i < string_array_element; i++) {
if ((strncmp(key, weather_key[i], strlen(weather_key[i])) == 0) && \
(key_str_len <= (strlen(weather_key[i]) + 2))) {
if (type != NULL) {
*type = (tuya_ble_weather_key_type_t)(1 << i);
}
if (day != NULL) {
if (key_str_len > strlen(weather_key[i])) {
/* key.n */
*day = key[strlen(weather_key[i]) + 1] - '0' + 1;
} else {
/* only today */
*day = 1;
}
}
return TUYA_BLE_SUCCESS;
}
}
return TUYA_BLE_ERR_NOT_FOUND;
}
tuya_ble_status_t tuya_ble_feature_weather_key_enum_type_to_string(tuya_ble_weather_key_type_t type, char *key)
{
int bit;
if (type >= WKT_COMBINE_BITMAP_MAXVAL || key == NULL) {
return TUYA_BLE_ERR_INVALID_PARAM;
}
/* Convert to actual weather key string based on type */
for (bit = 0; bit < SUPPORT_WEATHER_KEY_TYPE_MAX_NUMS; bit++) {
if (((type >> bit) & 0x01) == 0x01) {
memcpy(key, weather_key[bit], strlen(weather_key[bit]));
return TUYA_BLE_SUCCESS;
}
}
return TUYA_BLE_ERR_NOT_FOUND;
}
/**
* @brief Function for parse weather lktlv format data
*
* @param[in] recv_data The point of input data
* @param[in] recv_len The length of input data
*
* @retval TUYA_BLE_ERR_INVALID_PARAM The provided Parameters are not valid.
* @retval TUYA_BLE_SUCCESS Successful.
*
* */
static tuya_ble_status_t weather_data_lktlv_parse(uint8_t *in, uint16_t in_len, uint8_t *out, uint16_t *out_len, uint16_t *object_nums)
{
uint8_t key_len, value_len, n_day;
uint16_t object_len = 0;
tuya_ble_weather_key_type_t weather_type;
tuya_ble_weather_value_type_t value_type;
tuya_ble_wd_object_t *object;
uint16_t tmp_out_len = 0, tmp_object_nums = 0;
if (in == NULL || in_len == 0 || out == NULL || out_len == NULL || object_nums == NULL) {
return TUYA_BLE_ERR_INVALID_PARAM;
}
/*-------------------------------------------------------------------------
| 1byte | key_len | 1byte | 1byte | value_len |
| key_len | key | value_type | value_len | value |
---------------------------------------------------------------------------*/
for (;;) {
key_len = in[0 + object_len];
value_type = in[1 + key_len + object_len];
value_len = in[2 + key_len + object_len];
if (weather_key_string_to_enum_type((char *)&in[1 + object_len], key_len, &weather_type, &n_day) != TUYA_BLE_SUCCESS) {
return TUYA_BLE_ERR_INVALID_PARAM;
}
TUYA_BLE_LOG_DEBUG("parse weather data, n_day=[%d] type=[0x%08x] val_type=[%d] ,", n_day, weather_type, value_type);
TUYA_BLE_LOG_HEXDUMP_DEBUG("value :", &in[3 + key_len + object_len], value_len);
/* Convert lktlv format to tuya_ble_wd_object */
object = (tuya_ble_wd_object_t *)tuya_ble_malloc(sizeof(tuya_ble_wd_object_t) + value_len);
if (object == NULL) {
return TUYA_BLE_ERR_NO_MEM;
}
object->n_day = n_day;
object->key_type = weather_type;
object->val_type = value_type;
object->value_len = value_len;
memcpy(&(object->vaule), &in[3 + key_len + object_len], value_len);
memcpy(&out[tmp_out_len], object, (sizeof(tuya_ble_wd_object_t) + value_len));
tmp_out_len += (sizeof(tuya_ble_wd_object_t) + value_len);
tuya_ble_free((uint8_t *)object);
tmp_object_nums += 1;
object_len += (key_len + value_len + 3);
if (object_len >= in_len) {
*out_len = tmp_out_len;
*object_nums = tmp_object_nums;
break;
}
}
TUYA_BLE_LOG_DEBUG("parse weather data finish, total count=[%d]", tmp_object_nums);
return TUYA_BLE_SUCCESS;
}
tuya_ble_status_t tuya_ble_feature_weather_data_request_with_location(tuya_ble_weather_location_type_t location_type, uint32_t combine_type, uint8_t n_days)
{
tuya_ble_evt_param_t event;
uint8_t *ble_evt_buffer = NULL;
uint16_t ble_evt_buffer_len = 0;
uint16_t per_weather_key_malloc_size, weather_key_len;
int bit, count;
if ((location_type >= WLT_MAX) || (location_type == WLT_CUSTOM_LOCATION)) {
TUYA_BLE_LOG_ERROR("request weather location type this sdk version unsupport");
return TUYA_BLE_ERR_INVALID_PARAM;
}
if (combine_type >= WKT_COMBINE_BITMAP_MAXVAL || n_days < 1 || n_days > 7) {
return TUYA_BLE_ERR_INVALID_PARAM;
}
/* Calc total bit1 counters */
count = tuya_ble_count_bits((uint32_t)(combine_type));
if (0 == count) {
return TUYA_BLE_ERR_INVALID_PARAM;
}
/* Malloc data buffer */
count += 1; // add w.data.n
per_weather_key_malloc_size = (calc_weather_key_max_string_len() + 4);
ble_evt_buffer = (uint8_t *)tuya_ble_malloc(2 + per_weather_key_malloc_size * count);
if (ble_evt_buffer == NULL) {
return TUYA_BLE_ERR_NO_MEM;
}
/* Fill version & location info */
cur_req_weather_location_type = location_type;
ble_evt_buffer[0] = 0;
ble_evt_buffer[1] = (uint8_t)(location_type);
ble_evt_buffer_len += 2;
/* Convert to actual weather key based on type */
for (bit = 0; bit < SUPPORT_WEATHER_KEY_TYPE_MAX_NUMS; bit++) {
if (((combine_type >> bit) & 0x01) == 0x01) {
/* Weather data format: [len + key] */
weather_key_len = strlen(weather_key[bit]);
ble_evt_buffer[ble_evt_buffer_len] = weather_key_len;
memcpy(&ble_evt_buffer[ble_evt_buffer_len + 1], weather_key[bit], weather_key_len);
ble_evt_buffer_len += (1 + weather_key_len);
}
}
/* Fill request n_days */
weather_key_len = sprintf((char *)&ble_evt_buffer[ble_evt_buffer_len + 1], "w.date.%d", n_days);
ble_evt_buffer[ble_evt_buffer_len] = weather_key_len;
ble_evt_buffer_len += (1 + weather_key_len);
TUYA_BLE_LOG_DEBUG("request weather location=[%d] type=[0x%x], n_days=[%d]", location_type, combine_type, n_days);
TUYA_BLE_LOG_HEXDUMP_DEBUG("request weather data :", ble_evt_buffer, ble_evt_buffer_len);
event.hdr.event = TUYA_BLE_EVT_WEATHER_DATA_REQ;
event.weather_req_data.p_data = ble_evt_buffer;
event.weather_req_data.data_len = ble_evt_buffer_len;
if (tuya_ble_event_send(&event) != 0) {
TUYA_BLE_LOG_ERROR("tuya_event_send weather req data error");
tuya_ble_free(ble_evt_buffer);
return TUYA_BLE_ERR_NO_EVENT;
}
return TUYA_BLE_SUCCESS;
}
tuya_ble_status_t tuya_ble_feature_weather_data_request(uint32_t combine_type, uint8_t n_days)
{
return tuya_ble_feature_weather_data_request_with_location(WLT_APP_CURRENT_LOCATION, combine_type, n_days);
}
void tuya_ble_handle_weather_data_request_evt(tuya_ble_evt_param_t *evt)
{
uint8_t encry_mode = 0;
encry_mode = (tuya_ble_pair_rand_valid_get()) ? (ENCRYPTION_MODE_SESSION_KEY) : (ENCRYPTION_MODE_KEY_4);
tuya_ble_commData_send(FRM_WEATHER_DATA_REQUEST, 0, evt->weather_req_data.p_data, evt->weather_req_data.data_len, encry_mode);
if (evt->weather_req_data.p_data) {
tuya_ble_free(evt->weather_req_data.p_data);
}
}
void tuya_ble_handle_weather_data_request_response(uint8_t *recv_data, uint16_t recv_len)
{
tuya_ble_cb_evt_param_t event;
uint16_t data_len = recv_data[11] << 8 | recv_data[12];
if (data_len != 1) {
TUYA_BLE_LOG_ERROR("tuya_ble_handle_weather_data_request_response- invalid data len received.");
return;
}
event.evt = TUYA_BLE_CB_EVT_WEATHER_DATA_REQ_RESPONSE;
event.weather_req_response_data.status = recv_data[13];
if (tuya_ble_cb_event_send(&event) != 0) {
TUYA_BLE_LOG_ERROR("tuya_ble_handle_weather_data_request_response-tuya ble send cb event failed.");
} else {
}
}
void tuya_ble_handle_weather_data_received(uint8_t *recv_data, uint16_t recv_len)
{
uint8_t p_buf[1];
uint16_t data_len = 0;
uint32_t ack_sn = 0;
tuya_ble_cb_evt_param_t event;
uint16_t weather_data_start_pos, weather_data_len;
uint16_t buffer_len, object_count;
ack_sn = recv_data[1] << 24;
ack_sn += recv_data[2] << 16;
ack_sn += recv_data[3] << 8;
ack_sn += recv_data[4];
data_len = (recv_data[11] << 8) | recv_data[12];
if ((data_len < 5) || (data_len > TUYA_BLE_RECEIVE_MAX_DATA_LEN)) {
TUYA_BLE_LOG_ERROR("cmd weather data write error,receive data len == %d", data_len);
p_buf[0] = 0x01;
tuya_ble_commData_send(FRM_WEATHER_DATA_RECEIVED_RESP, ack_sn, p_buf, 1, ENCRYPTION_MODE_SESSION_KEY);
return;
} else if (recv_data[13] != 0x00) {
TUYA_BLE_LOG_ERROR("cmd weather data write error, version not support");
p_buf[0] = 0x01;
tuya_ble_commData_send(FRM_WEATHER_DATA_RECEIVED_RESP, ack_sn, p_buf, 1, ENCRYPTION_MODE_SESSION_KEY);
return;
} else if ((recv_data[14] >= WLT_MAX) || (recv_data[14] == WLT_CUSTOM_LOCATION)) {
TUYA_BLE_LOG_ERROR("cmd weather data write error, location type this sdk version unsupport");
p_buf[0] = 0x01;
tuya_ble_commData_send(FRM_WEATHER_DATA_RECEIVED_RESP, ack_sn, p_buf, 1, ENCRYPTION_MODE_SESSION_KEY);
return;
} else if (recv_data[14] != cur_req_weather_location_type) {
TUYA_BLE_LOG_ERROR("cmd weather data write error, location type no correspondence");
p_buf[0] = 0x01;
tuya_ble_commData_send(FRM_WEATHER_DATA_RECEIVED_RESP, ack_sn, p_buf, 1, ENCRYPTION_MODE_SESSION_KEY);
return;
}
TUYA_BLE_LOG_HEXDUMP_DEBUG("cmd weather data write : ", recv_data + 13, data_len);
/* parse location info */
weather_data_start_pos = 15;
weather_data_len = (data_len - 2);
uint8_t *ble_cb_evt_buffer = (uint8_t *)tuya_ble_malloc(weather_data_len);
if (ble_cb_evt_buffer == NULL) {
TUYA_BLE_LOG_ERROR("ble_cb_evt_buffer malloc failed.");
p_buf[0] = 0x01;
tuya_ble_commData_send(FRM_WEATHER_DATA_RECEIVED_RESP, ack_sn, p_buf, 1, ENCRYPTION_MODE_SESSION_KEY);
return;
}
if (weather_data_lktlv_parse(&recv_data[weather_data_start_pos], weather_data_len, ble_cb_evt_buffer, &buffer_len, &object_count) != TUYA_BLE_SUCCESS) {
tuya_ble_free(ble_cb_evt_buffer);
TUYA_BLE_LOG_ERROR("cmd weather data parse failed");
p_buf[0] = 0x01;
tuya_ble_commData_send(FRM_WEATHER_DATA_RECEIVED_RESP, ack_sn, p_buf, 1, ENCRYPTION_MODE_SESSION_KEY);
return;
}
event.evt = TUYA_BLE_CB_EVT_WEATHER_DATA_RECEIVED;
event.weather_received_data.object_count = object_count;
event.weather_received_data.location = recv_data[14];
event.weather_received_data.p_data = ble_cb_evt_buffer;
event.weather_received_data.data_len = buffer_len;
if (tuya_ble_cb_event_send(&event) != 0) {
tuya_ble_free(ble_cb_evt_buffer);
TUYA_BLE_LOG_ERROR("tuya_ble_handle_weather_data_received-tuya ble send cb event failed.");
p_buf[0] = 0x01;
tuya_ble_commData_send(FRM_WEATHER_DATA_RECEIVED_RESP, ack_sn, p_buf, 1, ENCRYPTION_MODE_SESSION_KEY);
} else {
p_buf[0] = 0x00;
tuya_ble_commData_send(FRM_WEATHER_DATA_RECEIVED_RESP, ack_sn, p_buf, 1, ENCRYPTION_MODE_SESSION_KEY);
}
}
#else
void tuya_ble_handle_weather_data_request_evt(tuya_ble_evt_param_t *evt)
{
}
void tuya_ble_handle_weather_data_request_response(uint8_t *recv_data, uint16_t recv_len)
{
}
void tuya_ble_handle_weather_data_received(uint8_t *recv_data, uint16_t recv_len)
{
}
#endif
@@ -0,0 +1,125 @@
/**
* \file tuya_ble_gatt_send_queue.c
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#include "tuya_ble_stdlib.h"
#include "tuya_ble_gatt_send_queue.h"
#include "tuya_ble_type.h"
#include "tuya_ble_config.h"
#include "tuya_ble_port.h"
#include "tuya_ble_mem.h"
#include "tuya_ble_main.h"
#include "tuya_ble_log.h"
static tuya_ble_queue_t gatt_send_queue;
static tuya_ble_gatt_send_data_t send_buf[TUYA_BLE_GATT_SEND_DATA_QUEUE_SIZE];
static volatile uint8_t gatt_queue_flag = 0;
void tuya_ble_gatt_send_queue_init(void)
{
gatt_queue_flag = 0;
tuya_ble_queue_init(&gatt_send_queue, (void *) send_buf, TUYA_BLE_GATT_SEND_DATA_QUEUE_SIZE, sizeof(tuya_ble_gatt_send_data_t));
}
static void tuya_ble_gatt_send_queue_free(void)
{
tuya_ble_gatt_send_data_t data = {0};
memset(&data, 0, sizeof(tuya_ble_gatt_send_data_t));
while (tuya_ble_dequeue(&gatt_send_queue, &data) == TUYA_BLE_SUCCESS) {
if (data.buf) {
tuya_ble_free(data.buf);
}
memset(&data, 0, sizeof(tuya_ble_gatt_send_data_t));
}
TUYA_BLE_LOG_DEBUG("tuya_ble_gatt_send_queue_free execute.");
}
void tuya_ble_gatt_send_data_handle(void *evt)
{
tuya_ble_gatt_send_data_t data = {0};
tuya_ble_evt_param_t event;
tuya_ble_connect_status_t currnet_connect_status;
while (tuya_ble_queue_get(&gatt_send_queue, &data) == TUYA_BLE_SUCCESS) {
currnet_connect_status = tuya_ble_connect_status_get();
if ((currnet_connect_status == BONDING_UNCONN) || (currnet_connect_status == UNBONDING_UNCONN)) {
tuya_ble_gatt_send_queue_free();
break;
}
if (tuya_ble_gatt_send_data(data.buf, data.size) == TUYA_BLE_SUCCESS) {
tuya_ble_free(data.buf);
tuya_ble_queue_decrease(&gatt_send_queue);
} else {
event.hdr.event = TUYA_BLE_EVT_GATT_SEND_DATA;
event.hdr.event_handler = tuya_ble_gatt_send_data_handle;
if (tuya_ble_event_send(&event) != 0) {
tuya_ble_gatt_send_queue_free();
TUYA_BLE_LOG_ERROR("TUYA_BLE_EVT_GATT_SEND_DATA error.");
}
break;
}
}
if (tuya_ble_get_queue_used(&gatt_send_queue) == 0) {
tuya_ble_queue_flush(&gatt_send_queue);
gatt_queue_flag = 0;
}
}
tuya_ble_status_t tuya_ble_gatt_send_data_enqueue(uint8_t *p_data, uint8_t data_len)
{
tuya_ble_gatt_send_data_t data = {0};
data.buf = tuya_ble_malloc(data_len);
if (data.buf) {
memcpy(data.buf, p_data, data_len);
data.size = data_len;
if (tuya_ble_enqueue(&gatt_send_queue, &data) == TUYA_BLE_SUCCESS) {
if (gatt_queue_flag == 0) {
gatt_queue_flag = 1;
tuya_ble_gatt_send_data_handle(NULL);
}
return TUYA_BLE_SUCCESS;
} else {
tuya_ble_free(data.buf);
return TUYA_BLE_ERR_NO_MEM;
}
} else {
return TUYA_BLE_ERR_NO_MEM;
}
}
uint32_t tuya_ble_get_gatt_send_queue_used(void)
{
return tuya_ble_get_queue_used(&gatt_send_queue);
}
@@ -0,0 +1,366 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#include "tuya_ble_stdlib.h"
#include "tuya_ble_heap.h"
#include "tuya_ble_port.h"
#include "tuya_ble_internal_config.h"
#if (TUYA_BLE_USE_PLATFORM_MEMORY_HEAP==0)
/* Block sizes must not get too small. */
#define heapMINIMUM_BLOCK_SIZE ( ( uint32_t ) ( xHeapStructSize << 1 ) )
/* Assumes 8bit bytes! */
#define heapBITS_PER_BYTE ( ( uint32_t ) 8 )
static uint8_t ucHeap[ TUYA_BLE_TOTAL_HEAP_SIZE ];
/* Define the linked list structure. This is used to link free blocks in order
of their memory address. */
typedef struct A_BLOCK_LINK {
struct A_BLOCK_LINK *pxNextFreeBlock; /*<< The next free block in the list. */
uint32_t xBlockSize; /*<< The size of the free block. */
} BlockLink_t;
/*-----------------------------------------------------------*/
/*
* Inserts a block of memory that is being freed into the correct position in
* the list of free memory blocks. The block being freed will be merged with
* the block in front it and/or the block behind it if the memory blocks are
* adjacent to each other.
*/
static void prvInsertBlockIntoFreeList(BlockLink_t *pxBlockToInsert);
/*
* Called automatically to setup the required heap structures the first time
* pvPortMalloc() is called.
*/
static void prvHeapInit(void);
/*-----------------------------------------------------------*/
/* The size of the structure placed at the beginning of each allocated memory
block must by correctly byte aligned. */
static const uint32_t xHeapStructSize = (sizeof(BlockLink_t) + ((uint32_t)(portBYTE_ALIGNMENT - 1))) & ~((uint32_t) portBYTE_ALIGNMENT_MASK);
/* Create a couple of list links to mark the start and end of the list. */
static BlockLink_t xStart, *pxEnd = NULL;
/* Keeps track of the number of free bytes remaining, but says nothing about
fragmentation. */
static uint32_t xFreeBytesRemaining = 0U;
static uint32_t xMinimumEverFreeBytesRemaining = 0U;
/* Gets set to the top bit of an size_t type. When this bit in the xBlockSize
member of an BlockLink_t structure is set then the block belongs to the
application. When the bit is free the block is still part of the free heap
space. */
static uint32_t xBlockAllocatedBit = 0;
/*-----------------------------------------------------------*/
void *pvTuyaPortMalloc(uint32_t xWantedSize)
{
BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink;
void *pvReturn = NULL;
tuya_ble_device_enter_critical();
{
/* If this is the first call to malloc then the heap will require
initialisation to setup the list of free blocks. */
if (pxEnd == NULL) {
prvHeapInit();
} else {
tuyaCOVERAGE_TEST_MARKER();
}
/* Check the requested block size is not so large that the top bit is
set. The top bit of the block size member of the BlockLink_t structure
is used to determine who owns the block - the application or the
kernel, so it must be free. */
if ((xWantedSize & xBlockAllocatedBit) == 0) {
/* The wanted size is increased so it can contain a BlockLink_t
structure in addition to the requested amount of bytes. */
if (xWantedSize > 0) {
xWantedSize += xHeapStructSize;
/* Ensure that blocks are always aligned to the required number
of bytes. */
if ((xWantedSize & portBYTE_ALIGNMENT_MASK) != 0x00) {
/* Byte alignment required. */
xWantedSize += (portBYTE_ALIGNMENT - (xWantedSize & portBYTE_ALIGNMENT_MASK));
tuyaASSERT((xWantedSize & portBYTE_ALIGNMENT_MASK) == 0);
} else {
tuyaCOVERAGE_TEST_MARKER();
}
} else {
tuyaCOVERAGE_TEST_MARKER();
}
if ((xWantedSize > 0) && (xWantedSize <= xFreeBytesRemaining)) {
/* Traverse the list from the start (lowest address) block until
one of adequate size is found. */
pxPreviousBlock = &xStart;
pxBlock = xStart.pxNextFreeBlock;
while ((pxBlock->xBlockSize < xWantedSize) && (pxBlock->pxNextFreeBlock != NULL)) {
pxPreviousBlock = pxBlock;
pxBlock = pxBlock->pxNextFreeBlock;
}
/* If the end marker was reached then a block of adequate size
was not found. */
if (pxBlock != pxEnd) {
/* Return the memory space pointed to - jumping over the
BlockLink_t structure at its start. */
pvReturn = (void *)(((uint8_t *) pxPreviousBlock->pxNextFreeBlock) + xHeapStructSize);
/* This block is being returned for use so must be taken out
of the list of free blocks. */
pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
/* If the block is larger than required it can be split into
two. */
if ((pxBlock->xBlockSize - xWantedSize) > heapMINIMUM_BLOCK_SIZE) {
/* This block is to be split into two. Create a new
block following the number of bytes requested. The void
cast is used to prevent byte alignment warnings from the
compiler. */
pxNewBlockLink = (void *)(((uint8_t *) pxBlock) + xWantedSize);
tuyaASSERT((((uint32_t) pxNewBlockLink) & portBYTE_ALIGNMENT_MASK) == 0);
/* Calculate the sizes of two blocks split from the
single block. */
pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
pxBlock->xBlockSize = xWantedSize;
/* Insert the new block into the list of free blocks. */
prvInsertBlockIntoFreeList(pxNewBlockLink);
} else {
tuyaCOVERAGE_TEST_MARKER();
}
xFreeBytesRemaining -= pxBlock->xBlockSize;
if (xFreeBytesRemaining < xMinimumEverFreeBytesRemaining) {
xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
} else {
tuyaCOVERAGE_TEST_MARKER();
}
/* The block is being returned - it is allocated and owned
by the application and has no "next" block. */
pxBlock->xBlockSize |= xBlockAllocatedBit;
pxBlock->pxNextFreeBlock = NULL;
} else {
tuyaCOVERAGE_TEST_MARKER();
}
} else {
tuyaCOVERAGE_TEST_MARKER();
}
} else {
tuyaCOVERAGE_TEST_MARKER();
}
tuya_traceMALLOC(pvReturn, xWantedSize);
}
(void) tuya_ble_device_exit_critical();
#if( tuyaUSE_MALLOC_FAILED_HOOK == 1 )
{
if (pvReturn == NULL) {
extern void vApplicationMallocFailedHook(void);
vApplicationMallocFailedHook();
} else {
tuyaCOVERAGE_TEST_MARKER();
}
}
#endif
tuyaASSERT((((uint32_t) pvReturn) & (uint32_t) portBYTE_ALIGNMENT_MASK) == 0);
return pvReturn;
}
/*-----------------------------------------------------------*/
void vTuyaPortFree(void *pv)
{
uint8_t *puc = (uint8_t *) pv;
BlockLink_t *pxLink;
if (pv != NULL) {
/* The memory being freed will have an BlockLink_t structure immediately
before it. */
puc -= xHeapStructSize;
/* This casting is to keep the compiler from issuing warnings. */
pxLink = (void *) puc;
/* Check the block is actually allocated. */
tuyaASSERT((pxLink->xBlockSize & xBlockAllocatedBit) != 0);
tuyaASSERT(pxLink->pxNextFreeBlock == NULL);
if ((pxLink->xBlockSize & xBlockAllocatedBit) != 0) {
if (pxLink->pxNextFreeBlock == NULL) {
/* The block is being returned to the heap - it is no longer
allocated. */
pxLink->xBlockSize &= ~xBlockAllocatedBit;
tuya_ble_device_enter_critical();
{
/* Add this block to the list of free blocks. */
xFreeBytesRemaining += pxLink->xBlockSize;
tuya_traceFREE(pv, pxLink->xBlockSize);
prvInsertBlockIntoFreeList(((BlockLink_t *) pxLink));
}
(void) tuya_ble_device_exit_critical();
} else {
tuyaCOVERAGE_TEST_MARKER();
}
} else {
tuyaCOVERAGE_TEST_MARKER();
}
}
}
/*-----------------------------------------------------------*/
uint32_t xTuyaPortGetFreeHeapSize(void)
{
return xFreeBytesRemaining;
}
/*-----------------------------------------------------------*/
uint32_t xTuyaPortGetMinimumEverFreeHeapSize(void)
{
return xMinimumEverFreeBytesRemaining;
}
/*-----------------------------------------------------------*/
void vTuyaPortInitialiseBlocks(void)
{
/* This just exists to keep the linker quiet. */
}
/*-----------------------------------------------------------*/
static void prvHeapInit(void)
{
BlockLink_t *pxFirstFreeBlock;
uint8_t *pucAlignedHeap;
uint32_t uxAddress;
uint32_t xTotalHeapSize = TUYA_BLE_TOTAL_HEAP_SIZE;
/* Ensure the heap starts on a correctly aligned boundary. */
uxAddress = (uint32_t) ucHeap;
if ((uxAddress & portBYTE_ALIGNMENT_MASK) != 0) {
uxAddress += (portBYTE_ALIGNMENT - 1);
uxAddress &= ~((uint32_t) portBYTE_ALIGNMENT_MASK);
xTotalHeapSize -= uxAddress - (uint32_t) ucHeap;
}
pucAlignedHeap = (uint8_t *) uxAddress;
/* xStart is used to hold a pointer to the first item in the list of free
blocks. The void cast is used to prevent compiler warnings. */
xStart.pxNextFreeBlock = (void *) pucAlignedHeap;
xStart.xBlockSize = (uint32_t) 0;
/* pxEnd is used to mark the end of the list of free blocks and is inserted
at the end of the heap space. */
uxAddress = ((uint32_t) pucAlignedHeap) + xTotalHeapSize;
uxAddress -= xHeapStructSize;
uxAddress &= ~((uint32_t) portBYTE_ALIGNMENT_MASK);
pxEnd = (void *) uxAddress;
pxEnd->xBlockSize = 0;
pxEnd->pxNextFreeBlock = NULL;
/* To start with there is a single free block that is sized to take up the
entire heap space, minus the space taken by pxEnd. */
pxFirstFreeBlock = (void *) pucAlignedHeap;
pxFirstFreeBlock->xBlockSize = uxAddress - (uint32_t) pxFirstFreeBlock;
pxFirstFreeBlock->pxNextFreeBlock = pxEnd;
/* Only one block exists - and it covers the entire usable heap space. */
xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
/* Work out the position of the top bit in a size_t variable. */
xBlockAllocatedBit = ((uint32_t) 1) << ((sizeof(uint32_t) * heapBITS_PER_BYTE) - 1);
}
/*-----------------------------------------------------------*/
static void prvInsertBlockIntoFreeList(BlockLink_t *pxBlockToInsert)
{
BlockLink_t *pxIterator;
uint8_t *puc;
/* Iterate through the list until a block is found that has a higher address
than the block being inserted. */
for (pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock) {
/* Nothing to do here, just iterate to the right position. */
}
/* Do the block being inserted, and the block it is being inserted after
make a contiguous block of memory? */
puc = (uint8_t *) pxIterator;
if ((puc + pxIterator->xBlockSize) == (uint8_t *) pxBlockToInsert) {
pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
pxBlockToInsert = pxIterator;
} else {
tuyaCOVERAGE_TEST_MARKER();
}
/* Do the block being inserted, and the block it is being inserted before
make a contiguous block of memory? */
puc = (uint8_t *) pxBlockToInsert;
if ((puc + pxBlockToInsert->xBlockSize) == (uint8_t *) pxIterator->pxNextFreeBlock) {
if (pxIterator->pxNextFreeBlock != pxEnd) {
/* Form one big block from the two blocks. */
pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
} else {
pxBlockToInsert->pxNextFreeBlock = pxEnd;
}
} else {
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
}
/* If the block being inserted plugged a gab, so was merged with the block
before and the block after, then it's pxNextFreeBlock pointer will have
already been set, and should not be set here as that would make it point
to itself. */
if (pxIterator != pxBlockToInsert) {
pxIterator->pxNextFreeBlock = pxBlockToInsert;
} else {
tuyaCOVERAGE_TEST_MARKER();
}
}
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,140 @@
/**
* \file tuya_ble_mem.c
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#include "tuya_ble_stdlib.h"
#include "tuya_ble_type.h"
#include "tuya_ble_heap.h"
#include "tuya_ble_mem.h"
#include "tuya_ble_internal_config.h"
#if (TUYA_BLE_USE_PLATFORM_MEMORY_HEAP==0)
/**
*@brief Allocate and clear a memory block with required size.
*@param[in] size Required memory size.
*
*@note
*
* */
void *tuya_ble_malloc(uint16_t size)
{
uint8_t *ptr = pvTuyaPortMalloc(size);
if (ptr) {
memset(ptr, 0x0, size); //allocate buffer need init
}
return ptr;
}
/**
*@brief Free a memory block that had been allocated.
*@param[in] ptr The address of memory block being freed.
*
*@note
*
* */
tuya_ble_status_t tuya_ble_free(uint8_t *ptr)
{
if (ptr == NULL) {
return TUYA_BLE_SUCCESS;
}
vTuyaPortFree(ptr);
return TUYA_BLE_SUCCESS;
}
/**
*@brief
*@param
*
*@note
*
* */
void *tuya_ble_calloc_n(uint32_t n, uint32_t size)
{
void *ptr = NULL;
ptr = pvTuyaPortMalloc(n * size);
if (ptr != NULL) {
memset(ptr, 0, n * size);
}
return ptr;
}
/**
*@brief
*@param
*
*@note
*
* */
void tuya_ble_free_n(void *ptr)
{
vTuyaPortFree(ptr);
}
#else
/**
*@brief Allocate and clear a memory block with required size.
*@param[in] size Required memory size.
*
*@note
*
* */
void *tuya_ble_malloc(uint16_t size)
{
uint8_t *ptr = tuya_ble_port_malloc(size);
if (ptr) {
memset(ptr, 0x0, size); //allocate buffer need init
}
return ptr;
}
/**
*@brief Free a memory block that had been allocated.
*@param[in] ptr The address of memory block being freed.
*
*@note
*
* */
tuya_ble_status_t tuya_ble_free(uint8_t *ptr)
{
if (ptr == NULL) {
return TUYA_BLE_SUCCESS;
}
tuya_ble_port_free(ptr);
return TUYA_BLE_SUCCESS;
}
#endif
@@ -0,0 +1,710 @@
/**
* \file tuya_ble_mutli_tsf_protocol.c
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#include "tuya_ble_stdlib.h"
#include "tuya_ble_type.h"
#include "tuya_ble_mem.h"
#include "tuya_ble_mutli_tsf_protocol.h"
#define __MUTLI_TSF_PROTOCOL_GLOBALS
/***********************************************************
*************************micro define***********************
***********************************************************/
#define MTP_DEBUG 1
#if MTP_DEBUG
#define MTP_PR_DEBUG(_fmt_, ...) \
printf("[mtp:dbg]%s:%d "_fmt_"\n\r", __FILE__, __LINE__, ##__VA_ARGS__)
#define MTP_PR_DEBUG_RAW(_fmt_, ...) \
printf(_fmt_, ##__VA_ARGS__)
#else
#define MTP_PR_DEBUG(...)
#define MTP_PR_DEBUG_RAW(_fmt_, ...)
#endif
#define MTP_PR_NOTICE(_fmt_, ...) \
printf("[mtp:notice]%s:%d "_fmt_"\n\r", __FILE__, __LINE__, ##__VA_ARGS__)
#define MTP_PR_ERR(_fmt_, ...) \
printf("[mtp:err]%s:%d "_fmt_"\n\r", __FILE__, __LINE__, ##__VA_ARGS__)
#undef NULL
#define NULL (void *)0
/***********************************************************
*************************variable define********************
***********************************************************/
static frame_seq_t frame_seq = 0;
/***********************************************************
*************************function define********************
***********************************************************/
/***********************************************************
* Function: create_trsmitr_init
* description: create a transmitter and initialize
* Input: none
* Output:
* Return: transmitter handle
***********************************************************/
frm_trsmitr_proc_s *create_trsmitr_init(void)
{
frm_trsmitr_proc_s *frm_trsmitr = NULL;
frm_trsmitr = (frm_trsmitr_proc_s *)tuya_ble_malloc(sizeof(frm_trsmitr_proc_s));
if ((void *)0 == frm_trsmitr) {
return (void *)0;
}
memset(frm_trsmitr, 0, sizeof(frm_trsmitr_proc_s));
return frm_trsmitr;
}
/***********************************************************
* Function: trsmitr_init
* description: init a transmitter
* Input: transmitter handle
* Output:
* Return:
***********************************************************/
void trsmitr_init(frm_trsmitr_proc_s *frm_trsmitr)
{
memset(frm_trsmitr, 0, sizeof(frm_trsmitr_proc_s));
}
/***********************************************************
* Function: delete_trsmitr
* description: delete transmitter
* Input: transmitter handle
* Output:
* Return:
***********************************************************/
void delete_trsmitr(frm_trsmitr_proc_s *frm_trsmitr)
{
//free(frm_trsmitr);
tuya_ble_free((uint8_t *)frm_trsmitr);
}
/***********************************************************
* Function: get_trsmitr_frame_total_len
* description: get a transmitter total data len
* Input: transmitter handle
* Output:
* Return: frame_total_t
***********************************************************/
frame_total_t get_trsmitr_frame_total_len(frm_trsmitr_proc_s *frm_trsmitr)
{
return frm_trsmitr->total;
}
/***********************************************************
* Function: get_trsmitr_frame_version
* description:
* Input: transmitter handle
* Output:
* Return:
***********************************************************/
uint8_t get_trsmitr_frame_version(frm_trsmitr_proc_s *frm_trsmitr)
{
return frm_trsmitr->version;
}
/***********************************************************
* Function: get_trsmitr_frame_seq
* description:
* Input: transmitter handle
* Output:
* Return: frame_seq_t
***********************************************************/
frame_seq_t get_trsmitr_frame_seq(frm_trsmitr_proc_s *frm_trsmitr)
{
return frm_trsmitr->seq;
}
/***********************************************************
* Function: get_trsmitr_subpkg_len
* description:
* Input: transmitter handle
* Output:
* Return: frame_subpkg_len_t
***********************************************************/
frame_subpkg_len_t get_trsmitr_subpkg_len(frm_trsmitr_proc_s *frm_trsmitr)
{
return frm_trsmitr->subpkg_len;
}
/***********************************************************
* Function: get_trsmitr_subpkg
* description:
* Input: transmitter handle
* Output:
* Return: subpackage buf
***********************************************************/
uint8_t *get_trsmitr_subpkg(frm_trsmitr_proc_s *frm_trsmitr)
{
return frm_trsmitr->subpkg;
}
static frame_seq_t get_frame_seq(void) //Because this type of data is not used temporarily, it can be used for multi-threaded calls temporarily
{
return (frame_seq >= FRAME_SEQ_LMT) ? 0 : frame_seq++;
}
/***********************************************************
* Function: trsmitr_send_pkg_encode
* description: frm_trsmitr->transmitter handle
* type->frame type
* buf->data buf
* len->data len
* Input:
* Output:
* Return: MTP_OK->buf send up
* MTP_TRSMITR_CONTINUE->need call again to be continue
* other->error
* Note: could get from encode data len and encode data by calling method
get_trsmitr_subpkg_len() and get_trsmitr_subpkg()
***********************************************************/
mtp_ret trsmitr_send_pkg_encode(frm_trsmitr_proc_s *frm_trsmitr, uint8_t version, uint8_t *buf, uint32_t len)
{
if (((void *)0) == frm_trsmitr) {
return MTP_INVALID_PARAM;
}
if (FRM_PKG_INIT == frm_trsmitr->pkg_desc) {
frm_trsmitr->total = len;
frm_trsmitr->version = version;
frm_trsmitr->seq = get_frame_seq();
frm_trsmitr->subpkg_num = 0;
frm_trsmitr->pkg_trsmitr_cnt = 0;
}
if (frm_trsmitr->subpkg_num >= 0x10000000 || len >= 0x10000000) {
return MTP_COM_ERROR;
}
uint16_t sunpkg_offset = 0;
// package code
// subpackage num encode
int32_t i;
uint32_t tmp = 0;
tmp = frm_trsmitr->subpkg_num;
for (i = 0; i < 4; i++) {
frm_trsmitr->subpkg[sunpkg_offset] = tmp % 0x80;
if ((tmp / 0x80)) {
frm_trsmitr->subpkg[sunpkg_offset] |= 0x80;
}
sunpkg_offset++;
tmp /= 0x80;
if (0 == tmp) {
break;
}
}
// the first package include the frame total len
if (0 == frm_trsmitr->subpkg_num) {
// frame len encode
tmp = len;
for (i = 0; i < 4; i++) {
frm_trsmitr->subpkg[sunpkg_offset] = tmp % 0x80;
if ((tmp / 0x80)) {
frm_trsmitr->subpkg[sunpkg_offset] |= 0x80;
}
sunpkg_offset++;
tmp /= 0x80;
if (0 == tmp) {
break;
}
}
// frame type and frame seq
frm_trsmitr->subpkg[sunpkg_offset++] = (frm_trsmitr->version << 0x04) | (frm_trsmitr->seq & 0x0f);
}
// frame data transfer
uint16_t send_data_len = (SNGL_PKG_TRSFR_LMT - sunpkg_offset);
if ((len - frm_trsmitr->pkg_trsmitr_cnt) < send_data_len) {
send_data_len = len - frm_trsmitr->pkg_trsmitr_cnt;
}
memcpy(&(frm_trsmitr->subpkg[sunpkg_offset]), buf + frm_trsmitr->pkg_trsmitr_cnt, send_data_len);
frm_trsmitr->subpkg_len = sunpkg_offset + send_data_len;
frm_trsmitr->pkg_trsmitr_cnt += send_data_len;
if (0 == frm_trsmitr->subpkg_num) {
frm_trsmitr->pkg_desc = FRM_PKG_FIRST;
} else {
frm_trsmitr->pkg_desc = FRM_PKG_MIDDLE;
}
if (frm_trsmitr->pkg_trsmitr_cnt < frm_trsmitr->total) {
frm_trsmitr->subpkg_num++;
return MTP_TRSMITR_CONTINUE;
}
frm_trsmitr->pkg_desc = FRM_PKG_END;
return MTP_OK;
}
/***********************************************************
* Function: trsmitr_send_pkg_encode_with_packet_length
* description: Encoding function for specifying sub-packet length
*
*
*
* Input:
* Output:
* Return: MTP_OK->buf send up
* MTP_TRSMITR_CONTINUE->need call again to be continue
* other->error
* Note: could get from encode data len and encode data by calling method
get_trsmitr_subpkg_len() and get_trsmitr_subpkg()
***********************************************************/
mtp_ret trsmitr_send_pkg_encode_with_packet_length(frm_trsmitr_proc_s *frm_trsmitr, uint32_t pkg_len_max, uint8_t version, uint8_t *buf, uint32_t len)
{
if (((void *)0) == frm_trsmitr) {
return MTP_INVALID_PARAM;
}
if ((pkg_len_max == 0) || (pkg_len_max > SNGL_PKG_TRSFR_LMT)) {
return MTP_INVALID_PARAM;
}
if (FRM_PKG_INIT == frm_trsmitr->pkg_desc) {
frm_trsmitr->total = len;
frm_trsmitr->version = version;
frm_trsmitr->seq = get_frame_seq();
frm_trsmitr->subpkg_num = 0;
frm_trsmitr->pkg_trsmitr_cnt = 0;
}
if (frm_trsmitr->subpkg_num >= 0x10000000 || len >= 0x10000000) {
return MTP_COM_ERROR;
}
uint16_t sunpkg_offset = 0;
// package code
// subpackage num encode
int32_t i;
uint32_t tmp = 0;
tmp = frm_trsmitr->subpkg_num;
for (i = 0; i < 4; i++) {
frm_trsmitr->subpkg[sunpkg_offset] = tmp % 0x80;
if ((tmp / 0x80)) {
frm_trsmitr->subpkg[sunpkg_offset] |= 0x80;
}
sunpkg_offset++;
tmp /= 0x80;
if (0 == tmp) {
break;
}
}
// the first package include the frame total len
if (0 == frm_trsmitr->subpkg_num) {
// frame len encode
tmp = len;
for (i = 0; i < 4; i++) {
frm_trsmitr->subpkg[sunpkg_offset] = tmp % 0x80;
if ((tmp / 0x80)) {
frm_trsmitr->subpkg[sunpkg_offset] |= 0x80;
}
sunpkg_offset++;
tmp /= 0x80;
if (0 == tmp) {
break;
}
}
// frame type and frame seq
frm_trsmitr->subpkg[sunpkg_offset++] = (frm_trsmitr->version << 0x04) | (frm_trsmitr->seq & 0x0f);
}
// frame data transfer
uint16_t send_data_len = (pkg_len_max - sunpkg_offset);
if ((len - frm_trsmitr->pkg_trsmitr_cnt) < send_data_len) {
send_data_len = len - frm_trsmitr->pkg_trsmitr_cnt;
}
memcpy(&(frm_trsmitr->subpkg[sunpkg_offset]), buf + frm_trsmitr->pkg_trsmitr_cnt, send_data_len);
frm_trsmitr->subpkg_len = sunpkg_offset + send_data_len;
frm_trsmitr->pkg_trsmitr_cnt += send_data_len;
if (0 == frm_trsmitr->subpkg_num) {
frm_trsmitr->pkg_desc = FRM_PKG_FIRST;
} else {
frm_trsmitr->pkg_desc = FRM_PKG_MIDDLE;
}
if (frm_trsmitr->pkg_trsmitr_cnt < frm_trsmitr->total) {
frm_trsmitr->subpkg_num++;
return MTP_TRSMITR_CONTINUE;
}
frm_trsmitr->pkg_desc = FRM_PKG_END;
return MTP_OK;
}
mtp_ret trsmitr_recv_pkg_decode(frm_trsmitr_proc_s *frm_trsmitr, uint8_t *raw_data, uint16_t raw_data_len)
{
if (NULL == raw_data || (raw_data_len > SNGL_PKG_TRSFR_LMT) || NULL == frm_trsmitr) {
return MTP_INVALID_PARAM;
}
if (FRM_PKG_INIT == frm_trsmitr->pkg_desc) {
frm_trsmitr->total = 0;
frm_trsmitr->version = 0;
frm_trsmitr->seq = 0;
frm_trsmitr->pkg_trsmitr_cnt = 0;
}
uint16_t sunpkg_offset = 0;
// package code
// subpackage num decode
int32_t i;
uint32_t multiplier = 1;
uint8_t digit;
frame_subpkg_num_t subpkg_num = 0;
//Package number
for (i = 0; i < 4; i++) {
digit = raw_data[sunpkg_offset++];
subpkg_num += (digit & 0x7f) * multiplier;
multiplier *= 0x80;
if (0 == (digit & 0x80)) {
break;
}
}
if (0 == subpkg_num) {
frm_trsmitr->total = 0;
frm_trsmitr->version = 0;
frm_trsmitr->seq = 0;
frm_trsmitr->pkg_trsmitr_cnt = 0;
frm_trsmitr->pkg_desc = FRM_PKG_FIRST;
} else {
frm_trsmitr->pkg_desc = FRM_PKG_MIDDLE;
}
if (frm_trsmitr->subpkg_num >= 0x10000000) {
return MTP_COM_ERROR;
}
// is receive the subpackage num valid?
if (frm_trsmitr->pkg_desc != FRM_PKG_FIRST) {
if (subpkg_num < frm_trsmitr->subpkg_num) {
return MTP_TRSMITR_ERROR;
} else if (subpkg_num == frm_trsmitr->subpkg_num) {
return MTP_TRSMITR_CONTINUE;
}
if (subpkg_num - frm_trsmitr->subpkg_num > 1) {
return MTP_TRSMITR_ERROR;
}
}
frm_trsmitr->subpkg_num = subpkg_num;
if (0 == frm_trsmitr->subpkg_num) {
// frame len decode
multiplier = 1;
for (i = 0; i < 4; i++) {
digit = raw_data[sunpkg_offset++];
frm_trsmitr->total += (digit & 0x7f) * multiplier;
multiplier *= 0x80;
if (0 == (digit & 0x80)) {
break;
}
}
if (frm_trsmitr->total >= 0x10000000) {
return MTP_COM_ERROR;
}
// frame type and frame seq decode
frm_trsmitr->version = (raw_data[sunpkg_offset] & FRM_VERSION_OFFSET) >> 4;
frm_trsmitr->seq = raw_data[sunpkg_offset++] & FRM_SEQ_OFFSET;
}
uint16_t recv_data_len = raw_data_len - sunpkg_offset;
if ((frm_trsmitr->total - frm_trsmitr->pkg_trsmitr_cnt) < recv_data_len) {
recv_data_len = frm_trsmitr->total - frm_trsmitr->pkg_trsmitr_cnt;
}
// decode data cp to transmitter subpackage buf
memcpy(frm_trsmitr->subpkg, &raw_data[sunpkg_offset], recv_data_len);
frm_trsmitr->subpkg_len = recv_data_len;
frm_trsmitr->pkg_trsmitr_cnt += recv_data_len;
if (frm_trsmitr->pkg_trsmitr_cnt < frm_trsmitr->total) {
return MTP_TRSMITR_CONTINUE;
}
//cannot add 'frm_trsmitr->pkg_desc = FRM_PKG_END;' here.
return MTP_OK;
}
/***********************************************************
* Function: free_klv_list
* description:
* Input: list
* Output:
* Return:
***********************************************************/
void free_klv_list(klv_node_s *list)
{
if (NULL == list) {
return;
}
klv_node_s *node = list;
klv_node_s *next_node = NULL;
do {
next_node = node->next;
//free(node);
tuya_ble_free((uint8_t *)(node->data));
tuya_ble_free((uint8_t *)node);
node = next_node;
} while (node);
}
/***********************************************************
* Function: make_klv_list
* description:
* Input:
* Output:
* Return:
***********************************************************/
klv_node_s *make_klv_list(klv_node_s *list, uint8_t id, dp_type type, void *p_data, uint16_t len)
{
klv_node_s *node = NULL;
uint32_t tmp4 = 0, tmp2 = 0;
if (NULL == p_data || type >= DT_LMT) {
return NULL;
}
if (DT_VALUE == type && DT_VALUE_LEN != len) {
goto err_ret;
} else if (DT_BITMAP == type && len != 1 && len != 2 && len != DT_BITMAP_MAX) {
goto err_ret;
} else if (DT_BOOL == type && DT_BOOL_LEN != len) {
goto err_ret;
} else if (DT_ENUM == type && DT_ENUM_LEN != len) {
goto err_ret;
}
node = (klv_node_s *)tuya_ble_malloc(sizeof(klv_node_s));
if (NULL == node) {
goto err_ret;
}
memset(node, 0, sizeof(klv_node_s));
if (len > 0) {
node->data = tuya_ble_malloc(len);
if (node->data == NULL) {
tuya_ble_free(node->data);
tuya_ble_free((uint8_t *)node);
goto err_ret;
}
}
node->id = id;
node->len = len;
node->type = type;
if (DT_VALUE == type) {
// change to big-end
tmp4 = *(uint32_t *)p_data;
// unsigned char shift = 0;
node->data[0] = (tmp4 >> 24) & 0xff;
node->data[1] = (tmp4 >> 16) & 0xff;
node->data[2] = (tmp4 >> 8) & 0xff;
node->data[3] = (tmp4 >> 0) & 0xff;
} else if (DT_BITMAP == type) {
if (len == 4) {
tmp4 = *(uint32_t *)p_data;
// unsigned char shift = 0;
node->data[0] = (tmp4 >> 24) & 0xff;
node->data[1] = (tmp4 >> 16) & 0xff;
node->data[2] = (tmp4 >> 8) & 0xff;
node->data[3] = (tmp4 >> 0) & 0xff;
} else if (len == 2) {
tmp2 = *(uint16_t *)p_data;
node->data[0] = (tmp2 >> 8) & 0xff;
node->data[1] = (tmp2 >> 0) & 0xff;
} else {
node->data[0] = *(uint8_t *)p_data;
}
} else {
if (len > 0) {
memcpy((void *)node->data, (uint8_t *)p_data, len);
}
}
node->next = list;
return node;
err_ret:
free_klv_list(list);
return NULL;
}
/***********************************************************
* Function: klvlist_2_data
* description:
* Input: type:0- 1 byte length1- 2 byte length
* Output:
* Return:
***********************************************************/
mtp_ret klvlist_2_data(klv_node_s *list, uint8_t **data, uint32_t *len, uint8_t type)
{
if (NULL == list || NULL == data || NULL == len) {
return MTP_INVALID_PARAM;
}
klv_node_s *node = list;
// count data len
uint32_t mk_data_len = 0;
while (node) {
mk_data_len += sizeof(klv_node_s) + node->len - sizeof(struct s_klv_node *);
node = node->next;
}
uint8_t *mk_data = (uint8_t *)tuya_ble_malloc(mk_data_len);
if (NULL == mk_data) {
return MTP_MALLOC_ERR;
}
// fill data
uint32_t offset = 0;
node = list;
while (node) {
mk_data[offset++] = node->id;
mk_data[offset++] = node->type;
if (1 == type) {
mk_data[offset++] = node->len >> 8;
mk_data[offset++] = node->len;
} else {
mk_data[offset++] = node->len;
}
if (node->len > 0) {
memcpy(&mk_data[offset], node->data, node->len);
}
offset += node->len;
node = node->next;
}
*len = offset;
*data = mk_data;
return MTP_OK;
}
/***********************************************************
* Function: data_2_klvlist
* description:
* Input: type: 0- 1 byte length1- 2 byte length
* Output:
* Return:
***********************************************************/
mtp_ret data_2_klvlist(uint8_t *data, uint32_t len, klv_node_s **list, uint8_t type)
{
uint16_t dp_len = 0;
//The data is parsed into a list of dp points dpid+dp_tp+len+data
if (NULL == data || NULL == list) {
return MTP_INVALID_PARAM;
}
uint32_t offset = 0;
klv_node_s *klv_list = NULL;
klv_node_s *node = NULL;
do {
// not full klv
if (type == 1) {
if ((len - offset) < 4) {
free_klv_list(klv_list);
return MTP_COM_ERROR;
}
} else {
if ((len - offset) < 3) {
free_klv_list(klv_list);
return MTP_COM_ERROR;
}
}
node = (klv_node_s *)tuya_ble_malloc(sizeof(klv_node_s));
if (NULL == node) {
free_klv_list(klv_list);
return MTP_MALLOC_ERR;
}
memset(node, 0, sizeof(klv_node_s));
if (1 == type) {
dp_len = (data[2 + offset] << 8) + data[3 + offset];
} else {
dp_len = data[2 + offset];
}
if (dp_len > 0) {
node->data = tuya_ble_malloc(dp_len);
if (node->data == NULL) {
tuya_ble_free(node->data);
tuya_ble_free((uint8_t *)node);
free_klv_list(klv_list);
return MTP_MALLOC_ERR;
}
}
node->id = data[offset++];
node->type = data[offset++];
if (1 == type) {
//offset++;
node->len = data[offset++];
node->len = (node->len << 8) + data[offset++];
} else {
node->len = data[offset++];
}
if ((len - offset) < node->len) {
// is remain data len enougn?
tuya_ble_free(node->data);
tuya_ble_free((uint8_t *)node);
free_klv_list(klv_list);
return MTP_COM_ERROR;
}
if (node->len > 0) {
memcpy(node->data, &data[offset], node->len);
}
offset += node->len;
node->next = klv_list;
klv_list = node;
} while (offset < len);
if (NULL == klv_list) {
return MTP_COM_ERROR;
}
*list = klv_list;
return MTP_OK;
}
@@ -0,0 +1,100 @@
/**
* \file tuya_ble_queue.c
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#include "tuya_ble_stdlib.h"
#include "tuya_ble_queue.h"
#include "tuya_ble_type.h"
tuya_ble_status_t tuya_ble_queue_init(tuya_ble_queue_t *q, void *buf, uint8_t queue_size, uint8_t elem_size)
{
if (buf == NULL || q == NULL) {
return TUYA_BLE_ERR_INVALID_PARAM;
}
q->buf = buf;
q->size = queue_size;
q->offset = elem_size;
q->rd_ptr = 0;
q->wr_ptr = 0;
q->used = 0;
return TUYA_BLE_SUCCESS;
}
tuya_ble_status_t tuya_ble_enqueue(tuya_ble_queue_t *q, void *in)
{
if (q->used >= q->size) {
return TUYA_BLE_ERR_NO_MEM;
}
memcpy((uint8_t *)q->buf + q->wr_ptr * q->offset, in, q->offset);
q->wr_ptr = (q->wr_ptr + 1) % q->size;
q->used++;
return TUYA_BLE_SUCCESS;
}
tuya_ble_status_t tuya_ble_queue_get(tuya_ble_queue_t *q, void *out)
{
if (q->used > 0) {
memcpy(out, (uint8_t *)q->buf + q->rd_ptr * q->offset, q->offset);
return TUYA_BLE_SUCCESS;
} else {
return TUYA_BLE_ERR_NOT_FOUND;
}
}
tuya_ble_status_t tuya_ble_dequeue(tuya_ble_queue_t *q, void *out)
{
if (q->used > 0) {
memcpy(out, (uint8_t *)q->buf + q->rd_ptr * q->offset, q->offset);
q->rd_ptr = (q->rd_ptr + 1) % q->size;
q->used--;
return TUYA_BLE_SUCCESS;
} else {
return TUYA_BLE_ERR_NOT_FOUND;
}
}
void tuya_ble_queue_decrease(tuya_ble_queue_t *q)
{
if (q->used > 0) {
q->rd_ptr = (q->rd_ptr + 1) % q->size;
q->used--;
}
}
void tuya_ble_queue_flush(tuya_ble_queue_t *q)
{
q->rd_ptr = 0;
q->wr_ptr = 0;
q->used = 0;
}
uint8_t tuya_ble_get_queue_used(tuya_ble_queue_t *q)
{
return q->used;
}
@@ -0,0 +1,498 @@
/**
* \file tuya_ble_storage.c
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#include "tuya_ble_stdlib.h"
#include "tuya_ble_api.h"
#include "tuya_ble_port.h"
#include "tuya_ble_type.h"
#include "tuya_ble_main.h"
#include "tuya_ble_mem.h"
#include "tuya_ble_data_handler.h"
#include "tuya_ble_internal_config.h"
#include "tuya_ble_mutli_tsf_protocol.h"
#include "tuya_ble_storage.h"
#include "tuya_ble_utils.h"
#include "tuya_ble_log.h"
typedef struct {
uint32_t crc;
uint32_t settings_version;
uint8_t h_id[H_ID_LEN];
uint8_t device_id[DEVICE_ID_LEN];
uint8_t mac[MAC_LEN];
uint8_t auth_key[AUTH_KEY_LEN];
} tuya_ble_auth_settings_old_t;
typedef struct {
uint32_t crc;
uint32_t settings_version;
tuya_ble_product_id_type_t pid_type;
uint8_t pid_len;
uint8_t common_pid[TUYA_BLE_PRODUCT_ID_MAX_LEN];
uint8_t login_key[LOGIN_KEY_LEN];
uint8_t ecc_secret_key[ECC_SECRET_KEY_LEN];
uint8_t device_virtual_id[DEVICE_VIRTUAL_ID_LEN];
uint8_t user_rand[PAIR_RANDOM_LEN];
uint8_t bound_flag;
} tuya_ble_sys_settings_old_t;
typedef struct {
tuya_ble_auth_settings_t flash_settings_auth;
tuya_ble_auth_settings_t flash_settings_auth_backup;
} tuya_ble_storage_auth_settings_t;
typedef struct {
tuya_ble_sys_settings_t flash_settings_sys;
tuya_ble_sys_settings_t flash_settings_sys_backup;
} tuya_ble_storage_sys_settings_t;
static bool buffer_value_is_all_x(uint8_t *buffer, uint16_t len, uint8_t value)
{
bool ret = true;
for (uint16_t i = 0; i < len; i++) {
if (buffer[i] != value) {
ret = false;
break;
}
}
return ret;
}
static uint32_t auth_settings_crc_get(tuya_ble_auth_settings_t const *p_settings)
{
// The crc is calculated from the s_dfu_settings struct, except the crc itself and the init command
return tuya_ble_crc32_compute((uint8_t *)(p_settings) + 4, sizeof(tuya_ble_auth_settings_t) - 4, NULL);
}
static bool auth_settings_crc_ok(tuya_ble_auth_settings_t const *p_settings, uint8_t *flash_update)
{
uint32_t crc, crc_old;
if (p_settings->crc != 0xFFFFFFFF) {
// CRC is set. Content must be valid
crc = auth_settings_crc_get(p_settings);
if (crc == p_settings->crc) {
return true;
} else {
crc_old = tuya_ble_crc32_compute((uint8_t *)(p_settings) + 4, sizeof(tuya_ble_auth_settings_old_t) - 4, NULL);
if (crc_old == p_settings->crc) {
*flash_update = 1;
return true;
}
}
}
return false;
}
static uint32_t sys_settings_crc_get(tuya_ble_sys_settings_t const *p_settings)
{
// The crc is calculated from the s_dfu_settings struct, except the crc itself and the init command
return tuya_ble_crc32_compute((uint8_t *)(p_settings) + 4, sizeof(tuya_ble_sys_settings_t) - 4, NULL);
}
static bool sys_settings_crc_ok(tuya_ble_sys_settings_t const *p_settings, uint8_t *flash_update)
{
uint32_t crc, crc_old;
if (p_settings->crc != 0xFFFFFFFF) {
// CRC is set. Content must be valid
crc = sys_settings_crc_get(p_settings);
if (crc == p_settings->crc) {
return true;
} else {
crc_old = tuya_ble_crc32_compute((uint8_t *)(p_settings) + 4, sizeof(tuya_ble_sys_settings_old_t) - 4, NULL);
if (crc_old == p_settings->crc) {
*flash_update = 1;
return true;
}
}
}
return false;
}
uint32_t tuya_ble_storage_load_settings(void)
{
uint32_t err_code = 0;
bool settings_valid ;
bool settings_backup_valid;
uint8_t auth_settings_flag = 1;
uint8_t sys_settings_flag = 1;
uint8_t auth_settings_update = 0;
uint8_t sys_settings_update = 0;
tuya_ble_storage_auth_settings_t *p_storage_settings_auth = NULL;
tuya_ble_storage_sys_settings_t *p_storage_settings_sys = NULL;
p_storage_settings_auth = (tuya_ble_storage_auth_settings_t *)tuya_ble_malloc(sizeof(tuya_ble_storage_auth_settings_t));
if (p_storage_settings_auth == NULL) {
TUYA_BLE_LOG_ERROR("p_storage_settings_auth malloc failed.");
memset(&tuya_ble_current_para.auth_settings, 0, sizeof(tuya_ble_auth_settings_t));
auth_settings_flag = 0;
} else {
memset(p_storage_settings_auth, 0, sizeof(tuya_ble_storage_auth_settings_t));
}
if (auth_settings_flag == 1) {
tuya_ble_nv_read(TUYA_BLE_AUTH_FLASH_ADDR, (uint8_t *)&p_storage_settings_auth->flash_settings_auth, sizeof(tuya_ble_auth_settings_t));
tuya_ble_nv_read(TUYA_BLE_AUTH_FLASH_BACKUP_ADDR, (uint8_t *)&p_storage_settings_auth->flash_settings_auth_backup, sizeof(tuya_ble_auth_settings_t));
settings_valid = auth_settings_crc_ok(&p_storage_settings_auth->flash_settings_auth, &auth_settings_update);
settings_backup_valid = auth_settings_crc_ok(&p_storage_settings_auth->flash_settings_auth_backup, &auth_settings_update);
if (settings_valid) {
memcpy(&tuya_ble_current_para.auth_settings, &p_storage_settings_auth->flash_settings_auth, sizeof(tuya_ble_auth_settings_t));
} else if (settings_backup_valid) {
memcpy(&tuya_ble_current_para.auth_settings, &p_storage_settings_auth->flash_settings_auth_backup, sizeof(tuya_ble_auth_settings_t));
} else {
memset(&tuya_ble_current_para.auth_settings, 0, sizeof(tuya_ble_auth_settings_t));
auth_settings_flag = 0;
}
if (auth_settings_update == 1) {
tuya_ble_storage_save_auth_settings();
auth_settings_update = 0;
}
tuya_ble_free((uint8_t *)p_storage_settings_auth);
}
p_storage_settings_sys = (tuya_ble_storage_sys_settings_t *)tuya_ble_malloc(sizeof(tuya_ble_storage_sys_settings_t));
if (p_storage_settings_sys == NULL) {
TUYA_BLE_LOG_ERROR("p_storage_settings_sys malloc failed.");
memset(&tuya_ble_current_para.sys_settings, 0, sizeof(tuya_ble_sys_settings_t));
sys_settings_flag = 0;
} else {
memset(p_storage_settings_sys, 0, sizeof(tuya_ble_storage_sys_settings_t));
}
if (sys_settings_flag == 1) {
tuya_ble_nv_read(TUYA_BLE_SYS_FLASH_ADDR, (uint8_t *)&p_storage_settings_sys->flash_settings_sys, sizeof(tuya_ble_sys_settings_t));
tuya_ble_nv_read(TUYA_BLE_SYS_FLASH_BACKUP_ADDR, (uint8_t *)&p_storage_settings_sys->flash_settings_sys_backup, sizeof(tuya_ble_sys_settings_t));
settings_valid = sys_settings_crc_ok(&p_storage_settings_sys->flash_settings_sys, &sys_settings_update);
settings_backup_valid = sys_settings_crc_ok(&p_storage_settings_sys->flash_settings_sys_backup, &sys_settings_update);
if (settings_valid) {
memcpy(&tuya_ble_current_para.sys_settings, &p_storage_settings_sys->flash_settings_sys, sizeof(tuya_ble_sys_settings_t));
} else if (settings_backup_valid) {
memcpy(&tuya_ble_current_para.sys_settings, &p_storage_settings_sys->flash_settings_sys_backup, sizeof(tuya_ble_sys_settings_t));
} else {
memset(&tuya_ble_current_para.sys_settings, 0, sizeof(tuya_ble_sys_settings_t));
tuya_ble_current_para.sys_settings.factory_test_flag = 0xFF;
sys_settings_flag = 0;
}
if (sys_settings_update == 1) {
tuya_ble_current_para.sys_settings.factory_test_flag = 0xFF;
tuya_ble_storage_save_sys_settings();
sys_settings_update = 0;
}
tuya_ble_free((uint8_t *)p_storage_settings_sys);
}
tuya_ble_current_para.pid_type = tuya_ble_current_para.sys_settings.pid_type;
tuya_ble_current_para.pid_len = tuya_ble_current_para.sys_settings.pid_len;
memcpy(tuya_ble_current_para.pid, tuya_ble_current_para.sys_settings.common_pid, tuya_ble_current_para.pid_len);
return err_code;
}
uint32_t tuya_ble_storage_save_auth_settings(void)
{
uint32_t err_code = 0;
tuya_ble_current_para.auth_settings.crc = tuya_ble_crc32_compute((uint8_t *)&tuya_ble_current_para.auth_settings + 4, sizeof(tuya_ble_current_para.auth_settings) - 4, NULL);
if (tuya_ble_nv_erase(TUYA_BLE_AUTH_FLASH_ADDR, TUYA_NV_ERASE_MIN_SIZE) == TUYA_BLE_SUCCESS) {
err_code = tuya_ble_nv_write(TUYA_BLE_AUTH_FLASH_ADDR, (uint8_t *)&tuya_ble_current_para.auth_settings, sizeof(tuya_ble_auth_settings_t));
if (err_code == TUYA_BLE_SUCCESS) {
TUYA_BLE_LOG_DEBUG("write flash_settings_auth data succeed!");
if (tuya_ble_nv_erase(TUYA_BLE_AUTH_FLASH_BACKUP_ADDR, TUYA_NV_ERASE_MIN_SIZE) == TUYA_BLE_SUCCESS) {
if (tuya_ble_nv_write(TUYA_BLE_AUTH_FLASH_BACKUP_ADDR, (uint8_t *)&tuya_ble_current_para.auth_settings, sizeof(tuya_ble_auth_settings_t)) != TUYA_BLE_SUCCESS) {
TUYA_BLE_LOG_ERROR("write flash_settings_auth data backup failed!");
err_code = 1;
}
} else {
TUYA_BLE_LOG_ERROR("erase flash_settings_auth data backup failed!");
err_code = 1;
}
} else {
TUYA_BLE_LOG_ERROR("write flash_settings_auth data failed!");
err_code = 1;
}
} else {
TUYA_BLE_LOG_ERROR("erase flash_settings_auth data failed!");
err_code = 1;
}
return err_code;
}
uint32_t tuya_ble_storage_save_sys_settings(void)
{
uint32_t err_code = 0;
#if (TUYA_BLE_DEVICE_AUTH_DATA_STORE)
tuya_ble_current_para.sys_settings.crc = tuya_ble_crc32_compute((uint8_t *)&tuya_ble_current_para.sys_settings + 4, sizeof(tuya_ble_sys_settings_t) - 4, NULL);
if (tuya_ble_nv_erase(TUYA_BLE_SYS_FLASH_ADDR, TUYA_NV_ERASE_MIN_SIZE) == TUYA_BLE_SUCCESS) {
err_code = tuya_ble_nv_write(TUYA_BLE_SYS_FLASH_ADDR, (uint8_t *)&tuya_ble_current_para.sys_settings, sizeof(tuya_ble_sys_settings_t));
if (err_code == TUYA_BLE_SUCCESS) {
TUYA_BLE_LOG_INFO("write flash_settings_sys data succeed!");
if (tuya_ble_nv_erase(TUYA_BLE_SYS_FLASH_BACKUP_ADDR, TUYA_NV_ERASE_MIN_SIZE) == TUYA_BLE_SUCCESS) {
if (tuya_ble_nv_write(TUYA_BLE_SYS_FLASH_BACKUP_ADDR, (uint8_t *)&tuya_ble_current_para.sys_settings, sizeof(tuya_ble_sys_settings_t)) != TUYA_BLE_SUCCESS) {
TUYA_BLE_LOG_ERROR("write flash_settings_sys data backup failed!");
err_code = 1;
}
} else {
TUYA_BLE_LOG_ERROR("erase flash_settings_sys data backup failed!");
err_code = 1;
}
} else {
TUYA_BLE_LOG_ERROR("write flash_settings_sys data failed!");
err_code = 1;
}
} else {
TUYA_BLE_LOG_ERROR("erase flash_settings_sys data failed!");
err_code = 1;
}
#endif
return err_code;
}
uint32_t tuya_ble_storage_init(void)
{
uint32_t err = 0;
tuya_ble_nv_init();
#if (TUYA_BLE_DEVICE_AUTH_DATA_STORE)
tuya_ble_storage_load_settings();
#endif
return err;
}
#if (TUYA_BLE_DEVICE_AUTH_DATA_STORE)
/**
* @brief Function for write pid to nv
*
* @note
*
* */
tuya_ble_status_t tuya_ble_storage_write_pid(tuya_ble_product_id_type_t pid_type, uint8_t pid_len, uint8_t *pid)
{
tuya_ble_status_t ret = TUYA_BLE_SUCCESS;
uint8_t is_write = 0;
if (pid_len > TUYA_BLE_PRODUCT_ID_MAX_LEN) {
return TUYA_BLE_ERR_INVALID_PARAM;
}
if ((pid_type != tuya_ble_current_para.pid_type) || (pid_len != tuya_ble_current_para.pid_len)) {
tuya_ble_current_para.pid_type = pid_type;
tuya_ble_current_para.pid_len = pid_len;
memcpy(tuya_ble_current_para.pid, pid, pid_len);
tuya_ble_current_para.sys_settings.pid_type = pid_type;
tuya_ble_current_para.sys_settings.pid_len = pid_len;
memcpy(tuya_ble_current_para.sys_settings.common_pid, pid, pid_len);
is_write = 1;
} else if (memcmp(pid, tuya_ble_current_para.pid, pid_len) != 0) {
tuya_ble_current_para.pid_type = pid_type;
tuya_ble_current_para.pid_len = pid_len;
memcpy(tuya_ble_current_para.pid, pid, pid_len);
tuya_ble_current_para.sys_settings.pid_type = pid_type;
tuya_ble_current_para.sys_settings.pid_len = pid_len;
memcpy(tuya_ble_current_para.sys_settings.common_pid, pid, pid_len);
is_write = 1;
} else {
}
if (is_write == 1) {
if (tuya_ble_storage_save_sys_settings()) {
ret = TUYA_BLE_ERR_BUSY;
}
}
return ret;
}
/**
* @brief Function for write hid to nv
*
* @note
*
* */
tuya_ble_status_t tuya_ble_storage_write_hid(uint8_t *hid, uint8_t len)
{
tuya_ble_status_t ret = TUYA_BLE_SUCCESS;
if (len != H_ID_LEN) {
ret = TUYA_BLE_ERR_INVALID_PARAM;
} else {
if (memcmp(hid, tuya_ble_current_para.auth_settings.h_id, H_ID_LEN) != 0) {
memcpy(tuya_ble_current_para.auth_settings.h_id, hid, H_ID_LEN);
if (tuya_ble_storage_save_auth_settings()) {
ret = TUYA_BLE_ERR_BUSY;
}
}
}
return ret;
}
/**
* @brief Function for read id parameters
*
* @note
*
* */
tuya_ble_status_t tuya_ble_storage_read_id_info(tuya_ble_factory_id_data_t *id)
{
tuya_ble_status_t ret = TUYA_BLE_SUCCESS;
id->pid_type = tuya_ble_current_para.pid_type;
id->pid_len = tuya_ble_current_para.pid_len;
memcpy(id->pid, tuya_ble_current_para.pid, tuya_ble_current_para.pid_len);
memcpy(id->h_id, tuya_ble_current_para.auth_settings.h_id, H_ID_LEN);
memcpy(id->device_id, tuya_ble_current_para.auth_settings.device_id, DEVICE_ID_LEN);
memcpy(id->mac, tuya_ble_current_para.auth_settings.mac, MAC_LEN);
memcpy(id->auth_key, tuya_ble_current_para.auth_settings.auth_key, AUTH_KEY_LEN);
return ret;
}
/**
* @brief Function for write auth key/uuid/mac/pid
*
* @note If the id length is 0, the corresponding id will not be written.
*
* */
tuya_ble_status_t tuya_ble_storage_write_auth_key_device_id_mac(uint8_t *auth_key, uint8_t auth_key_len, uint8_t *device_id, uint8_t device_id_len,
uint8_t *mac, uint8_t mac_len, uint8_t *mac_string, uint8_t mac_string_len, uint8_t *pid, uint8_t pid_len)
{
tuya_ble_status_t ret = TUYA_BLE_SUCCESS;
uint8_t is_write = 0;
if (((auth_key_len != AUTH_KEY_LEN) && (auth_key_len != 0)) || ((device_id_len != DEVICE_ID_LEN) && (device_id_len != 0)) || ((mac_len != MAC_LEN) && (mac_len != 0))) {
ret = TUYA_BLE_ERR_INVALID_PARAM;
} else {
if (auth_key_len == AUTH_KEY_LEN) {
if (memcmp(tuya_ble_current_para.auth_settings.auth_key, auth_key, AUTH_KEY_LEN) != 0) {
memcpy(tuya_ble_current_para.auth_settings.auth_key, auth_key, AUTH_KEY_LEN);
is_write = 1;
}
}
if (device_id_len == DEVICE_ID_LEN) {
if (memcmp(tuya_ble_current_para.auth_settings.device_id, device_id, DEVICE_ID_LEN) != 0) {
memcpy(tuya_ble_current_para.auth_settings.device_id, device_id, DEVICE_ID_LEN);
is_write = 1;
}
}
if (mac_len == MAC_LEN) {
if (memcmp(tuya_ble_current_para.auth_settings.mac, mac, MAC_LEN) != 0) {
memcpy(tuya_ble_current_para.auth_settings.mac, mac, MAC_LEN);
memcpy(tuya_ble_current_para.auth_settings.mac_string, mac_string, MAC_LEN * 2);
is_write = 1;
}
}
if (pid_len > 0) {
if ((tuya_ble_current_para.auth_settings.pid_len != pid_len) || (memcmp(tuya_ble_current_para.auth_settings.factory_pid, pid, pid_len) != 0)) {
memcpy(tuya_ble_current_para.auth_settings.factory_pid, pid, pid_len);
tuya_ble_current_para.auth_settings.pid_len = pid_len;
tuya_ble_current_para.auth_settings.pid_type = (uint8_t)TUYA_BLE_PRODUCT_ID_TYPE_PID;
is_write = 1;
}
}
if (is_write == 1) {
#if (!TUYA_BLE_DEVICE_AUTH_DATA_STORE_EXT_MEDIUM)
if (tuya_ble_storage_save_auth_settings()) {
ret = TUYA_BLE_ERR_BUSY;
}
#else
tuya_ble_current_para.auth_settings.crc = tuya_ble_crc32_compute((uint8_t *)&tuya_ble_current_para.auth_settings + 4, sizeof(tuya_ble_current_para.auth_settings) - 4, NULL);
if (tuya_ble_storage_private_data(PRIVATE_DATA_TUYA_AUTH_TOKEN, (uint8_t *)&tuya_ble_current_para.auth_settings, sizeof(tuya_ble_auth_settings_t))) {
ret = TUYA_BLE_ERR_BUSY;
}
#endif // (!TUYA_BLE_DEVICE_AUTH_DATA_STORE_EXT_MEDIUM)
else {
/* force clear device_virtual_id info */
//if(tuya_ble_current_para.sys_settings.bound_flag==1)
{
memset(tuya_ble_current_para.sys_settings.device_virtual_id, 0, DEVICE_VIRTUAL_ID_LEN);
memset(tuya_ble_current_para.sys_settings.login_key, 0, LOGIN_KEY_LEN);
tuya_ble_current_para.sys_settings.bound_flag = 0;
tuya_ble_storage_save_sys_settings();
tuya_ble_adv_change();
tuya_ble_connect_status_set(UNBONDING_UNCONN);
TUYA_BLE_LOG_INFO("The state has changed, current bound flag = %d", tuya_ble_current_para.sys_settings.bound_flag);
}
}
}
}
return ret;
}
#endif
@@ -0,0 +1,284 @@
/**
* \file tuya_ble_unix_time.c
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#include "tuya_ble_stdlib.h"
#include "tuya_ble_unix_time.h"
#define UTC_BASE_YEAR 1970
#define MONTH_PER_YEAR 12
#define DAY_PER_YEAR 365
#define SEC_PER_DAY 86400
#define SEC_PER_HOUR 3600
#define SEC_PER_MIN 60
/* Number of days per month */
static const uint8_t g_day_per_mon[MONTH_PER_YEAR] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
/**
* @brief Function for Determine whether it is a leap year.
*
* @return 1leap year
* @note
*.
* */
static uint8_t applib_dt_is_leap_year(uint16_t year)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
if ((year % 400) == 0) {
return 1;
} else if ((year % 100) == 0) {
return 0;
} else if ((year % 4) == 0) {
return 1;
} else {
return 0;
}
}
/**
* @brief Function for obtain the days of month.
*
* @return days
* @note
*.
* */
static uint8_t applib_dt_last_day_of_mon(uint8_t month, uint16_t year)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
if ((month == 0) || (month > 12)) {
return g_day_per_mon[1] + applib_dt_is_leap_year(year);
}
if (month != 2) {
return g_day_per_mon[month - 1];
} else {
return g_day_per_mon[1] + applib_dt_is_leap_year(year);
}
}
/**
* @brief Function for get the corresponding week based on the given date.
*
* @return
* @note 0-Sunday 6-Saturday
*.
* */
static uint8_t applib_dt_dayindex(uint16_t year, uint8_t month, uint8_t day)
{
int8_t century_code, year_code, month_code, day_code;
int32_t week = 0;
century_code = year_code = month_code = day_code = 0;
if (month == 1 || month == 2) {
century_code = (year - 1) / 100;
year_code = (year - 1) % 100;
month_code = month + 12;
day_code = day;
} else {
century_code = year / 100;
year_code = year % 100;
month_code = month;
day_code = day;
}
week = year_code + year_code / 4 + century_code / 4 - 2 * century_code + 26 * (month_code + 1) / 10 + day_code - 1;
week = week > 0 ? (week % 7) : ((week % 7) + 7);
return week;
}
/**
* @brief Function for Get the corresponding date according to the UTC timestamp.
*
* @param[in] daylightSaving:daylight saving time
* @return
* @note
*.
* */
void tuya_ble_utc_sec_2_mytime(uint32_t utc_sec, tuya_ble_time_struct_data_t *result, bool daylightSaving)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
int32_t sec, day;
uint16_t y;
uint8_t m;
uint16_t d;
// uint8_t dst;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
if (daylightSaving) {
utc_sec += SEC_PER_HOUR;
}
/* hour, min, sec */
/* hour */
sec = utc_sec % SEC_PER_DAY;
result->nHour = sec / SEC_PER_HOUR;
/* min */
sec %= SEC_PER_HOUR;
result->nMin = sec / SEC_PER_MIN;
/* sec */
result->nSec = sec % SEC_PER_MIN;
/* year, month, day */
/* year */
/* year */
day = utc_sec / SEC_PER_DAY;
for (y = UTC_BASE_YEAR; day > 0; y++) {
d = (DAY_PER_YEAR + applib_dt_is_leap_year(y));
if (day >= d) {
day -= d;
} else {
break;
}
}
result->nYear = y;
for (m = 1; m < MONTH_PER_YEAR; m++) {
d = applib_dt_last_day_of_mon(m, y);
if (day >= d) {
day -= d;
} else {
break;
}
}
result->nMonth = m;
result->nDay = (uint8_t)(day + 1);
result->DayIndex = applib_dt_dayindex(result->nYear, result->nMonth, result->nDay);
}
/**
* @brief Function for Get the UTC timestamp according to corresponding date .
*
* @param[in] daylightSaving:daylight saving time
* @return
* @note
*.
* */
uint32_t tuya_ble_mytime_2_utc_sec(tuya_ble_time_struct_data_t *currTime, bool daylightSaving)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
uint16_t i;
uint32_t no_of_days = 0;
uint32_t utc_time;
uint8_t dst = 1;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
if (currTime->nYear < UTC_BASE_YEAR) {
return 0;
}
/* year */
for (i = UTC_BASE_YEAR; i < currTime->nYear; i++) {
no_of_days += (DAY_PER_YEAR + applib_dt_is_leap_year(i));
}
/* month */
for (i = 1; i < currTime->nMonth; i++) {
no_of_days += applib_dt_last_day_of_mon((unsigned char) i, currTime->nYear);
}
/* day */
no_of_days += (currTime->nDay - 1);
/* sec */
utc_time = (unsigned int) no_of_days * SEC_PER_DAY + (unsigned int)(currTime->nHour * SEC_PER_HOUR +
currTime->nMin * SEC_PER_MIN + currTime->nSec);
if (dst && daylightSaving) {
utc_time -= SEC_PER_HOUR;
}
return utc_time;
}
void tuya_ble_utc_sec_2_mytime_string(uint32_t utc_sec, bool daylightSaving, char *s)
{
tuya_ble_time_struct_data_t rtc_time = {0};
uint32_t temp = 0;
tuya_ble_utc_sec_2_mytime(utc_sec, &rtc_time, daylightSaving);
temp = rtc_time.nYear;
s[0] = temp / 1000 + 0x30;
temp = rtc_time.nYear % 1000;
s[1] = temp / 100 + 0x30;
temp = temp % 100;
s[2] = temp / 10 + 0x30;
s[3] = temp % 10 + 0x30;
s[4] = '-';
s[5] = rtc_time.nMonth / 10 + 0x30;
s[6] = rtc_time.nMonth % 10 + 0x30;
s[7] = '-';
s[8] = rtc_time.nDay / 10 + 0x30;
s[9] = rtc_time.nDay % 10 + 0x30;
s[10] = ' ';
s[11] = rtc_time.nHour / 10 + 0x30;
s[12] = rtc_time.nHour % 10 + 0x30;
s[13] = ':';
s[14] = rtc_time.nMin / 10 + 0x30;
s[15] = rtc_time.nMin % 10 + 0x30;
s[16] = ':';
s[17] = rtc_time.nSec / 10 + 0x30;
s[18] = rtc_time.nSec % 10 + 0x30;
s[19] = '\0';
}
@@ -0,0 +1,773 @@
/**
* \file tuya_ble_utils.c
*
* \brief
*/
/*
* Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of tuya ble sdk
*/
#include "tuya_ble_stdlib.h"
#include "tuya_ble_utils.h"
#include "tuya_ble_port.h"
#include "tuya_ble_mem.h"
int32_t tuya_ble_count_bits(uint32_t data)
{
int32_t i = 0;
int32_t cnt = 0;
for (i = 0; i < 32; i++) {
if (data & 0x01) {
cnt++;
}
data >>= 1;
}
return cnt;
}
int32_t tuya_ble_rand_number(int32_t min, int32_t max)
{
static bool is_srand_init = false;
int32_t num;
if (!is_srand_init) {
is_srand_init = true;
//srand(time(NULL));
}
num = rand() % (max - min) + min; // [min<=num<=max]
return num;
}
void tuya_ble_inverted_array(uint8_t *array, uint16_t length)
{
uint8_t temp;
uint16_t i, j;
for (i = 0, j = length - 1; i < j; i++, j--) {
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
bool tuya_ble_buffer_value_is_all_x(uint8_t *buffer, uint16_t len, uint8_t value)
{
bool ret = true;
for (uint16_t i = 0; i < len; i++) {
if (buffer[i] != value) {
ret = false;
break;
}
}
return ret;
}
uint8_t tuya_ble_check_sum(uint8_t *pbuf, uint16_t len)
{
uint32_t i = 0, ck_sum = 0;
for (i = 0; i < len ; i++) {
ck_sum += pbuf[i];
}
return (uint8_t)ck_sum;
}
uint8_t tuya_ble_check_num(uint8_t *buf, uint8_t num)
{
uint8_t i = 0;
for (; i < buf[0]; i++) {
if (buf[i + 1] == num) {
return 1;
}
}
return 0;
}
void tuya_ble_hextoascii(uint8_t *hexbuf, uint8_t len, uint8_t *ascbuf)
{
uint8_t i = 0, j = 0, temp = 0;
for (i = 0; i < len; i++) {
temp = (hexbuf[i] >> 4) & 0xf;
if (temp <= 9) {
ascbuf[j] = temp + 0x30;
} else {
ascbuf[j] = temp + 87;
}
j++;
temp = (hexbuf[i]) & 0xf;
if (temp <= 9) {
ascbuf[j] = temp + 0x30;
} else {
ascbuf[j] = temp + 87;
}
j++;
}
}
void tuya_ble_hextostr(uint8_t *hexbuf, uint8_t len, uint8_t *strbuf)
{
uint8_t i = 0, j = 0, temp = 0;
for (i = 0; i < len; i++) {
temp = (hexbuf[i] >> 4) & 0x0f;
if (temp <= 9) {
strbuf[j] = temp + 0x30;
} else {
strbuf[j] = temp + 87;
}
j++;
temp = (hexbuf[i]) & 0x0f;
if (temp <= 9) {
strbuf[j] = temp + 0x30;
} else {
strbuf[j] = temp + 87;
}
j++;
}
strbuf[j] = 0x00;
}
void tuya_ble_asciitohex(uint8_t *ascbuf, uint8_t *hexbuf)
{
uint8_t i = 0, j = 0;
while (ascbuf[i]) {
j++;
if ((ascbuf[i] >= 0x30) && (ascbuf[i] <= 0x39)) {
hexbuf[j] = ((ascbuf[i] - 0x30) << 4);
} else if ((ascbuf[i] >= 65) && (ascbuf[i] <= 70)) {
hexbuf[j] = ((ascbuf[i] - 55) << 4);
} else if ((ascbuf[i] >= 97) && (ascbuf[i] <= 102)) {
hexbuf[j] = ((ascbuf[i] - 87) << 4);
}
i++;
if ((ascbuf[i] >= 0x30) && (ascbuf[i] <= 0x39)) {
hexbuf[j] |= (ascbuf[i] - 0x30);
} else if ((ascbuf[i] >= 65) && (ascbuf[i] <= 70)) {
hexbuf[j] |= (ascbuf[i] - 55);
} else if ((ascbuf[i] >= 97) && (ascbuf[i] <= 102)) {
hexbuf[j] |= (ascbuf[i] - 87);
}
i++;
}
hexbuf[0] = j;
}
uint8_t tuya_ble_char_2_ascii(uint8_t data)
{
uint8_t ret = 0xff;
if ((data >= 48) && (data <= 57)) {
ret = data - 48;
} else if ((data >= 65) && (data <= 70)) {
ret = data - 55;
} else if ((data >= 97) && (data <= 102)) {
ret = data - 87;
}
return ret;
}
void tuya_ble_str_to_hex(uint8_t *str_buf, uint8_t str_len, uint8_t *hex_buf)
{
uint8_t data_tmp = 0, i = 0, j = 0;
for (j = 0 ; j < str_len ; j++) {
data_tmp = tuya_ble_char_2_ascii(str_buf[j]);
if (data_tmp != 0xff) {
hex_buf[i] = (data_tmp << 4);
} else {
return;
}
j++;
data_tmp = tuya_ble_char_2_ascii(str_buf[j]);
if (data_tmp != 0xff) {
hex_buf[i] += data_tmp;
} else {
return;
}
i++;
}
}
void tuya_ble_swap(int16_t *a, int16_t *b)
{
int16_t temp;
temp = *a;
*a = *b;
*b = temp;
}
int32_t tuya_ble_hex2int(uint8_t mhex)
{
switch (mhex) {
case '0':
return 0;
case '1':
return 1;
case '2':
return 2;
case '3':
return 3;
case '4':
return 4;
case '5':
return 5;
case '6':
return 6;
case '7':
return 7;
case '8':
return 8;
case '9':
return 9;
case 'a':
case 'A':
return 10;
case 'b':
case 'B':
return 11;
case 'c':
case 'C':
return 12;
case 'd':
case 'D':
return 13;
case 'e':
case 'E':
return 14;
case 'f':
case 'F':
return 15;
default:
return -1;
}
}
char tuya_ble_hexstr2int(uint8_t *hexstr, int32_t len, uint8_t *sum)
{
*sum = 0;
int32_t value;
for (int32_t i = 0; i < len; i++) {
value = tuya_ble_hex2int(hexstr[i]);
if (value == -1) {
return 0;
}
(*sum) = (*sum) << 4;
(*sum) += value;
}
return 1;
}
char tuya_ble_hexstr2hex(uint8_t *hexstr, int32_t len, uint8_t *hex)
{
for (uint8_t i = 0; i < len; i += 2) {
if (tuya_ble_hexstr2int(&hexstr[i], 2, &hex[i / 2]) == 0) {
return 0;
}
}
return 1;
}
static void swapX(const uint8_t *src, uint8_t *dst, int32_t len)
{
int32_t i;
for (i = 0; i < len; i++) {
dst[len - 1 - i] = src[i];
}
}
void tuya_ble_swap24(uint8_t dst[3], const uint8_t src[3])
{
swapX(src, dst, 3);
}
void tuya_ble_swap32(uint8_t dst[4], const uint8_t src[4])
{
swapX(src, dst, 4);
}
void tuya_ble_swap48(uint8_t dst[7], const uint8_t src[7])
{
swapX(src, dst, 6);
}
void tuya_ble_swap56(uint8_t dst[7], const uint8_t src[7])
{
swapX(src, dst, 7);
}
void tuya_ble_swap64(uint8_t dst[8], const uint8_t src[8])
{
swapX(src, dst, 8);
}
void tuya_ble_swap128(uint8_t dst[16], const uint8_t src[16])
{
swapX(src, dst, 16);
}
uint16_t tuya_ble_crc16_compute(uint8_t *p_data, uint16_t size, uint16_t *p_crc)
{
uint16_t poly[2] = {0, 0xa001}; //0x8005 <==> 0xa001
uint16_t crc;
int i, j;
crc = (p_crc == NULL) ? 0xFFFF : *p_crc;
for (j = size; j > 0; j--) {
unsigned char ds = *p_data++;
for (i = 0; i < 8; i++) {
crc = (crc >> 1) ^ poly[(crc ^ ds) & 1];
ds = ds >> 1;
}
}
return crc;
}
uint32_t tuya_ble_crc32_compute(uint8_t const *p_data, uint32_t size, uint32_t const *p_crc)
{
uint32_t crc;
crc = (p_crc == NULL) ? 0xFFFFFFFF : ~(*p_crc);
for (uint32_t i = 0; i < size; i++) {
crc = crc ^ p_data[i];
for (uint32_t j = 8; j > 0; j--) {
crc = (crc >> 1) ^ (0xEDB88320U & ((crc & 1) ? 0xFFFFFFFF : 0));
}
}
return ~crc;
}
/**@brief Function for checking if a pointer value is aligned to a 4 byte boundary.
*
* @param[in] p Pointer value to be checked.
*
* @return TRUE if pointer is aligned to a 4 byte boundary, FALSE otherwise.
*/
bool tuya_ble_is_word_aligned_tuya(void const *p)
{
return (((uintptr_t)p & 0x03) == 0);
}
void tuya_ble_device_id_20_to_16(uint8_t *in, uint8_t *out)
{
uint8_t i, j;
uint8_t temp[4];
for (i = 0; i < 5; i++) {
for (j = i * 4; j < (i * 4 + 4); j++) {
if ((in[j] >= 0x30) && (in[j] <= 0x39)) {
temp[j - i * 4] = in[j] - 0x30;
} else if ((in[j] >= 0x41) && (in[j] <= 0x5A)) {
temp[j - i * 4] = in[j] - 0x41 + 36;
} else if ((in[j] >= 0x61) && (in[j] <= 0x7A)) {
temp[j - i * 4] = in[j] - 0x61 + 10;
} else {
}
}
out[i * 3] = temp[0] & 0x3F;
out[i * 3] <<= 2;
out[i * 3] |= ((temp[1] >> 4) & 0x03);
out[i * 3 + 1] = temp[1] & 0x0F;
out[i * 3 + 1] <<= 4;
out[i * 3 + 1] |= ((temp[2] >> 2) & 0x0F);
out[i * 3 + 2] = temp[2] & 0x03;
out[i * 3 + 2] <<= 6;
out[i * 3 + 2] |= temp[3] & 0x3F;
}
out[15] = 0xFF;
}
void tuya_ble_device_id_16_to_20(uint8_t *in, uint8_t *out)
{
uint8_t i, j;
uint8_t temp[4];
for (i = 0; i < 5; i++) {
j = i * 3;
temp[j - i * 3] = (in[j] >> 2) & 0x3F;
temp[j - i * 3 + 1] = in[j] & 0x03;
temp[j - i * 3 + 1] <<= 4;
temp[j - i * 3 + 1] |= (in[j + 1] >> 4) & 0x0F;
temp[j - i * 3 + 2] = (in[j + 1] & 0x0F) << 2;
temp[j - i * 3 + 2] |= ((in[j + 2] & 0xC0) >> 6) & 0x03;
temp[j - i * 3 + 3] = in[j + 2] & 0x3F;
for (j = i * 4; j < (i * 4 + 4); j++) {
if ((temp[j - i * 4] >= 0) && (temp[j - i * 4] <= 9)) {
out[j] = temp[j - i * 4] + 0x30;
} else if ((temp[j - i * 4] >= 10) && (temp[j - i * 4] <= 35)) {
out[j] = temp[j - i * 4] + 87;
} else if ((temp[j - i * 4] >= 36) && (temp[j - i * 4] <= 61)) {
out[j] = temp[j - i * 4] + 29;
} else {
}
}
}
}
/**
* @brief Function for search character/symbol index from input string
*
* @param
* [in]data : pointer to input data
* [in]data : Number of bytes of data
* [in]symbol : Search symbol or character, Such as ':' or ','
* [out]index[] : Array of indexs
*
* @return The number of matched character/symbol
*
* @note
*
* */
int32_t tuya_ble_search_symbol_index(char *data, uint16_t len, char symbol, uint8_t index[])
{
int32_t i;
uint8_t index_buf[64] = {0};
uint8_t symbol_cnt = 0;
if (data == NULL || len == 0 || index == NULL) {
return symbol_cnt;
}
for (i = 0; i < len; i++) {
if (data[i] == symbol) {
index_buf[symbol_cnt] = i;
symbol_cnt += 1;
if (symbol_cnt >= sizeof(index_buf)) {
/* error, too many symbols */
break;
}
}
}
if (symbol_cnt != 0) {
memcpy(index, index_buf, symbol_cnt);
}
return symbol_cnt;
}
int32_t tuya_ble_ascii_to_int(char *ascii, uint16_t len)
{
int32_t i;
int32_t num = 0;
bool negative = false;
if (ascii == NULL || len == 0) {
return num;
}
if (ascii[0] == 0x2D) {
negative = true;
} else {
num *= 10;
num += ascii[0] - '0';
}
for (i = 1; i < len; i++) {
num *= 10;
num += ascii[i] - '0';
}
if (negative) {
num = -1 * num;
}
return num;
}
static uint8_t base64_decode(const uint8_t *input, uint16_t inlen, uint8_t *output, uint16_t *outlen)
{
const char *base64_tbl = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
uint8_t reverse_tbl[256] = {0};
int32_t off = 0;
int32_t i = 0;
if (NULL == input) {
return 1;
}
if (inlen == 0) {
inlen = strlen((char *)input);
}
if (inlen == 0 || (inlen % 4 != 0)) {
return 1;
}
for (i = 0; i < 64; i++) {
reverse_tbl[base64_tbl[i]] = i;
}
for (i = 0; i < inlen - 4; i += 4) {
output[off++] = (reverse_tbl[input[i]] << 2) | ((reverse_tbl[input[i + 1]] >> 4) & 0xFF);
output[off++] = (reverse_tbl[input[i + 1]] << 4) | ((reverse_tbl[input[i + 2]] >> 2) & 0xFF);
output[off++] = (reverse_tbl[input[i + 2]] << 6) | ((reverse_tbl[input[i + 3]]) & 0xFF);
}
if (input[i + 2] == '=') {
output[off++] = (reverse_tbl[input[i]] << 2) | ((reverse_tbl[input[i + 1]] >> 4) & 0xFF);
} else if (input[i + 3] == '=') {
output[off++] = (reverse_tbl[input[i]] << 2) | ((reverse_tbl[input[i + 1]] >> 4) & 0xFF);
output[off++] = (reverse_tbl[input[i + 1]] << 4) | ((reverse_tbl[input[i + 2]] >> 2) & 0xFF);
} else {
output[off++] = (reverse_tbl[input[i]] << 2) | ((reverse_tbl[input[i + 1]] >> 4) & 0xFF);
output[off++] = (reverse_tbl[input[i + 1]] << 4) | ((reverse_tbl[input[i + 2]] >> 2) & 0xFF);
output[off++] = (reverse_tbl[input[i + 2]] << 6) | ((reverse_tbl[input[i + 3]]) & 0xFF);
}
if (NULL != outlen) {
*outlen = off;
}
return 0;
}
static int32_t delChar(char *s, uint16_t len, char match_char)
{
int32_t i, j;
int32_t counter = 0;
for (i = 0; i < len; i++) {
if (s[i] == match_char) {
counter++;
for (j = i; j < len; j++) {
s[j] = s[j + 1];
i--;
}
}
}
return counter;
}
/**
* @brief Function for pem format ecc key to hex foramt
*
* @param
* [in]pem : pointer to pem data
* [out]key : pointer to output data, hex format ecc key
* [out]key_len: Number of bytes of key.
*
* @return 0 - failed, 1 - success
*
* @note developer could use tuya_ble_ecc_key_pem2hex_example() function to test
*
* */
int32_t tuya_ble_ecc_key_pem2hex(const char *pem, uint8_t *key, uint16_t *key_len)
{
char buf1[256] = {0};
char buf2[256] = {0};
uint16_t inlen = 0;
uint16_t i, j, k = 0;
uint16_t len, len1, len2 = 0;
if (NULL == pem) {
return 0;
}
inlen = strlen(pem);
if (inlen > 256) {
return 0;
}
//head
if ((pem[0] != '-') || (pem[1] != '-') || (pem[2] != '-') || (pem[3] != '-') || (pem[4] != '-')) {
return 0;
}
//tail
if ((pem[inlen - 1] != '-') || (pem[inlen - 2] != '-') || (pem[inlen - 3] != '-') || (pem[inlen - 4] != '-') || (pem[inlen - 5] != '-')) {
return 0;
}
//find head end
for (i = 5; i < inlen - 5; i++) {
if (pem[i] == '-') {
if ((pem[i + 1] != '-') || (pem[i + 2] != '-') || (pem[i + 3] != '-') || (pem[i + 4] != '-')) {
return 0;
}
len1 = i + 5;
break;
}
}
//remove head
memcpy(buf1, pem + len1, inlen - len1);
//find tail
for (i = 0; i < inlen - len1; i++) {
if (buf1[i] == '-') {
if ((buf1[i + 1] != '-') || (buf1[i + 2] != '-') || (buf1[i + 3] != '-') || (buf1[i + 4] != '-')) {
return 0;
}
len2 = i;
break;
}
}
len = len2;
//remove \n
len1 = delChar(buf1, len, '\n');
len = len - len1;
//remove \r
len1 = delChar(buf1, len, '\r');
len = len - len1;
//decode
base64_decode((uint8_t *)buf1, len, (uint8_t *)buf2, (uint16_t *)&len2);
//next is asn.1 decode
if (buf2[0] != 0x30) { //0x30
return 0;
}
len1 = buf2[1];//0x30 0x41
if ((len1 + 2) != len2) {
return 0;
}
if (buf2[2] != 0x02) { //0x30 0x41 0x20 0x01 0x00
return 0;
}
if (buf2[5] != 0x30) {
return 0;
}
len1 = buf2[6];
if (buf2[7 + len1] != 0x04) { //0x04
return 0;
}
// len2 = buf2[8+len1];//0x04 0x27
if (buf2[9 + len1] != 0x30) { //0x30
return 0;
}
// len = buf2[10+len1];//0x25
if (buf2[11 + len1] != 0x02) { //0x02
return 0;
}
if (buf2[14 + len1] != 0x04) { //0x04
return 0;
}
*key_len = buf2[15 + len1];
memcpy(key, &buf2[16 + len1], *key_len);
return 1;
}
void tuya_ble_ecc_key_pem2hex_example(void)
{
uint8_t key[64] = {0};
uint16_t keylen = 0;
char test_char[] =
"-----BEGIN PRIVATE KEY-----MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCBX5s0E0DJowr3ibkG41jfvjRFgaoCO7v8fU/Wq/xLlDQ==-----END PRIVATE KEY-----";
tuya_ble_ecc_key_pem2hex(test_char, key, &keylen);
/* output hex format key */
// 57 E6 CD 04 D0 32 68 C2 BD E2 6E 41 B8 D6 37 EF
// 8D 11 60 6A 80 8E EE FF 1F 53 F5 AA FF 12 E5 0D
}
/**
* @brief Function for extract r+s from der from ecdsa sign
*
* @param
* [in]der : pointer to der data
* [out]raw_rs : pointer to output data, the raw data[r+s] of der
*
* @return 0 - failed, 1 - success
*
* @note
*
* */
int32_t tuya_ble_ecc_sign_secp256r1_extract_raw_from_der(const char *der, uint8_t *raw_rs)
{
/* extract r + s from der */
int pos = 0;
uint8_t raw[64] = {0};
if (der == NULL || raw_rs == NULL) {
return 0;
}
if (der[3] != 0x20) {
memcpy(raw, &der[5], 32);
pos = 5 + 32;
} else {
memcpy(raw, &der[4], 32);
pos = 4 + 32;
}
// 37
if (der[pos + 1] != 0x20) {
memcpy(&raw[32], &der[pos + 3], 32);
} else {
memcpy(&raw[32], &der[pos + 2], 32);
}
memcpy(raw_rs, raw, sizeof(raw));
return 1;
}