first
This commit is contained in:
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#ifndef QCLOUD_BLE_QIOT_COMMON_H
|
||||
#define QCLOUD_BLE_QIOT_COMMON_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BLE_QIOT_PRODUCT_ID_LEN (10) // fixed length of product id
|
||||
#define BLE_QIOT_DEVICE_NAME_LEN (48) // max length of device name
|
||||
#define BLE_QIOT_PSK_LEN (24) // fixed length of secret key
|
||||
#define BLE_QIOT_MAC_LEN (6) // fixed length of mac
|
||||
|
||||
#define SWAP_32(x) \
|
||||
((((x)&0xFF000000) >> 24) | (((x)&0x00FF0000) >> 8) | (((x)&0x0000FF00) << 8) | (((x)&0x000000FF) << 24))
|
||||
#define SWAP_16(x) ((((x)&0xFF00) >> 8) | (((x)&0x00FF) << 8))
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
#define HTONL(x) SWAP_32(x)
|
||||
#define HTONS(x) SWAP_16(x)
|
||||
#define NTOHL(x) SWAP_32(x)
|
||||
#define NTOHS(x) SWAP_16(x)
|
||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
#define HTONL(x) (x)
|
||||
#define HTONS(x) (x)
|
||||
#define NTOHL(x) (x)
|
||||
#define NTOHS(x) (x)
|
||||
#else
|
||||
#error "undefined byte order"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // QCLOUD_BLE_QIOT_COMMON_H
|
||||
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QCLOUD_BLE_QIOT_CONFIG_H
|
||||
#define QCLOUD_BLE_QIOT_CONFIG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <printf.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define BLE_QIOT_SDK_VERSION "1.5.0" // sdk version
|
||||
#define BLE_QIOT_SDK_DEBUG 0 // sdk debug
|
||||
|
||||
// the device broadcast is controlled by the user, but we provide a mechanism to help the device save more power.
|
||||
// if you want broadcast is triggered by something like press a button instead of all the time, and the broadcast
|
||||
// stopped automatically in a few minutes if the device is not bind, define BLE_QIOT_BUTTON_BROADCAST is 1 and
|
||||
// BLE_QIOT_BIND_TIMEOUT is the period that broadcast stopped.
|
||||
// if the device in the bound state, broadcast dose not stop automatically.
|
||||
#define BLE_QIOT_BUTTON_BROADCAST 0
|
||||
#if BLE_QIOT_BUTTON_BROADCAST
|
||||
#define BLE_QIOT_BIND_TIMEOUT (2 * 60 * 1000) // unit: ms
|
||||
#endif //BLE_QIOT_BUTTON_BROADCAST
|
||||
|
||||
// in some BLE stack the default ATT_MTU is 23, set BLE_QIOT_REMOTE_SET_MTU is 1 if you want to reset the mtu by the
|
||||
// Tencent Lianlian. Tencent Lianlian will set the mtu get from function ble_get_user_data_mtu_size()
|
||||
#define BLE_QIOT_REMOTE_SET_MTU (1)
|
||||
|
||||
// the following definition will affect the stack that LLSync used,the minimum value tested is 2048 bytes
|
||||
// the max length of llsync event data, depends on the length of user data reported to Tencent Lianlian at a time
|
||||
#define BLE_QIOT_EVENT_MAX_SIZE (128)
|
||||
// the minimum between BLE_QIOT_EVENT_MAX_SIZE and mtu
|
||||
#define BLE_QIOT_EVENT_BUF_SIZE (23)
|
||||
|
||||
// some data like integer need to be transmitted in a certain byte order, defined it according to your device
|
||||
#define __ORDER_LITTLE_ENDIAN__ 1234
|
||||
#define __ORDER_BIG_ENDIAN__ 4321
|
||||
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
|
||||
|
||||
// in some BLE stack ble_qiot_log_hex() maybe not work, user can use there own hexdump function
|
||||
#define BLE_QIOT_USER_DEFINE_HEXDUMP 0
|
||||
#if BLE_QIOT_USER_DEFINE_HEXDUMP
|
||||
// add your code here like this
|
||||
// #define ble_qiot_log_hex(level, hex_name, data, data_len) \
|
||||
// do { \
|
||||
// MY_RAW_LOG("\r\nble qiot dump: %s, length: %d\r\n", hex_name, data_len); \
|
||||
// MY_RAW_HEXDUMP_(data, data_len); \
|
||||
// } while(0)
|
||||
|
||||
// or use your own hexdump function with same definition
|
||||
// void ble_qiot_log_hex(e_ble_qiot_log_level level, const char *hex_name, const char *data, uint32_t data_len);
|
||||
#endif // BLE_QIOT_USER_DEFINE_HEXDUMP
|
||||
|
||||
// Macro for logging a formatted string, the function must printf raw string without any color, prefix, newline or
|
||||
// timestamp
|
||||
#define BLE_QIOT_LOG_PRINT(...) printf(__VA_ARGS__)
|
||||
|
||||
#define BLE_QIOT_LLSYNC_STANDARD 1 // support llsync standard
|
||||
#if BLE_QIOT_LLSYNC_STANDARD
|
||||
// some users hope to confirm on the device before the binding, set BLE_QIOT_SECURE_BIND is 1 to enable the secure
|
||||
// binding and enable secure bind in iot-explorer console. When the server is bound, the device callback ble_secure_bind_user_cb()
|
||||
// will be triggered, the user agree or refuse connect by ble_secure_bind_user_confirm(). If the device does not respond
|
||||
// and the connection timeout, or the user cancel the connection in Tencent Lianlian, a notify will received in function
|
||||
// ble_secure_bind_user_notify().
|
||||
#define BLE_QIOT_SECURE_BIND 0
|
||||
#if BLE_QIOT_SECURE_BIND
|
||||
#define BLE_QIOT_BIND_WAIT_TIME 60
|
||||
#endif //BLE_QIOT_SECURE_BIND
|
||||
|
||||
// some sdk info needs to stored on the device and the address is up to you
|
||||
#define BLE_QIOT_RECORD_FLASH_ADDR 5
|
||||
|
||||
// define user develop version, pick from "a-zA-Z0-9.-_" and length limits 1~32 bytes.
|
||||
// must be consistent with the firmware version that user write in the iot-explorer console
|
||||
// refer https://cloud.tencent.com/document/product/1081/40296
|
||||
#define BLE_QIOT_USER_DEVELOPER_VERSION "0.0.1"
|
||||
|
||||
#define BLE_QIOT_SUPPORT_OTA 1 // 1 is support ota, others not
|
||||
#if BLE_QIOT_SUPPORT_OTA
|
||||
#define BLE_QIOT_SUPPORT_RESUMING 0 // 1 is support resuming, others not
|
||||
#if BLE_QIOT_SUPPORT_RESUMING
|
||||
// storage ota info in the flash if support resuming ota file
|
||||
#define BLE_QIOT_OTA_INFO_FLASH_ADDR 10
|
||||
#endif //BLE_QIOT_SUPPORT_RESUMING
|
||||
|
||||
#define BLE_QIOT_TOTAL_PACKAGES 0x12 // the total package numbers in a loop
|
||||
#define BLE_QIOT_PACKAGE_LENGTH 0xb0 // the user data length in package, ble_get_user_data_mtu_size() - 3 is the max
|
||||
#define BLE_QIOT_RETRY_TIMEOUT 0x20 // the max interval between two packages, unit: second
|
||||
// the time spent for device reboot, the server waiting the device version reported after upgrade. unit: second
|
||||
#define BLE_QIOT_REBOOT_TIME 20
|
||||
#define BLE_QIOT_PACKAGE_INTERVAL 0xa // the interval between two packages send by the server
|
||||
// the package from the server will storage in the buffer, write the buffer to the flash at one time when the buffer
|
||||
// overflow. reduce the flash write can speed up file download, we suggest the BLE_QIOT_OTA_BUF_SIZE is multiples
|
||||
// of BLE_QIOT_PACKAGE_LENGTH and equal flash page size
|
||||
#define BLE_QIOT_OTA_BUF_SIZE (512 * 4)
|
||||
#endif //BLE_QIOT_SUPPORT_OTA
|
||||
#endif //BLE_QIOT_LLSYNC_STANDARD
|
||||
|
||||
#define BLE_QIOT_LLSYNC_CONFIG_NET (!BLE_QIOT_LLSYNC_STANDARD) // support llsync configure network
|
||||
|
||||
#if (1 == BLE_QIOT_LLSYNC_STANDARD) && (1 == BLE_QIOT_LLSYNC_CONFIG_NET)
|
||||
#error "llsync standard and llsync configure network is incompatible"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // QCLOUD_BLE_QIOT_CONFIG_H
|
||||
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making IoT Hub available.
|
||||
* Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QCLOUD_BLE_QIOT_CRC_H
|
||||
#define QCLOUD_BLE_QIOT_CRC_H
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <printf.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void ble_qiot_crc32_init();
|
||||
uint32_t ble_qiot_crc32(uint32_t crc, const uint8_t *buf, int len);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif // QCLOUD_BLE_QIOT_HMAC_H
|
||||
@ -0,0 +1,285 @@
|
||||
/*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#ifndef QCLOUD_BLE_QIOT_EXPORT_H
|
||||
#define QCLOUD_BLE_QIOT_EXPORT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ble_qiot_config.h"
|
||||
|
||||
#define TENCENT_COMPANY_IDENTIFIER 0xFEE7 // Tencent Company ID, another is 0xFEBA
|
||||
|
||||
#define IOT_BLE_UUID_BASE \
|
||||
{ \
|
||||
0xe2, 0xa4, 0x1b, 0x54, 0x93, 0xe4, 0x6a, 0xb5, 0x20, 0x4e, 0xd0, 0x65, 0x00, 0x00, 0x00, 0x00 \
|
||||
}
|
||||
|
||||
// llsync services uuid
|
||||
#if BLE_QIOT_LLSYNC_STANDARD
|
||||
#define IOT_BLE_UUID_SERVICE 0xFFE0
|
||||
#endif //BLE_QIOT_LLSYNC_STANDARD
|
||||
#if BLE_QIOT_LLSYNC_CONFIG_NET
|
||||
#define IOT_BLE_UUID_SERVICE 0xFFF0
|
||||
#endif //BLE_QIOT_LLSYNC_CONFIG_NET
|
||||
|
||||
// characteristics uuid
|
||||
#define IOT_BLE_UUID_DEVICE_INFO 0xFFE1 // used to connection and identity authentication
|
||||
#define IOT_BLE_UUID_EVENT 0xFFE3 // used to send data to the server from device
|
||||
|
||||
#if BLE_QIOT_LLSYNC_STANDARD
|
||||
#define IOT_BLE_UUID_DATA 0xFFE2 // used to send data to the device from server
|
||||
#define IOT_BLE_UUID_OTA 0xFFE4 // used to send ota data to the device from server
|
||||
#endif //BLE_QIOT_LLSYNC_STANDARD
|
||||
|
||||
typedef enum {
|
||||
GATT_CHAR_BROADCAST = (1 << 0), // Broadcasting of the value permitted.
|
||||
GATT_CHAR_READ = (1 << 1), // Reading the value permitted.
|
||||
GATT_CHAR_WRITE_WO_RESP = (1 << 2), // Writing the value with Write Command permitted.
|
||||
GATT_CHAR_WRITE = (1 << 3), // Writing the value with Write Request permitted.
|
||||
GATT_CHAR_NOTIFY = (1 << 4), // Notification of the value permitted.
|
||||
GATT_CHAR_INDICATE = (1 << 5), // Indications of the value permitted.
|
||||
GATT_CHAR_AUTH_SIGNED_WR = (1 << 6), // Writing the value with Signed Write Command permitted.
|
||||
} char_props_s;
|
||||
|
||||
// the callback function prototype definition for the characteristics
|
||||
typedef void (*ble_on_write_cb)(const uint8_t *buf, uint16_t len);
|
||||
|
||||
// the characteristics attributes
|
||||
typedef struct {
|
||||
uint16_t uuid16;
|
||||
uint8_t gatt_char_props;
|
||||
ble_on_write_cb on_write;
|
||||
} qiot_char_s;
|
||||
|
||||
// the service attributes
|
||||
typedef struct {
|
||||
uint16_t service_uuid16;
|
||||
uint8_t service_uuid128[16];
|
||||
uint16_t gatt_max_mtu;
|
||||
|
||||
qiot_char_s device_info;
|
||||
qiot_char_s data;
|
||||
qiot_char_s event;
|
||||
qiot_char_s ota;
|
||||
} qiot_service_init_s;
|
||||
|
||||
typedef enum {
|
||||
BLE_QIOT_RS_OK = 0, // success
|
||||
BLE_QIOT_RS_ERR = -1, // normal error
|
||||
BLE_QIOT_RS_ERR_FLASH = -2, // flash error
|
||||
BLE_QIOT_RS_ERR_PARA = -3, // parameters error
|
||||
BLE_QIOT_RS_VALID_SIGN_ERR = -4,
|
||||
} ble_qiot_ret_status_t;
|
||||
|
||||
/**
|
||||
* @brief get llsync services context
|
||||
*
|
||||
* @return llsync services struct
|
||||
*/
|
||||
const qiot_service_init_s *ble_get_qiot_services(void);
|
||||
|
||||
/**
|
||||
* @brief llsync sdck initialize
|
||||
* @note you should called it before any other sdk api
|
||||
* @return BLE_QIOT_RS_OK is success, other is error
|
||||
*/
|
||||
ble_qiot_ret_status_t ble_qiot_explorer_init(void);
|
||||
|
||||
/**
|
||||
* @brief report mtu of the device to the server
|
||||
* @note report mtu to the server to set the mtu
|
||||
* @return BLE_QIOT_RS_OK is success, other is error
|
||||
*/
|
||||
ble_qiot_ret_status_t ble_event_report_device_info(void);
|
||||
|
||||
/**
|
||||
* @brief sync the device mtu to The Tencent Lianlian.
|
||||
* @note if BLE_QIOT_REMOTE_SET_MTU is 1, The Tencent Lianlian will set the mtu get from function
|
||||
* ble_get_user_data_mtu_size(), but The Tencent Lianlian can not know the effective value even if the setting is
|
||||
* successful, so llsync need sync the mtu again. The user call this function in the BLE mtu callback.
|
||||
* @return BLE_QIOT_RS_OK is success, other is error
|
||||
*/
|
||||
ble_qiot_ret_status_t ble_event_sync_mtu(uint16_t llsync_mtu);
|
||||
|
||||
/**
|
||||
* @brief start llsync advertising
|
||||
* @note broadcast data according to the device bind state, reference to llsync protocol
|
||||
* @return BLE_QIOT_RS_OK is success, other is error
|
||||
*/
|
||||
ble_qiot_ret_status_t ble_qiot_advertising_start(void);
|
||||
|
||||
/**
|
||||
* @brief stop advertising
|
||||
* @return BLE_QIOT_RS_OK is success, other is error
|
||||
*/
|
||||
ble_qiot_ret_status_t ble_qiot_advertising_stop(void);
|
||||
|
||||
/**
|
||||
* @brief device info write callbcak, call the function when characteristic IOT_BLE_UUID_DEVICE_INFO received data
|
||||
* @param buf a pointer point to the data
|
||||
* @param len data length
|
||||
* @return none
|
||||
*/
|
||||
void ble_device_info_write_cb(const uint8_t *buf, uint16_t len);
|
||||
|
||||
/**
|
||||
* @brief gap event connect call-back, when gap get ble connect event, use this function
|
||||
* tell qiot ble sdk
|
||||
* @return none
|
||||
*/
|
||||
void ble_gap_connect_cb(void);
|
||||
|
||||
/**
|
||||
* @brief gap event disconnect call-back, when gap get ble disconnect event, use this function
|
||||
* tell qiot ble sdk
|
||||
* @return none
|
||||
*/
|
||||
void ble_gap_disconnect_cb(void);
|
||||
|
||||
#ifdef BLE_QIOT_LLSYNC_STANDARD
|
||||
/**
|
||||
* @brief get property of the device from the server
|
||||
* @note the property will be received from IOT_BLE_UUID_DATA if success
|
||||
* @return BLE_QIOT_RS_OK is success, other is error. if success, the data from server will come to
|
||||
*/
|
||||
ble_qiot_ret_status_t ble_event_get_status(void);
|
||||
|
||||
/**
|
||||
* @brief report property of the device to the server
|
||||
* @note the reply will be received from IOT_BLE_UUID_DATA if success
|
||||
* @return BLE_QIOT_RS_OK is success, other is error
|
||||
*/
|
||||
ble_qiot_ret_status_t ble_event_report_property(void);
|
||||
|
||||
/**
|
||||
* @brief post event to the server
|
||||
* @param event_id id of the event
|
||||
* @note the reply will be received from IOT_BLE_UUID_DATA if success
|
||||
* @return BLE_QIOT_RS_OK is success, other is error
|
||||
*/
|
||||
ble_qiot_ret_status_t ble_event_post(uint8_t event_id);
|
||||
|
||||
/**
|
||||
* @brief data write callback, call the function when characteristic IOT_BLE_UUID_DATA received data
|
||||
* @param buf a pointer point to the data
|
||||
* @param len data length
|
||||
* @return none
|
||||
*/
|
||||
void ble_lldata_write_cb(const uint8_t *buf, uint16_t len);
|
||||
|
||||
/**
|
||||
* @brief ota data write callback, call the function when characteristic IOT_BLE_UUID_OTA received data
|
||||
* @param buf a pointer point to the data
|
||||
* @param len data length
|
||||
* @return none
|
||||
*/
|
||||
void ble_ota_write_cb(const uint8_t *buf, uint16_t len);
|
||||
|
||||
typedef enum {
|
||||
BLE_QIOT_SECURE_BIND_CONFIRM = 0,
|
||||
BLE_QIOT_SECURE_BIND_REJECT = 1,
|
||||
} ble_qiot_secure_bind_t;
|
||||
|
||||
/**
|
||||
* @brief user choose whether to connect
|
||||
* @note call the function when the user choose connect or not
|
||||
* @return BLE_QIOT_RS_OK is success, other is error
|
||||
*/
|
||||
ble_qiot_ret_status_t ble_secure_bind_user_confirm(ble_qiot_secure_bind_t choose);
|
||||
|
||||
// inform user the ota start
|
||||
typedef void (*ble_ota_start_callback)(void);
|
||||
|
||||
enum {
|
||||
BLE_QIOT_OTA_SUCCESS = 0, // ota success
|
||||
BLE_QIOT_OTA_ERR_CRC = 1, // ota failed because crc error
|
||||
BLE_QIOT_OTA_ERR_TIMEOUT = 2, // ota failed because download timeout
|
||||
BLE_QIOT_OTA_DISCONNECT = 3, // ota failed because ble disconnect
|
||||
BLE_QIOT_OTA_ERR_FILE = 4, // ota failed because the file mismatch the device
|
||||
};
|
||||
// inform user the ota stop and the result
|
||||
typedef void (*ble_ota_stop_callback)(uint8_t result);
|
||||
|
||||
// llsync only valid the file crc, also allow the user valid the file by their way
|
||||
typedef ble_qiot_ret_status_t (*ble_ota_valid_file_callback)(uint32_t file_size, char *file_version);
|
||||
/**
|
||||
* @brief register ota callback
|
||||
* @param start_cb called before ota start, set null if not used
|
||||
* @param stop_cb called after ota stop, set null if not used
|
||||
* @param valid_file_cb called after the crc valid, set null if not used
|
||||
* @return none
|
||||
*/
|
||||
void ble_ota_callback_reg(ble_ota_start_callback start_cb, ble_ota_stop_callback stop_cb,
|
||||
ble_ota_valid_file_callback valid_file_cb);
|
||||
#endif //BLE_QIOT_LLSYNC_STANDARD
|
||||
|
||||
#if BLE_QIOT_LLSYNC_CONFIG_NET
|
||||
|
||||
typedef enum {
|
||||
BLE_WIFI_MODE_NULL = 0, // invalid mode
|
||||
BLE_WIFI_MODE_STA = 1, // station
|
||||
BLE_WIFI_MODE_AP = 2, // ap
|
||||
} BLE_WIFI_MODE;
|
||||
|
||||
typedef enum {
|
||||
BLE_WIFI_STATE_CONNECT = 0, // wifi connect
|
||||
BLE_WIFI_STATE_OTHER = 1, // other state
|
||||
} BLE_WIFI_STATE;
|
||||
|
||||
/**
|
||||
* @brief report wifi-mode setting result
|
||||
* @param result setting result, 0 is success, other failed
|
||||
* @return BLE_QIOT_RS_OK is success, other is error
|
||||
*/
|
||||
ble_qiot_ret_status_t ble_event_report_wifi_mode(uint8_t result);
|
||||
|
||||
/**
|
||||
* @brief report wifi-info setting result
|
||||
* @param result setting result, 0 is success, other failed
|
||||
* @return BLE_QIOT_RS_OK is success, other is error
|
||||
*/
|
||||
ble_qiot_ret_status_t ble_event_report_wifi_info(uint8_t result);
|
||||
|
||||
/**
|
||||
* @brief report wifi connection status
|
||||
* @param mode current wifi mode, reference BLE_WIFI_MODE
|
||||
* @param state current wifi state, reference BLE_WIFI_STATE
|
||||
* @param ssid_len length of ssid
|
||||
* @param ssid the ssid currently connected
|
||||
* @return BLE_QIOT_RS_OK is success, other is error
|
||||
*/
|
||||
ble_qiot_ret_status_t ble_event_report_wifi_connect(BLE_WIFI_MODE mode, BLE_WIFI_STATE state, uint8_t ssid_len,
|
||||
const char *ssid);
|
||||
|
||||
/**
|
||||
* @brief report wifi-token setting result
|
||||
* @param result setting result, 0 is success, other failed
|
||||
* @return BLE_QIOT_RS_OK is success, other is error
|
||||
*/
|
||||
ble_qiot_ret_status_t ble_event_report_wifi_token(uint8_t result);
|
||||
|
||||
/**
|
||||
* @brief report wifi-log
|
||||
* @param log log message
|
||||
* @param log_size length of log
|
||||
* @return BLE_QIOT_RS_OK is success, other is error
|
||||
*/
|
||||
ble_qiot_ret_status_t ble_event_report_wifi_log(const uint8_t *log, uint16_t log_size);
|
||||
|
||||
#endif //BLE_QIOT_LLSYNC_CONFIG_NET
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // QCLOUD_BLE_QIOT_EXPORT_H
|
||||
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making IoT Hub available.
|
||||
* Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QCLOUD_BLE_QIOT_HMAC_H
|
||||
#define QCLOUD_BLE_QIOT_HMAC_H
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define SHA1_DIGEST_SIZE 20
|
||||
|
||||
void utils_hmac_sha1(const char *msg, int msg_len, char *digest, const char *key, int key_len);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif // QCLOUD_BLE_QIOT_HMAC_H
|
||||
@ -0,0 +1,254 @@
|
||||
/*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#ifndef QCLOUD_BLE_QIOT_IMPORT_H
|
||||
#define QCLOUD_BLE_QIOT_IMPORT_H
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ble_qiot_export.h"
|
||||
|
||||
// 16 bits service UUIDs list, use advertising type 0x02 or 0x03
|
||||
typedef struct {
|
||||
uint8_t uuid_num;
|
||||
uint16_t *uuids;
|
||||
} uuid_list_s;
|
||||
|
||||
// advertise manufacture specific data, use advertising type 0xFF
|
||||
typedef struct {
|
||||
uint16_t company_identifier;
|
||||
uint8_t *adv_data;
|
||||
uint8_t adv_data_len;
|
||||
} manufacturer_data_s;
|
||||
|
||||
typedef struct {
|
||||
uuid_list_s uuid_info;
|
||||
manufacturer_data_s manufacturer_info;
|
||||
} adv_info_s;
|
||||
|
||||
/**
|
||||
* @brief get mac address
|
||||
* @param mac the buf storage mac, 6 bytes permanent
|
||||
* @return 0 is success, other is error
|
||||
*/
|
||||
int ble_get_mac(char *mac);
|
||||
|
||||
/**
|
||||
* @brief add llsync services to ble stack
|
||||
* @param qiot_service_init_s llsync service
|
||||
* @return none
|
||||
*/
|
||||
void ble_services_add(const qiot_service_init_s *p_service);
|
||||
|
||||
/**
|
||||
* @brief start llsync advertising
|
||||
* @param adv a pointer point to advertising data
|
||||
* @return BLE_QIOT_RS_OK is success, other is error
|
||||
*/
|
||||
ble_qiot_ret_status_t ble_advertising_start(adv_info_s *adv);
|
||||
|
||||
/**
|
||||
* @brief stop advertising
|
||||
* @return BLE_QIOT_RS_OK is success, other is error
|
||||
*/
|
||||
ble_qiot_ret_status_t ble_advertising_stop(void);
|
||||
|
||||
/**
|
||||
* @brief get the ATT_MTU user want to used
|
||||
* @return the value
|
||||
*/
|
||||
uint16_t ble_get_user_data_mtu_size(void);
|
||||
|
||||
/**
|
||||
* @brief send a notification to host, use characteristic IOT_BLE_UUID_EVENT
|
||||
* @param buf a pointer point to indication information
|
||||
* @param len indication information length
|
||||
* @return BLE_QIOT_RS_OK is success, other is error
|
||||
*/
|
||||
ble_qiot_ret_status_t ble_send_notify(uint8_t *buf, uint8_t len);
|
||||
|
||||
// timer type
|
||||
enum {
|
||||
BLE_TIMER_ONE_SHOT_TYPE = 0,
|
||||
BLE_TIMER_PERIOD_TYPE,
|
||||
BLE_TIMER_BUTT,
|
||||
};
|
||||
typedef void *ble_timer_t;
|
||||
|
||||
// timer callback prototype
|
||||
typedef void (*ble_timer_cb)(void *param);
|
||||
|
||||
/**
|
||||
* @brief create a timer
|
||||
* @param type timer type
|
||||
* @param timeout_handle timer callback
|
||||
* @return timer identifier is return, NULL is error
|
||||
*/
|
||||
ble_timer_t ble_timer_create(uint8_t type, ble_timer_cb timeout_handle);
|
||||
|
||||
/**
|
||||
* @brief start a timer
|
||||
* @param timer_id Timer identifier
|
||||
* @param period timer period(unit: ms)
|
||||
* @return BLE_QIOT_RS_OK is success, other is error
|
||||
*/
|
||||
ble_qiot_ret_status_t ble_timer_start(ble_timer_t timer_id, uint32_t period);
|
||||
|
||||
/**
|
||||
* @brief stop a timer
|
||||
* @param timer_id Timer identifier
|
||||
* @return BLE_QIOT_RS_OK is success, other is error
|
||||
*/
|
||||
ble_qiot_ret_status_t ble_timer_stop(ble_timer_t timer_id);
|
||||
|
||||
/**
|
||||
* @brief delete a timer
|
||||
* @param timer_id Timer identifier
|
||||
* @return BLE_QIOT_RS_OK is success, other is error
|
||||
*/
|
||||
ble_qiot_ret_status_t ble_timer_delete(ble_timer_t timer_id);
|
||||
|
||||
#ifdef BLE_QIOT_LLSYNC_STANDARD
|
||||
/**
|
||||
* @brief get device product id
|
||||
* @param product_id the buf storage product id, 10 bytes permanent
|
||||
* @return 0 is success, other is error
|
||||
*/
|
||||
int ble_get_product_id(char *product_id);
|
||||
|
||||
/**
|
||||
* @brief get device name
|
||||
* @param device_name the buf storage device name, the max length of the device name is 48 bytes
|
||||
* @return length of device name, 0 is error
|
||||
*/
|
||||
int ble_get_device_name(char *device_name);
|
||||
|
||||
/**
|
||||
* @brief get device secret
|
||||
* @param psk the buf storage secret, 24 bytes permanent
|
||||
* @return 0 is success, other is error
|
||||
*/
|
||||
int ble_get_psk(char *psk);
|
||||
|
||||
/**
|
||||
* @brief write data to flash
|
||||
* @param flash_addr write address in flash
|
||||
* @param write_buf point to write buf
|
||||
* @param write_len length of data to write
|
||||
* @return write_len is success, other is error
|
||||
*/
|
||||
int ble_write_flash(uint32_t flash_addr, const char *write_buf, uint16_t write_len);
|
||||
|
||||
/**
|
||||
* @brief read data from flash
|
||||
* @param flash_addr read address from flash
|
||||
* @param read_buf point to read buf
|
||||
* @param read_len length of data to read
|
||||
* @return read_len is success, other is error
|
||||
*/
|
||||
int ble_read_flash(uint32_t flash_addr, char *read_buf, uint16_t read_len);
|
||||
|
||||
/**
|
||||
* @brief secure binding user callback
|
||||
* @note when the secure binding is activated, the function notify user the connecting is coming, the function is
|
||||
* no-block
|
||||
* @return None
|
||||
*/
|
||||
void ble_secure_bind_user_cb(void);
|
||||
|
||||
enum {
|
||||
BLE_SECURE_BIND_CANCEL = 0, // user cancel in Tencent Lianlian
|
||||
BLE_SECURE_BIND_TIMEOUT = 1, // the binding timeout
|
||||
};
|
||||
/**
|
||||
* @brief secure binding user notify
|
||||
* @note notify user when the secure bind timeout or cancel
|
||||
* @return None
|
||||
*/
|
||||
void ble_secure_bind_user_notify(uint8_t result);
|
||||
|
||||
enum {
|
||||
BLE_OTA_ENABLE = 1, // ota enable
|
||||
BLE_OTA_DISABLE_LOW_POWER = 2, // the device low power can not upgrade
|
||||
BLE_OTA_DISABLE_LOW_VERSION = 3, // disable upgrade low version
|
||||
};
|
||||
/**
|
||||
* @brief get ota is enable
|
||||
* @param version the ota file version
|
||||
* @return BLE_OTA_ENABLE is enable, others disable
|
||||
* @note can not be blocking, the reason defined by users
|
||||
*/
|
||||
uint8_t ble_ota_is_enable(const char *version, u32 file_size, u32 file_crc);
|
||||
|
||||
/**
|
||||
* @brief get the address the ota file will be saved
|
||||
* @return the flash address
|
||||
*/
|
||||
uint32_t ble_ota_get_download_addr(void);
|
||||
|
||||
/**
|
||||
* @brief write data to flash
|
||||
* @param flash_addr write address in flash
|
||||
* @param write_buf point to write buf
|
||||
* @param write_len length of data to write
|
||||
* @return write_len is success, other is error
|
||||
*/
|
||||
int ble_ota_write_flash(uint32_t flash_addr, const char *write_buf, uint16_t write_len);
|
||||
#endif //BLE_QIOT_LLSYNC_STANDARD
|
||||
|
||||
#if BLE_QIOT_LLSYNC_CONFIG_NET
|
||||
/**
|
||||
* @brief set wifi mode
|
||||
* @param mode the target mode
|
||||
* @return BLE_QIOT_RS_OK is success, other is error
|
||||
*/
|
||||
ble_qiot_ret_status_t ble_combo_wifi_mode_set(BLE_WIFI_MODE mode);
|
||||
|
||||
/**
|
||||
* @brief set wifi info
|
||||
* @param ssid wifi ssid
|
||||
* @param ssid_len the length of ssid
|
||||
* @param passwd wifi password
|
||||
* @param passwd_len the length of password
|
||||
* @return BLE_QIOT_RS_OK is success, other is error
|
||||
*/
|
||||
ble_qiot_ret_status_t ble_combo_wifi_info_set(const char *ssid, uint8_t ssid_len, const char *passwd, uint8_t passwd_len);
|
||||
|
||||
/**
|
||||
* @brief connect wifi
|
||||
* @param none
|
||||
* @return BLE_QIOT_RS_OK is success, other is error
|
||||
*/
|
||||
ble_qiot_ret_status_t ble_combo_wifi_connect();
|
||||
|
||||
/**
|
||||
* @brief set wifi token
|
||||
* @param token token message
|
||||
* @param token_len length of token
|
||||
* @return BLE_QIOT_RS_OK is success, other is error
|
||||
*/
|
||||
ble_qiot_ret_status_t ble_combo_wifi_token_set(const char *token, uint16_t token_len);
|
||||
|
||||
/**
|
||||
* @brief get wifi log
|
||||
* @param none
|
||||
* @return BLE_QIOT_RS_OK is success, other is error
|
||||
*/
|
||||
ble_qiot_ret_status_t ble_combo_wifi_log_get(void);
|
||||
#endif //BLE_QIOT_LLSYNC_CONFIG_NET
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // QCLOUD_BLE_QIOT_IMPORT_H
|
||||
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#ifndef QCLOUD_BLE_QIOT_LLSYNC_DATA_H
|
||||
#define QCLOUD_BLE_QIOT_LLSYNC_DATA_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <ble_qiot_export.h>
|
||||
|
||||
#define BLE_QIOT_CONTROL_DATA_TYPE (0x00)
|
||||
#define BLE_QIOT_GET_STATUS_REPLY_DATA_TYPE (0x22)
|
||||
|
||||
#define BLE_QIOT_GET_STATUS_REPLY_HEADER_LEN (4)
|
||||
#define BLE_QIOT_DATA_FIXED_HEADER_LEN (3)
|
||||
|
||||
// handle property request
|
||||
ble_qiot_ret_status_t ble_lldata_property_request_handle(const char *in_buf, int buf_len);
|
||||
|
||||
// handle property reply
|
||||
ble_qiot_ret_status_t ble_lldata_property_reply_handle(uint8_t type, const char *in_buf, int buf_len);
|
||||
|
||||
// handle event data
|
||||
ble_qiot_ret_status_t ble_lldata_event_handle(uint8_t id, const char *in_buf, int len);
|
||||
|
||||
// handle action data
|
||||
ble_qiot_ret_status_t ble_lldata_action_handle(uint8_t id, const char *in_buf, int len);
|
||||
|
||||
// get report data
|
||||
ble_qiot_ret_status_t ble_user_property_get_report_data(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // QCLOUD_BLE_QIOT_LLSYNC_DATA_H
|
||||
@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#ifndef QCLOUD_BLE_QIOT_LLSYNC_DEVICE_H
|
||||
#define QCLOUD_BLE_QIOT_LLSYNC_DEVICE_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
//#include <stdbool.h>
|
||||
#include "ble_qiot_common.h"
|
||||
#include "ble_qiot_export.h"
|
||||
#include "ble_qiot_hmac.h"
|
||||
#include "ble_qiot_llsync_event.h"
|
||||
|
||||
#define LLSYNC_BIND_STATE_MASK 0x03
|
||||
#define LLSYNC_PROTO_VER_BIT 0x04
|
||||
#define LLSYNC_PROTOCOL_VERSION_MASK 0xF0
|
||||
#define LLSYNC_MTU_SET_MASK 0x8000
|
||||
|
||||
#define LLSYNC_MTU_SET_RESULT_ERR 0xFFFF // some error when setting mtu
|
||||
|
||||
#define BLE_QIOT_LLSYNC_PROTOCOL_VERSION (2) // llsync protocol version, equal or less than 15
|
||||
|
||||
#define ATT_DEFAULT_MTU 23 // default att mtu
|
||||
#define ATT_MTU_TO_LLSYNC_MTU(_att_mtu) ((_att_mtu)-3)
|
||||
|
||||
#define BLE_LOCAL_PSK_LEN 4
|
||||
#define BLE_BIND_IDENTIFY_STR_LEN 8
|
||||
#define BLE_EXPIRATION_TIME 60 // timestamp expiration value
|
||||
#define BLE_UNBIND_REQUEST_STR "UnbindRequest"
|
||||
#define BLE_UNBIND_REQUEST_STR_LEN (sizeof("UnbindRequest") - 1)
|
||||
#define BLE_UNBIND_RESPONSE "UnbindResponse"
|
||||
#define BLE_UNBIND_RESPONSE_STR_LEN (sizeof("UnbindResponse") - 1)
|
||||
|
||||
typedef enum {
|
||||
E_DEV_MSG_SYNC_TIME = 0, // sync info before bind
|
||||
E_DEV_MSG_CONN_VALID, // connect request
|
||||
E_DEV_MSG_BIND_SUCC, // inform bind success
|
||||
E_DEV_MSG_BIND_FAIL, // inform bind failed
|
||||
E_DEV_MSG_UNBIND, // unbind request
|
||||
E_DEV_MSG_CONN_SUCC, // inform connect result
|
||||
E_DEV_MSG_CONN_FAIL,
|
||||
E_DEV_MSG_UNBIND_SUCC, // inform unbind result
|
||||
E_DEV_MSG_UNBIND_FAIL,
|
||||
E_DEV_MSG_SET_MTU_RESULT, // inform set mtu result
|
||||
E_DEV_MSG_BIND_TIMEOUT, // inform bind timeout
|
||||
E_DEV_MSG_GET_DEV_INFO = 0xE0, // configure network start
|
||||
E_DEV_MSG_SET_WIFI_MODE,
|
||||
E_DEV_MSG_SET_WIFI_INFO,
|
||||
E_DEV_MSG_SET_WIFI_CONNECT,
|
||||
E_DEV_MSG_SET_WIFI_TOKEN,
|
||||
E_DEV_MSG_GET_DEV_LOG,
|
||||
E_DEV_MSG_MSG_BUTT,
|
||||
} e_dev_info_msg_type;
|
||||
|
||||
typedef enum {
|
||||
E_LLSYNC_BIND_IDLE = 0, // no bind
|
||||
E_LLSYNC_BIND_WAIT, // wait bind, return idle state if no bind in the period
|
||||
E_LLSYNC_BIND_SUCC, // bound
|
||||
} e_llsync_bind_state;
|
||||
|
||||
typedef enum {
|
||||
E_LLSYNC_DISCONNECTED = 0,
|
||||
E_LLSYNC_CONNECTED,
|
||||
} e_llsync_connection_state;
|
||||
|
||||
typedef enum {
|
||||
E_BLE_DISCONNECTED = 0,
|
||||
E_BLE_CONNECTED,
|
||||
} e_ble_connection_state;
|
||||
|
||||
typedef struct ble_device_info_t_ {
|
||||
char product_id[BLE_QIOT_PRODUCT_ID_LEN];
|
||||
char device_name[BLE_QIOT_DEVICE_NAME_LEN + 1];
|
||||
char psk[BLE_QIOT_PSK_LEN];
|
||||
char mac[BLE_QIOT_MAC_LEN];
|
||||
} ble_device_info;
|
||||
|
||||
typedef struct ble_core_data_ {
|
||||
uint8_t bind_state;
|
||||
char local_psk[BLE_LOCAL_PSK_LEN];
|
||||
char identify_str[BLE_BIND_IDENTIFY_STR_LEN];
|
||||
} ble_core_data;
|
||||
|
||||
// write to uuid FEE1 before bind
|
||||
typedef struct ble_bind_data_t_ {
|
||||
int nonce;
|
||||
int timestamp;
|
||||
} ble_bind_data;
|
||||
|
||||
// connect data struct
|
||||
typedef struct ble_conn_data_t_ {
|
||||
int timestamp;
|
||||
char sign_info[SHA1_DIGEST_SIZE];
|
||||
} ble_conn_data;
|
||||
|
||||
// unbind data struct
|
||||
typedef struct ble_unbind_data_t_ {
|
||||
char sign_info[SHA1_DIGEST_SIZE];
|
||||
} ble_unbind_data;
|
||||
|
||||
typedef struct {
|
||||
bool have_data; // start received package
|
||||
uint8_t type; // event type
|
||||
uint16_t buf_len; // the length of data
|
||||
char buf[BLE_QIOT_EVENT_MAX_SIZE];
|
||||
} ble_event_slice_t;
|
||||
|
||||
// read sdk data from flash
|
||||
ble_qiot_ret_status_t ble_init_flash_data(void);
|
||||
|
||||
// set llsync bind state
|
||||
void llsync_bind_state_set(e_llsync_bind_state new_state);
|
||||
|
||||
// get llsync bind state
|
||||
e_llsync_bind_state llsync_bind_state_get(void);
|
||||
|
||||
// set llsync connection state
|
||||
void llsync_connection_state_set(e_llsync_connection_state new_state);
|
||||
|
||||
// set ble connection state
|
||||
void ble_connection_state_set(e_ble_connection_state new_state);
|
||||
|
||||
// get llsync connection state
|
||||
bool llsync_is_connected(void);
|
||||
|
||||
// get ble connection state
|
||||
bool ble_is_connected(void);
|
||||
|
||||
// get broadcast data
|
||||
int ble_get_my_broadcast_data(char *out_buf, int buf_len);
|
||||
|
||||
// get bind authcode, return authcode length;
|
||||
// out_buf length must greater than SHA1_DIGEST_SIZE + BLE_QIOT_DEVICE_NAME_LEN
|
||||
int ble_bind_get_authcode(const char *bind_data, uint16_t data_len, char *out_buf, uint16_t buf_len);
|
||||
|
||||
// write bind result to flash, return 0 is success
|
||||
ble_qiot_ret_status_t ble_bind_write_result(const char *result, uint16_t len);
|
||||
|
||||
// write unbind result to flash, return 0 is success
|
||||
ble_qiot_ret_status_t ble_unbind_write_result(void);
|
||||
|
||||
// get connect authcode, return authcode length;
|
||||
// out_buf length must greater than SHA1_DIGEST_SIZE + BLE_QIOT_DEVICE_NAME_LEN
|
||||
int ble_conn_get_authcode(const char *conn_data, uint16_t data_len, char *out_buf, uint16_t buf_len);
|
||||
|
||||
// get connect authcode, return authcode length;
|
||||
// out_buf length must greater than SHA1_DIGEST_SIZE + BLE_UNBIND_RESPONSE_STR_LEN
|
||||
int ble_unbind_get_authcode(const char *unbind_data, uint16_t data_len, char *out_buf, uint16_t buf_len);
|
||||
|
||||
// inform device the result of mtu setting
|
||||
int ble_inform_mtu_result(const char *result, uint16_t data_len);
|
||||
|
||||
// get llsync mtu
|
||||
uint16_t llsync_mtu_get(void);
|
||||
|
||||
// update llsync mtu
|
||||
void llsync_mtu_update(uint16_t sync_mtu);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // QCLOUD_BLE_QIOT_LLSYNC_DEVICE_H
|
||||
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#ifndef QCLOUD_BLE_QIOT_LLSYNC_EVENT_H
|
||||
#define QCLOUD_BLE_QIOT_LLSYNC_EVENT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ble_qiot_config.h"
|
||||
#include "ble_qiot_export.h"
|
||||
|
||||
enum {
|
||||
BLE_QIOT_EVENT_NO_SLICE = 0,
|
||||
BLE_QIOT_EVENT_SLICE_HEAD = 1,
|
||||
BLE_QIOT_EVENT_SLICE_BODY = 2,
|
||||
BLE_QIOT_EVENT_SLICE_FOOT = 3,
|
||||
};
|
||||
|
||||
// 1 byte type + 2 bytes payload-length
|
||||
#define BLE_QIOT_EVENT_FIXED_HEADER_LEN (3)
|
||||
|
||||
// the bit 15 - 14 is slice flag, bit 13 - 0 is tlv length
|
||||
#define BLE_QIOT_IS_SLICE_PACKAGE(_C) ((_C)&0XC0)
|
||||
#define BLE_QIOT_IS_SLICE_HEADER(_C) (((_C)&0XC0) == 0X40)
|
||||
#define BLE_QIOT_IS_SLICE_BODY(_C) (((_C)&0XC0) == 0X80)
|
||||
#define BLE_QIOT_IS_SLICE_TAIL(_C) (((_C)&0XC0) == 0XC0)
|
||||
|
||||
#define BLE_QIOT_STRING_TYPE_LEN 2 // string/struct type length
|
||||
#define BLE_QIOT_MIN_STRING_TYPE_LEN (BLE_QIOT_STRING_TYPE_LEN + 1) // at least 2 bytes length and 1 byte payload
|
||||
#define BLE_QIOT_NOT_SUPPORT_WARN " not support, please check the data template"
|
||||
|
||||
ble_qiot_ret_status_t ble_event_notify(uint8_t type, uint8_t *header, uint8_t header_len, const char *buf,
|
||||
uint16_t buf_len);
|
||||
|
||||
ble_qiot_ret_status_t ble_event_notify2(uint8_t type, uint8_t length_flag, uint8_t *header, uint8_t header_len,
|
||||
const char *buf, uint16_t buf_len);
|
||||
|
||||
ble_qiot_ret_status_t ble_event_sync_wait_time(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // QCLOUD_BLE_QIOT_LLSYNC_EVENT_H
|
||||
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#ifndef QCLOUD_BLE_QIOT_LLSYNC_OTA_H
|
||||
#define QCLOUD_BLE_QIOT_LLSYNC_OTA_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ble_qiot_config.h"
|
||||
#include "ble_qiot_export.h"
|
||||
|
||||
#define BLE_QIOT_GET_OTA_REQUEST_HEADER_LEN 3 // the ota request header len
|
||||
#define BLE_QIOT_OTA_DATA_HEADER_LEN 3 // the ota data header len
|
||||
|
||||
// ota feature
|
||||
#define BLE_QIOT_OTA_ENABLE (1 << 0)
|
||||
#define BLE_QIOT_OTA_RESUME_ENABLE (1 << 1)
|
||||
|
||||
// ota file valid result
|
||||
#define BLE_QIOT_OTA_VALID_SUCCESS (1 << 7)
|
||||
#define BLE_QIOT_OTA_VALID_FAIL (0 << 7)
|
||||
|
||||
#define BLE_QIOT_OTA_MAX_VERSION_STR (32) // max ota version length
|
||||
#define BLE_QIOT_OTA_PAGE_VALID_VAL 0x5A // ota info valid flag
|
||||
|
||||
#define BLE_QIOT_OTA_FIRST_TIMEOUT (1)
|
||||
#define BLE_QIOT_OTA_MAX_RETRY_COUNT 5 // disconnect if retry times more than BLE_QIOT_OTA_MAX_RETRY_COUNT
|
||||
|
||||
// ota control bits
|
||||
#define BLE_QIOT_OTA_REQUEST_BIT (1 << 0)
|
||||
#define BLE_QIOT_OTA_RECV_END_BIT (1 << 1)
|
||||
#define BLE_QIOT_OTA_RECV_DATA_BIT (1 << 2)
|
||||
#define BLE_QIOT_OTA_FIRST_RETRY_BIT (1 << 3)
|
||||
#define BLE_QIOT_OTA_DO_VALID_BIT (1 << 4)
|
||||
#define BLE_QIOT_OTA_HAVE_DATA_BIT (1 << 5)
|
||||
|
||||
// the reason of ota file error
|
||||
enum {
|
||||
BLE_QIOT_OTA_CRC_ERROR = 0,
|
||||
BLE_QIOT_OTA_READ_FLASH_ERROR = 1,
|
||||
BLE_QIOT_OTA_FILE_ERROR = 2,
|
||||
};
|
||||
|
||||
// ota data type
|
||||
enum {
|
||||
BLE_QIOT_OTA_MSG_REQUEST = 0,
|
||||
BLE_QIOT_OTA_MSG_DATA = 1,
|
||||
BLE_QIOT_OTA_MSG_END = 2,
|
||||
BLE_QIOT_OTA_MSG_BUTT,
|
||||
};
|
||||
|
||||
// ota request reply
|
||||
typedef struct ble_ota_reply_info_ {
|
||||
uint8_t package_nums; // package numbers in a loop
|
||||
uint8_t package_size; // each package size
|
||||
uint8_t retry_timeout; // data retry
|
||||
uint8_t reboot_timeout; // max time of device reboot
|
||||
uint32_t last_file_size; // the file already received
|
||||
uint8_t package_interval; // package send interval on the server
|
||||
uint8_t rsv[3];
|
||||
} ble_ota_reply_info;
|
||||
|
||||
typedef struct ble_ota_file_info_ {
|
||||
uint32_t file_size;
|
||||
uint32_t file_crc;
|
||||
uint8_t file_version[BLE_QIOT_OTA_MAX_VERSION_STR];
|
||||
} ble_ota_file_info;
|
||||
|
||||
// ota info saved in flash if support resuming
|
||||
typedef struct ble_ota_info_record_ {
|
||||
uint8_t valid_flag;
|
||||
uint8_t rsv[3];
|
||||
uint32_t last_file_size; // the file size already write in flash
|
||||
uint32_t last_address; // the address file saved
|
||||
ble_ota_file_info download_file_info;
|
||||
} ble_ota_info_record;
|
||||
|
||||
// ota user callback
|
||||
typedef struct ble_ota_user_callback_ {
|
||||
ble_ota_start_callback start_cb;
|
||||
ble_ota_stop_callback stop_cb;
|
||||
ble_ota_valid_file_callback valid_file_cb;
|
||||
} ble_ota_user_callback;
|
||||
|
||||
// ota request package: 1 byte type + 2 bytes length + 4 bytes size + 4 bytes crc + 1 byte version length + 1 ~ 32 bytes
|
||||
// version
|
||||
typedef struct {
|
||||
bool have_data; // start received package
|
||||
uint8_t type; // event type
|
||||
uint16_t buf_len; // the length of data
|
||||
char buf[BLE_QIOT_GET_OTA_REQUEST_HEADER_LEN + 4 + 4 + 1 + BLE_QIOT_OTA_MAX_VERSION_STR];
|
||||
} ble_ota_request_slice_t;
|
||||
|
||||
// ota reply info
|
||||
typedef struct ble_ota_reply_t_ {
|
||||
uint32_t file_size;
|
||||
uint8_t req;
|
||||
} ble_ota_reply_t;
|
||||
|
||||
ble_qiot_ret_status_t ble_ota_request_handle(const char *in_buf, int buf_len);
|
||||
|
||||
ble_qiot_ret_status_t ble_ota_data_handle(const char *in_buf, int buf_len);
|
||||
|
||||
ble_qiot_ret_status_t ble_ota_file_end_handle(void);
|
||||
|
||||
void ble_ota_stop(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // QCLOUD_BLE_QIOT_LLSYNC_OTA_H
|
||||
103
apps/common/third_party_profile/Tecent_LL/include/ble_qiot_log.h
Normal file
103
apps/common/third_party_profile/Tecent_LL/include/ble_qiot_log.h
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#ifndef QCLOUD_BLE_QIOT_LOG_H
|
||||
#define QCLOUD_BLE_QIOT_LOG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ble_qiot_config.h"
|
||||
|
||||
typedef enum {
|
||||
BLE_QIOT_LOG_LEVEL_NONE = 0,
|
||||
BLE_QIOT_LOG_LEVEL_ERR,
|
||||
BLE_QIOT_LOG_LEVEL_WARN,
|
||||
BLE_QIOT_LOG_LEVEL_INFO,
|
||||
BLE_QIOT_LOG_LEVEL_DEBUG,
|
||||
BLE_QIOT_LOG_LEVEL_ALL,
|
||||
} e_ble_qiot_log_level;
|
||||
|
||||
// log new line feed type
|
||||
#define LINE_NONE
|
||||
#define LINE_LF "\n"
|
||||
#define LINE_CR "\r"
|
||||
#define LINE_CRLF "\r\n"
|
||||
|
||||
// log new line feed type config
|
||||
#define LOG_LINE_FEED_TYPE LINE_CRLF
|
||||
|
||||
extern e_ble_qiot_log_level g_log_level;
|
||||
|
||||
#ifndef ble_qiot_log_d
|
||||
#define ble_qiot_log_d(fmt, args...) \
|
||||
do { \
|
||||
if (g_log_level < BLE_QIOT_LOG_LEVEL_DEBUG) \
|
||||
break; \
|
||||
BLE_QIOT_LOG_PRINT("qiot debug: " fmt LOG_LINE_FEED_TYPE, ##args); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifndef ble_qiot_log_i
|
||||
#define ble_qiot_log_i(fmt, args...) \
|
||||
do { \
|
||||
if (g_log_level < BLE_QIOT_LOG_LEVEL_INFO) \
|
||||
break; \
|
||||
BLE_QIOT_LOG_PRINT("qiot info: " fmt LOG_LINE_FEED_TYPE, ##args); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifndef ble_qiot_log_w
|
||||
#define ble_qiot_log_w(fmt, args...) \
|
||||
do { \
|
||||
if (g_log_level < BLE_QIOT_LOG_LEVEL_WARN) \
|
||||
break; \
|
||||
BLE_QIOT_LOG_PRINT("qiot warn(%s|%d): " fmt LOG_LINE_FEED_TYPE, __FILE__, __LINE__, ##args); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifndef ble_qiot_log_e
|
||||
#define ble_qiot_log_e(fmt, args...) \
|
||||
do { \
|
||||
if (g_log_level < BLE_QIOT_LOG_LEVEL_ERR) \
|
||||
break; \
|
||||
BLE_QIOT_LOG_PRINT("qiot err(%s|%d): " fmt LOG_LINE_FEED_TYPE, __FILE__, __LINE__, ##args); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifndef ble_qiot_log
|
||||
#define ble_qiot_log(level, fmt, args...) \
|
||||
do { \
|
||||
if (g_log_level < level) \
|
||||
break; \
|
||||
BLE_QIOT_LOG_PRINT("qiot log(%s|%d): " fmt LOG_LINE_FEED_TYPE, __FILE__, __LINE__, ##args); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
// this function only use for ble_qiot_log_hex
|
||||
#ifndef ble_qiot_log_raw
|
||||
#define ble_qiot_log_raw(fmt, args...) \
|
||||
do { \
|
||||
BLE_QIOT_LOG_PRINT(fmt, ##args); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
void ble_qiot_set_log_level(e_ble_qiot_log_level level);
|
||||
|
||||
#if !BLE_QIOT_USER_DEFINE_HEXDUMP
|
||||
void ble_qiot_log_hex(e_ble_qiot_log_level level, const char *hex_name, const char *data, uint32_t data_len);
|
||||
#endif // BLE_QIOT_USER_DEFINE_HEXDUMP
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // QCLOUD_BLE_QIOT_LOG_H
|
||||
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making IoT Hub available.
|
||||
* Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QCLOUD_BLE_QIOT_MD5_H
|
||||
#define QCLOUD_BLE_QIOT_MD5_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MD5_DIGEST_SIZE 16
|
||||
|
||||
typedef struct {
|
||||
unsigned int total[2]; /*!< number of bytes processed */
|
||||
unsigned int state[4]; /*!< intermediate digest state */
|
||||
unsigned char buffer[64]; /*!< data block being processed */
|
||||
} iot_md5_context;
|
||||
|
||||
/**
|
||||
* @brief init MD5 context
|
||||
*
|
||||
* @param ctx MD5 context
|
||||
*/
|
||||
void utils_md5_init(iot_md5_context *ctx);
|
||||
|
||||
/**
|
||||
* @brief free MD5 context
|
||||
*
|
||||
* @param ctx MD5 context
|
||||
*/
|
||||
void utils_md5_free(iot_md5_context *ctx);
|
||||
|
||||
/**
|
||||
* @brief clone MD5 context
|
||||
*
|
||||
* @param dst destination MD5 context
|
||||
* @param src source MD5 context
|
||||
*/
|
||||
void utils_md5_clone(iot_md5_context *dst, const iot_md5_context *src);
|
||||
|
||||
/**
|
||||
* @brief start MD5 calculation
|
||||
*
|
||||
* @param ctx MD5 context
|
||||
*/
|
||||
void utils_md5_starts(iot_md5_context *ctx);
|
||||
|
||||
/**
|
||||
* @brief MD5 update
|
||||
*
|
||||
* @param ctx MD5 context
|
||||
* @param input input data
|
||||
* @param ilen data length
|
||||
*/
|
||||
void utils_md5_update(iot_md5_context *ctx, const unsigned char *input, unsigned int ilen);
|
||||
|
||||
/**
|
||||
* @brief finish MD5 calculation
|
||||
*
|
||||
* @param ctx MD5 context
|
||||
* @param output MD5 result
|
||||
*/
|
||||
void utils_md5_finish(iot_md5_context *ctx, unsigned char output[16]);
|
||||
|
||||
/* MD5 internal process */
|
||||
void utils_md5_process(iot_md5_context *ctx, const unsigned char data[64]);
|
||||
|
||||
/**
|
||||
* @brief Output = MD5( input buffer )
|
||||
*
|
||||
* @param input data input
|
||||
* @param ilen data lenght
|
||||
* @param output MD5 result
|
||||
*/
|
||||
void utils_md5(const unsigned char *input, unsigned int ilen, unsigned char output[16]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making IoT Hub available.
|
||||
* Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QCLOUD_BLE_IOT_PARAM_CHECK_H_
|
||||
#define QCLOUD_BLE_IOT_PARAM_CHECK_H_
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ble_qiot_log.h"
|
||||
|
||||
#define NUMBERIC_SANITY_CHECK(num, err) \
|
||||
do { \
|
||||
if (0 == (num)) { \
|
||||
ble_qiot_log_e("Invalid argument, numeric 0"); \
|
||||
return (err); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define NUMBERIC_SANITY_CHECK_RTN(num) \
|
||||
do { \
|
||||
if (0 == (num)) { \
|
||||
ble_qiot_log_e("Invalid argument, numeric 0"); \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define BUFF_LEN_SANITY_CHECK(num, min, err) \
|
||||
do { \
|
||||
if ((min) > (num)) { \
|
||||
ble_qiot_log_e("Invalid argument, %d <= %d", min, num); \
|
||||
return (err); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define POINTER_SANITY_CHECK(ptr, err) \
|
||||
do { \
|
||||
if (NULL == (ptr)) { \
|
||||
ble_qiot_log_e("Invalid argument, %s = %p", #ptr, ptr); \
|
||||
return (err); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define POINTER_SANITY_CHECK_RTN(ptr) \
|
||||
do { \
|
||||
if (NULL == (ptr)) { \
|
||||
ble_qiot_log_e("Invalid argument, %s = %p", #ptr, ptr); \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define STRING_PTR_SANITY_CHECK(ptr, err) \
|
||||
do { \
|
||||
if (NULL == (ptr)) { \
|
||||
ble_qiot_log_e("Invalid argument, %s = %p", #ptr, (ptr)); \
|
||||
return (err); \
|
||||
} \
|
||||
if (0 == strlen((ptr))) { \
|
||||
ble_qiot_log_e("Invalid argument, %s = '%s'", #ptr, (ptr)); \
|
||||
return (err); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define STRING_PTR_SANITY_CHECK_RTN(ptr) \
|
||||
do { \
|
||||
if (NULL == (ptr)) { \
|
||||
ble_qiot_log_e("Invalid argument, %s = %p", #ptr, (ptr)); \
|
||||
return; \
|
||||
} \
|
||||
if (0 == strlen((ptr))) { \
|
||||
ble_qiot_log_e("Invalid argument, %s = '%s'", #ptr, (ptr)); \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* QCLOUD_BLE_IOT_PARAM_CHECK_H_ */
|
||||
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#ifndef QCLOUD_BLE_IOT_SERVICE_H_
|
||||
#define QCLOUD_BLE_IOT_SERVICE_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ble_qiot_export.h"
|
||||
#include "ble_qiot_llsync_data.h"
|
||||
#include "ble_qiot_template.h"
|
||||
|
||||
// message type, reference data template
|
||||
enum {
|
||||
BLE_QIOT_MSG_TYPE_PROPERTY = 0,
|
||||
BLE_QIOT_MSG_TYPE_EVENT,
|
||||
BLE_QIOT_MSG_TYPE_ACTION,
|
||||
BLE_QIOT_MSG_TYPE_BUTT,
|
||||
};
|
||||
|
||||
// define reply result
|
||||
enum {
|
||||
BLE_QIOT_REPLY_SUCCESS = 0,
|
||||
BLE_QIOT_REPLY_FAIL,
|
||||
BLE_QIOT_REPLY_DATA_ERR,
|
||||
BLE_QIOT_REPLY_BUTT,
|
||||
};
|
||||
|
||||
// define message type that from server to device
|
||||
enum {
|
||||
BLE_QIOT_DATA_DOWN_REPORT_REPLY = 0,
|
||||
BLE_QIOT_DATA_DOWN_CONTROL,
|
||||
BLE_QIOT_DATA_DOWN_GET_STATUS_REPLY,
|
||||
BLE_QIOT_DATA_DOWN_ACTION,
|
||||
BLE_QIOT_DATA_DOWN_EVENT_REPLY,
|
||||
};
|
||||
|
||||
// define message type that from device to server
|
||||
enum {
|
||||
BLE_QIOT_EVENT_UP_PROPERTY_REPORT = 0,
|
||||
BLE_QIOT_EVENT_UP_CONTROL_REPLY,
|
||||
BLE_QIOT_EVENT_UP_GET_STATUS,
|
||||
BLE_QIOT_EVENT_UP_EVENT_POST,
|
||||
BLE_QIOT_EVENT_UP_ACTION_REPLY,
|
||||
BLE_QIOT_EVENT_UP_BIND_SIGN_RET,
|
||||
BLE_QIOT_EVENT_UP_CONN_SIGN_RET,
|
||||
BLE_QIOT_EVENT_UP_UNBIND_SIGN_RET,
|
||||
BLE_QIOT_EVENT_UP_REPORT_MTU,
|
||||
BLE_QIOT_EVENT_UP_REPLY_OTA_REPORT,
|
||||
BLE_QIOT_EVENT_UP_REPLY_OTA_DATA,
|
||||
BLE_QIOT_EVENT_UP_REPORT_CHECK_RESULT,
|
||||
BLE_QIOT_EVENT_UP_SYNC_MTU,
|
||||
BLE_QIOT_EVENT_UP_SYNC_WAIT_TIME,
|
||||
BLE_QIOT_EVENT_UP_WIFI_MODE = 0xE0,
|
||||
BLE_QIOT_EVENT_UP_WIFI_INFO,
|
||||
BLE_QIOT_EVENT_UP_WIFI_CONNECT,
|
||||
BLE_QIOT_EVENT_UP_WIFI_TOKEN,
|
||||
BLE_QIOT_EVENT_UP_WIFI_LOG,
|
||||
BLE_QIOT_EVENT_UP_BUTT,
|
||||
};
|
||||
|
||||
// msg header define, bit 7-6 is msg type, bit 5 means request or reply, bit 4 - 0 is id
|
||||
#define BLE_QIOT_PARSE_MSG_HEAD_TYPE(_C) (((_C) & 0XFF) >> 6)
|
||||
#define BLE_QIOT_PARSE_MSG_HEAD_EFFECT(_C) ((((_C) & 0XFF) & 0X20) ? BLE_QIOT_EFFECT_REPLY : BLE_QIOT_EFFECT_REQUEST)
|
||||
#define BLE_QIOT_PARSE_MSG_HEAD_ID(_C) ((_C) & 0X1F)
|
||||
|
||||
// tlv header define, bit 7 - 5 is type, bit 4 - 0 depends on type of data template
|
||||
#define BLE_QIOT_PARSE_TLV_HEAD_TYPE(_C) (((_C) & 0XFF) >> 5)
|
||||
#define BLE_QIOT_PARSE_TLV_HEAD_ID(_C) ((_C) & 0X1F)
|
||||
|
||||
// handle llsync device info
|
||||
// return 0 is success, other is error
|
||||
int ble_device_info_msg_handle(const char *in_buf, int in_len);
|
||||
|
||||
// lldata message from remote
|
||||
// return 0 is success, other is error
|
||||
int ble_lldata_msg_handle(const char *in_buf, int in_len);
|
||||
|
||||
// ota message from remote
|
||||
// return 0 is success, other is error
|
||||
int ble_ota_msg_handle(const char *buf, uint16_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // QCLOUD_BLE_IOT_SERVICE_H_
|
||||
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making IoT Hub available.
|
||||
* Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QCLOUD_BLE_LLSYNC_BLE_QIOT_SHA1_H
|
||||
#define QCLOUD_BLE_LLSYNC_BLE_QIOT_SHA1_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/**
|
||||
* \brief SHA-1 context structure
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t total[2]; /*!< number of bytes processed */
|
||||
uint32_t state[5]; /*!< intermediate digest state */
|
||||
unsigned char buffer[64]; /*!< data block being processed */
|
||||
} iot_sha1_context;
|
||||
|
||||
/**
|
||||
* \brief Initialize SHA-1 context
|
||||
*
|
||||
* \param ctx SHA-1 context to be initialized
|
||||
*/
|
||||
void utils_sha1_init(iot_sha1_context *ctx);
|
||||
|
||||
/**
|
||||
* \brief Clear SHA-1 context
|
||||
*
|
||||
* \param ctx SHA-1 context to be cleared
|
||||
*/
|
||||
void utils_sha1_free(iot_sha1_context *ctx);
|
||||
|
||||
/**
|
||||
* \brief Clone (the state of) a SHA-1 context
|
||||
*
|
||||
* \param dst The destination context
|
||||
* \param src The context to be cloned
|
||||
*/
|
||||
void utils_sha1_clone(iot_sha1_context *dst, const iot_sha1_context *src);
|
||||
|
||||
/**
|
||||
* \brief SHA-1 context setup
|
||||
*
|
||||
* \param ctx context to be initialized
|
||||
*/
|
||||
void utils_sha1_starts(iot_sha1_context *ctx);
|
||||
|
||||
/**
|
||||
* \brief SHA-1 process buffer
|
||||
*
|
||||
* \param ctx SHA-1 context
|
||||
* \param input buffer holding the data
|
||||
* \param ilen length of the input data
|
||||
*/
|
||||
void utils_sha1_update(iot_sha1_context *ctx, const unsigned char *input, size_t ilen);
|
||||
|
||||
/**
|
||||
* \brief SHA-1 final digest
|
||||
*
|
||||
* \param ctx SHA-1 context
|
||||
* \param output SHA-1 checksum result
|
||||
*/
|
||||
void utils_sha1_finish(iot_sha1_context *ctx, unsigned char output[20]);
|
||||
|
||||
/* Internal use */
|
||||
void utils_sha1_process(iot_sha1_context *ctx, const unsigned char data[64]);
|
||||
|
||||
/**
|
||||
* \brief Output = SHA-1( input buffer )
|
||||
*
|
||||
* \param input buffer holding the data
|
||||
* \param ilen length of the input data
|
||||
* \param output SHA-1 checksum result
|
||||
*/
|
||||
void utils_sha1(const unsigned char *input, size_t ilen, unsigned char output[20]);
|
||||
|
||||
#endif // QCLOUD_BLE_LLSYNC_BLE_QIOT_SHA1_H
|
||||
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#ifndef BLE_QIOT_TEMPLATE_H_
|
||||
#define BLE_QIOT_TEMPLATE_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
//#include <stdbool.h>
|
||||
|
||||
|
||||
// data type in template, corresponding to type in json file
|
||||
enum {
|
||||
BLE_QIOT_DATA_TYPE_BOOL = 0,
|
||||
BLE_QIOT_DATA_TYPE_INT,
|
||||
BLE_QIOT_DATA_TYPE_STRING,
|
||||
BLE_QIOT_DATA_TYPE_FLOAT,
|
||||
BLE_QIOT_DATA_TYPE_ENUM,
|
||||
BLE_QIOT_DATA_TYPE_TIME,
|
||||
BLE_QIOT_DATA_TYPE_STRUCT,
|
||||
BLE_QIOT_DATA_TYPE_BUTT,
|
||||
};
|
||||
|
||||
// message type, reference data template
|
||||
enum {
|
||||
BLE_QIOT_PROPERTY_AUTH_RW = 0,
|
||||
BLE_QIOT_PROPERTY_AUTH_READ,
|
||||
BLE_QIOT_PROPERTY_AUTH_BUTT,
|
||||
};
|
||||
|
||||
// define message flow direction
|
||||
enum {
|
||||
BLE_QIOT_EFFECT_REQUEST = 0,
|
||||
BLE_QIOT_EFFECT_REPLY,
|
||||
BLE_QIOT_EFFECT_BUTT,
|
||||
};
|
||||
#define BLE_QIOT_PACKAGE_MSG_HEAD(_TYPE, _REPLY, _ID) (((_TYPE) << 6) | (((_REPLY) == BLE_QIOT_EFFECT_REPLY) << 5) | ((_ID) & 0X1F))
|
||||
#define BLE_QIOT_PACKAGE_TLV_HEAD(_TYPE, _ID) (((_TYPE) << 5) | ((_ID) & 0X1F))
|
||||
|
||||
|
||||
// define tlv struct
|
||||
typedef struct {
|
||||
uint8_t type;
|
||||
uint8_t id;
|
||||
uint16_t len;
|
||||
char *val;
|
||||
} e_ble_tlv;
|
||||
#define BLE_QIOT_INCLUDE_PROPERTY
|
||||
|
||||
// define property id
|
||||
enum {
|
||||
BLE_QIOT_PROPERTY_ID_POWER_SWITCH = 0,
|
||||
BLE_QIOT_PROPERTY_ID_BUTT,
|
||||
};
|
||||
|
||||
// define property set handle return 0 if success, other is error
|
||||
// sdk call the function that inform the server data to the device
|
||||
typedef int (*property_set_cb)(const char *data, uint16_t len);
|
||||
|
||||
// define property get handle. return the data length obtained, -1 is error, 0 is no data
|
||||
// sdk call the function fetch user data and send to the server, the data should wrapped by user adn skd just transmit
|
||||
typedef int (*property_get_cb)(char *buf, uint16_t buf_len);
|
||||
|
||||
// each property have a struct ble_property_t, make up a array named sg_ble_property_array
|
||||
typedef struct {
|
||||
property_set_cb set_cb; //set callback
|
||||
property_get_cb get_cb; //get callback
|
||||
uint8_t authority; //property authority
|
||||
uint8_t type; //data type
|
||||
} ble_property_t;
|
||||
// property module
|
||||
#ifdef BLE_QIOT_INCLUDE_PROPERTY
|
||||
uint8_t ble_get_property_type_by_id(uint8_t id);
|
||||
|
||||
int ble_user_property_set_data(const e_ble_tlv *tlv);
|
||||
int ble_user_property_get_data_by_id(uint8_t id, char *buf, uint16_t buf_len);
|
||||
int ble_user_property_report_reply_handle(uint8_t result);
|
||||
int ble_lldata_parse_tlv(const char *buf, int buf_len, e_ble_tlv *tlv);
|
||||
int ble_user_property_struct_handle(const char *in_buf, uint16_t buf_len, ble_property_t *struct_arr, uint8_t arr_size);
|
||||
int ble_user_property_struct_get_data(char *in_buf, uint16_t buf_len, ble_property_t *struct_arr, uint8_t arr_size);
|
||||
void ll_sync_led_switch(void);
|
||||
void ll_sync_unbind(void);
|
||||
void llsync_device_state_sync(void);
|
||||
#endif
|
||||
|
||||
// event module
|
||||
#ifdef BLE_QIOT_INCLUDE_EVENT
|
||||
int ble_event_get_id_array_size(uint8_t event_id);
|
||||
uint8_t ble_event_get_param_id_type(uint8_t event_id, uint8_t param_id);
|
||||
int ble_event_get_data_by_id(uint8_t event_id, uint8_t param_id, char *out_buf, uint16_t buf_len);
|
||||
int ble_user_event_reply_handle(uint8_t event_id, uint8_t result);
|
||||
#endif
|
||||
|
||||
// action module
|
||||
#ifdef BLE_QIOT_INCLUDE_ACTION
|
||||
uint8_t ble_action_get_intput_type_by_id(uint8_t action_id, uint8_t input_id);
|
||||
uint8_t ble_action_get_output_type_by_id(uint8_t action_id, uint8_t output_id);
|
||||
int ble_action_get_input_id_size(uint8_t action_id);
|
||||
int ble_action_get_output_id_size(uint8_t action_id);
|
||||
int ble_action_user_handle_input_param(uint8_t action_id, e_ble_tlv *input_param_array, uint8_t input_array_size,
|
||||
uint8_t *output_id_array);
|
||||
int ble_action_user_handle_output_param(uint8_t action_id, uint8_t output_id, char *buf, uint16_t buf_len);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif //BLE_QIOT_TEMPLATE_H_
|
||||
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making IoT Hub available.
|
||||
* Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QCLOUD_BLE_IOT_UTILS_BASE64_H_
|
||||
#define QCLOUD_BLE_IOT_UTILS_BASE64_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "ble_qiot_export.h"
|
||||
|
||||
ble_qiot_ret_status_t qcloud_iot_utils_base64encode(unsigned char *dst, size_t dlen, size_t *olen,
|
||||
const unsigned char *src, size_t slen);
|
||||
|
||||
ble_qiot_ret_status_t qcloud_iot_utils_base64decode(unsigned char *dst, size_t dlen, size_t *olen,
|
||||
const unsigned char *src, size_t slen);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* QCLOUD_BLE_IOT_UTILS_BASE64_H_ */
|
||||
1341
apps/common/third_party_profile/Tecent_LL/tecent_ll_demo/ll_demo.c
Normal file
1341
apps/common/third_party_profile/Tecent_LL/tecent_ll_demo/ll_demo.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,76 @@
|
||||
// binary representation
|
||||
// attribute size in bytes (16), flags(16), handle (16), uuid (16/128), value(...)
|
||||
|
||||
#ifndef _LL_DEMO_H
|
||||
#define _LL_DEMO_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "app_config.h"
|
||||
|
||||
#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_LL_SYNC)
|
||||
//
|
||||
// gatt profile include file, generated by jieli gatt_inc_generator.exe
|
||||
//
|
||||
|
||||
const uint8_t profile_data[] = {
|
||||
//////////////////////////////////////////////////////
|
||||
//
|
||||
// 0x0001 PRIMARY_SERVICE 1800
|
||||
//
|
||||
//////////////////////////////////////////////////////
|
||||
0x0a, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x28, 0x00, 0x18,
|
||||
|
||||
/* CHARACTERISTIC, 2a00, READ | DYNAMIC, */
|
||||
// 0x0002 CHARACTERISTIC 2a00 READ | DYNAMIC
|
||||
0x0d, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x03, 0x00, 0x00, 0x2a,
|
||||
// 0x0003 VALUE 2a00 READ | DYNAMIC
|
||||
0x08, 0x00, 0x02, 0x01, 0x03, 0x00, 0x00, 0x2a,
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
//
|
||||
// 0x0004 PRIMARY_SERVICE 0000FFE0-65D0-4E20-B56A-E493541BA4E2
|
||||
//
|
||||
//////////////////////////////////////////////////////
|
||||
0x18, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x28, 0xe2, 0xa4, 0x1b, 0x54, 0x93, 0xe4, 0x6a, 0xb5, 0x20, 0x4e, 0xd0, 0x65, 0xe0, 0xff, 0x00, 0x00,
|
||||
|
||||
/* CHARACTERISTIC, 0000FFE1-65D0-4E20-B56A-E493541BA4E2, WRITE | DYNAMIC, */
|
||||
// 0x0005 CHARACTERISTIC 0000FFE1-65D0-4E20-B56A-E493541BA4E2 WRITE | DYNAMIC
|
||||
0x1b, 0x00, 0x02, 0x00, 0x05, 0x00, 0x03, 0x28, 0x08, 0x06, 0x00, 0xe2, 0xa4, 0x1b, 0x54, 0x93, 0xe4, 0x6a, 0xb5, 0x20, 0x4e, 0xd0, 0x65, 0xe1, 0xff, 0x00, 0x00,
|
||||
// 0x0006 VALUE 0000FFE1-65D0-4E20-B56A-E493541BA4E2 WRITE | DYNAMIC
|
||||
0x16, 0x00, 0x08, 0x03, 0x06, 0x00, 0xe2, 0xa4, 0x1b, 0x54, 0x93, 0xe4, 0x6a, 0xb5, 0x20, 0x4e, 0xd0, 0x65, 0xe1, 0xff, 0x00, 0x00,
|
||||
|
||||
/* CHARACTERISTIC, 0000FFE2-65D0-4E20-B56A-E493541BA4E2, WRITE | DYNAMIC, */
|
||||
// 0x0007 CHARACTERISTIC 0000FFE2-65D0-4E20-B56A-E493541BA4E2 WRITE | DYNAMIC
|
||||
0x1b, 0x00, 0x02, 0x00, 0x07, 0x00, 0x03, 0x28, 0x08, 0x08, 0x00, 0xe2, 0xa4, 0x1b, 0x54, 0x93, 0xe4, 0x6a, 0xb5, 0x20, 0x4e, 0xd0, 0x65, 0xe2, 0xff, 0x00, 0x00,
|
||||
// 0x0008 VALUE 0000FFE2-65D0-4E20-B56A-E493541BA4E2 WRITE | DYNAMIC
|
||||
0x16, 0x00, 0x08, 0x03, 0x08, 0x00, 0xe2, 0xa4, 0x1b, 0x54, 0x93, 0xe4, 0x6a, 0xb5, 0x20, 0x4e, 0xd0, 0x65, 0xe2, 0xff, 0x00, 0x00,
|
||||
|
||||
/* CHARACTERISTIC, 0000FFE3-65D0-4E20-B56A-E493541BA4E2, NOTIFY, */
|
||||
// 0x0009 CHARACTERISTIC 0000FFE3-65D0-4E20-B56A-E493541BA4E2 NOTIFY
|
||||
0x1b, 0x00, 0x02, 0x00, 0x09, 0x00, 0x03, 0x28, 0x10, 0x0a, 0x00, 0xe2, 0xa4, 0x1b, 0x54, 0x93, 0xe4, 0x6a, 0xb5, 0x20, 0x4e, 0xd0, 0x65, 0xe3, 0xff, 0x00, 0x00,
|
||||
// 0x000a VALUE 0000FFE3-65D0-4E20-B56A-E493541BA4E2 NOTIFY
|
||||
0x16, 0x00, 0x10, 0x02, 0x0a, 0x00, 0xe2, 0xa4, 0x1b, 0x54, 0x93, 0xe4, 0x6a, 0xb5, 0x20, 0x4e, 0xd0, 0x65, 0xe3, 0xff, 0x00, 0x00,
|
||||
// 0x000b CLIENT_CHARACTERISTIC_CONFIGURATION
|
||||
0x0a, 0x00, 0x0a, 0x01, 0x0b, 0x00, 0x02, 0x29, 0x00, 0x00,
|
||||
|
||||
/* CHARACTERISTIC, 0000FFE4-65D0-4E20-B56A-E493541BA4E2, WRITE_WITHOUT_RESPONSE | DYNAMIC, */
|
||||
// 0x000c CHARACTERISTIC 0000FFE4-65D0-4E20-B56A-E493541BA4E2 WRITE_WITHOUT_RESPONSE | DYNAMIC
|
||||
0x1b, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x03, 0x28, 0x04, 0x0d, 0x00, 0xe2, 0xa4, 0x1b, 0x54, 0x93, 0xe4, 0x6a, 0xb5, 0x20, 0x4e, 0xd0, 0x65, 0xe4, 0xff, 0x00, 0x00,
|
||||
// 0x000d VALUE 0000FFE4-65D0-4E20-B56A-E493541BA4E2 WRITE_WITHOUT_RESPONSE | DYNAMIC
|
||||
0x16, 0x00, 0x04, 0x03, 0x0d, 0x00, 0xe2, 0xa4, 0x1b, 0x54, 0x93, 0xe4, 0x6a, 0xb5, 0x20, 0x4e, 0xd0, 0x65, 0xe4, 0xff, 0x00, 0x00,
|
||||
|
||||
// END
|
||||
0x00, 0x00,
|
||||
};
|
||||
//
|
||||
// characteristics <--> handles
|
||||
//
|
||||
#define ATT_CHARACTERISTIC_2a00_01_VALUE_HANDLE 0x0003
|
||||
#define ATT_CHARACTERISTIC_0000FFE1_65D0_4E20_B56A_E493541BA4E2_01_VALUE_HANDLE 0x0006
|
||||
#define ATT_CHARACTERISTIC_0000FFE2_65D0_4E20_B56A_E493541BA4E2_01_VALUE_HANDLE 0x0008
|
||||
#define ATT_CHARACTERISTIC_0000FFE3_65D0_4E20_B56A_E493541BA4E2_01_VALUE_HANDLE 0x000a
|
||||
#define ATT_CHARACTERISTIC_0000FFE3_65D0_4E20_B56A_E493541BA4E2_01_CLIENT_CONFIGURATION_HANDLE 0x000b
|
||||
#define ATT_CHARACTERISTIC_0000FFE4_65D0_4E20_B56A_E493541BA4E2_01_VALUE_HANDLE 0x000d
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@ -0,0 +1,61 @@
|
||||
#include "ll_task.h"
|
||||
#include "os/os_api.h"
|
||||
#include "ble_qiot_config.h"
|
||||
#include "ble_qiot_service.h"
|
||||
#include "ble_qiot_import.h"
|
||||
|
||||
LL_PACKET_CONTROL LL_packet_c;
|
||||
|
||||
#define __this (&LL_packet_c)
|
||||
|
||||
static void tecent_ll_task(void *arg)
|
||||
{
|
||||
LL_PACKET_HEAD_T ll_packet_head;
|
||||
u8 *buffer = NULL;
|
||||
u8 result = 0;
|
||||
while (1) {
|
||||
os_sem_pend(&(__this->ll_sem), 0);
|
||||
if (cbuf_get_data_len(&(__this->cbuf)) > LL_PACKET_HEAD_LEN) {
|
||||
cbuf_read(&(__this->cbuf), &ll_packet_head, LL_PACKET_HEAD_LEN);
|
||||
buffer = malloc(ll_packet_head.len);
|
||||
if (buffer == NULL) {
|
||||
printf("buf malloc err\n");
|
||||
break;
|
||||
}
|
||||
cbuf_read(&(__this->cbuf), buffer, ll_packet_head.len);
|
||||
switch (ll_packet_head.packet_channel) {
|
||||
case LL_DEVICE_INFO_MSG_CH:
|
||||
result = ble_device_info_msg_handle(buffer, ll_packet_head.len);
|
||||
break;
|
||||
case LL_DATA_MSG_CH:
|
||||
result = ble_lldata_msg_handle(buffer, ll_packet_head.len);
|
||||
break;
|
||||
case LL_OTA_MSG_CH:
|
||||
result = ble_ota_msg_handle(buffer, ll_packet_head.len);
|
||||
break;
|
||||
}
|
||||
free(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int tecent_ll_task_init(void)
|
||||
{
|
||||
os_sem_create(&(__this->ll_sem), 0);
|
||||
u32 malloc_size = (ble_get_user_data_mtu_size() + LL_PACKET_HEAD_LEN) * BLE_QIOT_TOTAL_PACKAGES;
|
||||
__this->tecent_ll_buf = malloc(malloc_size);
|
||||
memset(__this->tecent_ll_buf, 0x0, malloc_size);
|
||||
cbuf_init(&(__this->cbuf), __this->tecent_ll_buf, malloc_size);
|
||||
os_task_create(tecent_ll_task, NULL, 31, 512, 0, "tecent_ll_task");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tecent_ll_packet_recieve(void *buf, u16 len)
|
||||
{
|
||||
if (cbuf_is_write_able(&(__this->cbuf), len) >= len) {
|
||||
cbuf_write(&(__this->cbuf), buf, len);
|
||||
} else {
|
||||
printf("[L]\n");
|
||||
}
|
||||
os_sem_post(&(__this->ll_sem));
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
#ifndef __LL_TASK_H__
|
||||
#define __LL_TASK_H__
|
||||
|
||||
#include "typedef.h"
|
||||
#include "os/os_api.h"
|
||||
#include "circular_buf.h"
|
||||
|
||||
typedef struct __LL_PACKET_HEAD {
|
||||
u8 packet_channel;
|
||||
u16 len;
|
||||
} LL_PACKET_HEAD_T;
|
||||
|
||||
typedef struct __LL_PACKET_CONTROL {
|
||||
OS_SEM ll_sem;
|
||||
cbuffer_t cbuf;
|
||||
volatile u8 wait;
|
||||
u8 *tecent_ll_buf;
|
||||
} LL_PACKET_CONTROL;
|
||||
|
||||
#define LL_PACKET_HEAD_LEN (sizeof(LL_PACKET_HEAD_T))
|
||||
|
||||
enum {
|
||||
LL_DEVICE_INFO_MSG_CH = 0,
|
||||
LL_DATA_MSG_CH,
|
||||
LL_OTA_MSG_CH,
|
||||
};
|
||||
|
||||
int tecent_ll_task_init(void);
|
||||
void tecent_ll_packet_recieve(void *buf, u16 len);
|
||||
|
||||
#endif //__LL_TASK_H__
|
||||
@ -0,0 +1,224 @@
|
||||
#include "ble_qiot_import.h"
|
||||
/* #include "le/ble_api.h" */
|
||||
#include "vm.h"
|
||||
#include "le_common.h"
|
||||
#include "dual_bank_updata_api.h"
|
||||
|
||||
#define PRODUCT_ID "YSUM4IEDOH"
|
||||
#define DEVICE_NAME "dev001"
|
||||
#define SECRET_KEY "6WNLgmVK4fThhVIgdOBmKQ=="
|
||||
|
||||
#define LOG_TAG "[ble_qiot_import]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_DEBUG_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#define LOG_CLI_ENABLE
|
||||
#include "debug.h"
|
||||
|
||||
#define ADV_INTERVAL_MIN (160)
|
||||
|
||||
static u8 scan_rsp_data[ADV_RSP_PACKET_MAX];//max is 31
|
||||
static char d_name[7] = "LLMAIN";
|
||||
static u8 d_name_len = 6; //名字长度,不包含结束符
|
||||
static u8 ble_work_state = 0; //ble 状态变化
|
||||
static u8 adv_ctrl_en; //广播控制
|
||||
static u16 protocol_MTU; //广播控制
|
||||
|
||||
static u8 adv_data_len;
|
||||
static u8 adv_data[ADV_RSP_PACKET_MAX];//max is 31
|
||||
static u8 scan_rsp_data_len;
|
||||
static u8 scan_rsp_data[ADV_RSP_PACKET_MAX];//max is 31
|
||||
|
||||
int ble_get_product_id(char *product_id)
|
||||
{
|
||||
log_info("ble_get_product_id");
|
||||
memcpy(product_id, PRODUCT_ID, strlen(PRODUCT_ID));
|
||||
put_buf(product_id, strlen(product_id));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ble_get_device_name(char *device_name)
|
||||
{
|
||||
log_info("ble_get_device_name");
|
||||
memcpy(device_name, DEVICE_NAME, strlen(DEVICE_NAME));
|
||||
put_buf(device_name, strlen(device_name));
|
||||
return strlen(device_name);
|
||||
}
|
||||
|
||||
int ble_get_psk(char *psk)
|
||||
{
|
||||
log_info("ble_get_psk");
|
||||
memcpy(psk, SECRET_KEY, strlen(SECRET_KEY));
|
||||
put_buf(psk, strlen(psk));
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern const u8 *ble_get_mac_addr(void);
|
||||
int ble_get_mac(char *mac)
|
||||
{
|
||||
log_info("ble_get_mac");
|
||||
le_controller_get_mac(mac);
|
||||
put_buf(mac, 6);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void (*app_set_adv_data)(u8 *adv_data, u8 adv_len) = NULL;
|
||||
static void (*app_set_rsp_data)(u8 *rsp_data, u8 rsp_len) = NULL;
|
||||
void app_set_adv_data_register(void (*handler)(u8 *adv_data, u8 adv_len))
|
||||
{
|
||||
app_set_adv_data = handler;
|
||||
}
|
||||
void app_set_rsp_data_register(void (*handler)(u8 *rsp_data, u8 rsp_len))
|
||||
{
|
||||
app_set_rsp_data = handler;
|
||||
}
|
||||
|
||||
static int llsync_set_rsp_data(void)
|
||||
{
|
||||
u8 offset = 0;
|
||||
u8 *buf = scan_rsp_data;
|
||||
|
||||
u8 name_len = sizeof(d_name);
|
||||
u8 vaild_len = ADV_RSP_PACKET_MAX - (offset + 2);
|
||||
if (name_len > vaild_len) {
|
||||
name_len = vaild_len;
|
||||
}
|
||||
offset += make_eir_packet_data(&buf[offset], offset, HCI_EIR_DATATYPE_COMPLETE_LOCAL_NAME, (void *)d_name, d_name_len);
|
||||
|
||||
if (offset > ADV_RSP_PACKET_MAX) {
|
||||
printf("***rsp_data overflow!!!!!!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
//printf("rsp_data(%d):", offset);
|
||||
//printf_buf(buf, offset);
|
||||
scan_rsp_data_len = offset;
|
||||
if (app_set_rsp_data) {
|
||||
app_set_rsp_data(scan_rsp_data, scan_rsp_data_len);
|
||||
}
|
||||
ble_op_set_rsp_data(offset, buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int llsync_set_adv_data(adv_info_s *adv)
|
||||
{
|
||||
u8 offset = 0;
|
||||
u8 *buf = adv_data;
|
||||
u8 manufacturer_buf[20];
|
||||
|
||||
memcpy(&manufacturer_buf[0], &adv->manufacturer_info.company_identifier, 2);
|
||||
memcpy(&manufacturer_buf[2], adv->manufacturer_info.adv_data, adv->manufacturer_info.adv_data_len);
|
||||
printf("manufacturer_buf\n");
|
||||
put_buf(manufacturer_buf, adv->manufacturer_info.adv_data_len + 2);
|
||||
|
||||
offset += make_eir_packet_val(&buf[offset], offset, HCI_EIR_DATATYPE_FLAGS, 0x06, 1);
|
||||
offset += make_eir_packet_val(&buf[offset], offset, HCI_EIR_DATATYPE_COMPLETE_16BIT_SERVICE_UUIDS, IOT_BLE_UUID_SERVICE, 2);
|
||||
offset += make_eir_packet_data(&buf[offset], offset, HCI_EIR_DATATYPE_MANUFACTURER_SPECIFIC_DATA, manufacturer_buf, adv->manufacturer_info.adv_data_len + 2);
|
||||
|
||||
if (offset > ADV_RSP_PACKET_MAX) {
|
||||
puts("***adv_data overflow!!!!!!\n");
|
||||
printf("offset = %d, limite is %d\n", offset, ADV_RSP_PACKET_MAX);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//log_info("adv_data(%d):", offset);
|
||||
//log_info_hexdump(buf, offset);
|
||||
adv_data_len = offset;
|
||||
if (app_set_adv_data) {
|
||||
app_set_adv_data(adv_data, adv_data_len);
|
||||
}
|
||||
ble_op_set_adv_data(offset, buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void (*llsync_ble_module_enable)(u8 en) = NULL;
|
||||
ble_qiot_ret_status_t ble_advertising_start(adv_info_s *adv)
|
||||
{
|
||||
log_info("ble_advertising_start\n");
|
||||
//log_info_hexdump(adv->manufacturer_info.adv_data, adv->manufacturer_info.adv_data_len);
|
||||
|
||||
llsync_set_adv_data(adv);
|
||||
llsync_set_rsp_data();
|
||||
|
||||
if (llsync_ble_module_enable) {
|
||||
llsync_ble_module_enable(1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void llsync_ble_module_enable_register(void (*handler)(u8 en))
|
||||
{
|
||||
llsync_ble_module_enable = handler;
|
||||
}
|
||||
|
||||
ble_qiot_ret_status_t ble_advertising_stop(void)
|
||||
{
|
||||
log_info("ble_advertising_stop\n");
|
||||
if (llsync_ble_module_enable) {
|
||||
llsync_ble_module_enable(0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int (*llsync_send_data)(void *priv, u8 *data, u16 len) = NULL;
|
||||
void llsync_send_data_register(int (*handler)(void *priv, void *buf, u16 len))
|
||||
{
|
||||
llsync_send_data = handler;
|
||||
}
|
||||
|
||||
ble_qiot_ret_status_t ble_send_notify(uint8_t *buf, uint8_t len)
|
||||
{
|
||||
if (llsync_send_data) {
|
||||
llsync_send_data(NULL, buf, len);
|
||||
} else {
|
||||
log_info("llsync_send_data no register");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t ble_get_user_data_mtu_size(void)
|
||||
{
|
||||
return BLE_QIOT_PACKAGE_LENGTH + 6;
|
||||
}
|
||||
|
||||
uint8_t ble_ota_is_enable(const char *version, u32 file_size, u32 file_crc)
|
||||
{
|
||||
log_info("ota version: %s, enable ota", version);
|
||||
if (dual_bank_passive_update_init(file_crc, file_size, BLE_QIOT_OTA_BUF_SIZE, NULL) == 0) {
|
||||
if (dual_bank_update_allow_check(file_size) == 0) {
|
||||
return BLE_OTA_ENABLE;
|
||||
}
|
||||
}
|
||||
dual_bank_passive_update_exit(NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern s32 vm_open(u16 index);
|
||||
extern s32 vm_read(vm_hdl hdl, u8 *data_buf, u16 len);
|
||||
extern s32 vm_write(vm_hdl hdl, u8 *data_buf, u16 len);
|
||||
|
||||
int ble_read_flash(uint32_t flash_addr, char *read_buf, uint16_t read_len)
|
||||
{
|
||||
int ret;
|
||||
s32 hdl = vm_open(flash_addr);
|
||||
|
||||
ret = vm_read(hdl, read_buf, read_len);
|
||||
if (ret < 0) {
|
||||
log_info("\n\nread flash error:%d", ret);
|
||||
}
|
||||
return read_len;
|
||||
}
|
||||
|
||||
int ble_write_flash(uint32_t flash_addr, const char *write_buf, uint16_t write_len)
|
||||
{
|
||||
int ret;
|
||||
s32 hdl = vm_open(flash_addr);
|
||||
|
||||
ret = vm_write(hdl, write_buf, write_len);
|
||||
if (ret < 0) {
|
||||
log_info("\n\nwrite flash error:%d", ret);
|
||||
}
|
||||
return write_len;
|
||||
}
|
||||
|
||||
@ -0,0 +1,346 @@
|
||||
/*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ble_qiot_config.h"
|
||||
|
||||
#if BLE_QIOT_LLSYNC_STANDARD
|
||||
|
||||
#include "ble_qiot_export.h"
|
||||
#include "ble_qiot_import.h"
|
||||
#include "ble_qiot_common.h"
|
||||
#include "ble_qiot_llsync_event.h"
|
||||
#include "ble_qiot_utils_base64.h"
|
||||
#include "ble_qiot_log.h"
|
||||
#include "ble_qiot_param_check.h"
|
||||
#include "ble_qiot_service.h"
|
||||
#include "ble_qiot_template.h"
|
||||
#include "ble_qiot_llsync_data.h"
|
||||
|
||||
// parse tlv data and return the length parsed
|
||||
int ble_lldata_parse_tlv(const char *buf, int buf_len, e_ble_tlv *tlv)
|
||||
{
|
||||
int ret_len = 0;
|
||||
uint16_t type_len = 0;
|
||||
|
||||
tlv->type = BLE_QIOT_PARSE_TLV_HEAD_TYPE(buf[0]);
|
||||
if (tlv->type >= BLE_QIOT_DATA_TYPE_BUTT) {
|
||||
ble_qiot_log_e("lldata parse invalid type: %d", tlv->type);
|
||||
return -1;
|
||||
}
|
||||
tlv->id = BLE_QIOT_PARSE_TLV_HEAD_ID(buf[0]);
|
||||
ret_len++;
|
||||
|
||||
switch (tlv->type) {
|
||||
case BLE_QIOT_DATA_TYPE_BOOL:
|
||||
tlv->len = sizeof(uint8_t);
|
||||
tlv->val = (char *)buf + ret_len;
|
||||
ret_len += sizeof(uint8_t);
|
||||
break;
|
||||
case BLE_QIOT_DATA_TYPE_ENUM:
|
||||
tlv->len = sizeof(uint16_t);
|
||||
tlv->val = (char *)buf + ret_len;
|
||||
ret_len += sizeof(uint16_t);
|
||||
break;
|
||||
case BLE_QIOT_DATA_TYPE_INT:
|
||||
case BLE_QIOT_DATA_TYPE_FLOAT:
|
||||
case BLE_QIOT_DATA_TYPE_TIME:
|
||||
tlv->len = sizeof(uint32_t);
|
||||
tlv->val = (char *)buf + ret_len;
|
||||
ret_len += sizeof(uint32_t);
|
||||
break;
|
||||
case BLE_QIOT_DATA_TYPE_STRUCT:
|
||||
case BLE_QIOT_DATA_TYPE_STRING:
|
||||
if (buf_len < BLE_QIOT_MIN_STRING_TYPE_LEN) {
|
||||
ble_qiot_log_e("lldata len invalid, type: %d, len: %d", tlv->type, buf_len);
|
||||
return -1;
|
||||
}
|
||||
memcpy(&type_len, &buf[ret_len], sizeof(uint16_t));
|
||||
tlv->len = NTOHS(type_len);
|
||||
ret_len += sizeof(uint16_t);
|
||||
tlv->val = (char *)buf + ret_len;
|
||||
ret_len += tlv->len;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ble_qiot_log_d("tlv parsed, type: %d, id: %d, len: %d", tlv->type, tlv->id, tlv->len);
|
||||
|
||||
return ret_len;
|
||||
}
|
||||
|
||||
// handle property data, method is control or get status
|
||||
static ble_qiot_ret_status_t ble_lldata_property_data_handle(bool is_request, const char *in_buf, int buf_len)
|
||||
{
|
||||
#ifdef BLE_QIOT_INCLUDE_PROPERTY
|
||||
uint16_t parse_len = 0;
|
||||
int ret_len = 0;
|
||||
e_ble_tlv tlv;
|
||||
int8_t ret = BLE_QIOT_REPLY_SUCCESS;
|
||||
|
||||
ble_qiot_ret_status_t inform_ret = BLE_QIOT_RS_OK;
|
||||
|
||||
ble_qiot_log_d("handle property data");
|
||||
while (parse_len < buf_len) {
|
||||
memset(&tlv, 0, sizeof(e_ble_tlv));
|
||||
ret_len = ble_lldata_parse_tlv(in_buf + parse_len, buf_len - parse_len, &tlv);
|
||||
if (ret_len < 0) {
|
||||
return BLE_QIOT_RS_ERR;
|
||||
}
|
||||
|
||||
parse_len += ret_len;
|
||||
if (parse_len > buf_len) {
|
||||
ble_qiot_log_e("invalid peroperty data, %d(property len) > %d(buf len)", parse_len, buf_len);
|
||||
ret = BLE_QIOT_REPLY_DATA_ERR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (BLE_QIOT_RS_OK != ble_user_property_set_data(&tlv)) {
|
||||
ret = BLE_QIOT_REPLY_FAIL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (is_request) {
|
||||
return ble_event_notify(BLE_QIOT_EVENT_UP_CONTROL_REPLY, NULL, 0, (const char *)&ret, sizeof(int8_t));
|
||||
} else {
|
||||
return (BLE_QIOT_REPLY_SUCCESS == ret) ? BLE_QIOT_RS_OK : BLE_QIOT_RS_ERR;
|
||||
}
|
||||
#else
|
||||
ble_qiot_log_e("property" BLE_QIOT_NOT_SUPPORT_WARN);
|
||||
return BLE_QIOT_RS_OK;
|
||||
#endif //BLE_QIOT_INCLUDE_PROPERTY
|
||||
}
|
||||
|
||||
#ifdef BLE_QIOT_INCLUDE_PROPERTY
|
||||
// post property
|
||||
ble_qiot_ret_status_t ble_user_property_get_report_data(void)
|
||||
{
|
||||
uint8_t property_id = 0;
|
||||
uint8_t property_type = 0;
|
||||
int property_len = 0;
|
||||
uint16_t type_len = 0;
|
||||
uint16_t data_len = 0;
|
||||
uint16_t data_buf_off = 0;
|
||||
|
||||
uint8_t data_buf[BLE_QIOT_EVENT_MAX_SIZE] = {0};
|
||||
|
||||
ble_qiot_log_d("report property");
|
||||
for (property_id = 0; property_id < BLE_QIOT_PROPERTY_ID_BUTT; property_id++) {
|
||||
property_type = ble_get_property_type_by_id(property_id);
|
||||
if (property_type >= BLE_QIOT_DATA_TYPE_BUTT) {
|
||||
ble_qiot_log_e("property(%d) type(%d) invalid", property_id, property_type);
|
||||
return BLE_QIOT_RS_ERR;
|
||||
}
|
||||
|
||||
data_buf[data_len++] = BLE_QIOT_PACKAGE_TLV_HEAD(property_type, property_id);
|
||||
data_buf_off = data_len;
|
||||
if ((BLE_QIOT_DATA_TYPE_STRING == property_type) || (BLE_QIOT_DATA_TYPE_STRUCT == property_type)) {
|
||||
// reserved 2 bytes for string/struct length
|
||||
data_buf_off += BLE_QIOT_STRING_TYPE_LEN;
|
||||
}
|
||||
property_len = ble_user_property_get_data_by_id(property_id, (char *)&data_buf[data_buf_off],
|
||||
sizeof(data_buf) - data_buf_off);
|
||||
if (property_len < 0) {
|
||||
return BLE_QIOT_RS_ERR;
|
||||
} else if (property_len == 0) {
|
||||
// clean the property head cause no data to post
|
||||
data_len--;
|
||||
data_buf[data_len] = '0';
|
||||
ble_qiot_log_d("property: %d no data to post", property_id);
|
||||
} else {
|
||||
if ((BLE_QIOT_DATA_TYPE_STRING == property_type) || (BLE_QIOT_DATA_TYPE_STRUCT == property_type)) {
|
||||
// filling the payload length
|
||||
type_len = HTONS(property_len);
|
||||
memcpy(data_buf + data_len, &type_len, sizeof(uint16_t));
|
||||
data_len += sizeof(uint16_t);
|
||||
}
|
||||
data_len += property_len;
|
||||
}
|
||||
}
|
||||
// ble_qiot_log_hex(BLE_QIOT_LOG_LEVEL_INFO, "user data", data_buf, data_len);
|
||||
|
||||
return ble_event_notify(BLE_QIOT_EVENT_UP_PROPERTY_REPORT, NULL, 0, (const char *)data_buf, data_len);
|
||||
}
|
||||
#endif //BLE_QIOT_INCLUDE_PROPERTY
|
||||
|
||||
// handle control
|
||||
ble_qiot_ret_status_t ble_lldata_property_request_handle(const char *in_buf, int buf_len)
|
||||
{
|
||||
return ble_lldata_property_data_handle(true, in_buf, buf_len);
|
||||
}
|
||||
|
||||
// handle report_reply
|
||||
static ble_qiot_ret_status_t ble_lldata_property_report_reply(const char *in_buf, int buf_len)
|
||||
{
|
||||
#ifdef BLE_QIOT_INCLUDE_PROPERTY
|
||||
(void)ble_user_property_report_reply_handle(in_buf[0]);
|
||||
#else
|
||||
ble_qiot_log_e("property" BLE_QIOT_NOT_SUPPORT_WARN);
|
||||
#endif //BLE_QIOT_INCLUDE_PROPERTY
|
||||
return BLE_QIOT_RS_OK;
|
||||
}
|
||||
|
||||
// handle get_status_reply
|
||||
static ble_qiot_ret_status_t ble_lldata_property_get_status_reply(const char *in_buf, int buf_len)
|
||||
{
|
||||
#ifdef BLE_QIOT_INCLUDE_PROPERTY
|
||||
uint8_t result = 0;
|
||||
uint16_t reply_len = 0;
|
||||
|
||||
result = in_buf[0];
|
||||
ble_qiot_log_d("get status reply result: %d", result);
|
||||
if (BLE_QIOT_REPLY_SUCCESS == result) {
|
||||
memcpy(&reply_len, &in_buf[1], sizeof(uint16_t));
|
||||
return ble_lldata_property_data_handle(false, in_buf + sizeof(uint8_t) + sizeof(uint16_t), NTOHS(reply_len));
|
||||
} else {
|
||||
return BLE_QIOT_RS_ERR;
|
||||
}
|
||||
#else
|
||||
ble_qiot_log_e("property" BLE_QIOT_NOT_SUPPORT_WARN);
|
||||
return BLE_QIOT_RS_OK;
|
||||
#endif //BLE_QIOT_INCLUDE_PROPERTY
|
||||
}
|
||||
|
||||
// handle reply from remote
|
||||
ble_qiot_ret_status_t ble_lldata_property_reply_handle(uint8_t type, const char *in_buf, int buf_len)
|
||||
{
|
||||
switch (type) {
|
||||
case BLE_QIOT_DATA_DOWN_REPORT_REPLY:
|
||||
return ble_lldata_property_report_reply(in_buf, buf_len);
|
||||
case BLE_QIOT_DATA_DOWN_GET_STATUS_REPLY:
|
||||
return ble_lldata_property_get_status_reply(in_buf, buf_len);
|
||||
default:
|
||||
ble_qiot_log_e("invalid property reply type");
|
||||
return BLE_QIOT_RS_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
// handle event_post_reply
|
||||
ble_qiot_ret_status_t ble_lldata_event_handle(uint8_t id, const char *in_buf, int len)
|
||||
{
|
||||
#ifdef BLE_QIOT_INCLUDE_EVENT
|
||||
(void)ble_user_event_reply_handle(id, in_buf[0]);
|
||||
#else
|
||||
ble_qiot_log_e("event" BLE_QIOT_NOT_SUPPORT_WARN);
|
||||
#endif //BLE_QIOT_INCLUDE_PROPERTY
|
||||
return BLE_QIOT_RS_OK;
|
||||
}
|
||||
|
||||
// handle action
|
||||
ble_qiot_ret_status_t ble_lldata_action_handle(uint8_t action_id, const char *in_buf, int len)
|
||||
{
|
||||
#ifdef BLE_QIOT_INCLUDE_ACTION
|
||||
POINTER_SANITY_CHECK(in_buf, BLE_QIOT_RS_ERR_PARA);
|
||||
|
||||
uint16_t parse_len = 0;
|
||||
uint8_t tlv_index = 0;
|
||||
int ret_len = 0;
|
||||
int handle_ret = BLE_QIOT_REPLY_SUCCESS;
|
||||
uint8_t output_id = 0;
|
||||
uint8_t output_type = 0;
|
||||
uint16_t data_len = 0;
|
||||
uint16_t data_buf_off = 0;
|
||||
int output_param_len = 0;
|
||||
uint16_t string_len = 0;
|
||||
uint8_t header_buf[2] = {0};
|
||||
|
||||
e_ble_tlv tlv[BLE_QIOT_ACTION_INPUT_ID_BUTT] = {0};
|
||||
uint8_t output_flag_array[BLE_QIOT_ACTION_OUTPUT_ID_BUTT] = {0}; // set true if the id have output
|
||||
uint8_t data_buf[BLE_QIOT_EVENT_MAX_SIZE] = {0};
|
||||
|
||||
header_buf[0] = BLE_QIOT_REPLY_SUCCESS;
|
||||
header_buf[1] = action_id;
|
||||
|
||||
ble_qiot_log_d("input action: %d", action_id);
|
||||
while (parse_len < len) {
|
||||
if (tlv_index >= BLE_QIOT_ACTION_INPUT_ID_BUTT) {
|
||||
ble_qiot_log_e("invalid action(id: %d) data", action_id);
|
||||
handle_ret = BLE_QIOT_REPLY_DATA_ERR;
|
||||
goto end;
|
||||
}
|
||||
ret_len = ble_lldata_parse_tlv(in_buf + parse_len, len - parse_len, &tlv[tlv_index]);
|
||||
if (ret_len < 0) {
|
||||
handle_ret = BLE_QIOT_REPLY_DATA_ERR;
|
||||
goto end;
|
||||
}
|
||||
parse_len += ret_len;
|
||||
tlv_index++;
|
||||
if (parse_len > len) {
|
||||
ble_qiot_log_e("action data parse failed, parse len: %d > data len: %d", parse_len, len);
|
||||
handle_ret = BLE_QIOT_REPLY_DATA_ERR;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
if (0 != ble_action_user_handle_input_param(action_id, tlv, tlv_index, output_flag_array)) {
|
||||
handle_ret = BLE_QIOT_REPLY_FAIL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
for (output_id = 0; output_id < BLE_QIOT_ACTION_OUTPUT_ID_BUTT; output_id++) {
|
||||
if (output_flag_array[output_id]) {
|
||||
output_type = ble_action_get_output_type_by_id(action_id, output_id);
|
||||
if (output_type >= BLE_QIOT_DATA_TYPE_BUTT) {
|
||||
ble_qiot_log_e("action id(%d:%d) type invalid", action_id, output_id);
|
||||
handle_ret = BLE_QIOT_REPLY_FAIL;
|
||||
goto end;
|
||||
}
|
||||
data_buf[data_len++] = BLE_QIOT_PACKAGE_TLV_HEAD(output_type, output_id);
|
||||
data_buf_off = data_len;
|
||||
if (BLE_QIOT_DATA_TYPE_STRING == output_type) {
|
||||
data_buf_off += BLE_QIOT_STRING_TYPE_LEN;
|
||||
}
|
||||
output_param_len = ble_action_user_handle_output_param(
|
||||
action_id, output_id, (char *)data_buf + data_buf_off, sizeof(data_buf) - data_buf_off);
|
||||
if (output_param_len < 0) {
|
||||
handle_ret = BLE_QIOT_REPLY_FAIL;
|
||||
goto end;
|
||||
} else if (output_param_len == 0) {
|
||||
// clean the head cause no data to post
|
||||
data_len--;
|
||||
data_buf[data_len] = '0';
|
||||
ble_qiot_log_d("action id(%d: %d) no data to post", action_id, output_id);
|
||||
} else {
|
||||
if (BLE_QIOT_DATA_TYPE_STRING == output_type) {
|
||||
string_len = HTONS(output_param_len);
|
||||
memcpy(data_buf + data_len, &string_len, sizeof(uint16_t));
|
||||
data_len += sizeof(uint16_t);
|
||||
}
|
||||
data_len += output_param_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ble_qiot_log_hex(BLE_QIOT_LOG_LEVEL_INFO, "user data", data_buf, data_len);
|
||||
return ble_event_notify(BLE_QIOT_EVENT_UP_ACTION_REPLY, header_buf, sizeof(header_buf), (const char *)data_buf,
|
||||
data_len);
|
||||
|
||||
end:
|
||||
header_buf[0] = BLE_QIOT_REPLY_FAIL;
|
||||
ble_event_notify(BLE_QIOT_EVENT_UP_ACTION_REPLY, header_buf, sizeof(header_buf), (const char *)&handle_ret,
|
||||
sizeof(uint8_t));
|
||||
return BLE_QIOT_RS_ERR;
|
||||
#else
|
||||
ble_qiot_log_e("action" BLE_QIOT_NOT_SUPPORT_WARN);
|
||||
return BLE_QIOT_RS_OK;
|
||||
#endif //BLE_QIOT_INCLUDE_PROPERTY
|
||||
}
|
||||
|
||||
#endif //BLE_QIOT_LLSYNC_STANDARD
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,428 @@
|
||||
/*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ble_qiot_config.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <printf.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ble_qiot_common.h"
|
||||
#include "ble_qiot_config.h"
|
||||
#include "ble_qiot_export.h"
|
||||
#include "ble_qiot_hmac.h"
|
||||
#include "ble_qiot_import.h"
|
||||
#include "ble_qiot_log.h"
|
||||
#include "ble_qiot_param_check.h"
|
||||
#include "ble_qiot_utils_base64.h"
|
||||
#include "ble_qiot_md5.h"
|
||||
#include "ble_qiot_llsync_device.h"
|
||||
|
||||
#define BLE_GET_EXPIRATION_TIME(_cur_time) ((_cur_time) + BLE_EXPIRATION_TIME)
|
||||
|
||||
static ble_core_data sg_core_data; // ble data storage in flash
|
||||
static ble_device_info sg_device_info; // device info storage in flash
|
||||
static e_llsync_bind_state sg_llsync_bind_state; // llsync bind state in used
|
||||
static e_llsync_connection_state sg_llsync_connection_state; // llsync connection state in used
|
||||
static e_ble_connection_state sg_ble_connection_state; // ble connection state in used
|
||||
static uint16_t sg_llsync_mtu; // the mtu for llsync slice data
|
||||
|
||||
uint16_t llsync_mtu_get(void)
|
||||
{
|
||||
// return default mtu if llsync mtu not set
|
||||
if (0 == sg_llsync_mtu) {
|
||||
sg_llsync_mtu = ATT_MTU_TO_LLSYNC_MTU(ATT_DEFAULT_MTU);
|
||||
}
|
||||
return sg_llsync_mtu;
|
||||
}
|
||||
|
||||
void llsync_mtu_update(uint16_t llsync_mtu)
|
||||
{
|
||||
sg_llsync_mtu = llsync_mtu;
|
||||
}
|
||||
|
||||
void llsync_bind_state_set(e_llsync_bind_state new_state)
|
||||
{
|
||||
ble_qiot_log_d("bind state: %d ---> %d", sg_llsync_bind_state, new_state);
|
||||
sg_llsync_bind_state = new_state;
|
||||
}
|
||||
|
||||
e_llsync_bind_state llsync_bind_state_get(void)
|
||||
{
|
||||
return sg_llsync_bind_state;
|
||||
}
|
||||
|
||||
void llsync_connection_state_set(e_llsync_connection_state new_state)
|
||||
{
|
||||
ble_qiot_log_d("llsync state: %d ---> %d", sg_llsync_connection_state, new_state);
|
||||
sg_llsync_connection_state = new_state;
|
||||
}
|
||||
|
||||
bool llsync_is_connected(void)
|
||||
{
|
||||
return sg_llsync_connection_state == E_LLSYNC_CONNECTED;
|
||||
}
|
||||
|
||||
void ble_connection_state_set(e_ble_connection_state new_state)
|
||||
{
|
||||
ble_qiot_log_d("ble state: %d ---> %d", sg_llsync_connection_state, new_state);
|
||||
sg_ble_connection_state = new_state;
|
||||
}
|
||||
|
||||
bool ble_is_connected(void)
|
||||
{
|
||||
return sg_ble_connection_state == E_BLE_CONNECTED;
|
||||
}
|
||||
|
||||
// [1byte bind state] + [6 bytes mac] + [8bytes identify string]/[10 bytes product id]
|
||||
int ble_get_my_broadcast_data(char *out_buf, int buf_len)
|
||||
{
|
||||
POINTER_SANITY_CHECK(out_buf, BLE_QIOT_RS_ERR_PARA);
|
||||
BUFF_LEN_SANITY_CHECK(buf_len, BLE_BIND_IDENTIFY_STR_LEN + BLE_QIOT_MAC_LEN + 1, BLE_QIOT_RS_ERR_PARA);
|
||||
int ret_len = 0;
|
||||
#if BLE_QIOT_LLSYNC_STANDARD
|
||||
int i = 0;
|
||||
uint8_t md5_in_buf[128] = {0};
|
||||
uint8_t md5_in_len = 0;
|
||||
uint8_t md5_out_buf[MD5_DIGEST_SIZE] = {0};
|
||||
|
||||
out_buf[ret_len++] = llsync_bind_state_get() | (BLE_QIOT_LLSYNC_PROTOCOL_VERSION << LLSYNC_PROTO_VER_BIT);
|
||||
if (E_LLSYNC_BIND_SUCC == llsync_bind_state_get()) {
|
||||
// 1 bytes state + 8 bytes device identify_str + 8 bytes identify_str
|
||||
memcpy((char *)md5_in_buf, sg_device_info.product_id, sizeof(sg_device_info.product_id));
|
||||
md5_in_len += sizeof(sg_device_info.product_id);
|
||||
memcpy((char *)md5_in_buf + md5_in_len, sg_device_info.device_name, strlen(sg_device_info.device_name));
|
||||
md5_in_len += strlen(sg_device_info.device_name);
|
||||
utils_md5(md5_in_buf, md5_in_len, md5_out_buf);
|
||||
for (i = 0; i < MD5_DIGEST_SIZE / 2; i++) {
|
||||
out_buf[i + ret_len] = md5_out_buf[i] ^ md5_out_buf[i + MD5_DIGEST_SIZE / 2];
|
||||
}
|
||||
ret_len += MD5_DIGEST_SIZE / 2;
|
||||
memcpy(out_buf + ret_len, sg_core_data.identify_str, sizeof(sg_core_data.identify_str));
|
||||
ret_len += sizeof(sg_core_data.identify_str);
|
||||
} else
|
||||
#endif //BLE_QIOT_LLSYNC_STANDARD
|
||||
{
|
||||
#if BLE_QIOT_LLSYNC_CONFIG_NET
|
||||
out_buf[ret_len++] = BLE_QIOT_LLSYNC_PROTOCOL_VERSION;
|
||||
#endif // BLE_QIOT_LLSYNC_CONFIG_NET
|
||||
// 1 bytes state + 6 bytes mac + 10 bytes product id
|
||||
memcpy(out_buf + ret_len, sg_device_info.mac, BLE_QIOT_MAC_LEN);
|
||||
ret_len += BLE_QIOT_MAC_LEN;
|
||||
memcpy(out_buf + ret_len, sg_device_info.product_id, sizeof(sg_device_info.product_id));
|
||||
ret_len += sizeof(sg_device_info.product_id);
|
||||
}
|
||||
ble_qiot_log_hex(BLE_QIOT_LOG_LEVEL_INFO, "broadcast", out_buf, ret_len);
|
||||
|
||||
return ret_len;
|
||||
}
|
||||
|
||||
int ble_inform_mtu_result(const char *result, uint16_t data_len)
|
||||
{
|
||||
uint16_t ret = 0;
|
||||
|
||||
memcpy(&ret, result, sizeof(uint16_t));
|
||||
ret = NTOHS(ret);
|
||||
ble_qiot_log_i("mtu setting result: %02x", ret);
|
||||
|
||||
if (LLSYNC_MTU_SET_RESULT_ERR == ret) {
|
||||
return ble_event_sync_mtu(ATT_DEFAULT_MTU);
|
||||
} else if (0 == ret) {
|
||||
return BLE_QIOT_RS_OK;
|
||||
} else {
|
||||
llsync_mtu_update(ATT_MTU_TO_LLSYNC_MTU(ret));
|
||||
return BLE_QIOT_RS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
#if BLE_QIOT_LLSYNC_STANDARD
|
||||
static int memchk(const uint8_t *buf, int len)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (buf[i] != 0xFF) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
extern void bt_tws_sync_ll_sync_state();
|
||||
static ble_qiot_ret_status_t ble_write_core_data(ble_core_data *core_data)
|
||||
{
|
||||
memcpy(&sg_core_data, core_data, sizeof(ble_core_data));
|
||||
if (sizeof(ble_core_data) !=
|
||||
ble_write_flash(BLE_QIOT_RECORD_FLASH_ADDR, (char *)&sg_core_data, sizeof(ble_core_data))) {
|
||||
ble_qiot_log_e("llsync write core failed");
|
||||
return BLE_QIOT_RS_ERR_FLASH;
|
||||
}
|
||||
|
||||
#if TCFG_USER_TWS_ENABLE
|
||||
bt_tws_sync_ll_sync_state();
|
||||
#endif
|
||||
|
||||
return BLE_QIOT_RS_OK;
|
||||
}
|
||||
|
||||
int ble_bind_get_authcode(const char *bind_data, uint16_t data_len, char *out_buf, uint16_t buf_len)
|
||||
{
|
||||
POINTER_SANITY_CHECK(bind_data, BLE_QIOT_RS_ERR_PARA);
|
||||
BUFF_LEN_SANITY_CHECK(data_len, (int32_t)sizeof(ble_bind_data), BLE_QIOT_RS_ERR_PARA);
|
||||
POINTER_SANITY_CHECK(out_buf, BLE_QIOT_RS_ERR_PARA);
|
||||
BUFF_LEN_SANITY_CHECK(buf_len, SHA1_DIGEST_SIZE + BLE_QIOT_DEVICE_NAME_LEN, BLE_QIOT_RS_ERR_PARA);
|
||||
|
||||
char out_sign[SHA1_DIGEST_SIZE] = {0};
|
||||
char sign_info[80] = {0};
|
||||
int sign_info_len = 0;
|
||||
int time_expiration = 0;
|
||||
int nonce = 0;
|
||||
int ret_len = 0;
|
||||
uint8_t secret[BLE_QIOT_PSK_LEN / 4 * 3] = {0};
|
||||
int secret_len = 0;
|
||||
|
||||
// if the pointer "char *bind_data" is not aligned with 4 byte, in some cpu convert it to
|
||||
// pointer "ble_bind_data *" work correctly, but some cpu will get wrong value, or cause
|
||||
// other "Unexpected Error". Here copy it to a local variable make sure aligned with 4 byte.
|
||||
ble_bind_data bind_data_aligned;
|
||||
memcpy(&bind_data_aligned, bind_data, sizeof(ble_bind_data));
|
||||
|
||||
nonce = NTOHL(bind_data_aligned.nonce);
|
||||
time_expiration = BLE_GET_EXPIRATION_TIME(NTOHL(bind_data_aligned.timestamp));
|
||||
|
||||
// [10 bytes product_id] + [x bytes device name] + ';' + [4 bytes nonce] + ';' + [4 bytes timestamp]
|
||||
memcpy(sign_info, sg_device_info.product_id, sizeof(sg_device_info.product_id));
|
||||
sign_info_len += sizeof(sg_device_info.product_id);
|
||||
memcpy(sign_info + sign_info_len, sg_device_info.device_name, strlen(sg_device_info.device_name));
|
||||
sign_info_len += strlen(sg_device_info.device_name);
|
||||
snprintf(sign_info + sign_info_len, sizeof(sign_info) - sign_info_len, ";%u", nonce);
|
||||
sign_info_len += strlen(sign_info + sign_info_len);
|
||||
snprintf(sign_info + sign_info_len, sizeof(sign_info) - sign_info_len, ";%u", time_expiration);
|
||||
sign_info_len += strlen(sign_info + sign_info_len);
|
||||
|
||||
qcloud_iot_utils_base64decode(secret, sizeof(secret), (size_t *)&secret_len,
|
||||
(const unsigned char *)sg_device_info.psk, sizeof(sg_device_info.psk));
|
||||
ble_qiot_log_hex(BLE_QIOT_LOG_LEVEL_INFO, "bind sign in", sign_info, sign_info_len);
|
||||
utils_hmac_sha1((const char *)sign_info, sign_info_len, out_sign, (const char *)secret, secret_len);
|
||||
ble_qiot_log_hex(BLE_QIOT_LOG_LEVEL_INFO, "bind sign out", out_sign, sizeof(out_sign));
|
||||
|
||||
// return [20 bytes sign] + [x bytes device_name]
|
||||
memset(out_buf, 0, buf_len);
|
||||
memcpy(out_buf, out_sign, SHA1_DIGEST_SIZE);
|
||||
ret_len = SHA1_DIGEST_SIZE;
|
||||
|
||||
memcpy(out_buf + ret_len, sg_device_info.device_name, strlen(sg_device_info.device_name));
|
||||
ret_len += strlen(sg_device_info.device_name);
|
||||
ble_qiot_log_hex(BLE_QIOT_LOG_LEVEL_INFO, "bind auth code", out_buf, ret_len);
|
||||
|
||||
return ret_len;
|
||||
}
|
||||
|
||||
ble_qiot_ret_status_t ble_bind_write_result(const char *result, uint16_t len)
|
||||
{
|
||||
POINTER_SANITY_CHECK(result, BLE_QIOT_RS_ERR_PARA);
|
||||
BUFF_LEN_SANITY_CHECK(len, (int32_t)sizeof(ble_core_data), BLE_QIOT_RS_ERR_PARA);
|
||||
|
||||
ble_core_data *bind_result = (ble_core_data *)result;
|
||||
|
||||
llsync_bind_state_set((e_llsync_bind_state)bind_result->bind_state);
|
||||
return ble_write_core_data(bind_result);
|
||||
}
|
||||
|
||||
ble_qiot_ret_status_t ble_unbind_write_result(void)
|
||||
{
|
||||
ble_core_data bind_result;
|
||||
|
||||
llsync_connection_state_set(E_LLSYNC_DISCONNECTED);
|
||||
llsync_bind_state_set(E_LLSYNC_BIND_IDLE);
|
||||
memset(&bind_result, 0, sizeof(bind_result));
|
||||
return ble_write_core_data(&bind_result);
|
||||
}
|
||||
|
||||
int ble_conn_get_authcode(const char *conn_data, uint16_t data_len, char *out_buf, uint16_t buf_len)
|
||||
{
|
||||
POINTER_SANITY_CHECK(conn_data, BLE_QIOT_RS_ERR_PARA);
|
||||
BUFF_LEN_SANITY_CHECK(data_len, (int32_t)sizeof(ble_conn_data), BLE_QIOT_RS_ERR_PARA);
|
||||
POINTER_SANITY_CHECK(out_buf, BLE_QIOT_RS_ERR_PARA);
|
||||
BUFF_LEN_SANITY_CHECK(buf_len, SHA1_DIGEST_SIZE + BLE_QIOT_DEVICE_NAME_LEN, BLE_QIOT_RS_ERR_PARA);
|
||||
|
||||
char sign_info[64] = {0};
|
||||
char out_sign[SHA1_DIGEST_SIZE] = {0};
|
||||
int sign_info_len = 0;
|
||||
int timestamp = 0;
|
||||
int ret_len = 0;
|
||||
|
||||
// if the pointer "char *bind_data" is not aligned with 4 byte, in some cpu convert it to
|
||||
// pointer "ble_bind_data *" work correctly, but some cpu will get wrong value, or cause
|
||||
// other "Unexpected Error". Here copy it to a local variable make sure aligned with 4 byte.
|
||||
ble_conn_data conn_data_aligned;
|
||||
memcpy(&conn_data_aligned, conn_data, sizeof(ble_conn_data));
|
||||
|
||||
// valid sign
|
||||
timestamp = NTOHL(conn_data_aligned.timestamp);
|
||||
snprintf(sign_info + sign_info_len, sizeof(sign_info) - sign_info_len, "%d", timestamp);
|
||||
sign_info_len = strlen(sign_info + sign_info_len);
|
||||
ble_qiot_log_hex(BLE_QIOT_LOG_LEVEL_INFO, "valid sign in", sign_info, sign_info_len);
|
||||
utils_hmac_sha1(sign_info, sign_info_len, out_sign, sg_core_data.local_psk, sizeof(sg_core_data.local_psk));
|
||||
ble_qiot_log_hex(BLE_QIOT_LOG_LEVEL_INFO, "valid sign out", out_sign, SHA1_DIGEST_SIZE);
|
||||
if (0 != memcmp(&conn_data_aligned.sign_info, out_sign, SHA1_DIGEST_SIZE)) {
|
||||
ble_qiot_log_e("llsync invalid connect sign");
|
||||
return BLE_QIOT_RS_VALID_SIGN_ERR;
|
||||
}
|
||||
|
||||
// calc sign
|
||||
memset(sign_info, 0, sizeof(sign_info));
|
||||
sign_info_len = 0;
|
||||
|
||||
// expiration time + product id + device name
|
||||
timestamp = BLE_GET_EXPIRATION_TIME(NTOHL(conn_data_aligned.timestamp));
|
||||
snprintf(sign_info + sign_info_len, sizeof(sign_info) - sign_info_len, "%d", timestamp);
|
||||
sign_info_len += strlen(sign_info + sign_info_len);
|
||||
memcpy(sign_info + sign_info_len, sg_device_info.product_id, sizeof(sg_device_info.product_id));
|
||||
sign_info_len += sizeof(sg_device_info.product_id);
|
||||
memcpy(sign_info + sign_info_len, sg_device_info.device_name, strlen(sg_device_info.device_name));
|
||||
sign_info_len += strlen(sg_device_info.device_name);
|
||||
|
||||
ble_qiot_log_hex(BLE_QIOT_LOG_LEVEL_INFO, "conn sign in", sign_info, sign_info_len);
|
||||
utils_hmac_sha1(sign_info, sign_info_len, out_sign, sg_core_data.local_psk, sizeof(sg_core_data.local_psk));
|
||||
ble_qiot_log_hex(BLE_QIOT_LOG_LEVEL_INFO, "conn sign out", out_sign, sizeof(out_sign));
|
||||
|
||||
// return authcode
|
||||
memset(out_buf, 0, buf_len);
|
||||
memcpy(out_buf, out_sign, SHA1_DIGEST_SIZE);
|
||||
ret_len += SHA1_DIGEST_SIZE;
|
||||
memcpy(out_buf + ret_len, sg_device_info.device_name, strlen(sg_device_info.device_name));
|
||||
ret_len += strlen(sg_device_info.device_name);
|
||||
ble_qiot_log_hex(BLE_QIOT_LOG_LEVEL_INFO, "conn auth code", out_buf, ret_len);
|
||||
|
||||
return ret_len;
|
||||
}
|
||||
|
||||
int ble_unbind_get_authcode(const char *unbind_data, uint16_t data_len, char *out_buf, uint16_t buf_len)
|
||||
{
|
||||
POINTER_SANITY_CHECK(unbind_data, BLE_QIOT_RS_ERR_PARA);
|
||||
BUFF_LEN_SANITY_CHECK(data_len, (int32_t)sizeof(ble_unbind_data), BLE_QIOT_RS_ERR_PARA);
|
||||
POINTER_SANITY_CHECK(out_buf, BLE_QIOT_RS_ERR_PARA);
|
||||
BUFF_LEN_SANITY_CHECK(buf_len, SHA1_DIGEST_SIZE, BLE_QIOT_RS_ERR_PARA);
|
||||
|
||||
char sign_info[32] = {0};
|
||||
char out_sign[SHA1_DIGEST_SIZE] = {0};
|
||||
int sign_info_len = 0;
|
||||
int ret_len = 0;
|
||||
|
||||
// valid sign
|
||||
memcpy(sign_info, BLE_UNBIND_REQUEST_STR, BLE_UNBIND_REQUEST_STR_LEN);
|
||||
sign_info_len = BLE_UNBIND_REQUEST_STR_LEN;
|
||||
utils_hmac_sha1(sign_info, sign_info_len, out_sign, sg_core_data.local_psk, sizeof(sg_core_data.local_psk));
|
||||
ble_qiot_log_hex(BLE_QIOT_LOG_LEVEL_INFO, "valid sign out", out_sign, SHA1_DIGEST_SIZE);
|
||||
|
||||
if (0 != memcmp(((ble_unbind_data *)unbind_data)->sign_info, out_sign, SHA1_DIGEST_SIZE)) {
|
||||
ble_qiot_log_e("llsync invalid unbind sign");
|
||||
return BLE_QIOT_RS_VALID_SIGN_ERR;
|
||||
}
|
||||
|
||||
// calc sign
|
||||
memset(sign_info, 0, sizeof(sign_info));
|
||||
sign_info_len = 0;
|
||||
|
||||
memcpy(sign_info, BLE_UNBIND_RESPONSE, strlen(BLE_UNBIND_RESPONSE));
|
||||
sign_info_len += BLE_UNBIND_RESPONSE_STR_LEN;
|
||||
utils_hmac_sha1(sign_info, sign_info_len, out_sign, sg_core_data.local_psk, sizeof(sg_core_data.local_psk));
|
||||
ble_qiot_log_hex(BLE_QIOT_LOG_LEVEL_INFO, "unbind auth code", out_sign, SHA1_DIGEST_SIZE);
|
||||
|
||||
memset(out_buf, 0, buf_len);
|
||||
memcpy(out_buf, out_sign, sizeof(out_sign));
|
||||
ret_len += sizeof(out_sign);
|
||||
|
||||
return ret_len;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
ble_qiot_ret_status_t ble_init_flash_data(void)
|
||||
{
|
||||
#if BLE_QIOT_LLSYNC_STANDARD
|
||||
if (sizeof(sg_core_data) !=
|
||||
ble_read_flash(BLE_QIOT_RECORD_FLASH_ADDR, (char *)&sg_core_data, sizeof(sg_core_data))) {
|
||||
ble_qiot_log_e("llsync read flash failed");
|
||||
return BLE_QIOT_RS_ERR_FLASH;
|
||||
}
|
||||
if (0 == memchk((const uint8_t *)&sg_core_data, sizeof(sg_core_data))) {
|
||||
memset(&sg_core_data, 0, sizeof(sg_core_data));
|
||||
}
|
||||
|
||||
if (0 != ble_get_psk(sg_device_info.psk)) {
|
||||
ble_qiot_log_e("llsync get secret key failed");
|
||||
return BLE_QIOT_RS_ERR_FLASH;
|
||||
}
|
||||
#endif //BLE_QIOT_LLSYNC_STANDARD
|
||||
|
||||
if (0 != ble_get_mac(sg_device_info.mac)) {
|
||||
ble_qiot_log_e("llsync get mac failed");
|
||||
return BLE_QIOT_RS_ERR_FLASH;
|
||||
}
|
||||
if (0 != ble_get_product_id(sg_device_info.product_id)) {
|
||||
ble_qiot_log_e("llsync get product id failed");
|
||||
return BLE_QIOT_RS_ERR_FLASH;
|
||||
}
|
||||
if (0 == ble_get_device_name(sg_device_info.device_name)) {
|
||||
ble_qiot_log_e("llsync get device name failed");
|
||||
return BLE_QIOT_RS_ERR_FLASH;
|
||||
}
|
||||
|
||||
#if BLE_QIOT_LLSYNC_STANDARD
|
||||
llsync_bind_state_set((e_llsync_bind_state)sg_core_data.bind_state);
|
||||
// ble_qiot_log_hex(BLE_QIOT_LOG_LEVEL_INFO, "core_data", (char *)&sg_core_data, sizeof(sg_core_data));
|
||||
// ble_qiot_log_hex(BLE_QIOT_LOG_LEVEL_INFO, "device_info", (char *)&sg_device_info, sizeof(sg_device_info));
|
||||
#endif //BLE_QIOT_LLSYNC_STANDARD
|
||||
|
||||
return BLE_QIOT_RS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ll_sync_state_deal(void *_data, u16 len)
|
||||
{
|
||||
ble_core_data data;
|
||||
|
||||
memcpy(&data, _data, len);
|
||||
|
||||
if (data.bind_state == E_LLSYNC_BIND_SUCC) {
|
||||
//g_printf("bind ok\n");
|
||||
ble_bind_write_result((u8 *)&data, len);
|
||||
} else if (data.bind_state == E_LLSYNC_BIND_WAIT) {
|
||||
//g_printf("bind wait\n");
|
||||
llsync_bind_state_set(E_LLSYNC_BIND_IDLE);
|
||||
} else {
|
||||
//g_printf("no bind \n");
|
||||
ble_unbind_write_result();
|
||||
}
|
||||
}
|
||||
|
||||
u16 ll_sync_get_core_data(u8 *data)
|
||||
{
|
||||
if (sizeof(ble_core_data) > 20) {
|
||||
ASSERT(0, "DATA ERROR\n");
|
||||
}
|
||||
memcpy(data, &sg_core_data, sizeof(ble_core_data));
|
||||
return sizeof(ble_core_data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,269 @@
|
||||
/*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ble_qiot_config.h"
|
||||
|
||||
//#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ble_qiot_import.h"
|
||||
#include "ble_qiot_common.h"
|
||||
#include "ble_qiot_param_check.h"
|
||||
#include "ble_qiot_service.h"
|
||||
#include "ble_qiot_template.h"
|
||||
#include "ble_qiot_llsync_device.h"
|
||||
#include "ble_qiot_llsync_event.h"
|
||||
|
||||
// report device info
|
||||
ble_qiot_ret_status_t ble_event_report_device_info(void)
|
||||
{
|
||||
char device_info[56] = {0}; // 1 byte llsync proto version + 2 bytes mtu size + 1 byte length of develop version
|
||||
uint16_t mtu_size = 0;
|
||||
|
||||
#if BLE_QIOT_REMOTE_SET_MTU
|
||||
mtu_size = LLSYNC_MTU_SET_MASK;
|
||||
#endif //BLE_QIOT_REMOTE_SET_MTU
|
||||
mtu_size |= ble_get_user_data_mtu_size();
|
||||
mtu_size = HTONS(mtu_size);
|
||||
device_info[0] = BLE_QIOT_LLSYNC_PROTOCOL_VERSION;
|
||||
memcpy(&device_info[1], &mtu_size, sizeof(mtu_size));
|
||||
#if BLE_QIOT_LLSYNC_CONFIG_NET
|
||||
device_info[3] = (char)ble_get_device_name(&device_info[4]);
|
||||
#else
|
||||
device_info[3] = (char)strlen(BLE_QIOT_USER_DEVELOPER_VERSION);
|
||||
memcpy(&device_info[4], BLE_QIOT_USER_DEVELOPER_VERSION, device_info[3]);
|
||||
#endif //BLE_QIOT_LLSYNC_CONFIG_NET
|
||||
return ble_event_notify(BLE_QIOT_EVENT_UP_REPORT_MTU, NULL, 0, device_info, 4 + device_info[3]);
|
||||
}
|
||||
|
||||
// sync mtu
|
||||
ble_qiot_ret_status_t ble_event_sync_mtu(uint16_t att_mtu)
|
||||
{
|
||||
uint16_t mtu_size = 0;
|
||||
|
||||
mtu_size = ATT_MTU_TO_LLSYNC_MTU(att_mtu);
|
||||
llsync_mtu_update(mtu_size);
|
||||
mtu_size = HTONS(mtu_size);
|
||||
return ble_event_notify(BLE_QIOT_EVENT_UP_SYNC_MTU, NULL, 0, (const char *)&mtu_size, sizeof(uint16_t));
|
||||
}
|
||||
|
||||
ble_qiot_ret_status_t ble_event_notify2(uint8_t type, uint8_t length_flag, uint8_t *header, uint8_t header_len,
|
||||
const char *buf, uint16_t buf_len)
|
||||
{
|
||||
char *p = (char *)buf;
|
||||
uint16_t left_len = buf_len;
|
||||
uint16_t send_len = 0;
|
||||
uint16_t mtu_size = 0;
|
||||
uint8_t slice_state = BLE_QIOT_EVENT_NO_SLICE;
|
||||
uint16_t send_buf_index = 0;
|
||||
uint16_t tmp_len = 0;
|
||||
|
||||
uint8_t send_buf[BLE_QIOT_EVENT_BUF_SIZE] = {0};
|
||||
|
||||
if (!llsync_is_connected() && type != BLE_QIOT_EVENT_UP_BIND_SIGN_RET && type != BLE_QIOT_EVENT_UP_CONN_SIGN_RET &&
|
||||
type != BLE_QIOT_EVENT_UP_UNBIND_SIGN_RET && type != BLE_QIOT_EVENT_UP_SYNC_WAIT_TIME) {
|
||||
ble_qiot_log_e("upload msg negate, device not connected");
|
||||
return BLE_QIOT_RS_ERR;
|
||||
}
|
||||
|
||||
// reserve event header length, 3 bytes fixed length + n bytes header
|
||||
mtu_size = llsync_mtu_get();
|
||||
mtu_size = mtu_size > sizeof(send_buf) ? sizeof(send_buf) : mtu_size;
|
||||
mtu_size -= (BLE_QIOT_EVENT_FIXED_HEADER_LEN + header_len);
|
||||
// ble_qiot_log_d("mtu size %d", mtu_size);
|
||||
|
||||
do {
|
||||
memset(send_buf, 0, sizeof(send_buf));
|
||||
send_buf_index = 0;
|
||||
send_len = left_len > mtu_size ? mtu_size : left_len;
|
||||
|
||||
send_buf[send_buf_index++] = type;
|
||||
if (NULL != buf) {
|
||||
tmp_len = HTONS(send_len + header_len);
|
||||
memcpy(send_buf + send_buf_index, &tmp_len, sizeof(uint16_t));
|
||||
send_buf_index += sizeof(uint16_t);
|
||||
if (NULL != header) {
|
||||
memcpy(send_buf + send_buf_index, header, header_len);
|
||||
send_buf_index += header_len;
|
||||
}
|
||||
memcpy(send_buf + send_buf_index, p, send_len);
|
||||
send_buf_index += send_len;
|
||||
|
||||
p += send_len;
|
||||
left_len -= send_len;
|
||||
send_len += (BLE_QIOT_EVENT_FIXED_HEADER_LEN + header_len);
|
||||
|
||||
if (0 == left_len) {
|
||||
slice_state =
|
||||
(BLE_QIOT_EVENT_NO_SLICE == slice_state) ? BLE_QIOT_EVENT_NO_SLICE : BLE_QIOT_EVENT_SLICE_FOOT;
|
||||
} else {
|
||||
slice_state =
|
||||
(BLE_QIOT_EVENT_NO_SLICE == slice_state) ? BLE_QIOT_EVENT_SLICE_HEAD : BLE_QIOT_EVENT_SLICE_BODY;
|
||||
}
|
||||
// the high 2 bits means slice state, and the left 14 bits is data length
|
||||
send_buf[1] |= slice_state << 6;
|
||||
send_buf[1] |= length_flag;
|
||||
} else {
|
||||
send_len = send_buf_index;
|
||||
}
|
||||
|
||||
ble_qiot_log_hex(BLE_QIOT_LOG_LEVEL_INFO, "post data", (char *)send_buf, send_len);
|
||||
if (0 != ble_send_notify(send_buf, send_len)) {
|
||||
ble_qiot_log_e("event(type: %d) post failed, len: %d", type, send_len);
|
||||
return BLE_QIOT_RS_ERR;
|
||||
}
|
||||
} while (left_len != 0);
|
||||
|
||||
return BLE_QIOT_RS_OK;
|
||||
}
|
||||
|
||||
ble_qiot_ret_status_t ble_event_notify(uint8_t type, uint8_t *header, uint8_t header_len, const char *buf,
|
||||
uint16_t buf_len)
|
||||
{
|
||||
return ble_event_notify2(type, 0, header, header_len, buf, buf_len);
|
||||
}
|
||||
|
||||
#if BLE_QIOT_LLSYNC_CONFIG_NET
|
||||
ble_qiot_ret_status_t ble_event_report_wifi_mode(uint8_t result)
|
||||
{
|
||||
return ble_event_notify(BLE_QIOT_EVENT_UP_WIFI_MODE, NULL, 0, (const char *)&result, sizeof(uint8_t));
|
||||
}
|
||||
|
||||
ble_qiot_ret_status_t ble_event_report_wifi_info(uint8_t result)
|
||||
{
|
||||
return ble_event_notify(BLE_QIOT_EVENT_UP_WIFI_INFO, NULL, 0, (const char *)&result, sizeof(uint8_t));
|
||||
}
|
||||
|
||||
ble_qiot_ret_status_t ble_event_report_wifi_connect(BLE_WIFI_MODE mode, BLE_WIFI_STATE state, uint8_t ssid_len,
|
||||
const char *ssid)
|
||||
{
|
||||
char buf[40] = {0};
|
||||
uint8_t pos = 0;
|
||||
|
||||
buf[pos++] = mode;
|
||||
buf[pos++] = state;
|
||||
buf[pos++] = 0;
|
||||
buf[pos++] = ssid_len;
|
||||
memcpy(buf + pos, ssid, ssid_len);
|
||||
|
||||
return ble_event_notify(BLE_QIOT_EVENT_UP_WIFI_CONNECT, NULL, 0, (const char *)buf, pos + ssid_len);
|
||||
}
|
||||
|
||||
ble_qiot_ret_status_t ble_event_report_wifi_token(uint8_t result)
|
||||
{
|
||||
return ble_event_notify(BLE_QIOT_EVENT_UP_WIFI_TOKEN, NULL, 0, (const char *)&result, sizeof(uint8_t));
|
||||
}
|
||||
|
||||
ble_qiot_ret_status_t ble_event_report_wifi_log(const uint8_t *log, uint16_t log_size)
|
||||
{
|
||||
return ble_event_notify(BLE_QIOT_EVENT_UP_WIFI_LOG, NULL, 0, (const char *)log, log_size);
|
||||
}
|
||||
#endif //BLE_QIOT_LLSYNC_CONFIG_NET
|
||||
|
||||
#if BLE_QIOT_LLSYNC_STANDARD
|
||||
// get_status
|
||||
ble_qiot_ret_status_t ble_event_get_status(void)
|
||||
{
|
||||
#ifdef BLE_QIOT_INCLUDE_PROPERTY
|
||||
return ble_event_notify(BLE_QIOT_EVENT_UP_GET_STATUS, NULL, 0, NULL, 0);
|
||||
#else
|
||||
ble_qiot_log_e("property" BLE_QIOT_NOT_SUPPORT_WARN);
|
||||
return BLE_QIOT_RS_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
// report
|
||||
ble_qiot_ret_status_t ble_event_report_property(void)
|
||||
{
|
||||
#ifdef BLE_QIOT_INCLUDE_PROPERTY
|
||||
return ble_user_property_get_report_data();
|
||||
#else
|
||||
ble_qiot_log_e("property" BLE_QIOT_NOT_SUPPORT_WARN);
|
||||
return BLE_QIOT_RS_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if BLE_QIOT_SECURE_BIND
|
||||
ble_qiot_ret_status_t ble_event_sync_wait_time(void)
|
||||
{
|
||||
uint16_t time = BLE_QIOT_BIND_WAIT_TIME;
|
||||
|
||||
time = HTONS(time);
|
||||
return ble_event_notify(BLE_QIOT_EVENT_UP_SYNC_WAIT_TIME, NULL, 0, (const char *)&time, sizeof(uint16_t));
|
||||
}
|
||||
#endif //BLE_QIOT_SECURE_BIND
|
||||
|
||||
ble_qiot_ret_status_t ble_event_post(uint8_t event_id)
|
||||
{
|
||||
#ifdef BLE_QIOT_INCLUDE_EVENT
|
||||
uint8_t param_id = 0;
|
||||
uint8_t param_id_size = 0;
|
||||
uint8_t param_type = 0;
|
||||
int param_len = 0;
|
||||
uint16_t data_len = 0;
|
||||
uint16_t data_buf_off = 0;
|
||||
uint16_t string_len = 0;
|
||||
uint8_t header_buf = {0};
|
||||
|
||||
uint8_t data_buf[BLE_QIOT_EVENT_MAX_SIZE] = {0};
|
||||
|
||||
ble_qiot_log_d("post event: %d", event_id);
|
||||
param_id_size = ble_event_get_id_array_size(event_id);
|
||||
// get all data
|
||||
for (param_id = 0; param_id < param_id_size; param_id++) {
|
||||
param_type = ble_event_get_param_id_type(event_id, param_id);
|
||||
if (param_type >= BLE_QIOT_DATA_TYPE_BUTT) {
|
||||
ble_qiot_log_e("invalid event(%d:%d) type", event_id, param_id);
|
||||
return BLE_QIOT_RS_ERR;
|
||||
}
|
||||
|
||||
data_buf[data_len++] = BLE_QIOT_PACKAGE_TLV_HEAD(param_type, param_id);
|
||||
data_buf_off = data_len;
|
||||
if (BLE_QIOT_DATA_TYPE_STRING == param_type) {
|
||||
// reserved 2 bytes for string type, other type have fixed length
|
||||
data_buf_off += BLE_QIOT_STRING_TYPE_LEN;
|
||||
}
|
||||
param_len = ble_event_get_data_by_id(event_id, param_id, (char *)data_buf + data_buf_off,
|
||||
sizeof(data_buf) - data_buf_off);
|
||||
if (param_len < 0) {
|
||||
return BLE_QIOT_RS_ERR;
|
||||
} else if (param_len == 0) {
|
||||
// clean the header cause no data to post
|
||||
data_len--;
|
||||
data_buf[data_len] = '0';
|
||||
ble_qiot_log_d("event(%d: %d) no data to post", event_id, param_id);
|
||||
} else {
|
||||
if (BLE_QIOT_DATA_TYPE_STRING == param_type) {
|
||||
string_len = HTONS(param_len);
|
||||
memcpy(data_buf + data_len, &string_len, sizeof(uint16_t));
|
||||
data_len += sizeof(uint16_t);
|
||||
}
|
||||
data_len += param_len;
|
||||
}
|
||||
}
|
||||
header_buf = event_id;
|
||||
|
||||
return ble_event_notify(BLE_QIOT_EVENT_UP_EVENT_POST, &header_buf, sizeof(header_buf), (const char *)data_buf,
|
||||
data_len);
|
||||
#else
|
||||
ble_qiot_log_e("event" BLE_QIOT_NOT_SUPPORT_WARN);
|
||||
return BLE_QIOT_RS_OK;
|
||||
#endif //BLE_QIOT_INCLUDE_EVENT
|
||||
}
|
||||
#endif //BLE_QIOT_LLSYNC_STANDARD
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,621 @@
|
||||
/*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ble_qiot_config.h"
|
||||
|
||||
#if BLE_QIOT_LLSYNC_STANDARD
|
||||
//#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ble_qiot_export.h"
|
||||
#include "ble_qiot_import.h"
|
||||
#include "ble_qiot_common.h"
|
||||
#include "ble_qiot_llsync_data.h"
|
||||
#include "ble_qiot_llsync_event.h"
|
||||
#include "ble_qiot_utils_base64.h"
|
||||
#include "ble_qiot_crc.h"
|
||||
#include "ble_qiot_log.h"
|
||||
#include "ble_qiot_param_check.h"
|
||||
#include "ble_qiot_service.h"
|
||||
#include "ble_qiot_template.h"
|
||||
#include "ble_qiot_llsync_ota.h"
|
||||
#include "dual_bank_updata_api.h"
|
||||
#include "timer.h"
|
||||
#include "os/os_api.h"
|
||||
#include "update_loader_download.h"
|
||||
#include "app_config.h"
|
||||
|
||||
#if BLE_QIOT_SUPPORT_OTA
|
||||
static ble_ota_user_callback sg_ota_user_cb; // user callback
|
||||
// 1. monitor the data and request from the server if data lost; 2. call the user function if no data for a long time
|
||||
static int sg_ota_timer = 0;
|
||||
static uint8_t sg_ota_timeout_cnt = 0; // count the number of no data times
|
||||
static uint8_t sg_ota_data_buf[BLE_QIOT_OTA_BUF_SIZE] = {0}; // storage ota data and write to the flash at once
|
||||
static uint16_t sg_ota_data_buf_size = 0; // the data size in the buffer
|
||||
static uint32_t sg_ota_download_file_size = 0; // the data size download from the server
|
||||
static uint8_t sg_ota_next_seq = 0; // the next expect seq
|
||||
static uint32_t sg_ota_download_address = 0; // the address saved ota file
|
||||
static uint8_t sg_ota_download_percent = 0; // the percent of file had download
|
||||
static uint8_t sg_ota_flag = 0; // ota control info
|
||||
static ble_ota_info_record sg_ota_info; // the ota info storage in flash if support resuming
|
||||
static ble_ota_reply_t sg_ota_reply_info; // record the last reply info
|
||||
|
||||
static OS_SEM sg_ota_sem;
|
||||
|
||||
static update_op_tws_api_t *sg_ota_tws_same_api = NULL;
|
||||
static u8 pkt_flag = PKT_FLAG_FIRST;
|
||||
|
||||
#define BLE_QIOT_OTA_FLAG_SET(_BIT) (sg_ota_flag |= (_BIT));
|
||||
#define BLE_QIOT_OTA_FLAG_CLR(_BIT) (sg_ota_flag &= ~(_BIT));
|
||||
#define BLE_QIOT_OTA_FLAG_IS_SET(_BIT) ((sg_ota_flag & (_BIT)) == (_BIT))
|
||||
|
||||
uint32_t ble_ota_get_download_addr(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool ble_qiot_ota_info_valid(void)
|
||||
{
|
||||
return sg_ota_info.valid_flag == BLE_QIOT_OTA_PAGE_VALID_VAL;
|
||||
}
|
||||
static inline uint8_t ble_ota_next_seq_get(void)
|
||||
{
|
||||
return sg_ota_next_seq;
|
||||
}
|
||||
static inline void ble_ota_next_seq_inc(void)
|
||||
{
|
||||
sg_ota_next_seq++;
|
||||
}
|
||||
static inline uint32_t ble_ota_download_address_get(void)
|
||||
{
|
||||
return sg_ota_download_address;
|
||||
}
|
||||
static inline void ble_ota_download_address_set(void)
|
||||
{
|
||||
sg_ota_download_address = ble_ota_get_download_addr();
|
||||
return;
|
||||
}
|
||||
static inline uint32_t ble_ota_download_size_get(void)
|
||||
{
|
||||
return sg_ota_download_file_size;
|
||||
}
|
||||
static inline void ble_ota_download_size_inc(uint32_t size)
|
||||
{
|
||||
sg_ota_download_file_size += size;
|
||||
}
|
||||
static inline uint8_t ble_ota_file_percent_get(void)
|
||||
{
|
||||
return sg_ota_download_percent;
|
||||
}
|
||||
static inline void ble_ota_file_percent_set(uint8_t percent)
|
||||
{
|
||||
sg_ota_download_percent = percent;
|
||||
}
|
||||
|
||||
int ble_ota_write_flash(uint32_t flash_addr, const char *write_buf, uint16_t write_len)
|
||||
{
|
||||
return sg_ota_data_buf_size;
|
||||
}
|
||||
|
||||
void ble_ota_callback_reg(ble_ota_start_callback start_cb, ble_ota_stop_callback stop_cb,
|
||||
ble_ota_valid_file_callback valid_file_cb)
|
||||
{
|
||||
sg_ota_user_cb.start_cb = start_cb;
|
||||
sg_ota_user_cb.stop_cb = stop_cb;
|
||||
sg_ota_user_cb.valid_file_cb = valid_file_cb;
|
||||
}
|
||||
static inline void ble_ota_user_start_cb(void)
|
||||
{
|
||||
if (NULL != sg_ota_user_cb.start_cb) {
|
||||
ble_qiot_log_i("start callback begin");
|
||||
sg_ota_user_cb.start_cb();
|
||||
ble_qiot_log_i("start callback end");
|
||||
}
|
||||
}
|
||||
static inline void ble_ota_user_stop_cb(uint8_t result)
|
||||
{
|
||||
if (NULL != sg_ota_user_cb.stop_cb) {
|
||||
ble_qiot_log_i("stop callback begin");
|
||||
sg_ota_user_cb.stop_cb(result);
|
||||
ble_qiot_log_i("stop callback end");
|
||||
}
|
||||
}
|
||||
static inline ble_qiot_ret_status_t ble_ota_user_valid_cb(void)
|
||||
{
|
||||
if (NULL != sg_ota_user_cb.valid_file_cb) {
|
||||
ble_qiot_log_i("valid callback begin");
|
||||
return sg_ota_user_cb.valid_file_cb(sg_ota_info.download_file_info.file_size,
|
||||
(char *)sg_ota_info.download_file_info.file_version);
|
||||
}
|
||||
return BLE_QIOT_RS_OK;
|
||||
}
|
||||
static inline ble_qiot_ret_status_t ble_ota_write_info(void)
|
||||
{
|
||||
#if BLE_QIOT_SUPPORT_RESUMING
|
||||
sg_ota_info.valid_flag = BLE_QIOT_OTA_PAGE_VALID_VAL;
|
||||
sg_ota_info.last_file_size = ble_ota_download_size_get();
|
||||
sg_ota_info.last_address = ble_ota_download_address_get();
|
||||
if (sizeof(ble_ota_info_record) !=
|
||||
ble_write_flash(BLE_QIOT_OTA_INFO_FLASH_ADDR, (const char *)&sg_ota_info, sizeof(ble_ota_info_record))) {
|
||||
ble_qiot_log_e("write ota info failed");
|
||||
return BLE_QIOT_RS_ERR;
|
||||
}
|
||||
#endif //BLE_QIOT_SUPPORT_RESUMING
|
||||
return BLE_QIOT_RS_OK;
|
||||
}
|
||||
static inline void ble_ota_clear_info(void)
|
||||
{
|
||||
#if BLE_QIOT_SUPPORT_RESUMING
|
||||
sg_ota_info.valid_flag = ~BLE_QIOT_OTA_PAGE_VALID_VAL;
|
||||
if (sizeof(ble_ota_info_record) !=
|
||||
ble_write_flash(BLE_QIOT_OTA_INFO_FLASH_ADDR, (const char *)&sg_ota_info, sizeof(ble_ota_info_record))) {
|
||||
ble_qiot_log_e("clear ota info failed");
|
||||
}
|
||||
#endif //BLE_QIOT_SUPPORT_RESUMING
|
||||
return;
|
||||
}
|
||||
static inline ble_qiot_ret_status_t ble_ota_reply_ota_data(void)
|
||||
{
|
||||
uint8_t req = ble_ota_next_seq_get();
|
||||
uint32_t file_size = ble_ota_download_size_get();
|
||||
|
||||
printf("used old file size %x, req %d", file_size, req);
|
||||
if (sg_ota_reply_info.file_size != file_size) {
|
||||
sg_ota_reply_info.file_size = file_size;
|
||||
sg_ota_reply_info.req = req;
|
||||
} else {
|
||||
// in the case that the device reply info missed, the timer reply info again but the seq increased, so we need
|
||||
// saved the last reply info and used in the time
|
||||
req = sg_ota_reply_info.req;
|
||||
}
|
||||
|
||||
file_size = HTONL(file_size);
|
||||
return ble_event_notify(BLE_QIOT_EVENT_UP_REPLY_OTA_DATA, &req, sizeof(uint8_t), (const char *)&file_size,
|
||||
sizeof(uint32_t));
|
||||
}
|
||||
static inline ble_qiot_ret_status_t ble_ota_report_check_result(uint8_t firmware_valid, uint8_t error_code)
|
||||
{
|
||||
uint8_t result = firmware_valid | error_code;
|
||||
return ble_event_notify(BLE_QIOT_EVENT_UP_REPORT_CHECK_RESULT, NULL, 0, (const char *)&result, sizeof(uint8_t));
|
||||
}
|
||||
static inline void ble_ota_timer_delete(void)
|
||||
{
|
||||
if (NULL == sg_ota_timer) {
|
||||
ble_qiot_log_e("ble ota timer invalid, delete failed");
|
||||
return;
|
||||
}
|
||||
|
||||
sys_timer_del(sg_ota_timer);
|
||||
/* if (BLE_QIOT_RS_OK != ble_timer_delete(sg_ota_timer)) { */
|
||||
/* ble_qiot_log_e("ble ota timer delete failed"); */
|
||||
/* } */
|
||||
sg_ota_timer = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
static int ble_ota_write_end_callback(void *priv)
|
||||
{
|
||||
os_sem_post(&sg_ota_sem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ble_qiot_ret_status_t ble_ota_write_data_to_flash(void)
|
||||
{
|
||||
int ret = 0;
|
||||
int write_addr = 0;
|
||||
|
||||
// the download size include the data size, so the write address exclude the data size
|
||||
//os_time_dly(10);
|
||||
/* g_printf("%s\n", __func__); */
|
||||
dual_bank_update_write((const char *)sg_ota_data_buf, sg_ota_data_buf_size, ble_ota_write_end_callback);
|
||||
os_sem_pend(&sg_ota_sem, 0);
|
||||
|
||||
#if OTA_TWS_SAME_TIME_ENABLE
|
||||
if (pkt_flag != PKT_FLAG_FIRST) {
|
||||
if (sg_ota_tws_same_api && sg_ota_tws_same_api->tws_ota_data_send_pend) {
|
||||
if (sg_ota_tws_same_api->tws_ota_data_send_pend()) {
|
||||
printf("pend timeout\n");
|
||||
return BLE_QIOT_RS_ERR;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sg_ota_tws_same_api && sg_ota_tws_same_api->tws_ota_data_send) {
|
||||
sg_ota_tws_same_api->tws_ota_data_send(sg_ota_data_buf, sg_ota_data_buf_size);
|
||||
}
|
||||
|
||||
pkt_flag = PKT_FLAG_MIDDLE;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
write_addr = ble_ota_download_address_get() + ble_ota_download_size_get() - sg_ota_data_buf_size;
|
||||
ret = ble_ota_write_flash(write_addr, (const char *)sg_ota_data_buf, sg_ota_data_buf_size);
|
||||
if (ret != sg_ota_data_buf_size) {
|
||||
ble_qiot_log_e("ota data write flash failed");
|
||||
return BLE_QIOT_RS_ERR;
|
||||
}
|
||||
#endif
|
||||
return BLE_QIOT_RS_OK;
|
||||
}
|
||||
static void ble_ota_timer_callback(void *param)
|
||||
{
|
||||
if (BLE_QIOT_OTA_FLAG_IS_SET(BLE_QIOT_OTA_RECV_DATA_BIT)) {
|
||||
BLE_QIOT_OTA_FLAG_CLR(BLE_QIOT_OTA_RECV_DATA_BIT);
|
||||
return;
|
||||
}
|
||||
sg_ota_timeout_cnt++;
|
||||
|
||||
ble_qiot_log_w("reply in the timer, count: %d", sg_ota_timeout_cnt);
|
||||
ble_ota_reply_ota_data();
|
||||
|
||||
if (sg_ota_timeout_cnt >= BLE_QIOT_OTA_MAX_RETRY_COUNT) {
|
||||
sg_ota_flag = 0;
|
||||
ble_ota_timer_delete();
|
||||
// inform the user ota failed because timeout
|
||||
#if BLE_QIOT_SUPPORT_OTA
|
||||
ble_ota_stop();
|
||||
#endif //BLE_QIOT_SUPPORT_OTA
|
||||
ble_ota_user_stop_cb(BLE_QIOT_OTA_ERR_TIMEOUT);
|
||||
}
|
||||
}
|
||||
static inline void ble_ota_timer_start(void)
|
||||
{
|
||||
if (NULL == sg_ota_timer) {
|
||||
sg_ota_timer = sys_timer_add(NULL, ble_ota_timer_callback, BLE_QIOT_RETRY_TIMEOUT * 1000);
|
||||
/* sg_ota_timer = ble_timer_create(BLE_TIMER_PERIOD_TYPE, ble_ota_timer_callback); */
|
||||
/* if (NULL == sg_ota_timer) { */
|
||||
/* ble_qiot_log_e("ble ota timer create failed"); */
|
||||
/* return; */
|
||||
/* } */
|
||||
}
|
||||
/* if (BLE_QIOT_RS_OK != ble_timer_start(sg_ota_timer, BLE_QIOT_RETRY_TIMEOUT * 1000)) { */
|
||||
/* ble_qiot_log_e("ble ota timer start failed"); */
|
||||
/* } */
|
||||
return;
|
||||
}
|
||||
static ble_qiot_ret_status_t ble_ota_init(void)
|
||||
{
|
||||
uint32_t size_align = 0;
|
||||
uint8_t file_percent = 0;
|
||||
|
||||
// init the ota env
|
||||
memset(sg_ota_data_buf, 0, sizeof(sg_ota_data_buf));
|
||||
sg_ota_data_buf_size = 0;
|
||||
sg_ota_timeout_cnt = 0;
|
||||
memset(&sg_ota_info, 0, sizeof(ble_ota_info_record));
|
||||
sg_ota_download_file_size = 0;
|
||||
sg_ota_next_seq = 0;
|
||||
sg_ota_download_percent = 0;
|
||||
sg_ota_flag = 0;
|
||||
ble_ota_download_address_set();
|
||||
memset(&sg_ota_reply_info, 0, sizeof(sg_ota_reply_info));
|
||||
|
||||
#if BLE_QIOT_SUPPORT_RESUMING
|
||||
// start from 0 if read flash fail, but ota will continue so ignored the return code
|
||||
ble_read_flash(BLE_QIOT_OTA_INFO_FLASH_ADDR, (char *)&sg_ota_info, sizeof(sg_ota_info));
|
||||
ble_qiot_log_hex(BLE_QIOT_LOG_LEVEL_INFO, "ota info", &sg_ota_info, sizeof(sg_ota_info));
|
||||
// check if the valid flag legalled
|
||||
if (ble_qiot_ota_info_valid()) {
|
||||
// the ota info write to flash may be mismatch the file write to flash, we should download file from the byte
|
||||
// align the flash page
|
||||
if (ble_ota_download_address_get() == sg_ota_info.last_address) {
|
||||
size_align = sg_ota_info.last_file_size / BLE_QIOT_RECORD_FLASH_PAGESIZE * BLE_QIOT_RECORD_FLASH_PAGESIZE;
|
||||
ble_ota_download_size_inc(size_align);
|
||||
file_percent = size_align * 100 / sg_ota_info.download_file_info.file_size;
|
||||
ble_ota_file_percent_set(file_percent);
|
||||
ble_qiot_log_i("align file size: %x, the percent: %d", size_align, file_percent);
|
||||
} else {
|
||||
memset(&sg_ota_info, 0, sizeof(ble_ota_info_record));
|
||||
}
|
||||
} else {
|
||||
memset(&sg_ota_info, 0, sizeof(ble_ota_info_record));
|
||||
}
|
||||
#endif //BLE_QIOT_SUPPORT_RESUMING
|
||||
return BLE_QIOT_RS_OK;
|
||||
}
|
||||
// stop ota if ble disconnect
|
||||
void ble_ota_stop(void)
|
||||
{
|
||||
if (!BLE_QIOT_OTA_FLAG_IS_SET(BLE_QIOT_OTA_REQUEST_BIT)) {
|
||||
ble_qiot_log_w("ota not start");
|
||||
return;
|
||||
}
|
||||
sg_ota_flag = 0;
|
||||
set_ota_status(0);
|
||||
ble_ota_timer_delete();
|
||||
// write data to flash if the ota stop
|
||||
ble_ota_write_data_to_flash();
|
||||
ble_ota_write_info();
|
||||
dual_bank_passive_update_exit(NULL);
|
||||
#if OTA_TWS_SAME_TIME_ENABLE
|
||||
if (sg_ota_tws_same_api && sg_ota_tws_same_api->tws_ota_err) {
|
||||
sg_ota_tws_same_api->tws_ota_err(0);
|
||||
}
|
||||
#endif
|
||||
// inform user ota failed because ble disconnect
|
||||
ble_ota_user_stop_cb(BLE_QIOT_OTA_DISCONNECT);
|
||||
}
|
||||
|
||||
ble_qiot_ret_status_t ble_ota_request_handle(const char *in_buf, int buf_len)
|
||||
{
|
||||
BUFF_LEN_SANITY_CHECK(buf_len, sizeof(ble_ota_file_info) - BLE_QIOT_OTA_MAX_VERSION_STR, BLE_QIOT_RS_ERR_PARA);
|
||||
|
||||
uint8_t ret = 0;
|
||||
uint8_t reply_flag = 0;
|
||||
uint32_t file_size = 0;
|
||||
uint32_t file_crc = 0;
|
||||
uint8_t version_len = 0;
|
||||
char *p = (char *)in_buf;
|
||||
char *notify_data = NULL;
|
||||
uint16_t notify_len = 0;
|
||||
ble_ota_reply_info ota_reply_info;
|
||||
|
||||
ble_ota_init();
|
||||
|
||||
memcpy(&file_size, p, sizeof(file_size));
|
||||
p += sizeof(file_size);
|
||||
memcpy(&file_crc, p, sizeof(file_crc));
|
||||
p += sizeof(file_crc);
|
||||
version_len = *p++;
|
||||
file_size = NTOHL(file_size);
|
||||
file_crc = NTOHL(file_crc);
|
||||
ble_qiot_log_i("request ota, size: %x, crc: %x, version: %s", file_size, file_crc, p);
|
||||
|
||||
// check if the ota is allowed
|
||||
ret = ble_ota_is_enable((const char *)p, file_size, file_crc);
|
||||
if (ret == BLE_OTA_ENABLE) {
|
||||
#if OTA_TWS_SAME_TIME_ENABLE
|
||||
sg_ota_tws_same_api = get_tws_update_api();
|
||||
if (sg_ota_tws_same_api == NULL) {
|
||||
ret = 0;
|
||||
} else {
|
||||
if (sg_ota_tws_same_api && sg_ota_tws_same_api->tws_ota_start) {
|
||||
struct __tws_ota_para tws_update_para;
|
||||
tws_update_para.fm_size = file_size;
|
||||
tws_update_para.fm_crc = file_crc;
|
||||
tws_update_para.max_pkt_len = BLE_QIOT_OTA_BUF_SIZE;
|
||||
if (sg_ota_tws_same_api->tws_ota_start(&tws_update_para) != 0) { //tws same time err
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (BLE_OTA_ENABLE == ret) {
|
||||
reply_flag = BLE_QIOT_OTA_ENABLE;
|
||||
ota_reply_info.package_nums = BLE_QIOT_TOTAL_PACKAGES;
|
||||
ota_reply_info.package_size = BLE_QIOT_PACKAGE_LENGTH + BLE_QIOT_OTA_DATA_HEADER_LEN;
|
||||
ota_reply_info.retry_timeout = BLE_QIOT_RETRY_TIMEOUT;
|
||||
ota_reply_info.reboot_timeout = BLE_QIOT_REBOOT_TIME;
|
||||
ota_reply_info.last_file_size = 0;
|
||||
ota_reply_info.package_interval = BLE_QIOT_PACKAGE_INTERVAL;
|
||||
#if BLE_QIOT_SUPPORT_RESUMING
|
||||
reply_flag |= BLE_QIOT_OTA_RESUME_ENABLE;
|
||||
// check file crc to determine its the same file, download the new file if its different
|
||||
if (ble_qiot_ota_info_valid() && (file_crc == sg_ota_info.download_file_info.file_crc) &&
|
||||
(file_size == sg_ota_info.download_file_info.file_size)) {
|
||||
ota_reply_info.last_file_size = HTONL(ble_ota_download_size_get());
|
||||
}
|
||||
#endif //BLE_QIOT_SUPPORT_RESUMING
|
||||
|
||||
sg_ota_info.download_file_info.file_size = file_size;
|
||||
sg_ota_info.download_file_info.file_crc = file_crc;
|
||||
memcpy(sg_ota_info.download_file_info.file_version, p, version_len);
|
||||
|
||||
ble_ota_user_start_cb();
|
||||
ble_ota_timer_start();
|
||||
// handler the ota data after ota request
|
||||
BLE_QIOT_OTA_FLAG_SET(BLE_QIOT_OTA_REQUEST_BIT);
|
||||
notify_data = (char *)&ota_reply_info;
|
||||
notify_len = sizeof(ble_ota_reply_info) - sizeof(ota_reply_info.rsv);
|
||||
|
||||
os_sem_create(&sg_ota_sem, 0);
|
||||
} else {
|
||||
reply_flag &= ~BLE_QIOT_OTA_ENABLE;
|
||||
notify_data = (char *)&ret;
|
||||
notify_len = sizeof(uint8_t);
|
||||
}
|
||||
return ble_event_notify(BLE_QIOT_EVENT_UP_REPLY_OTA_REPORT, &reply_flag, sizeof(uint8_t), (const char *)notify_data,
|
||||
notify_len);
|
||||
}
|
||||
|
||||
/* static int ble_ota_verify_result_hdl(int calc_crc){ */
|
||||
/* os_sem_post(&sg_ota_sem); */
|
||||
/* return 0; */
|
||||
/* } */
|
||||
// call the function after the server inform or the device receive the last package
|
||||
static void ble_ota_reboot_timer(void *priv)
|
||||
{
|
||||
cpu_reset();
|
||||
}
|
||||
|
||||
static int ble_ota_write_boot_info_callback(int err)
|
||||
{
|
||||
#if OTA_TWS_SAME_TIME_ENABLE
|
||||
if (sg_ota_tws_same_api && sg_ota_tws_same_api->tws_ota_result_hdl) {
|
||||
sg_ota_tws_same_api->tws_ota_result_hdl(err);
|
||||
}
|
||||
#else
|
||||
if (err == 0) {
|
||||
sys_timeout_add(NULL, ble_ota_reboot_timer, 500);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
ble_qiot_ret_status_t ble_ota_file_end_handle(void)
|
||||
{
|
||||
int crc_buf_len = 0;
|
||||
uint32_t crc_file_len = 0;
|
||||
uint32_t crc = 0;
|
||||
int slave_boot_info_state = 0;
|
||||
// the function called only once in the same ota process
|
||||
sg_ota_flag = 0;
|
||||
ble_ota_timer_delete();
|
||||
|
||||
ble_qiot_log_i("calc crc start");
|
||||
|
||||
/* u32 dual_bank_update_read_data(u32 offset, u8 *read_buf, u32 read_len); */
|
||||
while (crc_file_len < sg_ota_info.download_file_info.file_size) {
|
||||
crc_buf_len = sizeof(sg_ota_data_buf) > (sg_ota_info.download_file_info.file_size - crc_file_len)
|
||||
? (sg_ota_info.download_file_info.file_size - crc_file_len)
|
||||
: sizeof(sg_ota_data_buf);
|
||||
memset(sg_ota_data_buf, 0, sizeof(sg_ota_data_buf));
|
||||
dual_bank_update_read_data(ble_ota_download_address_get() + crc_file_len, (char *)sg_ota_data_buf, crc_buf_len);
|
||||
crc_file_len += crc_buf_len;
|
||||
crc = ble_qiot_crc32(crc, (const uint8_t *)sg_ota_data_buf, crc_buf_len);
|
||||
// maybe need task delay
|
||||
}
|
||||
|
||||
ble_qiot_log_i("calc crc %x, file crc %x", crc, sg_ota_info.download_file_info.file_crc);
|
||||
|
||||
#if OTA_TWS_SAME_TIME_ENABLE
|
||||
if (sg_ota_tws_same_api && sg_ota_tws_same_api->enter_verfiy_hdl) {
|
||||
if (sg_ota_tws_same_api->enter_verfiy_hdl(NULL)) { //slave verify err
|
||||
crc = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (crc == sg_ota_info.download_file_info.file_crc) {
|
||||
#if OTA_TWS_SAME_TIME_ENABLE
|
||||
if (sg_ota_tws_same_api && sg_ota_tws_same_api->exit_verify_hdl) {
|
||||
u8 update_boot_info_flag, verify_err;
|
||||
if (sg_ota_tws_same_api->exit_verify_hdl(&verify_err, &update_boot_info_flag) == 0) { //slave write boot_info err
|
||||
slave_boot_info_state = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (BLE_QIOT_RS_OK == ble_ota_user_valid_cb() && !slave_boot_info_state) {
|
||||
dual_bank_update_burn_boot_info(ble_ota_write_boot_info_callback);
|
||||
int ret = ble_ota_report_check_result(BLE_QIOT_OTA_VALID_SUCCESS, 0);
|
||||
ble_ota_user_stop_cb(BLE_QIOT_OTA_SUCCESS);
|
||||
} else {
|
||||
ble_ota_report_check_result(BLE_QIOT_OTA_VALID_FAIL, BLE_QIOT_OTA_FILE_ERROR);
|
||||
ble_ota_user_stop_cb(BLE_QIOT_OTA_ERR_FILE);
|
||||
}
|
||||
} else {
|
||||
ble_ota_report_check_result(BLE_QIOT_OTA_VALID_FAIL, BLE_QIOT_OTA_CRC_ERROR);
|
||||
ble_ota_user_stop_cb(BLE_QIOT_OTA_ERR_CRC);
|
||||
}
|
||||
ble_ota_clear_info();
|
||||
return BLE_QIOT_RS_OK;
|
||||
}
|
||||
|
||||
static ble_qiot_ret_status_t ble_qiot_ota_data_saved(char *data, uint16_t data_len)
|
||||
{
|
||||
int ret = 0;
|
||||
uint8_t percent = 0;
|
||||
|
||||
// write data to flash if the buffer overflow
|
||||
if ((data_len + sg_ota_data_buf_size) > sizeof(sg_ota_data_buf)) {
|
||||
// ble_qiot_log_e("data buf overflow, write data");
|
||||
if (BLE_QIOT_RS_OK != ble_ota_write_data_to_flash()) {
|
||||
return BLE_QIOT_RS_ERR;
|
||||
}
|
||||
// update the ota info if support resuming
|
||||
percent = (ble_ota_download_size_get() + sg_ota_data_buf_size) * 100 / sg_ota_info.download_file_info.file_size;
|
||||
if (percent > ble_ota_file_percent_get()) {
|
||||
ble_ota_file_percent_set(percent);
|
||||
ret = ble_ota_write_info();
|
||||
if (ret != BLE_QIOT_RS_OK) {
|
||||
ble_qiot_log_e("update ota info failed");
|
||||
return BLE_QIOT_RS_ERR;
|
||||
}
|
||||
}
|
||||
memset(sg_ota_data_buf, 0, sizeof(sg_ota_data_buf));
|
||||
sg_ota_data_buf_size = 0;
|
||||
}
|
||||
|
||||
memcpy(sg_ota_data_buf + sg_ota_data_buf_size, data, data_len);
|
||||
sg_ota_data_buf_size += data_len;
|
||||
ble_ota_download_size_inc(data_len);
|
||||
|
||||
// if the last package, write to flash and reply the server
|
||||
if (ble_ota_download_size_get() == sg_ota_info.download_file_info.file_size) {
|
||||
ble_qiot_log_i("receive the last package");
|
||||
if (BLE_QIOT_RS_OK != ble_ota_write_data_to_flash()) {
|
||||
return BLE_QIOT_RS_ERR;
|
||||
}
|
||||
ble_ota_reply_ota_data();
|
||||
// set the file receive end bit
|
||||
BLE_QIOT_OTA_FLAG_SET(BLE_QIOT_OTA_RECV_END_BIT);
|
||||
memset(sg_ota_data_buf, 0, sizeof(sg_ota_data_buf));
|
||||
sg_ota_data_buf_size = 0;
|
||||
}
|
||||
|
||||
return BLE_QIOT_RS_OK;
|
||||
}
|
||||
|
||||
ble_qiot_ret_status_t ble_ota_data_handle(const char *in_buf, int buf_len)
|
||||
{
|
||||
POINTER_SANITY_CHECK(in_buf, BLE_QIOT_RS_ERR_PARA);
|
||||
|
||||
uint8_t seq = 0;
|
||||
char *data = NULL;
|
||||
uint16_t data_len = 0;
|
||||
|
||||
if (!BLE_QIOT_OTA_FLAG_IS_SET(BLE_QIOT_OTA_REQUEST_BIT)) {
|
||||
ble_qiot_log_w("ota request is need first");
|
||||
return BLE_QIOT_RS_ERR;
|
||||
}
|
||||
|
||||
seq = in_buf[0];
|
||||
data = (char *)in_buf + 1;
|
||||
data_len = (uint16_t)buf_len - 1;
|
||||
|
||||
// ble_qiot_log_hex(BLE_QIOT_LOG_LEVEL_ERR, "data", in_buf, buf_len);
|
||||
if (seq == ble_ota_next_seq_get()) {
|
||||
BLE_QIOT_OTA_FLAG_SET(BLE_QIOT_OTA_RECV_DATA_BIT);
|
||||
BLE_QIOT_OTA_FLAG_SET(BLE_QIOT_OTA_FIRST_RETRY_BIT);
|
||||
sg_ota_timeout_cnt = 0;
|
||||
ble_ota_next_seq_inc();
|
||||
|
||||
if (BLE_QIOT_RS_OK != ble_qiot_ota_data_saved(data, data_len)) {
|
||||
// stop ota and inform the server
|
||||
ble_qiot_log_e("stop ota because save data failed");
|
||||
return BLE_QIOT_RS_ERR;
|
||||
}
|
||||
if (BLE_QIOT_OTA_FLAG_IS_SET(BLE_QIOT_OTA_RECV_END_BIT)) {
|
||||
return BLE_QIOT_RS_OK;
|
||||
}
|
||||
// reply the server if received the last package in the loop
|
||||
if (BLE_QIOT_TOTAL_PACKAGES == ble_ota_next_seq_get()) {
|
||||
ble_qiot_log_e("reply loop");
|
||||
ble_ota_reply_ota_data();
|
||||
sg_ota_next_seq = 0;
|
||||
}
|
||||
BLE_QIOT_OTA_FLAG_SET(BLE_QIOT_OTA_RECV_DATA_BIT);
|
||||
} else {
|
||||
// request data only once in the loop, controlled by the flag
|
||||
ble_qiot_log_w("unexpect seq %d, expect seq %d", seq, ble_ota_next_seq_get());
|
||||
if (BLE_QIOT_OTA_FLAG_IS_SET(BLE_QIOT_OTA_FIRST_RETRY_BIT)) {
|
||||
BLE_QIOT_OTA_FLAG_CLR(BLE_QIOT_OTA_FIRST_RETRY_BIT);
|
||||
BLE_QIOT_OTA_FLAG_CLR(BLE_QIOT_OTA_RECV_DATA_BIT);
|
||||
ble_ota_reply_ota_data();
|
||||
// refresh the timer
|
||||
ble_ota_timer_start();
|
||||
}
|
||||
}
|
||||
return BLE_QIOT_RS_OK;
|
||||
}
|
||||
#endif //BLE_QIOT_SUPPORT_OTA
|
||||
|
||||
#endif //BLE_QIOT_LLSYNC_STANDARD
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,664 @@
|
||||
/*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <printf.h>
|
||||
|
||||
#include "ble_qiot_config.h"
|
||||
|
||||
#include "ble_qiot_export.h"
|
||||
#include "ble_qiot_import.h"
|
||||
#include "ble_qiot_llsync_data.h"
|
||||
#include "ble_qiot_llsync_device.h"
|
||||
#include "ble_qiot_llsync_event.h"
|
||||
#include "ble_qiot_log.h"
|
||||
#include "ble_qiot_llsync_ota.h"
|
||||
#include "ble_qiot_param_check.h"
|
||||
#include "ble_qiot_service.h"
|
||||
#include "ble_qiot_template.h"
|
||||
#include "ble_qiot_service.h"
|
||||
#include "ble_qiot_crc.h"
|
||||
#include "asm/clock.h"
|
||||
#include "app_config.h"
|
||||
#include "update_loader_download.h"
|
||||
#include "os/os_api.h"
|
||||
|
||||
#define BLE_QIOT_OTA_HZ (120 * 1000000L)
|
||||
|
||||
// llsync support data fragment, so we need to package all the data before parsing if the data is slice
|
||||
static ble_event_slice_t sg_ble_slice_data;
|
||||
|
||||
#if BLE_QIOT_BUTTON_BROADCAST
|
||||
static ble_timer_t sg_bind_timer = NULL;
|
||||
#endif //BLE_QIOT_BUTTON_BROADCAST
|
||||
|
||||
#if BLE_QIOT_SECURE_BIND
|
||||
static ble_bind_data sg_bind_auth_data;
|
||||
#endif //BLE_QIOT_SECURE_BIND
|
||||
|
||||
static qiot_service_init_s service_info = {
|
||||
.service_uuid16 = IOT_BLE_UUID_SERVICE,
|
||||
.service_uuid128 = IOT_BLE_UUID_BASE,
|
||||
.device_info =
|
||||
{
|
||||
.uuid16 = IOT_BLE_UUID_DEVICE_INFO,
|
||||
.gatt_char_props = GATT_CHAR_WRITE,
|
||||
.on_write = ble_device_info_write_cb,
|
||||
},
|
||||
.event =
|
||||
{
|
||||
.uuid16 = IOT_BLE_UUID_EVENT,
|
||||
.gatt_char_props = GATT_CHAR_NOTIFY,
|
||||
.on_write = NULL,
|
||||
},
|
||||
#if BLE_QIOT_LLSYNC_STANDARD
|
||||
.data =
|
||||
{
|
||||
.uuid16 = IOT_BLE_UUID_DATA,
|
||||
.gatt_char_props = GATT_CHAR_WRITE,
|
||||
.on_write = ble_lldata_write_cb,
|
||||
},
|
||||
.ota =
|
||||
{
|
||||
.uuid16 = IOT_BLE_UUID_OTA,
|
||||
.gatt_char_props = GATT_CHAR_WRITE_WO_RESP,
|
||||
.on_write = ble_ota_write_cb,
|
||||
},
|
||||
#endif //BLE_QIOT_LLSYNC_STANDARD
|
||||
};
|
||||
|
||||
const qiot_service_init_s *ble_get_qiot_services(void)
|
||||
{
|
||||
return &service_info;
|
||||
}
|
||||
|
||||
#if BLE_QIOT_LLSYNC_STANDARD
|
||||
|
||||
#if BLE_QIOT_SECURE_BIND
|
||||
static ble_qiot_ret_status_t ble_secure_bind_handle(const char *data, uint16_t len)
|
||||
{
|
||||
memset(&sg_bind_auth_data, 0, sizeof(ble_bind_data));
|
||||
memcpy(&sg_bind_auth_data, data, sizeof(ble_bind_data));
|
||||
ble_event_sync_wait_time();
|
||||
ble_secure_bind_user_cb();
|
||||
|
||||
return BLE_QIOT_RS_OK;
|
||||
}
|
||||
|
||||
ble_qiot_ret_status_t ble_secure_bind_user_confirm(ble_qiot_secure_bind_t choose)
|
||||
{
|
||||
char out_buf[80] = {0};
|
||||
int ret_len = 0;
|
||||
uint8_t flag = 0;
|
||||
|
||||
ble_qiot_log_i("user choose: %d", choose);
|
||||
ret_len = ble_bind_get_authcode(&sg_bind_auth_data, sizeof(ble_bind_data), out_buf, sizeof(out_buf));
|
||||
if (ret_len <= 0) {
|
||||
ble_qiot_log_e("get bind authcode failed");
|
||||
return BLE_QIOT_RS_ERR;
|
||||
}
|
||||
flag = choose << 5;
|
||||
return ble_event_notify2((uint8_t)BLE_QIOT_EVENT_UP_BIND_SIGN_RET, flag, NULL, 0, out_buf, ret_len);
|
||||
}
|
||||
#endif //BLE_QIOT_SECURE_BIND
|
||||
|
||||
void ble_lldata_write_cb(const uint8_t *buf, uint16_t len)
|
||||
{
|
||||
(void)ble_lldata_msg_handle((const char *)buf, len);
|
||||
}
|
||||
|
||||
void ble_ota_write_cb(const uint8_t *buf, uint16_t len)
|
||||
{
|
||||
(void)ble_ota_msg_handle((const char *)buf, len);
|
||||
}
|
||||
|
||||
#endif //BLE_QIOT_LLSYNC_STANDARD
|
||||
|
||||
#if BLE_QIOT_BUTTON_BROADCAST
|
||||
static void ble_bind_timer_callback(void *param)
|
||||
{
|
||||
ble_qiot_log_i("timer timeout");
|
||||
if (E_LLSYNC_BIND_WAIT == llsync_bind_state_get()) {
|
||||
ble_advertising_stop();
|
||||
llsync_bind_state_set(E_LLSYNC_BIND_IDLE);
|
||||
ble_qiot_log_i("stop advertising");
|
||||
}
|
||||
}
|
||||
#endif //BLE_QIOT_BUTTON_BROADCAST
|
||||
|
||||
ble_qiot_ret_status_t ble_qiot_advertising_start(void)
|
||||
{
|
||||
printf("ble_qiot_advertising_start\n");
|
||||
adv_info_s my_adv_info;
|
||||
uint16_t uuids[1];
|
||||
uint8_t adv_data[32] = {0};
|
||||
uint8_t adv_data_len = 0;
|
||||
|
||||
uuids[0] = IOT_BLE_UUID_SERVICE;
|
||||
my_adv_info.uuid_info.uuid_num = 1;
|
||||
my_adv_info.uuid_info.uuids = uuids;
|
||||
|
||||
if (E_LLSYNC_BIND_IDLE == llsync_bind_state_get()) {
|
||||
#if BLE_QIOT_BUTTON_BROADCAST
|
||||
if (NULL == sg_bind_timer) {
|
||||
sg_bind_timer = ble_timer_create(BLE_TIMER_ONE_SHOT_TYPE, ble_bind_timer_callback);
|
||||
if (NULL == sg_bind_timer) {
|
||||
ble_qiot_log_e("create bind timer failed");
|
||||
return BLE_QIOT_RS_ERR;
|
||||
}
|
||||
}
|
||||
#endif //BLE_QIOT_BUTTON_BROADCAST
|
||||
|
||||
ble_advertising_stop();
|
||||
|
||||
llsync_bind_state_set(E_LLSYNC_BIND_WAIT);
|
||||
adv_data_len = ble_get_my_broadcast_data((char *)adv_data, sizeof(adv_data));
|
||||
my_adv_info.manufacturer_info.company_identifier = TENCENT_COMPANY_IDENTIFIER;
|
||||
my_adv_info.manufacturer_info.adv_data = adv_data;
|
||||
my_adv_info.manufacturer_info.adv_data_len = adv_data_len;
|
||||
printf("adv_data:");
|
||||
put_buf(adv_data, adv_data_len);
|
||||
ble_advertising_start(&my_adv_info);
|
||||
ble_qiot_log_i("start wait advertising");
|
||||
|
||||
#if BLE_QIOT_BUTTON_BROADCAST
|
||||
ble_timer_start(sg_bind_timer, BLE_QIOT_BIND_TIMEOUT);
|
||||
#endif //BLE_QIOT_BUTTON_BROADCAST
|
||||
} else if (E_LLSYNC_BIND_WAIT == llsync_bind_state_get()) {
|
||||
ble_advertising_stop();
|
||||
adv_data_len = ble_get_my_broadcast_data((char *)adv_data, sizeof(adv_data));
|
||||
my_adv_info.manufacturer_info.company_identifier = TENCENT_COMPANY_IDENTIFIER;
|
||||
my_adv_info.manufacturer_info.adv_data = adv_data;
|
||||
my_adv_info.manufacturer_info.adv_data_len = adv_data_len;
|
||||
ble_advertising_start(&my_adv_info);
|
||||
ble_qiot_log_i("restart wait advertising");
|
||||
|
||||
#if BLE_QIOT_BUTTON_BROADCAST
|
||||
ble_timer_stop(sg_bind_timer);
|
||||
ble_timer_start(sg_bind_timer, BLE_QIOT_BIND_TIMEOUT);
|
||||
#endif //BLE_QIOT_BUTTON_BROADCAST
|
||||
} else if (E_LLSYNC_BIND_SUCC == llsync_bind_state_get()) {
|
||||
ble_advertising_stop();
|
||||
adv_data_len = ble_get_my_broadcast_data((char *)adv_data, sizeof(adv_data));
|
||||
my_adv_info.manufacturer_info.company_identifier = TENCENT_COMPANY_IDENTIFIER;
|
||||
my_adv_info.manufacturer_info.adv_data = adv_data;
|
||||
my_adv_info.manufacturer_info.adv_data_len = adv_data_len;
|
||||
ble_advertising_start(&my_adv_info);
|
||||
ble_qiot_log_i("start bind advertising");
|
||||
} else {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
return BLE_QIOT_RS_OK;
|
||||
}
|
||||
|
||||
ble_qiot_ret_status_t ble_qiot_advertising_stop(void)
|
||||
{
|
||||
return 0 == ble_advertising_stop() ? BLE_QIOT_RS_OK : BLE_QIOT_RS_ERR;
|
||||
}
|
||||
|
||||
ble_qiot_ret_status_t ble_qiot_explorer_init(void)
|
||||
{
|
||||
printf("ble_qiot_explorer_init\n");
|
||||
ble_qiot_ret_status_t ret_code = BLE_QIOT_RS_OK;
|
||||
const qiot_service_init_s *service_info = NULL;
|
||||
|
||||
ble_qiot_set_log_level(BLE_QIOT_LOG_LEVEL_INFO);
|
||||
|
||||
service_info = ble_get_qiot_services();
|
||||
//ble_services_add(service_info);
|
||||
|
||||
ret_code = ble_init_flash_data();
|
||||
if (ret_code != BLE_QIOT_RS_OK) {
|
||||
ble_qiot_log_e("flash init failed, ret code %d", ret_code);
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
void ll_sync_init()
|
||||
{
|
||||
ble_qiot_explorer_init();
|
||||
#if BLE_QIOT_SUPPORT_OTA && OTA_TWS_SAME_TIME_ENABLE
|
||||
tws_sync_update_crc_handler_register(ble_qiot_crc32_init, ble_qiot_crc32);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ble_device_info_write_cb(const uint8_t *buf, uint16_t len)
|
||||
{
|
||||
(void)ble_device_info_msg_handle((const char *)buf, len);
|
||||
}
|
||||
|
||||
// when gap get ble connect event, use this function
|
||||
void ble_gap_connect_cb(void)
|
||||
{
|
||||
ble_connection_state_set(E_BLE_CONNECTED);
|
||||
}
|
||||
|
||||
// when gap get ble disconnect event, use this function
|
||||
void ble_gap_disconnect_cb(void)
|
||||
{
|
||||
llsync_mtu_update(0);
|
||||
llsync_connection_state_set(E_LLSYNC_DISCONNECTED);
|
||||
ble_connection_state_set(E_BLE_DISCONNECTED);
|
||||
#if BLE_QIOT_SUPPORT_OTA
|
||||
ble_ota_stop();
|
||||
#endif //BLE_QIOT_SUPPORT_OTA
|
||||
}
|
||||
|
||||
static uint8_t ble_msg_type_header_len(uint8_t type)
|
||||
{
|
||||
if (type == BLE_QIOT_GET_STATUS_REPLY_DATA_TYPE) {
|
||||
return BLE_QIOT_GET_STATUS_REPLY_HEADER_LEN;
|
||||
} else {
|
||||
return BLE_QIOT_DATA_FIXED_HEADER_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
static int8_t ble_package_slice_data(uint8_t data_type, uint8_t flag, uint8_t header_len, const char *in_buf,
|
||||
int in_len)
|
||||
{
|
||||
if (!BLE_QIOT_IS_SLICE_HEADER(flag)) {
|
||||
if (!sg_ble_slice_data.have_data) {
|
||||
ble_qiot_log_e("slice no header");
|
||||
return -1;
|
||||
}
|
||||
if (data_type != sg_ble_slice_data.type) {
|
||||
ble_qiot_log_e("msg type: %d != %d", data_type, sg_ble_slice_data.type);
|
||||
return -1;
|
||||
}
|
||||
if (sg_ble_slice_data.buf_len + (in_len - header_len) > sizeof(sg_ble_slice_data.buf)) {
|
||||
ble_qiot_log_e("too long data: %d > %d", sg_ble_slice_data.buf_len + (in_len - header_len),
|
||||
sizeof(sg_ble_slice_data.buf));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (BLE_QIOT_IS_SLICE_HEADER(flag)) {
|
||||
if (sg_ble_slice_data.have_data) {
|
||||
ble_qiot_log_i("new data coming, clean the package buffer");
|
||||
memset(&sg_ble_slice_data, 0, sizeof(sg_ble_slice_data));
|
||||
}
|
||||
sg_ble_slice_data.have_data = true;
|
||||
sg_ble_slice_data.type = data_type;
|
||||
// reserved space for payload length field
|
||||
sg_ble_slice_data.buf_len += header_len;
|
||||
sg_ble_slice_data.buf[0] = in_buf[0];
|
||||
memcpy(sg_ble_slice_data.buf + sg_ble_slice_data.buf_len, in_buf + header_len, in_len - header_len);
|
||||
sg_ble_slice_data.buf_len += (in_len - header_len);
|
||||
|
||||
return 1;
|
||||
} else if (BLE_QIOT_IS_SLICE_BODY(flag)) {
|
||||
memcpy(sg_ble_slice_data.buf + sg_ble_slice_data.buf_len, in_buf + header_len, in_len - header_len);
|
||||
sg_ble_slice_data.buf_len += (in_len - header_len);
|
||||
return 1;
|
||||
} else {
|
||||
memcpy(sg_ble_slice_data.buf + sg_ble_slice_data.buf_len, in_buf + header_len, in_len - header_len);
|
||||
sg_ble_slice_data.buf_len += (in_len - header_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int ble_device_info_msg_handle(const char *in_buf, int in_len)
|
||||
{
|
||||
POINTER_SANITY_CHECK(in_buf, BLE_QIOT_RS_ERR_PARA);
|
||||
uint8_t ch;
|
||||
char out_buf[80] = {0};
|
||||
char *p_data = NULL;
|
||||
int p_data_len = 0;
|
||||
int ret_len = 0;
|
||||
uint16_t tmp_len = 0;
|
||||
uint8_t header_len = 0;
|
||||
int ret = BLE_QIOT_RS_OK;
|
||||
char *p_ssid = NULL;
|
||||
char *p_passwd = NULL;
|
||||
// This flag is use to avoid attacker jump "ble_conn_get_authcode()" step, then
|
||||
// send 'E_DEV_MSG_CONN_SUCC' msg, and device straightly set 'E_LLSYNC_CONNECTED' flag.
|
||||
// This behavior make signature check useless lead to risk.
|
||||
static bool conn_flag = false;
|
||||
|
||||
p_data = (char *)in_buf;
|
||||
p_data_len = in_len;
|
||||
|
||||
// E_DEV_MSG_SYNC_TIME, E_DEV_MSG_CONN_VALID, E_DEV_MSG_BIND_SUCC, E_DEV_MSG_UNBIND this 4 type
|
||||
// of message has more than one bytes data, it may cut to several slices, here need to merge them
|
||||
// together, other type message only has 1 byte data, not need merge.
|
||||
if ((in_len > 3) && BLE_QIOT_IS_SLICE_PACKAGE(in_buf[1])) {
|
||||
// ble_qiot_log_hex(BLE_QIOT_LOG_LEVEL_INFO, "slice", p_data, p_data_len);
|
||||
header_len = ble_msg_type_header_len(in_buf[0]);
|
||||
ret = ble_package_slice_data(in_buf[0], in_buf[1], header_len, in_buf, in_len);
|
||||
if (ret < 0) {
|
||||
return BLE_QIOT_RS_ERR;
|
||||
} else if (ret == 0) {
|
||||
tmp_len = HTONS(sg_ble_slice_data.buf_len - header_len);
|
||||
memcpy(&sg_ble_slice_data.buf[1], &tmp_len, sizeof(tmp_len));
|
||||
p_data = sg_ble_slice_data.buf;
|
||||
p_data_len = sg_ble_slice_data.buf_len;
|
||||
} else if (ret > 0) {
|
||||
return BLE_QIOT_RS_OK;
|
||||
}
|
||||
}
|
||||
// ble_qiot_log_hex(BLE_QIOT_LOG_LEVEL_INFO, "tlv", p_data, p_data_len);
|
||||
|
||||
ch = p_data[0];
|
||||
printf("msg ch = %d\n", ch);
|
||||
switch (ch) {
|
||||
#if BLE_QIOT_LLSYNC_STANDARD
|
||||
case E_DEV_MSG_SYNC_TIME:
|
||||
#if BLE_QIOT_SECURE_BIND
|
||||
ret = ble_secure_bind_handle(p_data + 3, p_data_len - 3);
|
||||
#else
|
||||
ret_len = ble_bind_get_authcode(p_data + 3, p_data_len - 3, out_buf, sizeof(out_buf));
|
||||
if (ret_len <= 0) {
|
||||
ble_qiot_log_e("get bind authcode failed");
|
||||
ret = BLE_QIOT_RS_ERR;
|
||||
break;
|
||||
}
|
||||
ret = ble_event_notify((uint8_t)BLE_QIOT_EVENT_UP_BIND_SIGN_RET, NULL, 0, out_buf, ret_len);
|
||||
#endif //BLE_QIOT_SECURE_BIND
|
||||
break;
|
||||
case E_DEV_MSG_CONN_VALID:
|
||||
ret_len = ble_conn_get_authcode(p_data + 3, p_data_len - 3, out_buf, sizeof(out_buf));
|
||||
if (ret_len <= 0) {
|
||||
ble_qiot_log_e("get connect authcode failed");
|
||||
ret = BLE_QIOT_RS_ERR;
|
||||
break;
|
||||
}
|
||||
ret = ble_event_notify((uint8_t)BLE_QIOT_EVENT_UP_CONN_SIGN_RET, NULL, 0, out_buf, ret_len);
|
||||
conn_flag = true;
|
||||
break;
|
||||
case E_DEV_MSG_BIND_SUCC:
|
||||
if (BLE_QIOT_RS_OK != ble_bind_write_result(p_data + 3, p_data_len - 3)) {
|
||||
ble_qiot_log_e("write bind result failed");
|
||||
ret = BLE_QIOT_RS_ERR;
|
||||
}
|
||||
break;
|
||||
case E_DEV_MSG_BIND_FAIL:
|
||||
ble_qiot_log_i("get msg bind fail");
|
||||
break;
|
||||
case E_DEV_MSG_UNBIND:
|
||||
ret_len = ble_unbind_get_authcode(p_data + 3, p_data_len - 3, out_buf, sizeof(out_buf));
|
||||
if (ret_len <= 0) {
|
||||
ble_qiot_log_e("get unbind authcode failed");
|
||||
ret = BLE_QIOT_RS_ERR;
|
||||
break;
|
||||
}
|
||||
ret = ble_event_notify((uint8_t)BLE_QIOT_EVENT_UP_UNBIND_SIGN_RET, NULL, 0, out_buf, ret_len);
|
||||
break;
|
||||
case E_DEV_MSG_CONN_SUCC:
|
||||
if (!conn_flag) {
|
||||
break;
|
||||
}
|
||||
conn_flag = false;
|
||||
ble_qiot_log_i("get msg connect success");
|
||||
llsync_connection_state_set(E_LLSYNC_CONNECTED);
|
||||
ret = ble_event_report_device_info();
|
||||
//llsync_device_state_sync();
|
||||
break;
|
||||
case E_DEV_MSG_CONN_FAIL:
|
||||
ble_qiot_log_i("get msg connect fail");
|
||||
break;
|
||||
case E_DEV_MSG_UNBIND_SUCC:
|
||||
ble_qiot_log_i("get msg unbind success");
|
||||
if (BLE_QIOT_RS_OK != ble_unbind_write_result()) {
|
||||
ble_qiot_log_e("write unbind result failed");
|
||||
ret = BLE_QIOT_RS_ERR;
|
||||
}
|
||||
break;
|
||||
case E_DEV_MSG_UNBIND_FAIL:
|
||||
ble_qiot_log_i("get msg unbind fail");
|
||||
break;
|
||||
case E_DEV_MSG_BIND_TIMEOUT:
|
||||
ble_qiot_log_i("get msg bind result: %d", p_data[1]);
|
||||
#if (1 == BLE_QIOT_SECURE_BIND)
|
||||
ble_secure_bind_user_notify(p_data[1]);
|
||||
#endif
|
||||
break;
|
||||
#endif //BLE_QIOT_LLSYNC_STANDARD
|
||||
#if BLE_QIOT_LLSYNC_CONFIG_NET
|
||||
case E_DEV_MSG_GET_DEV_INFO:
|
||||
llsync_connection_state_set(E_LLSYNC_CONNECTED);
|
||||
ret = ble_event_report_device_info();
|
||||
break;
|
||||
case E_DEV_MSG_SET_WIFI_MODE:
|
||||
ret = ble_combo_wifi_mode_set(p_data[1]);
|
||||
break;
|
||||
case E_DEV_MSG_SET_WIFI_INFO:
|
||||
// 1 byte ssid len + N bytes ssid + 1 byte pwd len + N bytes pwd
|
||||
p_ssid = &p_data[3];
|
||||
p_passwd = &p_ssid[p_ssid[0] + 1];
|
||||
ret = ble_combo_wifi_info_set((const char *)&p_ssid[1], p_ssid[0], (const char *)&p_passwd[1], p_passwd[0]);
|
||||
break;
|
||||
case E_DEV_MSG_SET_WIFI_CONNECT:
|
||||
ret = ble_combo_wifi_connect();
|
||||
break;
|
||||
case E_DEV_MSG_SET_WIFI_TOKEN:
|
||||
ret = ble_combo_wifi_token_set(p_data + 3, p_data_len - 3);
|
||||
break;
|
||||
case E_DEV_MSG_GET_DEV_LOG:
|
||||
ret = ble_combo_wifi_log_get();
|
||||
break;
|
||||
#endif
|
||||
case E_DEV_MSG_SET_MTU_RESULT:
|
||||
ble_inform_mtu_result(p_data + 1, p_data_len - 1);
|
||||
llsync_device_state_sync();
|
||||
break;
|
||||
default:
|
||||
ble_qiot_log_e("unknow type %d", ch);
|
||||
break;
|
||||
}
|
||||
memset(&sg_ble_slice_data, 0, sizeof(sg_ble_slice_data));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if BLE_QIOT_LLSYNC_STANDARD
|
||||
// lldata message from remote
|
||||
int ble_lldata_msg_handle(const char *in_buf, int in_len)
|
||||
{
|
||||
POINTER_SANITY_CHECK(in_buf, BLE_QIOT_RS_ERR_PARA);
|
||||
|
||||
uint8_t data_type = 0;
|
||||
uint8_t data_effect = 0;
|
||||
uint8_t id = 0;
|
||||
uint8_t slice_flag = 0;
|
||||
uint8_t header_len = 0;
|
||||
uint8_t slice_type = 0;
|
||||
uint16_t tmp_len = 0;
|
||||
char *p_data = NULL;
|
||||
int p_data_len = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (!llsync_is_connected()) {
|
||||
ble_qiot_log_e("operation negate, device not connected");
|
||||
return BLE_QIOT_RS_ERR;
|
||||
}
|
||||
|
||||
p_data = (char *)in_buf;
|
||||
p_data_len = in_len;
|
||||
|
||||
data_type = BLE_QIOT_PARSE_MSG_HEAD_TYPE(in_buf[0]);
|
||||
if (data_type >= BLE_QIOT_DATA_TYPE_BUTT) {
|
||||
ble_qiot_log_e("invalid data type: %d", data_type);
|
||||
return BLE_QIOT_RS_ERR;
|
||||
}
|
||||
data_effect = BLE_QIOT_PARSE_MSG_HEAD_EFFECT(in_buf[0]);
|
||||
if (data_effect >= BLE_QIOT_EFFECT_BUTT) {
|
||||
ble_qiot_log_e("invalid data eff: ect");
|
||||
return BLE_QIOT_RS_ERR;
|
||||
}
|
||||
id = BLE_QIOT_PARSE_MSG_HEAD_ID(in_buf[0]);
|
||||
ble_qiot_log_d("data type: %d, effect: %d, id: %d", data_type, data_effect, id);
|
||||
|
||||
// if data is action_reply, control or get_status_reply, the data maybe need package
|
||||
if ((data_type == BLE_QIOT_MSG_TYPE_ACTION) || (in_buf[0] == BLE_QIOT_CONTROL_DATA_TYPE) ||
|
||||
(in_buf[0] == BLE_QIOT_GET_STATUS_REPLY_DATA_TYPE)) {
|
||||
slice_flag = (in_buf[0] == BLE_QIOT_GET_STATUS_REPLY_DATA_TYPE) ? in_buf[2] : in_buf[1];
|
||||
slice_type = (in_buf[0] == BLE_QIOT_GET_STATUS_REPLY_DATA_TYPE) ? in_buf[0] : data_type;
|
||||
|
||||
// ble_qiot_log_hex(BLE_QIOT_LOG_LEVEL_INFO, "slice", p_data, p_data_len);
|
||||
if (BLE_QIOT_IS_SLICE_PACKAGE(slice_flag)) {
|
||||
header_len = ble_msg_type_header_len(slice_type);
|
||||
ret = ble_package_slice_data(slice_type, slice_flag, header_len, in_buf, in_len);
|
||||
if (ret < 0) {
|
||||
return BLE_QIOT_RS_ERR;
|
||||
} else if (ret == 0) {
|
||||
tmp_len = HTONS(sg_ble_slice_data.buf_len - header_len);
|
||||
if (BLE_QIOT_GET_STATUS_REPLY_DATA_TYPE == slice_type) {
|
||||
sg_ble_slice_data.buf[1] = in_buf[1];
|
||||
memcpy(&sg_ble_slice_data.buf[2], &tmp_len, sizeof(tmp_len));
|
||||
} else {
|
||||
memcpy(&sg_ble_slice_data.buf[1], &tmp_len, sizeof(tmp_len));
|
||||
}
|
||||
p_data = sg_ble_slice_data.buf;
|
||||
p_data_len = sg_ble_slice_data.buf_len;
|
||||
} else if (ret > 0) {
|
||||
return BLE_QIOT_RS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ble_qiot_log_hex(BLE_QIOT_LOG_LEVEL_INFO, "tlv", p_data, p_data_len);
|
||||
|
||||
switch (data_type) {
|
||||
case BLE_QIOT_MSG_TYPE_PROPERTY:
|
||||
if (BLE_QIOT_EFFECT_REQUEST == data_effect) {
|
||||
// default E_BLE_DATA_DOWN_TYPE_CONTROL
|
||||
ret = ble_lldata_property_request_handle(p_data + 3, p_data_len - 3);
|
||||
} else if (BLE_QIOT_EFFECT_REPLY == data_effect) {
|
||||
// id means BLE_QIOT_DATA_DOWN_GET_STATUS_REPLY or BLE_QIOT_DATA_DOWN_REPORT_REPLY
|
||||
ret = ble_lldata_property_reply_handle(id, p_data + 1, p_data_len - 1);
|
||||
} else {
|
||||
ret = BLE_QIOT_RS_ERR;
|
||||
}
|
||||
break;
|
||||
case BLE_QIOT_MSG_TYPE_EVENT:
|
||||
if (BLE_QIOT_EFFECT_REPLY == data_effect) {
|
||||
ret = ble_lldata_event_handle(id, p_data + 1, p_data_len - 1);
|
||||
} else {
|
||||
ble_qiot_log_e("invalid event data effect");
|
||||
ret = BLE_QIOT_RS_ERR;
|
||||
}
|
||||
break;
|
||||
case BLE_QIOT_MSG_TYPE_ACTION:
|
||||
if (BLE_QIOT_EFFECT_REQUEST == data_effect) {
|
||||
ret = ble_lldata_action_handle(id, p_data + 3, p_data_len - 3);
|
||||
} else {
|
||||
ble_qiot_log_e("invalid action data effect");
|
||||
ret = BLE_QIOT_RS_ERR;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
memset(&sg_ble_slice_data, 0, sizeof(sg_ble_slice_data));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if BLE_QIOT_SUPPORT_OTA
|
||||
static uint8_t ble_ota_type_header_len(uint8_t type)
|
||||
{
|
||||
return BLE_QIOT_GET_OTA_REQUEST_HEADER_LEN;
|
||||
}
|
||||
|
||||
int ble_ota_msg_handle(const char *buf, uint16_t len)
|
||||
{
|
||||
POINTER_SANITY_CHECK(buf, BLE_QIOT_RS_ERR_PARA);
|
||||
|
||||
uint8_t data_type = 0;
|
||||
int ret = BLE_QIOT_RS_OK;
|
||||
uint8_t header_len = 0;
|
||||
uint8_t slice_flag = 0;
|
||||
char *p_data = NULL;
|
||||
int p_data_len = 0;
|
||||
uint16_t tmp_len = 0;
|
||||
|
||||
if (!llsync_is_connected()) {
|
||||
ble_qiot_log_e("upgrade forbidden, device not connected");
|
||||
return BLE_QIOT_RS_ERR;
|
||||
}
|
||||
|
||||
data_type = (buf[0] == BLE_QIOT_OTA_MSG_REQUEST) ? BLE_QIOT_OTA_MSG_REQUEST : buf[0];
|
||||
slice_flag = (buf[0] == BLE_QIOT_OTA_MSG_REQUEST) ? buf[1] : buf[0];
|
||||
if (data_type >= BLE_QIOT_OTA_MSG_BUTT) {
|
||||
ble_qiot_log_e("invalid data type %d", data_type);
|
||||
return BLE_QIOT_RS_ERR;
|
||||
}
|
||||
p_data = (char *)buf;
|
||||
p_data_len = len;
|
||||
|
||||
// ble_qiot_log_i("ota data type %d, flag %d", data_type, slice_flag);
|
||||
if (BLE_QIOT_IS_SLICE_PACKAGE(slice_flag)) {
|
||||
ble_qiot_log_hex(BLE_QIOT_LOG_LEVEL_INFO, "tlv", p_data, p_data_len);
|
||||
header_len = ble_ota_type_header_len(data_type);
|
||||
ret = ble_package_slice_data(data_type, slice_flag, header_len, buf, len);
|
||||
if (ret < 0) {
|
||||
return BLE_QIOT_RS_ERR;
|
||||
} else if (ret == 0) {
|
||||
if (data_type == BLE_QIOT_OTA_MSG_REQUEST) {
|
||||
tmp_len = HTONS(sg_ble_slice_data.buf_len - header_len);
|
||||
memcpy(&sg_ble_slice_data.buf[1], &tmp_len, sizeof(tmp_len));
|
||||
} else {
|
||||
sg_ble_slice_data.buf[1] = sg_ble_slice_data.buf_len - header_len;
|
||||
}
|
||||
if (data_type == BLE_QIOT_OTA_MSG_DATA) {
|
||||
sg_ble_slice_data.buf[2] = buf[2];
|
||||
}
|
||||
p_data = sg_ble_slice_data.buf;
|
||||
p_data_len = sg_ble_slice_data.buf_len;
|
||||
} else if (ret > 0) {
|
||||
return BLE_QIOT_RS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// ble_qiot_log_hex(BLE_QIOT_LOG_LEVEL_INFO, "tlv", p_data, p_data_len);
|
||||
switch (data_type) {
|
||||
case BLE_QIOT_OTA_MSG_REQUEST:
|
||||
clk_set("sys", BLE_QIOT_OTA_HZ);
|
||||
|
||||
#if (!defined CONFIG_TRANSFER_ENABLE)
|
||||
update_start_exit_sniff();
|
||||
#endif
|
||||
set_ota_status(1);
|
||||
ret = ble_ota_request_handle(p_data + 3, p_data_len);
|
||||
break;
|
||||
case BLE_QIOT_OTA_MSG_DATA:
|
||||
ret = ble_ota_data_handle(p_data + 2, p_data_len - 2);
|
||||
break;
|
||||
case BLE_QIOT_OTA_MSG_END:
|
||||
clk_set("sys", BT_NORMAL_HZ);
|
||||
set_ota_status(0);
|
||||
ret = ble_ota_file_end_handle();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
memset(&sg_ble_slice_data, 0, sizeof(sg_ble_slice_data));
|
||||
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
int ble_ota_msg_handle(const char *buf, uint16_t len)
|
||||
{
|
||||
return BLE_QIOT_RS_OK;
|
||||
}
|
||||
#endif //BLE_QIOT_SUPPORT_OTA
|
||||
|
||||
#endif //BLE_QIOT_LLSYNC_STANDARD
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,264 @@
|
||||
/*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ble_qiot_template.h"
|
||||
|
||||
#include <printf.h>
|
||||
//#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ble_qiot_export.h"
|
||||
#include "ble_qiot_common.h"
|
||||
#include "ble_qiot_param_check.h"
|
||||
#include "ble_qiot_llsync_event.h"
|
||||
#include "ble_qiot_service.h"
|
||||
#include "ble_qiot_llsync_device.h"
|
||||
#include "gpio.h"
|
||||
|
||||
static uint8_t LL_led = 0;
|
||||
#define LLSYNC_SWITCH_PIN IO_PORTA_01
|
||||
static int ble_property_power_switch_set(const char *data, uint16_t len)
|
||||
{
|
||||
printf("ble_property_power_switch_set led to %d\n", data[0]);
|
||||
LL_led = data[0];
|
||||
gpio_write(LLSYNC_SWITCH_PIN, LL_led);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ble_property_power_switch_get(char *data, uint16_t buf_len)
|
||||
{
|
||||
printf("ble_property_power_switch_get, led state is %d\n", LL_led);
|
||||
data[0] = LL_led;
|
||||
return sizeof(uint8_t);
|
||||
}
|
||||
|
||||
static ble_property_t sg_ble_property_array[BLE_QIOT_PROPERTY_ID_BUTT] = {
|
||||
{ble_property_power_switch_set, ble_property_power_switch_get, BLE_QIOT_PROPERTY_AUTH_RW, BLE_QIOT_DATA_TYPE_BOOL},
|
||||
};
|
||||
|
||||
ble_qiot_ret_status_t ble_event_report_device_switch_state(u8 led_state)
|
||||
{
|
||||
char device_info[2] = {0};
|
||||
|
||||
device_info[0] = BLE_QIOT_PROPERTY_ID_POWER_SWITCH;
|
||||
device_info[1] = led_state;
|
||||
|
||||
return ble_event_notify(BLE_QIOT_EVENT_UP_PROPERTY_REPORT, NULL, 0, device_info, sizeof(device_info));
|
||||
}
|
||||
|
||||
void ll_sync_led_switch(void)
|
||||
{
|
||||
LL_led = !LL_led;
|
||||
|
||||
printf("ll_sync set led to %d\n", LL_led);
|
||||
gpio_write(LLSYNC_SWITCH_PIN, LL_led);
|
||||
ble_event_report_device_switch_state(LL_led);
|
||||
}
|
||||
|
||||
void ll_sync_unbind(void)
|
||||
{
|
||||
printf("ll_sync factory data reset\n");
|
||||
ble_unbind_write_result();
|
||||
}
|
||||
|
||||
void llsync_device_state_sync(void)
|
||||
{
|
||||
printf("llsync_device_state_sync, led = %d\n", LL_led);
|
||||
ble_event_report_device_switch_state(LL_led);
|
||||
}
|
||||
|
||||
static bool ble_check_space_enough_by_type(uint8_t type, uint16_t left_size)
|
||||
{
|
||||
switch (type) {
|
||||
case BLE_QIOT_DATA_TYPE_BOOL:
|
||||
return left_size >= sizeof(uint8_t);
|
||||
case BLE_QIOT_DATA_TYPE_INT:
|
||||
case BLE_QIOT_DATA_TYPE_FLOAT:
|
||||
case BLE_QIOT_DATA_TYPE_TIME:
|
||||
return left_size >= sizeof(uint32_t);
|
||||
case BLE_QIOT_DATA_TYPE_ENUM:
|
||||
return left_size >= sizeof(uint16_t);
|
||||
default:
|
||||
// string length is unknow, default true
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t ble_check_ret_value_by_type(uint8_t type, uint16_t buf_len, uint16_t ret_val)
|
||||
{
|
||||
switch (type) {
|
||||
case BLE_QIOT_DATA_TYPE_BOOL:
|
||||
return ret_val <= sizeof(uint8_t);
|
||||
case BLE_QIOT_DATA_TYPE_INT:
|
||||
case BLE_QIOT_DATA_TYPE_FLOAT:
|
||||
case BLE_QIOT_DATA_TYPE_TIME:
|
||||
return ret_val <= sizeof(uint32_t);
|
||||
case BLE_QIOT_DATA_TYPE_ENUM:
|
||||
return ret_val <= sizeof(uint16_t);
|
||||
default:
|
||||
// string length is unknow, default true
|
||||
return ret_val <= buf_len;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t ble_get_property_type_by_id(uint8_t id)
|
||||
{
|
||||
if (id >= BLE_QIOT_PROPERTY_ID_BUTT) {
|
||||
ble_qiot_log_e("invalid property id %d", id);
|
||||
return BLE_QIOT_DATA_TYPE_BUTT;
|
||||
}
|
||||
return sg_ble_property_array[id].type;
|
||||
}
|
||||
|
||||
int ble_user_property_set_data(const e_ble_tlv *tlv)
|
||||
{
|
||||
POINTER_SANITY_CHECK(tlv, BLE_QIOT_RS_ERR_PARA);
|
||||
if (tlv->id >= BLE_QIOT_PROPERTY_ID_BUTT) {
|
||||
ble_qiot_log_e("invalid property id %d", tlv->id);
|
||||
return BLE_QIOT_RS_ERR;
|
||||
}
|
||||
|
||||
if (NULL != sg_ble_property_array[tlv->id].set_cb) {
|
||||
if (0 != sg_ble_property_array[tlv->id].set_cb(tlv->val, tlv->len)) {
|
||||
ble_qiot_log_e("set property id %d failed", tlv->id);
|
||||
return BLE_QIOT_RS_ERR;
|
||||
} else {
|
||||
return BLE_QIOT_RS_OK;
|
||||
}
|
||||
}
|
||||
ble_qiot_log_e("invalid set callback, id %d", tlv->id);
|
||||
|
||||
return BLE_QIOT_RS_ERR;
|
||||
}
|
||||
|
||||
int ble_user_property_get_data_by_id(uint8_t id, char *buf, uint16_t buf_len)
|
||||
{
|
||||
int ret_len = 0;
|
||||
|
||||
POINTER_SANITY_CHECK(buf, BLE_QIOT_RS_ERR_PARA);
|
||||
if (id >= BLE_QIOT_PROPERTY_ID_BUTT) {
|
||||
ble_qiot_log_e("invalid property id %d", id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (NULL != sg_ble_property_array[id].get_cb) {
|
||||
if (!ble_check_space_enough_by_type(sg_ble_property_array[id].type, buf_len)) {
|
||||
ble_qiot_log_e("not enough space get property id %d data", id);
|
||||
return -1;
|
||||
}
|
||||
ret_len = sg_ble_property_array[id].get_cb(buf, buf_len);
|
||||
if (ret_len < 0) {
|
||||
ble_qiot_log_e("get property id %d data failed", id);
|
||||
return -1;
|
||||
} else {
|
||||
if (ble_check_ret_value_by_type(sg_ble_property_array[id].type, buf_len, ret_len)) {
|
||||
return ret_len;
|
||||
} else {
|
||||
ble_qiot_log_e("property id %d length invalid", id);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
ble_qiot_log_e("invalid callback, property id %d", id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ble_user_property_report_reply_handle(uint8_t result)
|
||||
{
|
||||
ble_qiot_log_d("report reply result %d", result);
|
||||
|
||||
return BLE_QIOT_RS_OK;
|
||||
}
|
||||
|
||||
int ble_user_property_struct_handle(const char *in_buf, uint16_t buf_len, ble_property_t struct_arr[], uint8_t arr_size)
|
||||
{
|
||||
uint16_t parse_len = 0;
|
||||
uint16_t ret_len = 0;
|
||||
e_ble_tlv tlv;
|
||||
|
||||
while (parse_len < buf_len) {
|
||||
memset(&tlv, 0, sizeof(e_ble_tlv));
|
||||
ret_len = ble_lldata_parse_tlv(in_buf + parse_len, buf_len - parse_len, &tlv);
|
||||
parse_len += ret_len;
|
||||
if (parse_len > buf_len) {
|
||||
ble_qiot_log_e("parse struct failed");
|
||||
return parse_len;
|
||||
}
|
||||
|
||||
if (tlv.id >= arr_size) {
|
||||
ble_qiot_log_e("invalid array index %d", tlv.id);
|
||||
return parse_len;
|
||||
}
|
||||
if (NULL == struct_arr[tlv.id].set_cb) {
|
||||
ble_qiot_log_e("invalid member id %d", tlv.id);
|
||||
return parse_len;
|
||||
}
|
||||
if (BLE_QIOT_RS_OK != struct_arr[tlv.id].set_cb(tlv.val, tlv.len)) {
|
||||
ble_qiot_log_e("user handle property error, member id %d, type %d, len %d", tlv.id, tlv.type, tlv.len);
|
||||
return parse_len;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ble_user_property_struct_get_data(char *in_buf, uint16_t buf_len, ble_property_t struct_arr[], uint8_t arr_size)
|
||||
{
|
||||
uint8_t property_id = 0;
|
||||
uint8_t property_type = 0;
|
||||
int property_len = 0;
|
||||
char *data_buf = in_buf;
|
||||
uint16_t data_len = 0;
|
||||
uint16_t string_len = 0;
|
||||
|
||||
for (property_id = 0; property_id < arr_size; property_id++) {
|
||||
property_type = struct_arr[property_id].type;
|
||||
if (property_type >= BLE_QIOT_DATA_TYPE_BUTT) {
|
||||
ble_qiot_log_e("member id %d type %d invalid", property_id, property_type);
|
||||
return BLE_QIOT_RS_ERR;
|
||||
}
|
||||
data_buf[data_len++] = BLE_QIOT_PACKAGE_TLV_HEAD(property_type, property_id);
|
||||
if (BLE_QIOT_DATA_TYPE_STRING == property_type) {
|
||||
// reserved 2 bytes for string length
|
||||
property_len = struct_arr[property_id].get_cb((char *)data_buf + data_len + 2, buf_len - data_len - 2);
|
||||
} else {
|
||||
property_len = struct_arr[property_id].get_cb((char *)data_buf + data_len, buf_len - data_len);
|
||||
}
|
||||
if (property_len < 0) {
|
||||
ble_qiot_log_e("too long data, member id %d, data length %d", property_id, data_len);
|
||||
return BLE_QIOT_RS_ERR;
|
||||
} else if (property_len == 0) {
|
||||
// no data to post
|
||||
data_len--;
|
||||
data_buf[data_len] = '0';
|
||||
ble_qiot_log_d("member id %d no data to post", property_id);
|
||||
} else {
|
||||
if (BLE_QIOT_DATA_TYPE_STRING == property_type) {
|
||||
string_len = HTONS(property_len);
|
||||
memcpy(data_buf + data_len, &string_len, sizeof(uint16_t));
|
||||
data_len += sizeof(uint16_t);
|
||||
}
|
||||
data_len += property_len;
|
||||
}
|
||||
}
|
||||
|
||||
return data_len;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making IoT Hub available.
|
||||
* Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ble_qiot_utils_base64.h"
|
||||
#include "ble_qiot_export.h"
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static const unsigned char base64_enc_map[64] = {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
|
||||
'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
|
||||
's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
|
||||
};
|
||||
|
||||
static const unsigned char base64_dec_map[128] = {
|
||||
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
|
||||
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 62,
|
||||
127, 127, 127, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 127, 127, 127, 64, 127, 127, 127, 0,
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
|
||||
23, 24, 25, 127, 127, 127, 127, 127, 127, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
|
||||
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 127, 127, 127, 127, 127
|
||||
};
|
||||
|
||||
#define BASE64_SIZE_T_MAX ((size_t)-1) /* SIZE_T_MAX is not standard */
|
||||
|
||||
ble_qiot_ret_status_t qcloud_iot_utils_base64encode(unsigned char *dst, size_t dlen, size_t *olen,
|
||||
const unsigned char *src, size_t slen)
|
||||
{
|
||||
size_t i, n;
|
||||
unsigned char *p;
|
||||
|
||||
if (slen == 0) {
|
||||
*olen = 0;
|
||||
return (BLE_QIOT_RS_OK);
|
||||
}
|
||||
|
||||
n = slen / 3 + (slen % 3 != 0);
|
||||
|
||||
if (n > (BASE64_SIZE_T_MAX - 1) / 4) {
|
||||
*olen = BASE64_SIZE_T_MAX;
|
||||
return (BLE_QIOT_RS_ERR);
|
||||
}
|
||||
|
||||
n *= 4;
|
||||
|
||||
if ((dlen < n + 1) || (NULL == dst)) {
|
||||
*olen = n + 1;
|
||||
return (BLE_QIOT_RS_ERR);
|
||||
}
|
||||
|
||||
n = (slen / 3) * 3;
|
||||
|
||||
int C1, C2, C3;
|
||||
for (i = 0, p = dst; i < n; i += 3) {
|
||||
C1 = *src++;
|
||||
C2 = *src++;
|
||||
C3 = *src++;
|
||||
|
||||
*p++ = base64_enc_map[(C1 >> 2) & 0x3F];
|
||||
*p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
|
||||
*p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
|
||||
*p++ = base64_enc_map[C3 & 0x3F];
|
||||
}
|
||||
|
||||
if (i < slen) {
|
||||
C1 = *src++;
|
||||
C2 = ((i + 1) < slen) ? *src++ : 0;
|
||||
|
||||
*p++ = base64_enc_map[(C1 >> 2) & 0x3F];
|
||||
*p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
|
||||
|
||||
if ((i + 1) < slen) {
|
||||
*p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
|
||||
} else {
|
||||
*p++ = '=';
|
||||
}
|
||||
|
||||
*p++ = '=';
|
||||
}
|
||||
|
||||
*olen = p - dst;
|
||||
*p = 0;
|
||||
|
||||
return (BLE_QIOT_RS_OK);
|
||||
}
|
||||
|
||||
ble_qiot_ret_status_t qcloud_iot_utils_base64decode(unsigned char *dst, size_t dlen, size_t *olen,
|
||||
const unsigned char *src, size_t slen)
|
||||
{
|
||||
size_t i, n;
|
||||
uint32_t j, x;
|
||||
unsigned char *p;
|
||||
|
||||
/* First pass: check for validity and get output length */
|
||||
for (i = n = j = 0; i < slen; i++) {
|
||||
/* Skip spaces before checking for EOL */
|
||||
x = 0;
|
||||
while (i < slen && src[i] == ' ') {
|
||||
++i;
|
||||
++x;
|
||||
}
|
||||
|
||||
/* Spaces at end of buffer are OK */
|
||||
if (i == slen) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ((slen - i) >= 2 && src[i] == '\r' && src[i + 1] == '\n') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (src[i] == '\n') {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Space inside a line is an error */
|
||||
if (x != 0) {
|
||||
return (BLE_QIOT_RS_ERR);
|
||||
}
|
||||
|
||||
if (src[i] == '=' && ++j > 2) {
|
||||
return (BLE_QIOT_RS_ERR);
|
||||
}
|
||||
|
||||
if (src[i] > 127 || base64_dec_map[src[i]] == 127) {
|
||||
return (BLE_QIOT_RS_ERR);
|
||||
}
|
||||
|
||||
if (base64_dec_map[src[i]] < 64 && j != 0) {
|
||||
return (BLE_QIOT_RS_ERR);
|
||||
}
|
||||
|
||||
n++;
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
*olen = 0;
|
||||
return (BLE_QIOT_RS_OK);
|
||||
}
|
||||
|
||||
n = ((n * 6) + 7) >> 3;
|
||||
n -= j;
|
||||
|
||||
if (dst == NULL || dlen < n) {
|
||||
*olen = n;
|
||||
return (BLE_QIOT_RS_ERR);
|
||||
}
|
||||
|
||||
for (j = 3, n = x = 0, p = dst; i > 0; i--, src++) {
|
||||
if (*src == '\r' || *src == '\n' || *src == ' ') {
|
||||
continue;
|
||||
}
|
||||
|
||||
j -= (base64_dec_map[*src] == 64);
|
||||
x = (x << 6) | (base64_dec_map[*src] & 0x3F);
|
||||
|
||||
if (++n == 4) {
|
||||
n = 0;
|
||||
if (j > 0) {
|
||||
*p++ = (unsigned char)(x >> 16);
|
||||
}
|
||||
if (j > 1) {
|
||||
*p++ = (unsigned char)(x >> 8);
|
||||
}
|
||||
if (j > 2) {
|
||||
*p++ = (unsigned char)(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*olen = p - dst;
|
||||
|
||||
return (BLE_QIOT_RS_OK);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making IoT Hub available.
|
||||
* Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ble_qiot_crc.h"
|
||||
|
||||
#include <printf.h>
|
||||
|
||||
const uint32_t crc32_tab[] = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832,
|
||||
0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
||||
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a,
|
||||
0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
|
||||
0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
||||
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab,
|
||||
0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4,
|
||||
0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074,
|
||||
0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525,
|
||||
0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
|
||||
0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76,
|
||||
0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
||||
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6,
|
||||
0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7,
|
||||
0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
||||
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7,
|
||||
0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
|
||||
0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
||||
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330,
|
||||
0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||
};
|
||||
void ble_qiot_crc32_init(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
uint32_t ble_qiot_crc32(uint32_t crc, const uint8_t *buf, int len)
|
||||
{
|
||||
const uint8_t *p;
|
||||
|
||||
p = buf;
|
||||
crc = crc ^ ~0U;
|
||||
|
||||
while (len--) {
|
||||
crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
|
||||
}
|
||||
|
||||
return crc ^ ~0U;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ble_qiot_log.h"
|
||||
#include "ble_qiot_sha1.h"
|
||||
#include "ble_qiot_hmac.h"
|
||||
|
||||
#define KEY_IOPAD_SIZE 64
|
||||
|
||||
int8_t utils_hb2hex(uint8_t hb)
|
||||
{
|
||||
hb = hb & 0xF;
|
||||
return (int8_t)(hb < 10 ? '0' + hb : hb - 10 + 'a');
|
||||
}
|
||||
|
||||
void utils_hmac_sha1(const char *msg, int msg_len, char *digest, const char *key, int key_len)
|
||||
{
|
||||
if ((NULL == msg) || (NULL == digest) || (NULL == key)) {
|
||||
ble_qiot_log_e("parameter is Null,failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (key_len > KEY_IOPAD_SIZE) {
|
||||
ble_qiot_log_e("key_len > size(%d) of array", KEY_IOPAD_SIZE);
|
||||
return;
|
||||
}
|
||||
|
||||
iot_sha1_context context;
|
||||
unsigned char k_ipad[KEY_IOPAD_SIZE]; /* inner padding - key XORd with ipad */
|
||||
unsigned char k_opad[KEY_IOPAD_SIZE]; /* outer padding - key XORd with opad */
|
||||
unsigned char out[SHA1_DIGEST_SIZE];
|
||||
int i;
|
||||
|
||||
/* start out by storing key in pads */
|
||||
memset(k_ipad, 0, sizeof(k_ipad));
|
||||
memset(k_opad, 0, sizeof(k_opad));
|
||||
memcpy(k_ipad, key, key_len);
|
||||
memcpy(k_opad, key, key_len);
|
||||
|
||||
/* XOR key with ipad and opad values */
|
||||
for (i = 0; i < KEY_IOPAD_SIZE; i++) {
|
||||
k_ipad[i] ^= 0x36;
|
||||
k_opad[i] ^= 0x5c;
|
||||
}
|
||||
|
||||
/* perform inner SHA */
|
||||
utils_sha1_init(&context); /* init context for 1st pass */
|
||||
utils_sha1_starts(&context); /* setup context for 1st pass */
|
||||
utils_sha1_update(&context, k_ipad, KEY_IOPAD_SIZE); /* start with inner pad */
|
||||
utils_sha1_update(&context, (unsigned char *)msg, msg_len); /* then text of datagram */
|
||||
utils_sha1_finish(&context, out); /* finish up 1st pass */
|
||||
|
||||
/* perform outer SHA */
|
||||
utils_sha1_init(&context); /* init context for 2nd pass */
|
||||
utils_sha1_starts(&context); /* setup context for 2nd pass */
|
||||
utils_sha1_update(&context, k_opad, KEY_IOPAD_SIZE); /* start with outer pad */
|
||||
utils_sha1_update(&context, out, SHA1_DIGEST_SIZE); /* then results of 1st hash */
|
||||
utils_sha1_finish(&context, out); /* finish up 2nd pass */
|
||||
|
||||
memcpy(digest, out, SHA1_DIGEST_SIZE);
|
||||
/* for (i = 0; i < SHA1_DIGEST_SIZE; ++i) {
|
||||
digest[i * 2] = utils_hb2hex(out[i] >> 4);
|
||||
digest[i * 2 + 1] = utils_hb2hex(out[i]);
|
||||
}*/
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ble_qiot_log.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <printf.h>
|
||||
#include <string.h>
|
||||
|
||||
#define HEX_DUMP_BYTE_PER_LINE 16
|
||||
|
||||
e_ble_qiot_log_level g_log_level = BLE_QIOT_LOG_LEVEL_INFO;
|
||||
|
||||
void ble_qiot_set_log_level(e_ble_qiot_log_level level)
|
||||
{
|
||||
g_log_level = level;
|
||||
return;
|
||||
}
|
||||
|
||||
#if !BLE_QIOT_USER_DEFINE_HEXDUMP
|
||||
void ble_qiot_log_hex(e_ble_qiot_log_level level, const char *hex_name, const char *data, uint32_t data_len)
|
||||
{
|
||||
char buf[HEX_DUMP_BYTE_PER_LINE * 5] = {0};
|
||||
int line_count = 0, line = 0, byte = 0, rest = 0, start_byte = 0;
|
||||
|
||||
if (g_log_level < level) {
|
||||
return;
|
||||
}
|
||||
|
||||
line_count = data_len / HEX_DUMP_BYTE_PER_LINE;
|
||||
if (data_len % HEX_DUMP_BYTE_PER_LINE) {
|
||||
line_count += 1;
|
||||
}
|
||||
|
||||
ble_qiot_log_raw("\r\nble qiot dump: %s, length: %d\r\n", hex_name, data_len);
|
||||
ble_qiot_log_raw(" 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15\r\n");
|
||||
ble_qiot_log_raw("===============================================\r\n");
|
||||
for (line = 0; line < line_count; line++) {
|
||||
start_byte = line * HEX_DUMP_BYTE_PER_LINE;
|
||||
if (data_len - start_byte < HEX_DUMP_BYTE_PER_LINE) {
|
||||
rest = data_len % HEX_DUMP_BYTE_PER_LINE;
|
||||
} else {
|
||||
rest = HEX_DUMP_BYTE_PER_LINE;
|
||||
}
|
||||
|
||||
for (byte = 0; byte < HEX_DUMP_BYTE_PER_LINE; byte++) {
|
||||
if (byte < rest) {
|
||||
sprintf(&buf[byte * 3], "%02X ", data[start_byte + byte]);
|
||||
} else {
|
||||
sprintf(&buf[byte * 3], " ");
|
||||
}
|
||||
}
|
||||
|
||||
sprintf(&buf[HEX_DUMP_BYTE_PER_LINE * 3], "| ");
|
||||
for (byte = 0; byte < rest; byte++) {
|
||||
if (data[start_byte + byte] >= ' ' && data[start_byte + byte] <= '~') {
|
||||
buf[HEX_DUMP_BYTE_PER_LINE * 3 + 2 + byte] = data[start_byte + byte];
|
||||
} else {
|
||||
buf[HEX_DUMP_BYTE_PER_LINE * 3 + 2 + byte] = '.';
|
||||
}
|
||||
}
|
||||
sprintf(&buf[HEX_DUMP_BYTE_PER_LINE * 3 + 2 + rest], "\r\n");
|
||||
|
||||
ble_qiot_log_raw("%s", buf); // do not use printf(buf), that cause '%' transfer next character
|
||||
}
|
||||
ble_qiot_log_raw("\r\n");
|
||||
}
|
||||
#endif // BLE_QIOT_USER_DEFINE_HEXDUMP
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,302 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making IoT Hub available.
|
||||
* Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ble_qiot_md5.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Implementation that should never be optimized out by the compiler */
|
||||
static void _utils_md5_zeroize(void *v, size_t n)
|
||||
{
|
||||
volatile unsigned char *p = v;
|
||||
while (n--) {
|
||||
*p++ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 32-bit integer manipulation macros (little endian)
|
||||
*/
|
||||
#ifndef IOT_MD5_GET_UINT32_LE
|
||||
#define IOT_MD5_GET_UINT32_LE(n, b, i) \
|
||||
{ \
|
||||
(n) = ((uint32_t)(b)[(i)]) | ((uint32_t)(b)[(i) + 1] << 8) | ((uint32_t)(b)[(i) + 2] << 16) | \
|
||||
((uint32_t)(b)[(i) + 3] << 24); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef IOT_MD5_PUT_UINT32_LE
|
||||
#define IOT_MD5_PUT_UINT32_LE(n, b, i) \
|
||||
{ \
|
||||
(b)[(i)] = (unsigned char)(((n)) & 0xFF); \
|
||||
(b)[(i) + 1] = (unsigned char)(((n) >> 8) & 0xFF); \
|
||||
(b)[(i) + 2] = (unsigned char)(((n) >> 16) & 0xFF); \
|
||||
(b)[(i) + 3] = (unsigned char)(((n) >> 24) & 0xFF); \
|
||||
}
|
||||
#endif
|
||||
|
||||
void utils_md5_init(iot_md5_context *ctx)
|
||||
{
|
||||
memset(ctx, 0, sizeof(iot_md5_context));
|
||||
}
|
||||
|
||||
void utils_md5_free(iot_md5_context *ctx)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
_utils_md5_zeroize(ctx, sizeof(iot_md5_context));
|
||||
}
|
||||
|
||||
void utils_md5_clone(iot_md5_context *dst, const iot_md5_context *src)
|
||||
{
|
||||
*dst = *src;
|
||||
}
|
||||
|
||||
/*
|
||||
* MD5 context setup
|
||||
*/
|
||||
void utils_md5_starts(iot_md5_context *ctx)
|
||||
{
|
||||
ctx->total[0] = 0;
|
||||
ctx->total[1] = 0;
|
||||
|
||||
ctx->state[0] = 0x67452301;
|
||||
ctx->state[1] = 0xEFCDAB89;
|
||||
ctx->state[2] = 0x98BADCFE;
|
||||
ctx->state[3] = 0x10325476;
|
||||
}
|
||||
|
||||
void utils_md5_process(iot_md5_context *ctx, const unsigned char data[64])
|
||||
{
|
||||
uint32_t X[16], A, B, C, D;
|
||||
|
||||
IOT_MD5_GET_UINT32_LE(X[0], data, 0);
|
||||
IOT_MD5_GET_UINT32_LE(X[1], data, 4);
|
||||
IOT_MD5_GET_UINT32_LE(X[2], data, 8);
|
||||
IOT_MD5_GET_UINT32_LE(X[3], data, 12);
|
||||
IOT_MD5_GET_UINT32_LE(X[4], data, 16);
|
||||
IOT_MD5_GET_UINT32_LE(X[5], data, 20);
|
||||
IOT_MD5_GET_UINT32_LE(X[6], data, 24);
|
||||
IOT_MD5_GET_UINT32_LE(X[7], data, 28);
|
||||
IOT_MD5_GET_UINT32_LE(X[8], data, 32);
|
||||
IOT_MD5_GET_UINT32_LE(X[9], data, 36);
|
||||
IOT_MD5_GET_UINT32_LE(X[10], data, 40);
|
||||
IOT_MD5_GET_UINT32_LE(X[11], data, 44);
|
||||
IOT_MD5_GET_UINT32_LE(X[12], data, 48);
|
||||
IOT_MD5_GET_UINT32_LE(X[13], data, 52);
|
||||
IOT_MD5_GET_UINT32_LE(X[14], data, 56);
|
||||
IOT_MD5_GET_UINT32_LE(X[15], data, 60);
|
||||
|
||||
#define S(x, n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
|
||||
|
||||
#define P(a, b, c, d, k, s, t) \
|
||||
{ \
|
||||
a += F(b, c, d) + X[k] + t; \
|
||||
a = S(a, s) + b; \
|
||||
}
|
||||
|
||||
A = ctx->state[0];
|
||||
B = ctx->state[1];
|
||||
C = ctx->state[2];
|
||||
D = ctx->state[3];
|
||||
|
||||
#define F(x, y, z) (z ^ (x & (y ^ z)))
|
||||
|
||||
P(A, B, C, D, 0, 7, 0xD76AA478);
|
||||
P(D, A, B, C, 1, 12, 0xE8C7B756);
|
||||
P(C, D, A, B, 2, 17, 0x242070DB);
|
||||
P(B, C, D, A, 3, 22, 0xC1BDCEEE);
|
||||
P(A, B, C, D, 4, 7, 0xF57C0FAF);
|
||||
P(D, A, B, C, 5, 12, 0x4787C62A);
|
||||
P(C, D, A, B, 6, 17, 0xA8304613);
|
||||
P(B, C, D, A, 7, 22, 0xFD469501);
|
||||
P(A, B, C, D, 8, 7, 0x698098D8);
|
||||
P(D, A, B, C, 9, 12, 0x8B44F7AF);
|
||||
P(C, D, A, B, 10, 17, 0xFFFF5BB1);
|
||||
P(B, C, D, A, 11, 22, 0x895CD7BE);
|
||||
P(A, B, C, D, 12, 7, 0x6B901122);
|
||||
P(D, A, B, C, 13, 12, 0xFD987193);
|
||||
P(C, D, A, B, 14, 17, 0xA679438E);
|
||||
P(B, C, D, A, 15, 22, 0x49B40821);
|
||||
|
||||
#undef F
|
||||
|
||||
#define F(x, y, z) (y ^ (z & (x ^ y)))
|
||||
|
||||
P(A, B, C, D, 1, 5, 0xF61E2562);
|
||||
P(D, A, B, C, 6, 9, 0xC040B340);
|
||||
P(C, D, A, B, 11, 14, 0x265E5A51);
|
||||
P(B, C, D, A, 0, 20, 0xE9B6C7AA);
|
||||
P(A, B, C, D, 5, 5, 0xD62F105D);
|
||||
P(D, A, B, C, 10, 9, 0x02441453);
|
||||
P(C, D, A, B, 15, 14, 0xD8A1E681);
|
||||
P(B, C, D, A, 4, 20, 0xE7D3FBC8);
|
||||
P(A, B, C, D, 9, 5, 0x21E1CDE6);
|
||||
P(D, A, B, C, 14, 9, 0xC33707D6);
|
||||
P(C, D, A, B, 3, 14, 0xF4D50D87);
|
||||
P(B, C, D, A, 8, 20, 0x455A14ED);
|
||||
P(A, B, C, D, 13, 5, 0xA9E3E905);
|
||||
P(D, A, B, C, 2, 9, 0xFCEFA3F8);
|
||||
P(C, D, A, B, 7, 14, 0x676F02D9);
|
||||
P(B, C, D, A, 12, 20, 0x8D2A4C8A);
|
||||
|
||||
#undef F
|
||||
|
||||
#define F(x, y, z) (x ^ y ^ z)
|
||||
|
||||
P(A, B, C, D, 5, 4, 0xFFFA3942);
|
||||
P(D, A, B, C, 8, 11, 0x8771F681);
|
||||
P(C, D, A, B, 11, 16, 0x6D9D6122);
|
||||
P(B, C, D, A, 14, 23, 0xFDE5380C);
|
||||
P(A, B, C, D, 1, 4, 0xA4BEEA44);
|
||||
P(D, A, B, C, 4, 11, 0x4BDECFA9);
|
||||
P(C, D, A, B, 7, 16, 0xF6BB4B60);
|
||||
P(B, C, D, A, 10, 23, 0xBEBFBC70);
|
||||
P(A, B, C, D, 13, 4, 0x289B7EC6);
|
||||
P(D, A, B, C, 0, 11, 0xEAA127FA);
|
||||
P(C, D, A, B, 3, 16, 0xD4EF3085);
|
||||
P(B, C, D, A, 6, 23, 0x04881D05);
|
||||
P(A, B, C, D, 9, 4, 0xD9D4D039);
|
||||
P(D, A, B, C, 12, 11, 0xE6DB99E5);
|
||||
P(C, D, A, B, 15, 16, 0x1FA27CF8);
|
||||
P(B, C, D, A, 2, 23, 0xC4AC5665);
|
||||
|
||||
#undef F
|
||||
|
||||
#define F(x, y, z) (y ^ (x | ~z))
|
||||
|
||||
P(A, B, C, D, 0, 6, 0xF4292244);
|
||||
P(D, A, B, C, 7, 10, 0x432AFF97);
|
||||
P(C, D, A, B, 14, 15, 0xAB9423A7);
|
||||
P(B, C, D, A, 5, 21, 0xFC93A039);
|
||||
P(A, B, C, D, 12, 6, 0x655B59C3);
|
||||
P(D, A, B, C, 3, 10, 0x8F0CCC92);
|
||||
P(C, D, A, B, 10, 15, 0xFFEFF47D);
|
||||
P(B, C, D, A, 1, 21, 0x85845DD1);
|
||||
P(A, B, C, D, 8, 6, 0x6FA87E4F);
|
||||
P(D, A, B, C, 15, 10, 0xFE2CE6E0);
|
||||
P(C, D, A, B, 6, 15, 0xA3014314);
|
||||
P(B, C, D, A, 13, 21, 0x4E0811A1);
|
||||
P(A, B, C, D, 4, 6, 0xF7537E82);
|
||||
P(D, A, B, C, 11, 10, 0xBD3AF235);
|
||||
P(C, D, A, B, 2, 15, 0x2AD7D2BB);
|
||||
P(B, C, D, A, 9, 21, 0xEB86D391);
|
||||
|
||||
#undef F
|
||||
|
||||
ctx->state[0] += A;
|
||||
ctx->state[1] += B;
|
||||
ctx->state[2] += C;
|
||||
ctx->state[3] += D;
|
||||
}
|
||||
|
||||
/*
|
||||
* MD5 process buffer
|
||||
*/
|
||||
void utils_md5_update(iot_md5_context *ctx, const unsigned char *input, unsigned int ilen)
|
||||
{
|
||||
uint32_t fill;
|
||||
uint32_t left;
|
||||
|
||||
if (ilen == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
left = ctx->total[0] & 0x3F;
|
||||
fill = 64 - left;
|
||||
|
||||
ctx->total[0] += (uint32_t)ilen;
|
||||
ctx->total[0] &= 0xFFFFFFFF;
|
||||
|
||||
if (ctx->total[0] < (uint32_t)ilen) {
|
||||
ctx->total[1]++;
|
||||
}
|
||||
|
||||
if (left && ilen >= fill) {
|
||||
memcpy((void *)(ctx->buffer + left), input, fill);
|
||||
utils_md5_process(ctx, ctx->buffer);
|
||||
input += fill;
|
||||
ilen -= fill;
|
||||
left = 0;
|
||||
}
|
||||
|
||||
while (ilen >= 64) {
|
||||
utils_md5_process(ctx, input);
|
||||
input += 64;
|
||||
ilen -= 64;
|
||||
}
|
||||
|
||||
if (ilen > 0) {
|
||||
memcpy((void *)(ctx->buffer + left), input, ilen);
|
||||
}
|
||||
}
|
||||
|
||||
static const unsigned char iot_md5_padding[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/*
|
||||
* MD5 final digest
|
||||
*/
|
||||
void utils_md5_finish(iot_md5_context *ctx, unsigned char output[16])
|
||||
{
|
||||
uint32_t last, padn;
|
||||
uint32_t high, low;
|
||||
unsigned char msglen[8];
|
||||
|
||||
high = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
|
||||
low = (ctx->total[0] << 3);
|
||||
|
||||
IOT_MD5_PUT_UINT32_LE(low, msglen, 0);
|
||||
IOT_MD5_PUT_UINT32_LE(high, msglen, 4);
|
||||
|
||||
last = ctx->total[0] & 0x3F;
|
||||
padn = (last < 56) ? (56 - last) : (120 - last);
|
||||
|
||||
utils_md5_update(ctx, iot_md5_padding, padn);
|
||||
utils_md5_update(ctx, msglen, 8);
|
||||
|
||||
IOT_MD5_PUT_UINT32_LE(ctx->state[0], output, 0);
|
||||
IOT_MD5_PUT_UINT32_LE(ctx->state[1], output, 4);
|
||||
IOT_MD5_PUT_UINT32_LE(ctx->state[2], output, 8);
|
||||
IOT_MD5_PUT_UINT32_LE(ctx->state[3], output, 12);
|
||||
}
|
||||
|
||||
/*
|
||||
* output = MD5( input buffer )
|
||||
*/
|
||||
void utils_md5(const unsigned char *input, unsigned int ilen, unsigned char output[16])
|
||||
{
|
||||
iot_md5_context ctx;
|
||||
|
||||
utils_md5_init(&ctx);
|
||||
utils_md5_starts(&ctx);
|
||||
utils_md5_update(&ctx, input, ilen);
|
||||
utils_md5_finish(&ctx, output);
|
||||
utils_md5_free(&ctx);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,328 @@
|
||||
/*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ble_qiot_sha1.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Implementation that should never be optimized out by the compiler */
|
||||
static void utils_sha1_zeroize(void *v, size_t n)
|
||||
{
|
||||
volatile unsigned char *p = v;
|
||||
while (n--) {
|
||||
*p++ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 32-bit integer manipulation macros (big endian)
|
||||
*/
|
||||
#ifndef IOT_SHA1_GET_UINT32_BE
|
||||
#define IOT_SHA1_GET_UINT32_BE(n, b, i) \
|
||||
{ \
|
||||
(n) = ((uint32_t)(b)[(i)] << 24) | ((uint32_t)(b)[(i) + 1] << 16) | ((uint32_t)(b)[(i) + 2] << 8) | \
|
||||
((uint32_t)(b)[(i) + 3]); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef IOT_SHA1_PUT_UINT32_BE
|
||||
#define IOT_SHA1_PUT_UINT32_BE(n, b, i) \
|
||||
{ \
|
||||
(b)[(i)] = (unsigned char)((n) >> 24); \
|
||||
(b)[(i) + 1] = (unsigned char)((n) >> 16); \
|
||||
(b)[(i) + 2] = (unsigned char)((n) >> 8); \
|
||||
(b)[(i) + 3] = (unsigned char)((n)); \
|
||||
}
|
||||
#endif
|
||||
|
||||
void utils_sha1_init(iot_sha1_context *ctx)
|
||||
{
|
||||
memset(ctx, 0, sizeof(iot_sha1_context));
|
||||
}
|
||||
|
||||
void utils_sha1_free(iot_sha1_context *ctx)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
utils_sha1_zeroize(ctx, sizeof(iot_sha1_context));
|
||||
}
|
||||
|
||||
void utils_sha1_clone(iot_sha1_context *dst, const iot_sha1_context *src)
|
||||
{
|
||||
*dst = *src;
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA-1 context setup
|
||||
*/
|
||||
void utils_sha1_starts(iot_sha1_context *ctx)
|
||||
{
|
||||
ctx->total[0] = 0;
|
||||
ctx->total[1] = 0;
|
||||
|
||||
ctx->state[0] = 0x67452301;
|
||||
ctx->state[1] = 0xEFCDAB89;
|
||||
ctx->state[2] = 0x98BADCFE;
|
||||
ctx->state[3] = 0x10325476;
|
||||
ctx->state[4] = 0xC3D2E1F0;
|
||||
}
|
||||
|
||||
void utils_sha1_process(iot_sha1_context *ctx, const unsigned char data[64])
|
||||
{
|
||||
uint32_t temp, W[16], A, B, C, D, E;
|
||||
|
||||
IOT_SHA1_GET_UINT32_BE(W[0], data, 0);
|
||||
IOT_SHA1_GET_UINT32_BE(W[1], data, 4);
|
||||
IOT_SHA1_GET_UINT32_BE(W[2], data, 8);
|
||||
IOT_SHA1_GET_UINT32_BE(W[3], data, 12);
|
||||
IOT_SHA1_GET_UINT32_BE(W[4], data, 16);
|
||||
IOT_SHA1_GET_UINT32_BE(W[5], data, 20);
|
||||
IOT_SHA1_GET_UINT32_BE(W[6], data, 24);
|
||||
IOT_SHA1_GET_UINT32_BE(W[7], data, 28);
|
||||
IOT_SHA1_GET_UINT32_BE(W[8], data, 32);
|
||||
IOT_SHA1_GET_UINT32_BE(W[9], data, 36);
|
||||
IOT_SHA1_GET_UINT32_BE(W[10], data, 40);
|
||||
IOT_SHA1_GET_UINT32_BE(W[11], data, 44);
|
||||
IOT_SHA1_GET_UINT32_BE(W[12], data, 48);
|
||||
IOT_SHA1_GET_UINT32_BE(W[13], data, 52);
|
||||
IOT_SHA1_GET_UINT32_BE(W[14], data, 56);
|
||||
IOT_SHA1_GET_UINT32_BE(W[15], data, 60);
|
||||
|
||||
#define S(x, n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
|
||||
|
||||
#define R(t) \
|
||||
(temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ W[(t - 14) & 0x0F] ^ W[t & 0x0F], (W[t & 0x0F] = S(temp, 1)))
|
||||
|
||||
#define P(a, b, c, d, e, x) \
|
||||
{ \
|
||||
e += S(a, 5) + F(b, c, d) + K + x; \
|
||||
b = S(b, 30); \
|
||||
}
|
||||
|
||||
A = ctx->state[0];
|
||||
B = ctx->state[1];
|
||||
C = ctx->state[2];
|
||||
D = ctx->state[3];
|
||||
E = ctx->state[4];
|
||||
|
||||
#define F(x, y, z) (z ^ (x & (y ^ z)))
|
||||
#define K 0x5A827999
|
||||
|
||||
P(A, B, C, D, E, W[0]);
|
||||
P(E, A, B, C, D, W[1]);
|
||||
P(D, E, A, B, C, W[2]);
|
||||
P(C, D, E, A, B, W[3]);
|
||||
P(B, C, D, E, A, W[4]);
|
||||
P(A, B, C, D, E, W[5]);
|
||||
P(E, A, B, C, D, W[6]);
|
||||
P(D, E, A, B, C, W[7]);
|
||||
P(C, D, E, A, B, W[8]);
|
||||
P(B, C, D, E, A, W[9]);
|
||||
P(A, B, C, D, E, W[10]);
|
||||
P(E, A, B, C, D, W[11]);
|
||||
P(D, E, A, B, C, W[12]);
|
||||
P(C, D, E, A, B, W[13]);
|
||||
P(B, C, D, E, A, W[14]);
|
||||
P(A, B, C, D, E, W[15]);
|
||||
P(E, A, B, C, D, R(16));
|
||||
P(D, E, A, B, C, R(17));
|
||||
P(C, D, E, A, B, R(18));
|
||||
P(B, C, D, E, A, R(19));
|
||||
|
||||
#undef K
|
||||
#undef F
|
||||
|
||||
#define F(x, y, z) (x ^ y ^ z)
|
||||
#define K 0x6ED9EBA1
|
||||
|
||||
P(A, B, C, D, E, R(20));
|
||||
P(E, A, B, C, D, R(21));
|
||||
P(D, E, A, B, C, R(22));
|
||||
P(C, D, E, A, B, R(23));
|
||||
P(B, C, D, E, A, R(24));
|
||||
P(A, B, C, D, E, R(25));
|
||||
P(E, A, B, C, D, R(26));
|
||||
P(D, E, A, B, C, R(27));
|
||||
P(C, D, E, A, B, R(28));
|
||||
P(B, C, D, E, A, R(29));
|
||||
P(A, B, C, D, E, R(30));
|
||||
P(E, A, B, C, D, R(31));
|
||||
P(D, E, A, B, C, R(32));
|
||||
P(C, D, E, A, B, R(33));
|
||||
P(B, C, D, E, A, R(34));
|
||||
P(A, B, C, D, E, R(35));
|
||||
P(E, A, B, C, D, R(36));
|
||||
P(D, E, A, B, C, R(37));
|
||||
P(C, D, E, A, B, R(38));
|
||||
P(B, C, D, E, A, R(39));
|
||||
|
||||
#undef K
|
||||
#undef F
|
||||
|
||||
#define F(x, y, z) ((x & y) | (z & (x | y)))
|
||||
#define K 0x8F1BBCDC
|
||||
|
||||
P(A, B, C, D, E, R(40));
|
||||
P(E, A, B, C, D, R(41));
|
||||
P(D, E, A, B, C, R(42));
|
||||
P(C, D, E, A, B, R(43));
|
||||
P(B, C, D, E, A, R(44));
|
||||
P(A, B, C, D, E, R(45));
|
||||
P(E, A, B, C, D, R(46));
|
||||
P(D, E, A, B, C, R(47));
|
||||
P(C, D, E, A, B, R(48));
|
||||
P(B, C, D, E, A, R(49));
|
||||
P(A, B, C, D, E, R(50));
|
||||
P(E, A, B, C, D, R(51));
|
||||
P(D, E, A, B, C, R(52));
|
||||
P(C, D, E, A, B, R(53));
|
||||
P(B, C, D, E, A, R(54));
|
||||
P(A, B, C, D, E, R(55));
|
||||
P(E, A, B, C, D, R(56));
|
||||
P(D, E, A, B, C, R(57));
|
||||
P(C, D, E, A, B, R(58));
|
||||
P(B, C, D, E, A, R(59));
|
||||
|
||||
#undef K
|
||||
#undef F
|
||||
|
||||
#define F(x, y, z) (x ^ y ^ z)
|
||||
#define K 0xCA62C1D6
|
||||
|
||||
P(A, B, C, D, E, R(60));
|
||||
P(E, A, B, C, D, R(61));
|
||||
P(D, E, A, B, C, R(62));
|
||||
P(C, D, E, A, B, R(63));
|
||||
P(B, C, D, E, A, R(64));
|
||||
P(A, B, C, D, E, R(65));
|
||||
P(E, A, B, C, D, R(66));
|
||||
P(D, E, A, B, C, R(67));
|
||||
P(C, D, E, A, B, R(68));
|
||||
P(B, C, D, E, A, R(69));
|
||||
P(A, B, C, D, E, R(70));
|
||||
P(E, A, B, C, D, R(71));
|
||||
P(D, E, A, B, C, R(72));
|
||||
P(C, D, E, A, B, R(73));
|
||||
P(B, C, D, E, A, R(74));
|
||||
P(A, B, C, D, E, R(75));
|
||||
P(E, A, B, C, D, R(76));
|
||||
P(D, E, A, B, C, R(77));
|
||||
P(C, D, E, A, B, R(78));
|
||||
P(B, C, D, E, A, R(79));
|
||||
|
||||
#undef K
|
||||
#undef F
|
||||
|
||||
ctx->state[0] += A;
|
||||
ctx->state[1] += B;
|
||||
ctx->state[2] += C;
|
||||
ctx->state[3] += D;
|
||||
ctx->state[4] += E;
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA-1 process buffer
|
||||
*/
|
||||
void utils_sha1_update(iot_sha1_context *ctx, const unsigned char *input, size_t ilen)
|
||||
{
|
||||
size_t fill;
|
||||
uint32_t left;
|
||||
|
||||
if (ilen == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
left = ctx->total[0] & 0x3F;
|
||||
fill = 64 - left;
|
||||
|
||||
ctx->total[0] += (uint32_t)ilen;
|
||||
ctx->total[0] &= 0xFFFFFFFF;
|
||||
|
||||
if (ctx->total[0] < (uint32_t)ilen) {
|
||||
ctx->total[1]++;
|
||||
}
|
||||
|
||||
if (left && ilen >= fill) {
|
||||
memcpy((void *)(ctx->buffer + left), input, fill);
|
||||
utils_sha1_process(ctx, ctx->buffer);
|
||||
input += fill;
|
||||
ilen -= fill;
|
||||
left = 0;
|
||||
}
|
||||
|
||||
while (ilen >= 64) {
|
||||
utils_sha1_process(ctx, input);
|
||||
input += 64;
|
||||
ilen -= 64;
|
||||
}
|
||||
|
||||
if (ilen > 0) {
|
||||
memcpy((void *)(ctx->buffer + left), input, ilen);
|
||||
}
|
||||
}
|
||||
|
||||
static const unsigned char iot_sha1_padding[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/*
|
||||
* SHA-1 final digest
|
||||
*/
|
||||
void utils_sha1_finish(iot_sha1_context *ctx, unsigned char output[20])
|
||||
{
|
||||
uint32_t last, padn;
|
||||
uint32_t high, low;
|
||||
unsigned char msglen[8];
|
||||
|
||||
high = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
|
||||
low = (ctx->total[0] << 3);
|
||||
|
||||
IOT_SHA1_PUT_UINT32_BE(high, msglen, 0);
|
||||
IOT_SHA1_PUT_UINT32_BE(low, msglen, 4);
|
||||
|
||||
last = ctx->total[0] & 0x3F;
|
||||
padn = (last < 56) ? (56 - last) : (120 - last);
|
||||
|
||||
utils_sha1_update(ctx, iot_sha1_padding, padn);
|
||||
utils_sha1_update(ctx, msglen, 8);
|
||||
|
||||
IOT_SHA1_PUT_UINT32_BE(ctx->state[0], output, 0);
|
||||
IOT_SHA1_PUT_UINT32_BE(ctx->state[1], output, 4);
|
||||
IOT_SHA1_PUT_UINT32_BE(ctx->state[2], output, 8);
|
||||
IOT_SHA1_PUT_UINT32_BE(ctx->state[3], output, 12);
|
||||
IOT_SHA1_PUT_UINT32_BE(ctx->state[4], output, 16);
|
||||
}
|
||||
|
||||
/*
|
||||
* output = SHA-1( input buffer )
|
||||
*/
|
||||
void utils_sha1(const unsigned char *input, size_t ilen, unsigned char output[20])
|
||||
{
|
||||
iot_sha1_context ctx;
|
||||
|
||||
utils_sha1_init(&ctx);
|
||||
utils_sha1_starts(&ctx);
|
||||
utils_sha1_update(&ctx, input, ilen);
|
||||
utils_sha1_finish(&ctx, output);
|
||||
utils_sha1_free(&ctx);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user