feat: Add rfid feature and .gitignore file

This commit is contained in:
lmx
2025-11-28 16:25:35 +08:00
parent 818e8c3778
commit ade4b0a1f8
1244 changed files with 342105 additions and 0 deletions

View File

@ -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

View File

@ -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 usedthe 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 132 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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View 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

View File

@ -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

View File

@ -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_ */

View File

@ -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_

View File

@ -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

View File

@ -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_

View File

@ -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_ */

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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));
}

View File

@ -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__

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,115 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "typedef.h"
#include "3th_profile_api.h"
#include "bt_tws.h"
#include "key_event_deal.h"
#include "system/timer.h"
#include "bt_common.h"
#include "btstack/avctp_user.h"
#include "os/os_api.h"
#if BT_FOR_APP_EN
#if (OTA_TWS_SAME_TIME_ENABLE && RCSP_ADV_EN && USER_APP_EN)
#include "rcsp_adv_tws_ota.h"
#endif
#if (OTA_TWS_SAME_TIME_ENABLE && SMART_BOX_EN)
#include "smartbox_update_tws.h"
#else
#include "update_tws.h"
#endif
static u8 mic_data_type = SOURCE_TYPE;
static u8 connect_type = TYPE_NULL;
static u8 tws_ble_type = TYPE_NULL;
void mic_set_data_source(u8 data_type)
{
mic_data_type = data_type;
}
u8 mic_get_data_source(void)
{
return mic_data_type;
}
u8 get_ble_connect_type(void)
{
return tws_ble_type;
}
void set_ble_connect_type(u8 type)
{
tws_ble_type = type;
}
u8 get_app_connect_type(void)
{
return connect_type;
}
void set_app_connect_type(u8 type)
{
connect_type = type;
}
#if TCFG_USER_TWS_ENABLE
int tws_data_to_sibling_send(u8 opcode, u8 *data, u8 len)
{
u8 send_data[len + 2];
printf(">>>>>>>>>>send data to sibling \n");
send_data[0] = opcode;
send_data[1] = len;
memcpy(send_data + 2, data, len);
return tws_api_send_data_to_sibling(send_data, sizeof(send_data), TWS_FUNC_ID_AI_SYNC);
}
static void __ai_tws_rx_from_sibling(u8 *data)
{
u8 opcode = data[0];
u8 len = data[1];
u8 *rx_data = data + 2;
#if (OTA_TWS_SAME_TIME_ENABLE && (RCSP_BTMATE_EN || RCSP_ADV_EN || SMART_BOX_EN))
tws_ota_get_data_from_sibling(opcode, rx_data, len);
#endif
free(data);
}
static void ai_tws_rx_from_sibling(void *_data, u16 len, bool rx)
{
int err = 0;
if (rx) {
printf(">>>%s \n", __func__);
printf("len :%d\n", len);
put_buf(_data, len);
u8 *rx_data = malloc(len);
memcpy(rx_data, _data, len);
int msg[4];
msg[0] = (int)__ai_tws_rx_from_sibling;
msg[1] = 1;
msg[2] = (int)rx_data;
err = os_taskq_post_type("app_core", Q_CALLBACK, 3, msg);
if (err) {
printf("tws rx post fail\n");
}
}
}
//发送给对耳
REGISTER_TWS_FUNC_STUB(app_vol_sync_stub) = {
.func_id = TWS_FUNC_ID_AI_SYNC,
.func = ai_tws_rx_from_sibling,
};
#endif
#endif

View File

@ -0,0 +1,34 @@
#ifndef _3TH_PROFILE_API_H
#define _3TH_PROFILE_API_H
#include<string.h>
#include <stdint.h>
#include "le_common.h"
#define TYPE_NULL 0
#define TYPE_BLE 1
#define TYPE_SPP 2
#define TYPE_MASTER_BLE 3
#define TYPE_SLAVE_BLE 4
#define TYPE_MASTER_SPP 5
#define TYPE_SLAVE_SPP 6
#define SOURCE_TYPE 0
#define SINK_TYPE_MASTER 1
#define SINK_TYPE_SLAVE 2
void set_app_connect_type(u8 type);
u8 get_app_connect_type(void);
u8 get_ble_connect_type(void);
void set_ble_connect_type(u8 type);
void mic_set_data_source(u8 data_type);
u8 mic_get_data_source(void);
int tws_data_to_sibling_send(u8 opcode, u8 *data, u8 len); //发送数据给对耳
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,114 @@
#ifndef _CUSTOM_CFG_H_
#define _CUSTOM_CFG_H_
#include "typedef.h"
//#include "hw_cpu.h"
#include <string.h>
#include "app_config.h"
#define BT_CONNECTION_VERIFY 0 // 0是校验,1是不校验
#if (JL_EARPHONE_APP_EN && RCSP_UPDATE_EN)
#define VER_INFO_EXT_COUNT 2 //2
#else
#define VER_INFO_EXT_COUNT 0 //2
#endif
#define VER_INFO_EXT_MAX_LEN 24
enum {
CFG_ITEM_ADV_IND = 0,
CFG_ITEM_SCAN_RSP,
CFG_ITEM_BLE_NAME,
CFG_ITEM_BT_ADDR,
CFG_ITEM_BT_NAME = 4,
CFG_ITEM_PIN_CODE,
CFG_ITEM_VER_INFO,
CFG_ITEM_LOW_POWER_VOLTAGE,
CFG_ITEM_EDR_ADDR = 8,
CFG_ITEM_BLE_ADDR,
CFG_ITEM_GATT_PROFILE,
CFG_ITEM_RESET_IO_INFO,
CFG_ITEM_PILOT_LAMP_IO_INFO = 12,
CFG_ITEM_LINK_KEY_INFO,
CFG_ITEM_POWER_IO_ON_OFF,
CFG_ITEM_LAST_DEVICE_LINK_KEY_INFO,
CFG_ITEM_BLE_READ_WRITE_UUID_INFO = 16,
#if VER_INFO_EXT_COUNT
CFG_ITEM_VER_INFO_AUTHKEY,
CFG_ITEM_VER_INFO_PROCODE,
#endif
CFG_ITEM_PVID, //供loader使用
CFG_ITEM_MD5,
CFG_ITEM_SDK_TYPE,
};
enum {
EX_CFG_ERR_NONE = 0,
EX_CFG_INDEX_ERR,
EX_CFG_LEN_ERR,
};
enum {
GET_VID_FROM_EX_CFG = 0,
GET_PID_FROM_EX_CFG,
GET_VER_FROM_EX_CFG,
#if VER_INFO_EXT_COUNT
GET_AUTH_KEY_FROM_EX_CFG,
GET_PRO_CODE_FROM_EX_CFG,
#endif
};
typedef struct _update_file_id {
u8 vid[2];
u8 pid[2];
u8 ver[2];
u8 len[4];
u8 reserve[4];
u8 crc[2];
} update_file_id_t;
typedef struct _update_file_ext_id {
update_file_id_t update_file_id_info;
#if VER_INFO_EXT_COUNT
u8 ext[VER_INFO_EXT_COUNT * (VER_INFO_EXT_MAX_LEN * 2)];
#endif
} update_file_ext_id_t;
typedef struct _update_file_reset_io {
u8 io_num;
u8 resever[15];
} update_file_reset_io_t;
typedef struct _update_file_pilot_lamp_io {
u8 pilot_lamp_io[16];
} update_file_pilot_lamp_io_t;
typedef struct _update_file_link_key {
u8 link_key[16];
} update_file_link_key_t;
struct excfg_rsp_payload {
u16 vid;
u8 logo[5];
u8 version;
u8 addr[6];
};
//u32 custom_cfg_file_init(void);
//void ex_cfg_write_to_flash(void);
//u32 ex_cfg_fill_content_api(u8 cfg_index, u8 *data, u16 len);
u32 ex_cfg_fill_content_api(void);
u16 get_vid_pid_ver_from_cfg_file(u8 type);
#if VER_INFO_EXT_COUNT
u32 get_authkey_procode_from_cfg_file(u8 *data[], u8 *len, u8 type);
#endif
#if RCSP_UPDATE_EN
extern int rcsp_update_msg[10];
#endif
#endif

View File

@ -0,0 +1,391 @@
/*****************************************************************
>file name : mic_rec.c
>author : lichao
>create time : Wed 26 Jun 2019 04:31:50 PM CST
*****************************************************************/
#include "system/includes.h"
#include "media/includes.h"
#include "app_config.h"
#include "audio_config.h"
#include "classic/tws_local_media_sync.h"
#include "3th_profile_api.h"
#include "classic/tws_api.h"
#include "btstack/avctp_user.h"
#include "bt_tws.h"
#if (BT_MIC_EN)
#define LOG_TAG "[MIC_REC]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
#define LOG_CLI_ENABLE
#include "debug.h"
enum {
STANDARD_OPUS = 0 << 6,
KUGOU_OPUS = 1 << 6,
};
enum {
ENC_OPUS_16KBPS = 0,
ENC_OPUS_32KBPS = 1,
ENC_OPUS_64KBPS = 2,
};
typedef struct __ai_encode_info {
const u8 *info;
u32 enc_type;
u8 opus_type;
u16(*sender)(u8 *buf, u16 len);
} _ai_encode_info;
struct __speech_buf_ctl {
cbuffer_t cbuffer;
volatile u8 speech_init_flg;
u16 cbuf_size;
u8 *speech_cbuf;
};
struct __mic_rec_t {
struct __speech_buf_ctl buf_ctl;
struct __ai_encode_info ai_enc_info;
u8 ai_mic_busy_flg;
u8 init_ok;
u16 frame_num;
u16 frame_size;
OS_MUTEX mutex_ai_mic;
};
static struct __mic_rec_t mic_rec;
#define __this (&mic_rec)
extern void bt_sniff_ready_clean(void);
bool get_tws_sibling_connect_state(void);
int a2dp_tws_dec_suspend(void *p);
void a2dp_tws_dec_resume(void);
int audio_mic_enc_open(int (*mic_output)(void *priv, void *buf, int len), u32 code_type, u8 ai_type);
int audio_mic_enc_close();
static void ai_mic_tws_stop_opus();
static void speech_cbuf_init(void)
{
__this->buf_ctl.speech_init_flg = 1;
ASSERT(__this->buf_ctl.speech_cbuf == NULL, "speech_cbuf is err\n");
__this->buf_ctl.speech_cbuf = malloc(__this->buf_ctl.cbuf_size);
ASSERT(__this->buf_ctl.speech_cbuf, "speech_cbuf is not ok\n");
cbuf_init(&(__this->buf_ctl.cbuffer), __this->buf_ctl.speech_cbuf, __this->buf_ctl.cbuf_size);
}
static void speech_cbuf_exit(void)
{
__this->buf_ctl.speech_init_flg = 0;
cbuf_clear(&(__this->buf_ctl.cbuffer));
free(__this->buf_ctl.speech_cbuf);
__this->buf_ctl.speech_cbuf = NULL;
}
static u16 speech_data_send(u8 *buf, u16 len, u16(*send_data)(u8 *buf, u16 len))
{
u16 res = 0;
u16 send_len = __this->frame_num * len;
u8 temp_buf[send_len];
if (__this->buf_ctl.speech_init_flg == 0) {
return 0;
}
if (cbuf_write(&(__this->buf_ctl.cbuffer), buf, len) != len) {
res = (u16)(-1);
}
/* printf("cl %d\n",cbuf_get_data_size(&(__this->buf_ctl.cbuffer))); */
while (cbuf_get_data_size(&(__this->buf_ctl.cbuffer)) >= send_len) {
cbuf_read_alloc_len(&(__this->buf_ctl.cbuffer), temp_buf, send_len);
if (send_data) {
if (!send_data(temp_buf, send_len)) {
putchar('S');
cbuf_read_alloc_len_updata(&(__this->buf_ctl.cbuffer), send_len);
} else {
putchar('E');
break;
}
}
}
return res;
}
#if TCFG_USER_TWS_ENABLE
#if 0
void tws_api_local_media_sync_rx_handler_notify()
{
u8 *tws_buf = NULL;
int len = 0;
if (mic_get_data_source() == SINK_TYPE_SLAVE) {
if (dma_tws_mic_pool) {
tws_buf = tws_api_local_media_trans_pop(&len);
/* log_info("sf %d %0x\n",len, tws_buf); */
if (tws_buf) {
tws_api_local_media_trans_free(tws_buf);
}
}
}
}
static u16 tws_data_send_slave_to_master(u8 *buf, u16 len)
{
u8 *tws_buf = NULL;
if (dma_tws_mic_pool == 0) {
return -1;
}
tws_buf = tws_api_local_media_trans_alloc(len);
if (tws_buf == NULL) {
return -1;
}
/* log_info("sd %0x %d\n",tws_buf,len); */
memcpy(tws_buf, buf, len);
/* printf("tdlen\n"); */
/* put_buf(tws_buf,len); */
tws_api_local_media_trans_push(tws_buf, len);
return 0;
}
#endif
enum {
//send to sibling
TWS_AI_A2DP_DROP_FRAME_CTL_V2 = 0,
//tws sync deal
TWS_AI_MIC_RESUME_A2DP = 0x80,
};
static int mic_rec_tws_send_cmd(u8 cmd)
{
return tws_api_send_data_to_sibling(&cmd, sizeof(cmd), 0x3890AB12);
}
static void __mic_rec_tws_rx_cb_deal(int cmd)
{
switch (cmd) { //tws sync deal
case TWS_AI_A2DP_DROP_FRAME_CTL_V2:
a2dp_tws_dec_suspend(NULL);
break;
case TWS_AI_MIC_RESUME_A2DP:
ai_mic_tws_stop_opus();
break;
}
}
static void mic_rec_tws_rx_data(void *_data, u16 len, bool rx)
{
int msg[4];
int err = 0;
u8 *data = (u8 *)_data;
printf(">>>%s \n", __func__);
printf("len :%d\n", len);
put_buf(_data, len);
if (!rx && data[0] < TWS_AI_MIC_RESUME_A2DP) { //not need deal
return;
}
msg[0] = (int)__mic_rec_tws_rx_cb_deal;
msg[1] = 1;
msg[2] = *data;
err = os_taskq_post_type("app_core", Q_CALLBACK, 3, msg);
if (err) {
printf("tws rx post fail\n");
}
}
REGISTER_TWS_FUNC_STUB(mic_rec_sync_stub) = {
.func_id = 0x3890AB12,
.func = mic_rec_tws_rx_data,
};
#endif
u16 ai_mic_get_frame_size()
{
return __this->frame_size;
}
static int rec_enc_output(void *priv, void *buf, int len)
{
bt_sniff_ready_clean();
u8 *send_buf = (u8 *)buf;
int send_len = len;
//printf("len:%d\n", len);
__this->frame_size = len;
if (speech_data_send(send_buf, send_len, __this->ai_enc_info.sender) == (u16)(-1)) {
log_info("opus data miss !!! line:%d \n", __LINE__);
}
return 0;
}
_WEAK_ int a2dp_tws_dec_suspend(void *p)
{
return 0;
}
_WEAK_ void a2dp_tws_dec_resume(void)
{
}
_WEAK_ void bt_sniff_ready_clean(void)
{
}
_WEAK_ void mic_rec_clock_set(void)
{
}
_WEAK_ void mic_rec_clock_recover(void)
{
}
int ai_mic_rec_start(void)
{
if (0 == __this->init_ok) {
printf("init err\n");
return -1;
}
os_mutex_pend(&__this->mutex_ai_mic, 0);
if (__this->ai_mic_busy_flg) {
os_mutex_post(&__this->mutex_ai_mic);
return -1;
}
user_send_cmd_prepare(USER_CTRL_ALL_SNIFF_EXIT, 0, NULL);
#if TCFG_USER_TWS_ENABLE
if (get_tws_sibling_connect_state() && (tws_api_get_role() == TWS_ROLE_MASTER)) {
mic_rec_tws_send_cmd(TWS_AI_A2DP_DROP_FRAME_CTL_V2);
}
#endif
int err = a2dp_tws_dec_suspend(NULL);
if (err == 0) {
printf("opus init \n");
mic_rec_clock_set();
speech_cbuf_init();
printf("%s \n", __this->ai_enc_info.info);
audio_mic_enc_open(rec_enc_output, __this->ai_enc_info.enc_type, __this->ai_enc_info.opus_type);
__this->ai_mic_busy_flg = 1;
}
os_mutex_post(&__this->mutex_ai_mic);
return 0;
}
int ai_mic_is_busy(void)
{
return __this->ai_mic_busy_flg;
}
static void ai_mic_tws_stop_opus()
{
if (__this->ai_mic_busy_flg == 0) {
a2dp_tws_dec_resume();
}
}
static int ai_mic_resume_a2dp(void)
{
int err = 0;
int msg[8];
msg[0] = (int)ai_mic_tws_stop_opus;
msg[1] = 1;
msg[2] = 0;
while (1) {
err = os_taskq_post_type("app_core", Q_CALLBACK, 3, msg);
if (err != OS_Q_FULL) {
break;
}
os_time_dly(2);
}
return err;
}
int ai_mic_rec_close(void)
{
os_mutex_pend(&__this->mutex_ai_mic, 0);
if (__this->ai_mic_busy_flg) {
printf(">>>>opus close: %d, %s\n", cpu_in_irq(), os_current_task());
audio_mic_enc_close();
speech_cbuf_exit();
mic_rec_clock_recover();
__this->ai_mic_busy_flg = 0;
}
os_mutex_post(&__this->mutex_ai_mic);
#if TCFG_USER_TWS_ENABLE
if ((tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED)) {
if (tws_api_get_role() == TWS_ROLE_MASTER) {
mic_rec_tws_send_cmd(TWS_AI_MIC_RESUME_A2DP);
}
} else {
/*a2dp_tws_dec_resume();*/
ai_mic_resume_a2dp();
}
#else
ai_mic_resume_a2dp();
/*a2dp_tws_dec_resume();*/
#endif
return 0;
}
static int ai_mic_mutex_init(void)
{
os_mutex_create(&__this->mutex_ai_mic);
return 0;
}
late_initcall(ai_mic_mutex_init);
int mic_rec_pram_init(/* const char **name, */u32 enc_type, u8 opus_type, u16(*speech_send)(u8 *buf, u16 len), u16 frame_num, u16 cbuf_size)
{
/* __this->ai_enc_info.info = name; */
__this->init_ok = 0;
if (enc_type == AUDIO_CODING_OPUS && !TCFG_ENC_OPUS_ENABLE) {
printf("please enable opus deceder");
return -1;
} else if (enc_type == AUDIO_CODING_SPEEX && !TCFG_ENC_SPEEX_ENABLE) {
printf("please enable speex deceder");
return -1;
}
__this->ai_enc_info.enc_type = enc_type;
__this->ai_enc_info.opus_type = opus_type;
__this->ai_enc_info.sender = speech_send;
__this->frame_num = frame_num;
__this->buf_ctl.cbuf_size = cbuf_size;
__this->init_ok = 1;
return 0;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,84 @@
#ifndef _3TH_PROTOCOL_API_H
#define _3TH_PROTOCOL_API_H
#include<string.h>
#include <stdint.h>
#include "typedef.h"
#include "os/os_api.h"
#include "btstack/third_party/app_protocol_event.h"
#include "app_protocol_common.h"
#define APP_PROTOCOL_TASK_NAME "app_proto"
//定义这几个宏仅仅用于编译优化代码量。需要那个选哪个flash够大可以全部都打开的。
//不要在板级头文件重复定义。
#define APP_PROTOCOL_DEMO_CODE 0
#define APP_PROTOCOL_GMA_CODE 0
#define APP_PROTOCOL_AMA_CODE 0
#define APP_PROTOCOL_DMA_CODE 0
#define APP_PROTOCOL_TME_CODE 0
#define APP_PROTOCOL_MMA_CODE 0
#define APP_PROTOCOL_GFPS_CODE 1
#define APP_PROTOCOL_SPEECH_EN 0 //语音助手功能,若无此功能则关掉
#define APP_PROTOCOL_READ_CFG_EN 0 //从custom.dat中读取配置信息若无此功能则关掉
#define DEMO_HANDLER_ID 0x300 /*作为一个使用的例子同时也可作为客户自己添加协议的ID*/
#define GMA_HANDLER_ID 0x400 /*阿里天猫协议接口ID*/
#define MMA_HANDLER_ID 0x500 /*小米MMA协议接口ID*/
#define DMA_HANDLER_ID 0x600 /*百度DMA协议接口ID*/
#define TME_HANDLER_ID 0x700 /*腾讯酷狗TME协议接口ID*/
#define AMA_HANDLER_ID 0x800 /*亚马逊的AMA协议接口ID*/
#define GFPS_HANDLER_ID 0x900 /*谷歌快对的协议接口ID*/
//app os task message
enum {
//Q_USER =0x400000
APP_PROTOCOL_RX_DATA_EVENT = (Q_USER + 100),
APP_PROTOCOL_TX_DATA_EVENT,
APP_PROTOCOL_TASK_EXIT,
};
//参数配置类接口(在库外面的文件common区)
//配置在init之前的参数接口
void app_protocol_set_product_id(u32 handler_id, u32 pid);
void app_protocol_set_vendor_id(u32 handler_id, u32 vid);
void app_protocol_set_local_version(u32 handler_id, u32 version);
void app_protocol_set_info_group(u32 handler_id, void *addr); //如配置三元组
void app_protocol_tws_role_check_register(u8(*handler)(void)); /*注册获取tws状态的函数接口*/
void app_protocol_set_tws_sibling_mac(u8 *mac);
//公共类函数接口
/*这个接口主要是建立一个线程注册一些协议需要用的公共接口比如resumemessage_handler等函数。建立了线程之后初始化*/
void app_protocol_all_init();
void app_protocol_init(int handler_id);
/*主要是删除线程操作在删除完之后再释放APP协议栈的资源*/
void app_protocol_exit(int handler_id);
/*开始语音识别功能*/
int app_protocol_start_speech_cmd();
/*手动停止语音识别功能*/
int app_protocol_stop_speech_cmd();
int app_protocol_left_start_speech_cmd();
int app_protocol_right_start_speech_cmd();
void app_protocol_update_battery(u8 main, u8 left, u8 right, u8 box);
void app_protocol_ble_adv_switch(int sw);
void app_protocol_ibeacon_switch(int sw);
void app_protocol_disconnect(void *addr);
void app_protocol_get_tws_data_for_lib(u8 *data, u32 len);
/*发送mic相应编码后的数据*/
int app_protocol_send_voice_data(uint8_t *voice_buf, uint16_t voice_len);
/*获取有没有链路连接完成状态*/
int app_protocol_check_connect_success();
bool is_tws_master_role();
u32 app_protocol_get_cur_handle_id();
int app_protocol_get_version_by_id(int id);
int app_protocol_reply_frame_check_result(int result);
void app_protocal_update_tws_state_to_lib(int state);
#endif

View File

@ -0,0 +1,774 @@
#include "app_protocol_api.h"
#include "app_protocol_common.h"
#include "system/includes.h"
#include "app_config.h"
#include "audio_config.h"
#include "app_chargestore.h"
#include "app_power_manage.h"
#include "asm/charge.h"
#include "bt_tws.h"
#include "btstack/avctp_user.h"
#include "3th_profile_api.h"
#include "bt_common.h"
#include "tone_player.h"
#include "app_main.h"
#include "key_event_deal.h"
#if AI_APP_PROTOCOL
#if 1
#define APP_PROTOCOL_LOG printf
#define APP_PROTOCOL_DUMP put_buf
#else
#define APP_PROTOCOL_LOG(...)
#define APP_PROTOCOL_DUMP(...)
#endif
__attribute__((weak))
void app_protocol_tone_play(int index, int tws_sync)
{
}
static const char **app_tone_table = NULL;
static struct app_protocol_private_handle_t *private_handle;
extern u8 get_remote_dev_company(void);
#define REMOTE_DEV_ANDROID 1
#define REMOTE_DEV_IOS 2
bool is_ios_system(void)
{
APP_PROTOCOL_LOG("remote_dev_company :%d \n", get_remote_dev_company());
return (get_remote_dev_company() == REMOTE_DEV_IOS);
}
void app_protocol_tone_register(const char **tone_table)
{
app_tone_table = tone_table;
}
const char *app_protocol_get_tone(int index)
{
if (app_tone_table) {
return app_tone_table[index];
}
return NULL;
}
void app_protocol_handle_register(struct app_protocol_private_handle_t *hd)
{
private_handle = hd;
}
struct app_protocol_private_handle_t *app_protocol_get_handle()
{
return private_handle;
}
//协议私有同步消息处理函数
void app_protocol_tws_sync_private_deal(int cmd, int value)
{
if (private_handle && private_handle->tws_sync_func) {
private_handle->tws_sync_func(cmd, value);
}
}
//协议私有收到对耳数据处理函数
void app_protocol_tws_rx_data_private_deal(u16 opcode, u8 *data, u16 len)
{
if (private_handle && private_handle->tws_rx_from_siblling) {
private_handle->tws_rx_from_siblling(opcode, data, len);
}
}
int app_protocol_sys_event_private_deal(struct sys_event *event)
{
if (private_handle && private_handle->sys_event_handler) {
return private_handle->sys_event_handler(event);
}
return 0;
}
#if APP_PROTOCOL_SPEECH_EN
#define APP_PROTOCOL_MIC_TIMEOUT 8000 //mic使用超时时间0不限时
static u16 mic_timer = 0;
static u16 tone_after_exit_sniff_timer = 0;
static u8 exit_sniff_cnt = 0;
void __app_protocol_speech_stop(void)
{
if (ai_mic_is_busy()) {
if (mic_timer) {
sys_timeout_del(mic_timer);
mic_timer = 0;
}
APP_PROTOCOL_LOG("app_protocol_speech_stop\n");
ai_mic_rec_close();
app_protocol_stop_speech_cmd();
}
}
static void app_protocol_speech_timeout(void *priv)
{
APP_PROTOCOL_LOG(" speech timeout !!! \n");
__app_protocol_speech_stop();
}
static int app_protocol_speech_start_check()
{
if (BT_STATUS_TAKEING_PHONE == get_bt_connect_status()) {
APP_PROTOCOL_LOG("phone ing...\n");
return -1;
}
if (ai_mic_is_busy()) {
APP_PROTOCOL_LOG("mic activing...\n");
return -1;
}
return 0;
}
int __app_protocol_speech_start(void)
{
if (!app_protocol_speech_start_check() && ai_mic_rec_start() == 0) {
#if APP_PROTOCOL_MIC_TIMEOUT
mic_timer = sys_timeout_add(NULL, app_protocol_speech_timeout, APP_PROTOCOL_MIC_TIMEOUT);
#endif
return 0;
}
APP_PROTOCOL_LOG("speech start fail\n");
return -1;
}
int app_protocol_start_speech_by_app(u8 tone_en)
{
if (app_protocol_speech_start_check()) {
return -1;
}
if (app_var.siri_stu) {
APP_PROTOCOL_LOG("siri activing...\n");
return -1;
}
if (tone_en) {
app_protocol_tone_play(APP_RROTOCOL_TONE_SPEECH_APP_START, 1);
} else {
app_protocol_post_bt_event(AI_EVENT_SPEECH_START, NULL);
}
return 0;
}
int app_protocol_stop_speech_by_app()
{
app_protocol_post_bt_event(AI_EVENT_SPEECH_STOP, NULL);
return 0;
}
static void speech_tone_play_after_exit_sniff()
{
tone_after_exit_sniff_timer = 0;
if (bt_is_sniff_close() && exit_sniff_cnt < 13) {
exit_sniff_cnt++;
tone_after_exit_sniff_timer = sys_timeout_add(NULL, speech_tone_play_after_exit_sniff, 100);
return;
}
exit_sniff_cnt = 0;
if (!app_protocol_speech_start_check()) {
app_protocol_tone_play(APP_RROTOCOL_TONE_SPEECH_KEY_START, 1);
}
}
int app_protocol_start_speech_by_key(struct sys_event *event)
{
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status() && !is_tws_master_role()) {
APP_PROTOCOL_LOG("tws slave, return\n");
return 0;
}
#endif
user_send_cmd_prepare(USER_CTRL_HFP_GET_SIRI_STATUS, 0, NULL);
if (app_protocol_speech_start_check()) {
return -1;
}
if (app_protocol_check_connect_success() && (get_curr_channel_state()&A2DP_CH)) {
printf("no connect\n");
} else {
if (get_curr_channel_state()&A2DP_CH) {
//<协议未连接, 但是A2DP已连接 点击唤醒键, 提示TTS【请打开小度APP】
if (is_ios_system()) {
APP_PROTOCOL_LOG("ble adv ibeaconn");
app_protocol_ibeacon_switch(1);
} else {
user_send_cmd_prepare(USER_CTRL_HFP_GET_SIRI_OPEN, 0, NULL);
}
app_protocol_tone_play(APP_PROTOCOL_TONE_DISCONNECTED_ALL, 1);
} else {
//<蓝牙完全关闭状态, 用户按唤醒键, 提示TTS【蓝牙未连接 请用手机蓝牙和我连接吧】
app_protocol_tone_play(APP_RROTOCOL_TONE_OPEN_APP, 1);
}
APP_PROTOCOL_LOG("A2dp or protocol no connect err!!!\n");
return -1;
}
#if 1//等退出sniff后再播提示音
if (bt_is_sniff_close()) {
user_send_cmd_prepare(USER_CTRL_ALL_SNIFF_EXIT, 0, NULL);
if (tone_after_exit_sniff_timer == 0) {
tone_after_exit_sniff_timer = sys_timeout_add(NULL, speech_tone_play_after_exit_sniff, 100);
}
return 0;
}
exit_sniff_cnt = 0;
#endif
app_protocol_tone_play(APP_RROTOCOL_TONE_SPEECH_KEY_START, 1);
return 0;
}
int app_protocol_stop_speech_by_key(void)
{
return 0;
}
#else
void __app_protocol_speech_stop(void)
{
}
#endif
void app_speech_tone_play_end_callback(void *priv, int flag)
{
u32 index = (u32)priv;
switch (index) {
#if APP_PROTOCOL_SPEECH_EN
case APP_RROTOCOL_TONE_SPEECH_KEY_START:
APP_PROTOCOL_LOG("APP_RROTOCOL_TONE_SPEECH_KEY_START\n");
if (app_protocol_speech_start_check()) {
break;
}
if (app_var.siri_stu) {
APP_PROTOCOL_LOG("siri activing...\n");
break;
}
///按键启动需要report, app启动 直接启动语音即可
if (is_tws_master_role() && !app_protocol_start_speech_cmd()) {//从转发mic数据给主机或主机上报完成开启mic
APP_PROTOCOL_LOG("app_protocol_mic_status_report success\n");
app_protocol_post_bt_event(AI_EVENT_SPEECH_START, NULL);
}
break;
case APP_RROTOCOL_TONE_SPEECH_APP_START:
APP_PROTOCOL_LOG("APP_RROTOCOL_TONE_SPEECH_APP_START\n");
if (app_protocol_speech_start_check()) {
break;
}
if (app_var.siri_stu) {
APP_PROTOCOL_LOG("siri activing...\n");
break;
}
if (is_tws_master_role()) {
app_protocol_post_bt_event(AI_EVENT_SPEECH_START, NULL);
}
break;
#endif
default:
break;
}
}
int app_protocol_set_volume(u8 vol)
{
u8 vol_l = (vol * get_max_sys_vol()) / 0x64;
u8 vol_r = (vol * get_max_sys_vol()) / 0x64;
app_audio_set_volume(APP_AUDIO_STATE_MUSIC, APP_AUDIO_STATE_MUSIC, vol_r);
return 0;
}
__attribute__((weak))
bool vbat_is_low_power(void)
{
return 0;
}
u8 app_protocal_get_bat_by_type(u8 type)
{
u8 value = 0;
extern u8 get_tws_sibling_bat_persent(void);
u8 sibling_val = get_tws_sibling_bat_persent();
#if TCFG_CHARGESTORE_ENABLE
if (sibling_val == 0xff) {
sibling_val = chargestore_get_sibling_power_level();
}
#endif
switch (type) {
case APP_PROTOCOL_BAT_T_CHARGE_FLAG:
value = get_charge_online_flag();
break;
case APP_PROTOCOL_BAT_T_MAIN:
value = get_vbat_percent();
break;
#if TCFG_CHARGESTORE_ENABLE
case APP_PROTOCOL_BAT_T_BOX:
value = chargestore_get_power_level();
break;
#endif
case APP_PROTOCOL_BAT_T_TWS_LEFT:
value = (tws_api_get_local_channel() == 'L') ? get_vbat_percent() : sibling_val;
break;
case APP_PROTOCOL_BAT_T_TWS_RIGHT:
value = (tws_api_get_local_channel() == 'R') ? get_vbat_percent() : sibling_val;
break;
case APP_PROTOCOL_BAT_T_TWS_SIBLING:
value = sibling_val;
break;
case APP_PROTOCOL_BAT_T_LOW_POWER:
value = vbat_is_low_power();
break;
default:
break;
}
if (value == 0xff) { //获取不到电量返回0
value = 0;
}
return value;
}
u32 read_cfg_file(void *buf, u16 len, char *path)
{
FILE *fp = fopen(path, "r");
int rlen;
if (!fp) {
//printf("read_cfg_file:fopen err!\n");
return FALSE;
}
rlen = fread(fp, buf, len);
if (rlen <= 0) {
//printf("read_cfg_file:fread err!\n");
return FALSE;
}
fclose(fp);
return TRUE;
}
#define LIC_PAGE_OFFSET 80
#define FORCE_TO_ERASE 1
typedef enum _FLASH_ERASER {
CHIP_ERASER = 0,
BLOCK_ERASER,
SECTOR_ERASER,
PAGE_ERASER,
} FLASH_ERASER;
typedef struct __flash_of_lic_para_head {
s16 crc;
u16 string_len;
const u8 para_string[];
} __attribute__((packed)) _flash_of_lic_para_head;
static bool license_para_head_check(u8 *para)
{
_flash_of_lic_para_head *head;
//fill head
head = (_flash_of_lic_para_head *)para;
///crc check
u8 *crc_data = (u8 *)(para + sizeof(((_flash_of_lic_para_head *)0)->crc));
u32 crc_len = sizeof(_flash_of_lic_para_head) - sizeof(((_flash_of_lic_para_head *)0)->crc)/*head crc*/ + (head->string_len)/*content crc,include end character '\0'*/;
s16 crc_sum = 0;
crc_sum = CRC16(crc_data, crc_len);
if (crc_sum != head->crc) {
printf("license crc error !!! %x %x \n", (u32)crc_sum, (u32)head->crc);
return false;
}
return true;
}
//获取三元组信息的头指针
const u8 *app_protocal_get_license_ptr(void)
{
u32 flash_capacity = sdfile_get_disk_capacity();
u32 flash_addr = flash_capacity - 256 + LIC_PAGE_OFFSET;
u8 *lic_ptr = NULL;
_flash_of_lic_para_head *head;
printf("flash capacity:%x \n", flash_capacity);
lic_ptr = (u8 *)sdfile_flash_addr2cpu_addr(flash_addr);
//head length check
head = (_flash_of_lic_para_head *)lic_ptr;
if (head->string_len >= 0xff) {
printf("license length error !!! \n");
return NULL;
}
////crc check
if (license_para_head_check(lic_ptr) == (false)) {
printf("license head check fail\n");
return NULL;
}
//put_buf(lic_ptr, 128);
lic_ptr += sizeof(_flash_of_lic_para_head);
return lic_ptr;
}
extern bool sfc_erase(int cmd, u32 addr);
extern u32 sfc_write(const u8 *buf, u32 addr, u32 len);
//将三元组信息保存到flash里面
int app_protocol_license2flash(const u8 *data, u16 len)
{
_flash_of_lic_para_head header;
u8 buffer[256];
u32 flash_capacity = sdfile_get_disk_capacity();
u32 sector = flash_capacity - 4 * 1024;
u32 page_addr = flash_capacity - 256;
u8 *auif_ptr = (u8 *)sdfile_flash_addr2cpu_addr(page_addr);
#if (!FORCE_TO_ERASE)
APP_PROTOCOL_LOG("not supported flash erase !!! \n");
return (-1);
#endif
///save last 256 byte
/* memset(buffer, 0xff, sizeof(buffer)); */
memcpy(buffer, auif_ptr, sizeof(buffer));
auif_ptr += LIC_PAGE_OFFSET;
header.string_len = len;
///length
memcpy(&buffer[LIC_PAGE_OFFSET + sizeof(header.crc)], &(header.string_len), sizeof(header.string_len));
///context
memcpy(&buffer[LIC_PAGE_OFFSET + sizeof(header)], data, len);
///crc
header.crc = CRC16(&buffer[LIC_PAGE_OFFSET + sizeof(header.crc)], sizeof(header.string_len) + header.string_len);
memcpy(&buffer[LIC_PAGE_OFFSET], &(header.crc), sizeof(header.crc));
///check if need update data to flash,erease license erea if there are some informations in license erea
if (!memcmp(auif_ptr, buffer + LIC_PAGE_OFFSET, len + sizeof(_flash_of_lic_para_head))) {
APP_PROTOCOL_LOG("flash information the same with license\n");
return 0;
}
APP_PROTOCOL_LOG("erase license sector \n");
sfc_erase(SECTOR_ERASER, sector);
APP_PROTOCOL_LOG("write license to flash \n");
sfc_write(buffer, page_addr, 256);
return 0;
}
int app_protocol_tws_send_to_sibling(u16 opcode, u8 *data, u16 len)
{
u8 send_data[len + 4];
printf("app protocol send data to sibling \n");
send_data[0] = opcode & 0xff;
send_data[1] = opcode >> 8;
send_data[2] = len & 0xff;
send_data[3] = len >> 8;
memcpy(send_data + 4, data, len);
return tws_api_send_data_to_sibling(send_data, sizeof(send_data), APP_PROTOCOL_TWS_SEND_ID);
}
static void __tws_rx_from_sibling(u8 *data)
{
u16 opcode = (data[1] << 8) | data[0];
u16 len = (data[3] << 8) | data[2];
u8 *rx_data = data + 4;
switch (opcode) {
case APP_PROTOCOL_TWS_FOR_LIB:
APP_PROTOCOL_LOG("APP_PROTOCOL_TWS_FOR_LIB");
app_protocol_get_tws_data_for_lib(rx_data, len);
break;
}
app_protocol_tws_rx_data_private_deal(opcode, rx_data, len);
free(data);
}
static void app_protocol_rx_from_sibling(void *_data, u16 len, bool rx)
{
int err = 0;
if (rx) {
printf(">>>%s \n", __func__);
printf("len :%d\n", len);
put_buf(_data, len);
u8 *rx_data = malloc(len);
memcpy(rx_data, _data, len);
int msg[4];
msg[0] = (int)__tws_rx_from_sibling;
msg[1] = 1;
msg[2] = (int)rx_data;
err = os_taskq_post_type("app_core", Q_CALLBACK, 3, msg);
if (err) {
printf("tws rx post fail\n");
}
}
}
//发送给对耳
REGISTER_TWS_FUNC_STUB(app_vol_sync_stub) = {
.func_id = APP_PROTOCOL_TWS_SEND_ID,
.func = app_protocol_rx_from_sibling,
};
//对耳同步执行
int app_protocol_tws_sync_send(int cmd, int value)
{
int data[2];
data[0] = cmd;
data[1] = value;
return tws_api_send_data_to_slave(data, sizeof(data), APP_PROTOCOL_TWS_SYNC_ID);
}
void app_protocol_tws_sync_deal(int cmd, int value)
{
switch (cmd) {
case APP_PROTOCOL_SYNC_TONE:
printf("APP_PROTOCOL_SYNC_TONE:%d\n", value);
app_protocol_tone_play(value, 0);
break;
}
app_protocol_tws_sync_private_deal(cmd, value);
}
static void app_protocol_tws_sync_rx(void *data, u16 len, bool rx)
{
int err = 0;
int *arg = (int *)data;
int msg[8];
msg[0] = (int)app_protocol_tws_sync_deal;
msg[1] = len / sizeof(int);
msg[2] = arg[0]; //cmd
msg[3] = arg[1]; //value
err = os_taskq_post_type("app_core", Q_CALLBACK, 2 + len / sizeof(int), msg);
if (err) {
printf("tws sync post fail\n");
}
}
REGISTER_TWS_FUNC_STUB(app_protocol_sync) = {
.func_id = APP_PROTOCOL_TWS_SYNC_ID,
.func = app_protocol_tws_sync_rx,
};
//在app_core任务里面进行处理
int app_protocol_post_app_core_callback(int callback, void *priv)
{
int msg[8];
msg[0] = callback;
msg[1] = 1;
msg[2] = (int)priv;
return os_taskq_post_type("app_core", Q_CALLBACK, 3, msg);
}
void app_protocol_post_bt_event(u8 event, void *priv)
{
struct sys_event e;
memset(&e, 0, sizeof(e));
e.type = SYS_BT_EVENT;
e.arg = (void *)SYS_BT_AI_EVENT_TYPE_STATUS;
e.u.bt.event = event;
e.u.bt.value = (int)priv;
sys_event_notify(&e);
}
static int app_protocol_bt_status_event_handler(struct bt_event *bt)
{
switch (bt->event) {
case BT_STATUS_INIT_OK:
app_protocol_all_init();
break;
case BT_STATUS_SECOND_CONNECTED:
case BT_STATUS_FIRST_CONNECTED:
if (app_protocol_check_connect_success()) {
app_protocol_tone_play(APP_PROTOCOL_TONE_CONNECTED_ALL_FINISH, 1);
} else {
app_protocol_tone_play(APP_PROTOCOL_TONE_CONNECTED_NEED_OPEN_APP, 1);
}
break;
case BT_STATUS_FIRST_DISCONNECT:
case BT_STATUS_SECOND_DISCONNECT:
app_protocol_tone_play(APP_PROTOCOL_TONE_DISCONNECTED, 1);
app_protocal_update_tws_state_to_lib(USER_NOTIFY_STATE_MOBILE_DISCONNECTED);
break;
case BT_STATUS_PHONE_INCOME:
case BT_STATUS_PHONE_OUT:
case BT_STATUS_PHONE_ACTIVE:
__app_protocol_speech_stop();
app_protocol_ble_adv_switch(0);
break;
case BT_STATUS_PHONE_HANGUP:
app_protocol_ble_adv_switch(1);
break;
case BT_STATUS_PHONE_MANUFACTURER:
if (!app_protocol_check_connect_success()) {
if (is_ios_system()) {
app_protocol_ibeacon_switch(1);
}
if (get_call_status() != BT_CALL_HANGUP) {
app_protocol_ble_adv_switch(0);
}
}
break;
case BT_STATUS_VOICE_RECOGNITION:
if ((app_var.siri_stu == 1) || (app_var.siri_stu == 2)) {
__app_protocol_speech_stop();
app_protocol_ble_adv_switch(0);
} else if (app_var.siri_stu == 0) {
app_protocol_ble_adv_switch(1);
}
break;
case BT_STATUS_CONN_A2DP_CH:
app_protocal_update_tws_state_to_lib(USER_NOTIFY_STATE_MOBILE_CONNECTED);
break;
}
return 0;
}
static void app_protocol_bt_tws_event_handler(struct bt_event *bt)
{
int role = bt->args[0];
int phone_link_connection = bt->args[1];
int reason = bt->args[2];
switch (bt->event) {
case TWS_EVENT_CONNECTED:
if (!is_tws_master_role()) {
app_protocol_disconnect(NULL);
app_protocol_ble_adv_switch(0);
} else {
#if APP_PROTOCOL_SPEECH_EN
if (ai_mic_is_busy()) { //mic在解码过程中从机连接成功挂起音频
ai_mic_tws_sync_suspend();
}
#endif
}
app_protocal_update_tws_state_to_lib(USER_NOTIFY_STATE_TWS_CONNECT);
break;
case TWS_EVENT_CONNECTION_DETACH:
if (!app_protocol_check_connect_success()) { //APP未连接开启广播
if (0 == get_esco_coder_busy_flag()) {
//esco在用的时候开广播会影响质量
app_protocol_ble_adv_switch(1);
}
}
#if APP_PROTOCOL_SPEECH_EN
if (!ai_mic_is_busy()) {
__app_protocol_speech_stop(); //对耳断开时没启动mic停止语音
}
#endif
app_protocal_update_tws_state_to_lib(USER_NOTIFY_STATE_BATTERY_LEVEL_UPDATE); //主动上报电量
app_protocal_update_tws_state_to_lib(USER_NOTIFY_STATE_TWS_DISCONNECT);
break;
case TWS_EVENT_ROLE_SWITCH:
app_protocal_update_tws_state_to_lib(USER_NOTIFY_STATE_ROLE_SWITCH_FINISH);
app_protocol_disconnect(NULL);
if (role == TWS_ROLE_MASTER && (0 == get_esco_coder_busy_flag())) {
app_protocol_ble_adv_switch(1);
} else {
app_protocol_ble_adv_switch(0);
}
break;
}
}
static int app_protocol_bt_ai_event_handler(struct bt_event *bt)
{
switch (bt->event) {
#if APP_PROTOCOL_SPEECH_EN
case AI_EVENT_SPEECH_START:
APP_PROTOCOL_LOG("AI_EVENT_SPEECH_START");
__app_protocol_speech_start();
break;
case AI_EVENT_SPEECH_STOP:
APP_PROTOCOL_LOG("AI_EVENT_SPEECH_STOP");
__app_protocol_speech_stop();
break;
#endif
case AI_EVENT_APP_CONNECT:
APP_PROTOCOL_LOG("AI_EVENT_APP_CONNECT");
if (get_curr_channel_state()&A2DP_CH) {
app_protocol_tone_play(APP_PROTOCOL_TONE_CONNECTED_ALL_FINISH, 1);
} else {
app_protocol_tone_play(APP_PROTOCOL_TONE_PROTOCOL_CONNECTED, 1);
}
break;
case AI_EVENT_APP_DISCONNECT:
APP_PROTOCOL_LOG("AI_EVENT_APP_DISCONNECT");
__app_protocol_speech_stop();
break;
}
return 0;
}
int app_protocol_sys_event_handler(struct sys_event *event)
{
#if TCFG_USER_GFPS_PROCESS_CTL
if (app_user_protocol_sys_event_remap_hdl(event) == true) {
return 0;
}
#endif
switch (event->type) {
case SYS_BT_EVENT:
if ((u32)event->arg == SYS_BT_EVENT_TYPE_CON_STATUS) {
app_protocol_bt_status_event_handler(&event->u.bt);
}
#if TCFG_USER_TWS_ENABLE
else if (((u32)event->arg == SYS_BT_EVENT_FROM_TWS)) {
app_protocol_bt_tws_event_handler(&event->u.bt);
}
#endif
else if (((u32)event->arg == SYS_BT_AI_EVENT_TYPE_STATUS)) {
app_protocol_bt_ai_event_handler(&event->u.bt);
}
break;
case SYS_KEY_EVENT:
app_protocol_key_event_handler(event);
break;
}
app_protocol_sys_event_private_deal(event);
return 0;
}
void tell_lib_start_role_switch()
{
app_protocol_ble_adv_switch(0);
if (is_tws_master_role()) {
printf("master dev will role switch\n");
app_protocal_update_tws_state_to_lib(USER_NOTIFY_STATE_ROLE_SWITCH_START);
/* os_time_dly(10); */
}
}
#else
int app_protocol_sys_event_handler(struct sys_event *event)
{
return 0;
}
void tell_lib_start_role_switch()
{
}
#endif

View File

@ -0,0 +1,108 @@
#ifndef _3TH_PROTOCOL_COMMON_H
#define _3TH_PROTOCOL_COMMON_H
#include <string.h>
#include <stdint.h>
#include "typedef.h"
#include "tone_player.h"
#include "audio_base.h"
#include "system/event.h"
#ifndef TONE_RES_ROOT_PATH
#if TCFG_NOR_FS && (TCFG_VIRFAT_FLASH_ENABLE == 0)
#define NOR_FLASH_RES_ROOT_PATH "storage/res_nor/C/"
#define TONE_RES_ROOT_PATH NOR_FLASH_RES_ROOT_PATH //内置flash提示音根路径
#else
#define TONE_RES_ROOT_PATH SDFILE_RES_ROOT_PATH //内置flash提示音根路径
#endif//TCFG_NOR_FS
#endif
#define APP_PROTOCOL_TWS_SYNC_ID 0xFFFF321A
#define APP_PROTOCOL_TWS_SEND_ID 0xFFFF321B
enum {
APP_PROTOCOL_TONE_CONNECTED_ALL_FINISH = 0,//所有连接完成【已连接你可以按AI键来和我进行对话】 ok
APP_PROTOCOL_TONE_PROTOCOL_CONNECTED,//APP已连接经典蓝牙未连接【请在手机上完成蓝牙配对】 con
APP_PROTOCOL_TONE_CONNECTED_NEED_OPEN_APP,//经典蓝牙已连接app未连接【已配对请打开app进行连接】 btcon
APP_PROTOCOL_TONE_DISCONNECTED,//经典蓝牙已断开【蓝牙已断开,请在手机上完成蓝牙配对】 dis
APP_PROTOCOL_TONE_DISCONNECTED_ALL,//经典蓝牙和【蓝牙未连接请用手机蓝牙和我连接吧】alldis
APP_RROTOCOL_TONE_OPEN_APP,//经典蓝牙已连接APP未连接【请打开APP】 app
APP_RROTOCOL_TONE_SPEECH_APP_START,//手机APP启动语音助手
APP_RROTOCOL_TONE_SPEECH_KEY_START,//按键启动语音助手
APP_RROTOCOL_TONE_MAX,//提示音最大数量
};
//发送给对耳的消息格式为opcode len data
enum {
APP_PROTOCOL_TWS_FOR_LIB = 0,
GMA_TWS_CMD_SYNC_LIC,
};
//对耳同步的命令格式为cmd value
enum {
APP_PROTOCOL_SYNC_TONE = 0,
};
//发送到系统事件处理的事件
enum {
AI_EVENT_SPEECH_START = 0,
AI_EVENT_SPEECH_STOP,
AI_EVENT_APP_CONNECT,
AI_EVENT_APP_DISCONNECT,
};
struct app_protocol_private_handle_t {
void (*tws_rx_from_siblling)(u16 opcode, u8 *data, u16 len); //收到对耳数据的处理接口
void (*tws_sync_func)(int cmd, int value); //对耳同步执行的接口
int (*sys_event_handler)(struct sys_event *event); //系统事件
};
//提示音注册和播放
void app_protocol_tone_register(const char **tone_table);
const char *app_protocol_get_tone(int index);
void app_protocol_tone_play(int index, int tws_sync);
void app_speech_tone_play_end_callback(void *priv, int flag); //提示音播放完毕回调函数
extern int ai_mic_is_busy(void); //mic正在被使用
extern int ai_mic_rec_start(void); //启动mic和编码模块
extern int ai_mic_rec_close(void); //停止mic和编码模块
extern bool bt_is_sniff_close(void);
//语音识别接口
int mic_rec_pram_init(/* const char **name, */u32 enc_type, u8 opus_type, u16(*speech_send)(u8 *buf, u16 len), u16 frame_num, u16 cbuf_size);
int __app_protocol_speech_start(void);
void __app_protocol_speech_stop(void);
int app_protocol_start_speech_by_app(u8 tone_en); //APP启动
int app_protocol_stop_speech_by_app(); //APP停止
int app_protocol_start_speech_by_key(struct sys_event *event); //按键启动
int app_protocol_stop_speech_by_key(void); //按键停止
//协议获取和设置一些设备信息接口
int app_protocol_set_volume(u8 vol);
u8 app_protocal_get_bat_by_type(u8 type);
u32 read_cfg_file(void *buf, u16 len, char *path);
const u8 *app_protocal_get_license_ptr(void); //获取三元组信息的头指针
int app_protocol_license2flash(const u8 *data, u16 len); //将三元组信息保存到flash里面
//事件处理函数指针列表注册和接口
void app_protocol_handle_register(struct app_protocol_private_handle_t *hd);
struct app_protocol_private_handle_t *app_protocol_get_handle();
void app_protocol_tws_sync_private_deal(int cmd, int value); //对耳同步事件私有协议处理函数
void app_protocol_tws_rx_data_private_deal(u16 opcode, u8 *data, u16 len); //私有协议处理来自对耳的数据函数
int app_protocol_sys_event_private_deal(struct sys_event *event); //私有协议处理系统事件函数
void app_protocol_post_bt_event(u8 event, void *priv); //发送到系统事件处理
int app_protocol_post_app_core_callback(int callback, void *priv); //放到app_core中处理
int app_protocol_tws_send_to_sibling(u16 opcode, u8 *data, u16 len); //发送命令数据给对耳
int app_protocol_tws_sync_send(int cmd, int value); //对耳同步执行命令
int app_protocol_key_event_handler(struct sys_event *event); //按键事件处理函数
int app_protocol_sys_event_handler(struct sys_event *event); //系统事件处理函数
#endif

View File

@ -0,0 +1,147 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "app_protocol_api.h"
#include "system/includes.h"
#include "vm.h"
#include "audio_config.h"
#include "app_power_manage.h"
#include "user_cfg.h"
#if APP_PROTOCOL_DMA_CODE
#if 1
#define APP_DMA_LOG printf
#define APP_DMA_DUMP put_buf
#else
#define APP_DMA_LOG(...)
#define APP_DMA_DUMP(...)
#endif
//*********************************************************************************//
// DMA认证信息 //
//*********************************************************************************//
#define DMA_PRODUCT_INFO_TEST 0
#if DMA_PRODUCT_INFO_TEST
static const char *dma_product_id = "abcdeYghv0fy6HFexl6bTIZU123Z4n6H";
static const char *dma_triad_id = "A254BcBb000E00D200A0C0E3";
static const char *dma_secret = "bab8d7e0dc616630";
#endif
static const char *dma_product_key = "rcPXDpFbBOxXaDL9GZ8qLTWq7Yz8rWFm";
#define DMA_PRODUCT_ID_LEN 65
#define DMA_PRODUCT_KEY_LEN 65
#define DMA_TRIAD_ID_LEN 32
#define DMA_SECRET_LEN 32
#define DMA_LEGAL_CHAR(c) ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
static u16 dma_get_one_info(const u8 *in, u8 *out)
{
int read_len = 0;
const u8 *p = in;
while (DMA_LEGAL_CHAR(*p) && *p != ',') { //read Product ID
*out++ = *p++;
read_len++;
}
return read_len;
}
u8 read_dma_product_info_from_flash(u8 *read_buf, u16 buflen)
{
u8 *rp = read_buf;
const u8 *dma_ptr = (u8 *)app_protocal_get_license_ptr();
if (dma_ptr == NULL) {
return FALSE;
}
if (dma_get_one_info(dma_ptr, rp) != 32) {
return FALSE;
}
dma_ptr += 33;
rp = read_buf + DMA_PRODUCT_ID_LEN;
memcpy(rp, dma_product_key, strlen(dma_product_key));
rp = read_buf + DMA_PRODUCT_ID_LEN + DMA_PRODUCT_KEY_LEN;
if (dma_get_one_info(dma_ptr, rp) != 24) {
return FALSE;
}
dma_ptr += 25;
rp = read_buf + DMA_PRODUCT_ID_LEN + DMA_PRODUCT_KEY_LEN + DMA_TRIAD_ID_LEN;
if (dma_get_one_info(dma_ptr, rp) != 16) {
return FALSE;
}
return TRUE;
}
__attribute__((weak))
void bt_update_testbox_addr(u8 *addr)
{
}
void dueros_dma_manufacturer_info_init()
{
u8 read_buf[DMA_PRODUCT_ID_LEN + DMA_PRODUCT_KEY_LEN + DMA_TRIAD_ID_LEN + DMA_SECRET_LEN + 1] = {0};
bool ret = FALSE;
APP_DMA_LOG("dueros_dma_manufacturer_info_init\n");
#if DMA_PRODUCT_INFO_TEST
memcpy(read_buf, dma_product_id, strlen(dma_product_id));
memcpy(read_buf + DMA_PRODUCT_ID_LEN, dma_product_key, strlen(dma_product_key));
memcpy(read_buf + DMA_PRODUCT_ID_LEN + DMA_PRODUCT_KEY_LEN, dma_triad_id, strlen(dma_triad_id));
memcpy(read_buf + DMA_PRODUCT_ID_LEN + DMA_PRODUCT_KEY_LEN + DMA_TRIAD_ID_LEN, dma_secret, strlen(dma_secret));
ret = TRUE;
#else
// ret = read_dma_product_info_from_flash(read_buf, sizeof(read_buf));
#endif
if (ret == TRUE) {
APP_DMA_LOG("read license success\n");
APP_DMA_LOG("product id: %s\n", read_buf);
APP_DMA_LOG("product key: %s\n", read_buf + DMA_PRODUCT_ID_LEN);
APP_DMA_LOG("triad id: %s\n", read_buf + DMA_PRODUCT_ID_LEN + DMA_PRODUCT_KEY_LEN);
APP_DMA_LOG("secret: %s\n", read_buf + DMA_PRODUCT_ID_LEN + DMA_PRODUCT_KEY_LEN + DMA_TRIAD_ID_LEN);
app_protocol_set_info_group(DMA_HANDLER_ID, read_buf);
} else {
app_protocol_set_info_group(DMA_HANDLER_ID, NULL);
}
#if 1
u8 mac[] = {0xF4, 0x43, 0x8D, 0x29, 0x17, 0x02};
u8 ble_mac[6];
void bt_update_mac_addr(u8 * addr);
void lmp_hci_write_local_address(const u8 * addr);
void bt_update_testbox_addr(u8 * addr);
extern int le_controller_set_mac(void *addr);
//extern void lib_make_ble_address(u8 * ble_address, u8 * edr_address);
bt_update_mac_addr(mac);
lmp_hci_write_local_address(mac);
bt_update_testbox_addr(mac);
//lib_make_ble_address(ble_mac, mac);
le_controller_set_mac(mac); //修改BLE地址
APP_DMA_DUMP(mac, 6);
APP_DMA_DUMP(ble_mac, 6);
#endif
}
//*********************************************************************************//
// DMA提示音 //
//*********************************************************************************//
const char *dma_notice_tab[APP_RROTOCOL_TONE_MAX] = {
[APP_PROTOCOL_TONE_CONNECTED_ALL_FINISH] = TONE_RES_ROOT_PATH"tone/xd_ok.*",//所有连接完成【已连接你可以按AI键来和我进行对话】
[APP_PROTOCOL_TONE_PROTOCOL_CONNECTED] = TONE_RES_ROOT_PATH"tone/xd_con.*",//小度APP已连接经典蓝牙未连接【请在手机上完成蓝牙配对】
[APP_PROTOCOL_TONE_CONNECTED_NEED_OPEN_APP] = TONE_RES_ROOT_PATH"tone/xd_btcon.*",//经典蓝牙已连接小度app未连接【已配对请打开小度app进行连接】
[APP_PROTOCOL_TONE_DISCONNECTED] = TONE_RES_ROOT_PATH"tone/xd_dis.*",//经典蓝牙已断开【蓝牙已断开,请在手机上完成蓝牙配对】
[APP_PROTOCOL_TONE_DISCONNECTED_ALL] = TONE_RES_ROOT_PATH"tone/xd_alldis.*",//经典蓝牙和小度都断开了【蓝牙未连接,请用手机蓝牙和我连接吧】
[APP_RROTOCOL_TONE_SPEECH_APP_START] = TONE_NORMAL,
[APP_RROTOCOL_TONE_SPEECH_KEY_START] = TONE_NORMAL,
};
#endif

View File

@ -0,0 +1,424 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "app_protocol_api.h"
#include "system/includes.h"
#include "vm.h"
#include "audio_config.h"
#include "app_power_manage.h"
#include "user_cfg.h"
#include "earphone.h"
#include "btstack/avctp_user.h"
#include "btstack/bluetooth.h"
#include "bt_tws.h"
#if AI_APP_PROTOCOL
#if APP_PROTOCOL_GFPS_CODE
extern void *gfps_app_ble_hdl;
/* extern u32 unactice_device_cmd_prepare(USER_CMD_TYPE cmd, u16 param_len, u8 *param); */
extern void tws_dual_conn_close();
extern int gfps_tws_data_deal(u8 *data, int len);
extern void audio_app_volume_set(u8 state, s16 volume, u8 fade);
extern bool get_gfps_pair_state(void);
extern void set_gfps_pair_state(u8 state);
extern void gfps_set_battery_ui_enable(uint8_t enable);
extern void gfps_set_pair_mode(void *priv);
extern void gfps_all_info_recover(u8 name_reset);
extern void gfps_sibling_sync_info();
extern int gfps_disconnect(void *addr);
extern void gfps_bt_ble_adv_enable(u8 enable);
extern void gfps_adv_interval_set(u16 value);
extern void gfps_sibling_data_send(u8 type, u8 *data, u16 len);
extern int gfps_ble_adv_enable(u8 enable);
extern void gfps_battery_update(void);
extern void bt_set_need_keep_scan(u8 en);
extern int audio_digital_vol_update_parm(u8 dvol_idx, s32 param);
extern void set_wait_poweroff_time(u16 time);
/**
弹窗的逻辑:
1、没有任何手机配对记录情况广播初始配对广播。
2、开机有配对记录广播后续配对广播回连超时进入配对状态时广播初始配对广播。
3、回连手机发现linkkey_missing且没有任何手机配对记录了广播初始配对广播。
4、连上任意一台手机后 广播后续配对广播,断开进入配对状态也是广播后续配对广播。(客户要求断开后也广播初始配对广播)
5、恢复出厂设置时需要调用一下gfps_all_info_recover(1)清除一下GFP的账号信息和修改的蓝牙名字
6、认证的时候需要有一个UI来触发初始配对广播调用gfps_set_pair_mode(NULL)可以为长按左右耳5秒之类的
7、耳机关机要关电量显示
*/
#define TONE_GOOGLE "tone_en/google.*"
#define GFPS_SIBLING_SYNC_TYPE_ADV_MAC_STATE 0x04
#define ADV_INIT_PAIR_IN_PAIR_MODE 0 //进入配对状态广播初始配对广播
struct gfps_protocol_t {
u8 poweron_reconn;
u8 close_icon;
};
static struct gfps_protocol_t gfps_protocol = {0};
#define __this (&gfps_protocol)
#define INIT_PAIR_ADV_INTERVAL 150
#define SUBS_PAIR_ADV_INTERVAL 352
void gfps_set_pair_mode_by_user(u8 disconn_ble)
{
if (disconn_ble) {
gfps_disconnect(NULL);
}
gfps_adv_interval_set(INIT_PAIR_ADV_INTERVAL);
set_gfps_pair_state(0);
gfps_bt_ble_adv_enable(0);
gfps_bt_ble_adv_enable(1);
}
//重写弱函数,获取电量
extern u8 get_charge_online_flag(void);
extern u8 get_tws_sibling_bat_persent(void);
void generate_rfcomm_battery_data(u8 *data)
{
u8 self_val = get_charge_online_flag() << 7 | get_vbat_percent();
#if TCFG_USER_TWS_ENABLE
u8 sibling_val = get_tws_sibling_bat_persent();
data[2] = 0xFF; //充电仓电量
#if TCFG_CHARGESTORE_ENABLE
if (self_val >> 7 || sibling_val >> 7) { //有任意一直耳机充电时才显示充电仓电量
data[2] = chargestore_get_power_level(); //充电仓电量
}
#endif
data[0] = (tws_api_get_local_channel() == 'L') ? self_val : sibling_val; //左耳电量
data[1] = (tws_api_get_local_channel() == 'R') ? self_val : sibling_val; //右耳电量
#else
data[0] = self_val;
data[1] = 0xFF;
data[2] = 0xFF;
#endif
printf("%s, l:%x, r:%x, bat:%x", __func__, data[0], data[1], data[2]);
}
extern int lmp_hci_write_scan_enable(u8 enable);
static void gfps_ctl_bt_enter_pair_mode()
{
printf("%s", __func__);
tws_dual_conn_close();
lmp_hci_write_scan_enable((1 << 1) | 1);
bt_set_need_keep_scan(1);
}
//重写弱函数GFP-BLE配对认证成功后需要先断开一个设备或者开可连接等手机连接经典蓝牙
extern u8 *get_cur_connect_phone_mac_addr(void);
void gfps_before_pair_new_device(u8 *seeker_addr)
{
#if TCFG_USER_GFPS_PROCESS_CTL
app_user_gfps_before_pair_new_device(seeker_addr);
#else
u8 remote_edr_addr[6];
u8 *tmp_addr = NULL;
for (int i = 0; i < 6; i ++) {
remote_edr_addr[i] = seeker_addr[5 - i];
}
if (get_curr_channel_state()) {
tmp_addr = get_cur_connect_phone_mac_addr();
if (memcmp(tmp_addr, remote_edr_addr, 6) != 0) {
printf("Subsequent pair\n");
printf("USER_CTRL_DISCONNECTION_HCI send\n");
user_send_cmd_prepare(USER_CTRL_DISCONNECTION_HCI, 0, NULL);
} else {
printf("Retroactive Pair\n");
}
}
printf("func:%s, line:%d", __FUNCTION__, __LINE__);
#endif
}
struct google_tone_ctl_t {
u8 l_en;
u8 r_en;
u8 l_mute;
u8 r_mute;
};
static struct google_tone_ctl_t google_tone_ctl = {0};
static void google_tone_set_volume()
{
printf("google_tone_set_volume");
/* printf("func:%s:%d", __FUNCTION__, app_audio_volume_max_query(SysVol_TONE)); */
/* u32 param = VOLUME_NODE_CMD_SET_VOL | app_audio_volume_max_query(SysVol_TONE); */
/* jlstream_set_node_param(NODE_UUID_VOLUME_CTRLER, "Vol_BtcRing", &param, sizeof(param)); */
}
/* #if TCFG_USER_TWS_ENABLE */
/* static void tws_google_tone_callback(int priv, enum stream_event event) */
/* { */
/* printf("func:%s, event:%d", __FUNCTION__, event); */
/* if (event == STREAM_EVENT_START) { */
/* int msg[] = {(int)google_tone_set_volume, 0}; */
/* os_taskq_post_type("app_core", Q_CALLBACK, ARRAY_SIZE(msg), msg); */
/* } */
/* } */
/* REGISTER_TWS_TONE_CALLBACK(tws_google_tone_stub) = { */
/* .func_uuid = 0x2EC850AE, */
/* .callback = tws_google_tone_callback, */
/* }; */
/* #endif */
/* static int google_tone_play_callback(void *priv, enum stream_event event) */
/* { */
/* printf("func:%s, event:%d", __FUNCTION__, event); */
/* if (event == STREAM_EVENT_START) { */
/* int msg[] = {(int)google_tone_set_volume, 0}; */
/* os_taskq_post_type("app_core", Q_CALLBACK, ARRAY_SIZE(msg), msg); */
/* } */
/* return 0; */
/* } */
void google_tone_play_deal()
{
if (strcmp(os_current_task(), "app_core")) {
printf("%s, task:%s", __func__, os_current_task());
int msg[] = {(int)google_tone_play_deal, 0};
os_taskq_post_type("app_core", Q_CALLBACK, ARRAY_SIZE(msg), msg);
return;
}
/* tone_player_stop(); */
/* tone_player_play(); */
}
void google_tone_mute_ctl(u8 self, u8 charge_flag)
{
u8 *mute = &google_tone_ctl.l_mute;
if ((tws_api_get_local_channel() == 'L' && !self) ||
(tws_api_get_local_channel() == 'R' && self)) {
mute = &google_tone_ctl.r_mute;
printf("%s, r_mute:%d, charge_flag:%d", __func__, *mute, charge_flag);
} else {
printf("%s, l_mute:%d, charge_flag:%d", __func__, *mute, charge_flag);
}
if (*mute != charge_flag) {
*mute = charge_flag;
google_tone_play_deal();
}
}
int gfps_protocol_tws_send_to_sibling(u16 opcode, u8 *data, u16 len)
{
return tws_api_send_data_to_sibling(data, len, 0x23080315);
}
static void __tws_rx_from_sibling(u8 *data, int len)
{
gfps_tws_data_deal(data, len);
switch (data[0]) {
case GFPS_SIBLING_SYNC_TYPE_ADV_MAC_STATE:
gfps_adv_interval_set(data[1] ? SUBS_PAIR_ADV_INTERVAL : INIT_PAIR_ADV_INTERVAL);
set_gfps_pair_state(data[1]);
le_controller_set_mac((void *)&data[2]);
gfps_bt_ble_adv_enable(0);
gfps_bt_ble_adv_enable(1);
break;
}
free(data);
}
static void gfps_protocol_rx_from_sibling(void *_data, u16 len, bool rx)
{
int err = 0;
if (rx) {
printf(">>>%s \n", __func__);
printf("len :%d\n", len);
put_buf(_data, len);
u8 *rx_data = malloc(len);
if (!rx_data) {
return;
}
memcpy(rx_data, _data, len);
int msg[4];
msg[0] = (int)__tws_rx_from_sibling;
msg[1] = 2;
msg[2] = (int)rx_data;
msg[3] = (int)len;
err = os_taskq_post_type("app_core", Q_CALLBACK, ARRAY_SIZE(msg), msg);
if (err) {
printf("tws rx post fail\n");
}
}
}
//发送给对耳
REGISTER_TWS_FUNC_STUB(app_vol_sync_stub) = {
.func_id = 0x23080315,
.func = gfps_protocol_rx_from_sibling,
};
int gfps_message_deal_handler(int id, int opcode, u8 *data, u32 len)
{
switch (opcode) {
case APP_PROTOCOL_LIB_TWS_DATA_SYNC:
gfps_protocol_tws_send_to_sibling(opcode, data, len);
break;
case APP_PROTOCOL_GFPS_RING_STOP_ALL:
printf("GFPS_RING_STOP_ALL");
google_tone_ctl.l_en = 0;
google_tone_ctl.r_en = 0;
google_tone_play_deal();
break;
case APP_PROTOCOL_GFPS_RING_RIGHT:
printf("GFPS_RING_RIGHT");
google_tone_ctl.l_en = 0;
google_tone_ctl.r_en = 1;
google_tone_play_deal();
break;
case APP_PROTOCOL_GFPS_RING_LEFT:
printf("GFPS_RING_LEFT");
google_tone_ctl.l_en = 1;
google_tone_ctl.r_en = 0;
google_tone_play_deal();
break;
case APP_PROTOCOL_GFPS_RING_ALL:
printf("GFPS_RING_ALL");
google_tone_ctl.l_en = 1;
google_tone_ctl.r_en = 1;
google_tone_play_deal();
break;
case APP_PROTOCOL_GFPS_HEARABLE_CONTROLS:
printf("APP_PROTOCOL_GFPS_HEARABLE_CONTROLS display:%x settable:%x current:%x\n", data[0], data[1], data[2]);
break;
}
return 0;
}
//关机广播收仓
void gfps_need_adv_close_icon_set(u8 en)
{
printf("func:%s, en:%d", __FUNCTION__, en);
__this->close_icon = en;
}
void gfps_poweroff_adv_close_icon()
{
printf("func:%s, line:%d", __FUNCTION__, __LINE__);
if (__this->close_icon) {
void set_wait_poweroff_time(u16 time);
set_wait_poweroff_time(2000); //广播800ms
gfps_adv_interval_set(48); //连接上手机间隔改为30ms
gfps_set_battery_ui_enable(0); //关闭电量显示,会重新开关广播
}
}
int gfps_hci_event_handler(struct bt_event *bt)
{
switch (bt->event) {
case HCI_EVENT_DISCONNECTION_COMPLETE:
switch (bt->value) {
case ERROR_CODE_PIN_OR_KEY_MISSING:
printf("GFP linkkey missing");
if (!btstack_get_num_of_remote_device_recorded()) { //没有配对记录的时候,广播初始配对广播
gfps_all_info_recover(0);
gfps_adv_interval_set(INIT_PAIR_ADV_INTERVAL); //连接上手机间隔改为93.75ms
gfps_set_pair_mode_by_user(0);
}
break;
}
break;
}
return 0;
}
int gfps_bt_status_event_handler(struct bt_event *bt)
{
u8 ret = 0;
switch (bt->event) {
// 需要切换蓝牙的命令
case BT_STATUS_A2DP_MEDIA_START:
break;
case BT_STATUS_INIT_OK:
if (btstack_get_num_of_remote_device_recorded()) {
__this->poweron_reconn = 1;
}
break;
case BT_STATUS_SECOND_CONNECTED:
case BT_STATUS_FIRST_CONNECTED:
__this->poweron_reconn = 0;
gfps_adv_interval_set(SUBS_PAIR_ADV_INTERVAL); //连接上手机间隔改为220ms防止fast pair validator测试fail
set_gfps_pair_state(1);
gfps_bt_ble_adv_enable(0);
gfps_bt_ble_adv_enable(1);
break;
case BT_STATUS_PHONE_INCOME:
case BT_STATUS_PHONE_OUT:
case BT_STATUS_PHONE_ACTIVE:
gfps_ble_adv_enable(0);
break;
case BT_STATUS_PHONE_HANGUP:
gfps_ble_adv_enable(1);
break;
}
return 0;
}
static int gfps_app_power_event_handler(struct device_event *dev)
{
switch (dev->event) {
#if TCFG_USER_TWS_ENABLE
case POWER_EVENT_SYNC_TWS_VBAT_LEVEL:
printf("update gfps bat");
if (get_tws_sibling_bat_persent() != 0xFF) {
google_tone_mute_ctl(0, get_tws_sibling_bat_persent() >> 7);
}
gfps_battery_update();
break;
#endif
case POWER_EVENT_POWER_CHANGE:
printf("update gfps bat");
google_tone_mute_ctl(1, get_charge_online_flag());
gfps_battery_update();
break;
}
return 0;
}
int gfps_sys_event_handler_specific(struct sys_event *event)
{
switch (event->type) {
case SYS_DEVICE_EVENT:
if ((u32)event->arg == DEVICE_EVENT_FROM_POWER) {
gfps_app_power_event_handler(&event->u.dev);
}
break;
case SYS_BT_EVENT:
if ((u32)event->arg == SYS_BT_EVENT_TYPE_CON_STATUS) {
gfps_bt_status_event_handler(&event->u.bt);
} else if ((u32)event->arg == SYS_BT_EVENT_TYPE_HCI_STATUS) {
gfps_hci_event_handler(&event->u.bt);
}
break;
}
return 0;
}
struct app_protocol_private_handle_t gfps_private_handle = {
.sys_event_handler = gfps_sys_event_handler_specific,
};
#endif
#endif

View File

@ -0,0 +1,557 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "app_protocol_api.h"
#include "system/includes.h"
#include "vm.h"
#include "audio_config.h"
#include "app_power_manage.h"
#include "user_cfg.h"
#if APP_PROTOCOL_GMA_CODE
#if 1
#define APP_GMA_LOG printf
#define APP_GMA_DUMP put_buf
#else
#define APP_GMA_LOG(...)
#define APP_GMA_DUMP(...)
#endif
//*********************************************************************************//
// GMA认证信息 //
//*********************************************************************************//
#define GMA_GMA_FROM_FLASH 0
#define GMA_GMA_FROM_FILE 1
#define GMA_GMA_SOURCH GMA_GMA_FROM_FLASH
extern int le_controller_set_mac(void *addr);
extern void lmp_hci_write_local_address(const u8 *addr);
extern void lmp_hci_read_local_address(u8 *addr);
extern void bt_update_testbox_addr(u8 *addr);
typedef struct {
uint8_t mac[6];
uint32_t pid;
uint8_t secret[16];
} ali_para_s;
static ali_para_s ali_para;
static ali_para_s *active_ali_para = NULL;
///mac reverse
void gma_mac_addr_reverse_get(uint8_t *buf)
{
memcpy(buf, (const void *)active_ali_para->mac, 6);
}
#define LEGAL_PID_NUM(cha) (cha>='0' && cha<='9')
#define LEGAL_MAC_NUM(cha) ((cha>='0'&&cha<='9') || (cha>='a'&&cha<='f') || (cha>='A'&&cha<='F') || (cha==':'))
#define LEGAL_SECRET_NUM(cha) ((cha>='0'&&cha<='9') || (cha>='a'&&cha<='f') || (cha>='A'&&cha<='F'))
#define USELESS_CHAR ':'
#define GMA_ALI_PARA_END_CHAR ','
#define GMA_ALI_PARA_MAC_CHAR_NUMS (sizeof(((ali_para_s *)0)->mac))
#define GMA_ALI_PARA_PID_CHAR_NUMS 4//(sizeof(((ali_para_s *)0)->pid))
#define GMA_ALI_PARA_SECRET_CHAR_NUMS (sizeof(((ali_para_s *)0)->secret))
static u8 gma_ali_para_char2num(u8 cha)
{
u8 num = 0;
if (cha >= '0' && cha <= '9') {
num = cha - '0';
} else if (cha >= 'a' && cha <= 'f') {
num = cha - 'a' + 10;
} else if (cha >= 'A' && cha <= 'F') {
num = cha - 'A' + 10;
}
return num;
}
static int gma_license_set(ali_para_s *ali_para)
{
const u8 *gma_ptr = (u8 *)app_protocal_get_license_ptr();
if (gma_ptr == NULL) {
return -1;
}
///license fill
//pid
memcpy((u8 *) & (ali_para->pid), gma_ptr, sizeof(ali_para->pid));
gma_ptr += sizeof(ali_para->pid);
APP_GMA_LOG("gma pid:%d \n", ali_para->pid);
//secret
memcpy((u8 *)(ali_para->secret), gma_ptr, sizeof(ali_para->secret));
gma_ptr += sizeof(ali_para->secret);
APP_GMA_LOG("gma secret:");
APP_GMA_DUMP(ali_para->secret, sizeof(ali_para->secret));
//mac
memcpy((u8 *)(ali_para->mac), gma_ptr, sizeof(ali_para->mac));
gma_ptr += sizeof(ali_para->mac);
{
//mac reverse
u8 mac_backup_buf[6];
memcpy(mac_backup_buf, ali_para->mac, 6);
int i;
for (i = 0; i < 6; i++) {
ali_para->mac[i] = (mac_backup_buf)[5 - i];
}
}
APP_GMA_LOG("gma mac:");
APP_GMA_DUMP(ali_para->mac, sizeof(ali_para->mac));
return 0;
}
#if GMA_GMA_SOURCH == GMA_GMA_FROM_FILE
#define ALI_PARA_ACTIVE_NUM 1
static const char *ali_para_string[] = {
"jl_auif",
//Product ID,Device Secret,Mac,Md5
//此处可以用户自行填写从阿里申请的三元组信息
" ",
};
static bool gma_ali_para_info_fill(const u8 *para, ali_para_s *ali_para)
{
const u8 *para_string = para;
u8 highbit_en = 0;
uint32_t pid = 0;
uint32_t char_nums = 0;
uint8_t *secret = ali_para->secret;
uint8_t *mac = ali_para->mac;
while (*para_string && *para_string != GMA_ALI_PARA_END_CHAR) {
if (!LEGAL_PID_NUM(*para_string)) {
/* APP_GMA_LOG("pid illegal character !!! \n"); */
para_string++;
continue;
}
///check pid character numbers legal scope
char_nums++;
if (char_nums > GMA_ALI_PARA_PID_CHAR_NUMS) {
APP_GMA_LOG("pid character numbers overflow !!! \n");
return false;
}
pid *= 10;
pid += gma_ali_para_char2num(*para_string);
para_string++;
}
///check pid character numbers legal scope
if (char_nums != GMA_ALI_PARA_PID_CHAR_NUMS) {
APP_GMA_LOG("pid character numbers error:%d !!! \n", char_nums);
return false;
}
APP_GMA_LOG(">>pid:%d \n", pid);
ali_para->pid = pid;
para_string++;
char_nums = 0;
memset(ali_para->secret, 0x00, sizeof(ali_para->secret));
while (*para_string != GMA_ALI_PARA_END_CHAR) {
if (!LEGAL_SECRET_NUM(*para_string)) {
APP_GMA_LOG("secret illegal character !!! \n");
para_string++;
continue;
}
///assignment secret
if (!highbit_en) {
*secret += gma_ali_para_char2num(*para_string);
highbit_en ^= 1;
} else {
///check secret character numbers legal scope
char_nums++;
if (char_nums > GMA_ALI_PARA_SECRET_CHAR_NUMS) {
APP_GMA_LOG("secret character number overflow !!! \n");
return false;
}
*secret <<= 4;
*secret++ += gma_ali_para_char2num(*para_string);
highbit_en ^= 1;
}
para_string++;
}
///check secret character numbers legal scope
if (char_nums != GMA_ALI_PARA_SECRET_CHAR_NUMS) {
APP_GMA_LOG("secret character number error !!! :%d \n", char_nums);
return false;
}
///print secret
APP_GMA_LOG(">>ali_para secret: ");
for (int i = 0; i < sizeof(ali_para->secret) / sizeof(ali_para->secret[0]); i++) {
APP_GMA_LOG("%x ", ali_para->secret[i]);
}
memset(ali_para->mac, 0x00, sizeof(ali_para->mac));
para_string++;
highbit_en = 0;
char_nums = 0;
while (*para_string != GMA_ALI_PARA_END_CHAR) {
//if legal character
if (!LEGAL_MAC_NUM(*para_string)) {
APP_GMA_LOG("mac illegal character !!! \n");
para_string++;
continue;
// return false;
}
if (*para_string == USELESS_CHAR) {
para_string++;
continue;
}
///assignment mac
if (!highbit_en) {
*mac += gma_ali_para_char2num(*para_string);
highbit_en ^= 1;
} else {
//check mac character numbers legal scope
char_nums++;
if (char_nums > GMA_ALI_PARA_MAC_CHAR_NUMS) {
APP_GMA_LOG("mac character numbers overflow !!! \n");
return false;
}
*mac <<= 4;
*mac++ += gma_ali_para_char2num(*para_string);
highbit_en ^= 1;
}
para_string++;
}
//check mac character numbers legal scope
if (char_nums != GMA_ALI_PARA_MAC_CHAR_NUMS) {
APP_GMA_LOG("mac character numbers error !!! \n");
return false;
}
///mac reverse
for (int i = 0, tmp_mac = 0, array_size = (sizeof(ali_para->mac) / sizeof(ali_para->mac[0])); \
i < (sizeof(ali_para->mac) / sizeof(ali_para->mac[0]) / 2); i++) {
tmp_mac = ali_para->mac[i];
ali_para->mac[i] = ali_para->mac[array_size - 1 - i];
ali_para->mac[array_size - 1 - i] = tmp_mac;
}
///print secret
APP_GMA_LOG(">>ali_para mac: ");
for (int i = 0; i < sizeof(ali_para->mac) / sizeof(ali_para->mac[0]); i++) {
APP_GMA_LOG("%x ", ali_para->mac[i]);
}
return true;
}
static int gma_license2flash(const ali_para_s *ali_para)
{
int i;
u8 mac[6];
u8 rdata[sizeof(ali_para_s)];
for (i = 0; i < sizeof(mac); i++) {
mac[i] = ali_para->mac[5 - i];
}
memcpy(rdata, &ali_para->pid, sizeof(ali_para->pid));
memcpy(rdata + sizeof(ali_para->pid), ali_para->secret, sizeof(ali_para->secret));
memcpy(rdata + sizeof(ali_para->pid) + sizeof(ali_para->secret), mac, sizeof(mac));
return app_protocol_license2flash(rdata, sizeof(rdata));
}
#endif
#if TCFG_USER_TWS_ENABLE
#include "bt_tws.h"
static ali_para_s ali_para_remote; //对耳的三元组
//VM_GMA_MAC 对耳的地址
//VM_GMA_ALI_PARA 对耳的三元组
static int gma_strcmp(const u8 *ptr1, const u8 *ptr2, u8 len)
{
while (len--) {
if (*ptr1 != *ptr2) {
return (*ptr1 - *ptr2);
}
ptr1++;
ptr2++;
}
return 0;
}
///mac reverse
u8 *gma_sibling_mac_get() //获取地址较小的那个
{
ali_para_s *sibling_ali_para = NULL;//&ali_para;
if (active_ali_para == &ali_para) {
printf("ali_para active \n");
sibling_ali_para = &ali_para_remote;
}
if (active_ali_para == &ali_para_remote) {
printf("ali_para active \n");
sibling_ali_para = &ali_para;
}
return (sibling_ali_para ? sibling_ali_para->mac : NULL);
}
int gma_select_ali_para_by_common_mac()
{
u8 ret = 0;
u8 mac[6];
u8 mac_buf_tmp[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
ret = syscfg_read(CFG_TWS_COMMON_ADDR, mac, 6);
if (ret != 6 || !memcmp(mac, mac_buf_tmp, 6)) {
printf("tws no conn\n");
return -1;
}
APP_GMA_LOG("active mac:");
APP_GMA_DUMP(mac, 6);
///select para
ali_para_s ali_para_temp;
syscfg_read(VM_GMA_ALI_PARA, (u8 *) &ali_para_temp, sizeof(ali_para_s));
if (ali_para_temp.pid == ali_para.pid) {
memcpy(&ali_para_remote, &ali_para_temp, sizeof(ali_para_s));
APP_GMA_LOG("remote mac:");
APP_GMA_DUMP(ali_para_remote.mac, 6);
APP_GMA_LOG("remote pid:%d \n", ali_para_remote.pid);
APP_GMA_LOG("remote secret:");
APP_GMA_DUMP(ali_para_remote.secret, sizeof(ali_para_remote.secret));
if (gma_strcmp(mac, ali_para_remote.mac, 6) == 0) {
APP_GMA_LOG("used remote para \n");
active_ali_para = &ali_para_remote;
return 0;
} else if (gma_strcmp(mac, ali_para.mac, 6) == 0) {
APP_GMA_LOG("used local para \n");
active_ali_para = &ali_para;
return 0;
} else {
APP_GMA_LOG("MAC ERROR !!!!!!!!!!!!!!!!\n");
return -1;
}
} else {
APP_GMA_LOG("no remote mac \n");
}
return -1;
}
void gma_slave_sync_remote_addr(u8 *buf)
{
u8 common_addr[6];
///remote ali_para fill
memcpy(&ali_para_remote, buf, sizeof(ali_para_remote));
syscfg_write(VM_GMA_MAC, ali_para_remote.mac, 6);
///write ali para to vm
syscfg_write(VM_GMA_ALI_PARA, (u8 *)&ali_para_remote, sizeof(ali_para_remote));
tws_api_get_local_addr(common_addr);
if (memcmp(active_ali_para->mac, common_addr, 6)) { //common地址发生变化
APP_GMA_LOG("gma addr change");
///used slave address
active_ali_para = &ali_para_remote;
app_protocol_set_tws_sibling_mac(ali_para.mac);
app_protocol_set_info_group(GMA_HANDLER_ID, active_ali_para); //设置三元组
//断开APP接口
if (is_tws_master_role()) {
APP_GMA_LOG("gma need reconn app");
app_protocol_disconnect(NULL);
app_protocol_ble_adv_switch(0);
le_controller_set_mac(active_ali_para->mac);
app_protocol_ble_adv_switch(1);
}
}
}
#ifdef CONFIG_NEW_BREDR_ENABLE
void tws_host_get_common_addr(u8 *remote_addr, u8 *common_addr, char channel)
#else
void tws_host_get_common_addr(u8 *local_addr, u8 *remote_addr, u8 *common_addr, char channel)
#endif
{
APP_GMA_LOG(">>>>>>>>>tws_host_get_common_addr ch:%c \n", channel);
u8 mac_buf[6];
gma_mac_addr_reverse_get(mac_buf);
APP_GMA_LOG(">>>local mac: ");
APP_GMA_DUMP(mac_buf, 6);
///used the bigger one as host bt mac
if (gma_strcmp(mac_buf, (const u8 *)remote_addr, 6) < 0) {
///used slave mac addr;remote_addr from slave addr reverse
memcpy(common_addr, remote_addr, 6);
} else {
///used master mac addr
gma_mac_addr_reverse_get(common_addr);
}
APP_GMA_LOG("common_addr: ");
APP_GMA_DUMP((const u8 *)common_addr, 6);
APP_GMA_LOG("remote_addr: ");
APP_GMA_DUMP((const u8 *)remote_addr, 6);
}
void gma_kick_license_to_sibling(void)
{
APP_GMA_LOG("send license info to sibling\n");
app_protocol_tws_send_to_sibling(GMA_TWS_CMD_SYNC_LIC, (u8 *) & (ali_para), sizeof(ali_para));;
}
void gma_tws_remove_paired(void)
{
ali_para_s ali_para_temp;
memset(&ali_para_temp, 0xff, sizeof(ali_para_s));
syscfg_write(VM_GMA_ALI_PARA, (u8 *)&ali_para_temp, sizeof(ali_para_s));
active_ali_para = &ali_para;
app_protocol_set_tws_sibling_mac(ali_para_temp.mac);
app_protocol_set_info_group(GMA_HANDLER_ID, active_ali_para); //设置三元组
app_protocol_disconnect(NULL);
app_protocol_ble_adv_switch(0);
le_controller_set_mac(active_ali_para->mac);
app_protocol_ble_adv_switch(1);
}
#endif
__attribute__((weak))
void bt_update_testbox_addr(u8 *addr)
{
}
int gma_prev_init(void)
{
int err = 0;
/* ali_para_s ali_para; */
#if GMA_GMA_SOURCH == GMA_GMA_FROM_FLASH
err = gma_license_set(&ali_para);
#elif GMA_GMA_SOURCH == GMA_GMA_FROM_FILE
u8 *ali_str = ali_para_string[ALI_PARA_ACTIVE_NUM];
u8 ali_license[128] = {0};
//check if exist flash file
if (read_cfg_file(ali_license, sizeof(ali_license), SDFILE_RES_ROOT_PATH"license.txt") == TRUE) {
ali_str = ali_license;
}
APP_GMA_LOG("ali_str:%s\n", ali_str);
if (gma_ali_para_info_fill((const u8 *)ali_str, &ali_para) == false) {
APP_GMA_LOG("array context not good \n");
///read license from flash
err = gma_license_set(&ali_para);
}
///write license to flash
if (!err) {
gma_license2flash(&ali_para);
}
#endif
if (!err) {
active_ali_para = &ali_para;
#if TCFG_USER_TWS_ENABLE
if (!gma_select_ali_para_by_common_mac()) {
app_protocol_set_tws_sibling_mac(gma_sibling_mac_get());
}
#endif
app_protocol_set_info_group(GMA_HANDLER_ID, active_ali_para); //设置三元组
bt_update_mac_addr(active_ali_para->mac);
lmp_hci_write_local_address(active_ali_para->mac);
app_protocol_ble_adv_switch(0);
le_controller_set_mac(active_ali_para->mac); //修改BLE地址
bt_update_testbox_addr(ali_para.mac);
}
return err;
}
//*********************************************************************************//
// GMA 提示音 //
//*********************************************************************************//
const char *gma_tone_tab[APP_RROTOCOL_TONE_MAX] = {
[APP_RROTOCOL_TONE_SPEECH_KEY_START] = TONE_NORMAL,
};
//*********************************************************************************//
// DMA私有消息处理 //
//*********************************************************************************//
#if TCFG_USER_TWS_ENABLE
void gma_rx_tws_data_deal(u16 opcode, u8 *data, u16 len)
{
switch (opcode) {
case GMA_TWS_CMD_SYNC_LIC:
printf(">>> TWS_AI_GMA_START_SYNC_LIC \n");
gma_slave_sync_remote_addr(data);
break;
}
}
static void gma_bt_tws_event_handler(struct bt_event *bt)
{
int role = bt->args[0];
int phone_link_connection = bt->args[1];
int reason = bt->args[2];
switch (bt->event) {
case TWS_EVENT_CONNECTED:
gma_kick_license_to_sibling();
break;
case TWS_EVENT_REMOVE_PAIRS:
gma_tws_remove_paired();
break;
}
}
#endif
static int gma_bt_status_event_handler(struct bt_event *bt)
{
return 0;
}
int gma_sys_event_deal(struct sys_event *event)
{
switch (event->type) {
case SYS_BT_EVENT:
if ((u32)event->arg == SYS_BT_EVENT_TYPE_CON_STATUS) {
gma_bt_status_event_handler(&event->u.bt);
}
#if TCFG_USER_TWS_ENABLE
else if (((u32)event->arg == SYS_BT_EVENT_FROM_TWS)) {
gma_bt_tws_event_handler(&event->u.bt);
}
#endif
break;
}
return 0;
}
struct app_protocol_private_handle_t gma_private_handle = {
#if TCFG_USER_TWS_ENABLE
.tws_rx_from_siblling = gma_rx_tws_data_deal,
#endif
/* .tws_sync_func = ; */
.sys_event_handler = gma_sys_event_deal,
};
#endif

View File

@ -0,0 +1,146 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "app_protocol_api.h"
#include "system/includes.h"
#include "audio_config.h"
#include "app_power_manage.h"
#include "user_cfg.h"
#include "bt_tws.h"
#include "custom_cfg.h"
#if APP_PROTOCOL_MMA_CODE
#if 1
#define APP_MMA_LOG printf
#define APP_MMA_DUMP put_buf
#else
#define APP_MMA_LOG(...)
#define APP_MMA_DUMP(...)
#endif
//*********************************************************************************//
// MMA初始化 //
//*********************************************************************************//
void mma_prev_init()
{
u16 pid = 0x210c;
u16 vid = 0x05d6;
u16 ver = 0x1100;
#if APP_PROTOCOL_READ_CFG_EN
vid = get_vid_pid_ver_from_cfg_file(GET_VID_FROM_EX_CFG);
pid = get_vid_pid_ver_from_cfg_file(GET_PID_FROM_EX_CFG);
ver = get_vid_pid_ver_from_cfg_file(GET_VER_FROM_EX_CFG);
#endif
APP_MMA_LOG("mma pid:%x, vid:%x, ver:%x\n", pid, vid, ver);
app_protocol_set_vendor_id(MMA_HANDLER_ID, vid);
app_protocol_set_product_id(MMA_HANDLER_ID, pid);
app_protocol_set_local_version(MMA_HANDLER_ID, ver);
}
//*********************************************************************************//
// MMA提示音 //
//*********************************************************************************//
const char *mma_notice_tab[APP_RROTOCOL_TONE_MAX] = {
[APP_RROTOCOL_TONE_SPEECH_KEY_START] = TONE_NORMAL,
};
//*********************************************************************************//
// MMA私有消息处理 //
//*********************************************************************************//
#if 1
extern int le_controller_get_mac(void *addr);
#ifdef CONFIG_NEW_BREDR_ENABLE
void tws_host_get_common_addr(u8 *remote_addr, u8 *common_addr, char channel)
#else
void tws_host_get_common_addr(u8 *local_addr, u8 *remote_addr, u8 *common_addr, char channel)
#endif
{
APP_MMA_LOG(">>>>>>>>>tws_host_get_common_addr ch:%c \n", channel);
if (channel == 'L') {
memcpy(common_addr, bt_get_mac_addr(), 6);
} else {
memcpy(common_addr, remote_addr, 6);
}
APP_MMA_LOG(">>>local mac: ");
APP_MMA_DUMP(bt_get_mac_addr(), 6);
APP_MMA_LOG("remote_addr: ");
APP_MMA_DUMP((const u8 *)remote_addr, 6);
APP_MMA_LOG("common_addr: ");
APP_MMA_DUMP((const u8 *)common_addr, 6);
}
static void mma_tws_get_data_analysis(u16 cmd, u8 *data, u16 len)
{
}
static void mma_update_ble_addr()
{
u8 ble_old_addr[6];
u8 ble_new_addr[6];
u8 comm_addr[6];
tws_api_get_local_addr(comm_addr);
le_controller_get_mac(ble_old_addr);
void ble_update_address_tws_paired(u8 * comm_addr);
ble_update_address_tws_paired(comm_addr);
le_controller_get_mac(ble_new_addr);
if (is_tws_master_role() && memcmp(ble_old_addr, ble_new_addr, 6)) {
app_protocol_disconnect(NULL);
app_protocol_ble_adv_switch(0);
app_protocol_ble_adv_switch(1);
}
}
static void mma_bt_tws_event_handler(struct bt_event *bt)
{
int role = bt->args[0];
int phone_link_connection = bt->args[1];
int reason = bt->args[2];
switch (bt->event) {
case TWS_EVENT_CONNECTED:
mma_update_ble_addr();
break;
case TWS_EVENT_REMOVE_PAIRS:
mma_update_ble_addr();
break;
}
}
static int mma_bt_status_event_handler(struct bt_event *bt)
{
return 0;
}
int mma_sys_event_deal(struct sys_event *event)
{
switch (event->type) {
case SYS_BT_EVENT:
if ((u32)event->arg == SYS_BT_EVENT_TYPE_CON_STATUS) {
mma_bt_status_event_handler(&event->u.bt);
}
#if TCFG_USER_TWS_ENABLE
else if (((u32)event->arg == SYS_BT_EVENT_FROM_TWS)) {
mma_bt_tws_event_handler(&event->u.bt);
}
#endif
break;
}
return 0;
}
struct app_protocol_private_handle_t mma_private_handle = {
/* .tws_rx_from_siblling = mma_tws_get_data_analysis, */
.sys_event_handler = mma_sys_event_deal,
};
#endif
#endif

View File

@ -0,0 +1,527 @@
#include "app_config.h"
#if AI_APP_PROTOCOL
#include "app_protocol_ota.h"
#include "app_protocol_api.h"
#include "fs.h"
#include "os/os_error.h"
#include "update_loader_download.h"
#include "dual_bank_updata_api.h"
#include "update.h"
#include "timer.h"
#include "debug.h"
#define LOG_TAG_CONST APP_OTA
#define LOG_TAG "[APP_OTA]"
int clk_set(const char *name, int clk);
update_op_tws_api_t *get_tws_update_api(void);
void tws_sync_update_crc_handler_register(void (*crc_init_hdl)(void), u32(*crc_calc_hdl)(u32 init_crc, u8 *data, u32 len));
#define APP_UPDATE_FAILED 0
#define APP_UPDATE_SUCC 1
#define APP_CHECK_CRC_SUCC 0
#define APP_CHECK_CRC_FAILED 1
typedef struct _app_protocol_ota_param_t {
u32 state;
u32 read_len;
u32 need_rx_len;
u8 *read_buf;
void (*resume_hdl)(void *priv);
int (*sleep_hdl)(void *priv);
app_protocol_ota_api ota_api;
u32 file_offset;
u8 seek_type;
u8 update_result;
u8 sync_update_first_packet;
u8 ota_cancle_flag;
u8 wait_app_reboot;
OS_SEM ota_sem;
} app_protocol_ota_param_t;
static app_protocol_ota_param_t app_protocol_ota_param;
static update_op_tws_api_t *app_protocol_update_tws_api = NULL;
#define __this (&app_protocol_ota_param)
enum {
BT_SEEK_SET = 0x01,
BT_SEEK_CUR = 0x02,
BT_SEEK_TYPE_UPDATE_LEN = 0x10,
};
typedef enum {
UPDATA_START = 0x00,
UPDATA_REV_DATA,
UPDATA_STOP,
} UPDATA_BIT_FLAG;
#define RETRY_TIMES 3
const app_protocol_ota_type_map ota_type_map[] = {
{.protocol_id = GMA_HANDLER_ID, .ota_type = PASSIVE_OTA},
{.protocol_id = MMA_HANDLER_ID, .ota_type = INITIATIVE_OTA},
{.protocol_id = DMA_HANDLER_ID, .ota_type = NO_SUPPORT_OTA},
{.protocol_id = TME_HANDLER_ID, .ota_type = INITIATIVE_OTA},
{.protocol_id = AMA_HANDLER_ID, .ota_type = NO_SUPPORT_OTA},
};
//根据protocol_id获取协议升级类型
u8 check_ota_type_by_protocol_id(int id)
{
u8 i = 0;
for (; i < sizeof(ota_type_map) / sizeof(app_protocol_ota_type_map); i++) {
if (id == ota_type_map[i].protocol_id) {
return ota_type_map[i].ota_type;
}
}
return NO_SUPPORT_OTA;
}
static void initiative_ota_resume_hdl_register(void (*resume_hdl)(void *priv), int (*sleep_hdl)(void *priv))
{
__this->resume_hdl = resume_hdl;
__this->sleep_hdl = sleep_hdl;
}
void app_protocol_ota_init(app_protocol_ota_api *api, u8 need_wait_app_reboot)
{
memcpy(&(__this->ota_api), api, sizeof(app_protocol_ota_api));
__this->wait_app_reboot = need_wait_app_reboot;
#if OTA_TWS_SAME_TIME_ENABLE
tws_sync_update_crc_handler_register(__this->ota_api.ota_crc_init_hdl, __this->ota_api.ota_crc_calc_hdl);
g_printf("crc_init_hdl:0x%x crc_calc_hdl:0x%x\n", __this->ota_api.ota_crc_init_hdl, __this->ota_api.ota_crc_calc_hdl);
#endif
}
void initiative_ota_init(void (*resume_hdl)(void *priv), int (*sleep_hdl)(void *priv))
{
os_sem_create(&(__this->ota_sem), 0);
initiative_ota_resume_hdl_register(resume_hdl, sleep_hdl);
}
u16 initiative_ota_f_open(void)
{
log_info(">>>initiative_ota_f_open\n");
__this->file_offset = 0;
__this->seek_type = BT_SEEK_SET;
return 1;
}
void initiative_ota_handle(u8 state, void *buf, int len)
{
/* log_info("R"); */
if (state != __this->state) {
log_info(">>>initiative state err\n");
return;
}
switch (state) {
case UPDATA_REV_DATA:
if (__this->read_buf) {
memcpy(__this->read_buf, buf, len);
__this->read_len = len;
__this->state = 0;
}
break;
case UPDATA_STOP:
__this->state = 0;
break;
}
if (__this->resume_hdl) {
__this->resume_hdl(NULL);
}
}
u16 initiative_ota_f_read(void *fp, u8 *buff, u16 len)
{
u8 retry_cnt = 0;
__this->need_rx_len = len;
__this->state = UPDATA_REV_DATA;
__this->read_len = 0;
__this->read_buf = buff;
__RETRY:
if (app_protocol_get_cur_handle_id() == 0) { //如果已经断开连接直接返回-1 */
return -1;
}
if (__this->ota_cancle_flag) {
return -1;
}
if (__this->ota_api.ota_request_data == NULL) {
return -1;
}
printf("initiative_ota_read\n");
__this->ota_api.ota_request_data(fp, __this->file_offset, len);
while (!((0 == __this->state) && (__this->read_len == len))) {
if (__this->sleep_hdl && app_protocol_get_cur_handle_id()) {
__this->sleep_hdl(NULL);
} else {
len = -1;
break;
}
if (!((0 == __this->state) && (__this->read_len == len))) {
if (retry_cnt++ > RETRY_TIMES) {
len = (u16) - 1;
break;
} else {
goto __RETRY;
}
}
}
if ((u16) - 1 != len) {
__this->file_offset += len;
}
return len;
}
int initiative_ota_f_seek(void *fp, u8 type, u32 offset)
{
if (type == SEEK_SET) {
__this->file_offset = offset;
__this->seek_type = BT_SEEK_SET;
} else if (type == SEEK_CUR) {
__this->file_offset += offset;
__this->seek_type = BT_SEEK_CUR;
}
return 0;//FR_OK;
}
static u16 initiative_ota_f_stop(u8 err)
{
//err = update_result_handle(err);
__this->state = UPDATA_STOP;
log_info(">>>initiative_ota_stop:%x err:0x%x\n", __this->state, err);
if (__this->ota_cancle_flag) {
return -1;
}
if (__this->ota_api.ota_request_data) {
__this->ota_api.ota_request_data(NULL, 0, 0);
}
while (!(0 == __this->state)) {
if (__this->sleep_hdl) { // && get_rcsp_connect_status()) {
if (__this->sleep_hdl(NULL) == OS_TIMEOUT) {
break;
}
} else {
break;
}
}
if (__this->ota_api.ota_report_result) {
__this->ota_api.ota_report_result(err);
}
return 1;
}
static int initiative_ota_notify_update_content_size(void *priv, u32 size)
{
int err;
u8 data[4];
/* WRITE_BIG_U32(data, size); */
/* user_change_ble_conn_param(0); */
log_info("send content_size:%x\n", size);
if (__this->ota_api.ota_notify_file_size) {
__this->ota_api.ota_notify_file_size(size);
}
/* err = JL_CMD_send(JL_OPCODE_NOTIFY_UPDATE_CONENT_SIZE, data, sizeof(data), JL_NEED_RESPOND); */
return err;
}
const update_op_api_t initiative_update_op = {
.ch_init = initiative_ota_init,
.f_open = initiative_ota_f_open,
.f_read = initiative_ota_f_read,
.f_seek = initiative_ota_f_seek,
.f_stop = initiative_ota_f_stop,
.notify_update_content_size = initiative_ota_notify_update_content_size,
};
void app_protocol_ota_update_success_reset(void *priv)
{
cpu_reset();
}
static void initiative_ota_state_cbk(int type, u32 state, void *priv)
{
update_ret_code_t *ret_code = (update_ret_code_t *)priv;
if (ret_code) {
log_info("state:%x err:%x\n", ret_code->stu, ret_code->err_code);
}
switch (state) {
case UPDATE_CH_EXIT:
if (UPDATE_DUAL_BANK_IS_SUPPORT()) {
if ((0 == ret_code->stu) && (0 == ret_code->err_code)) {
/* set_jl_update_flag(1); */
log_info(">>>initiative update succ\n");
update_result_set(UPDATA_SUCC);
__this->update_result = APP_UPDATE_SUCC;
#if !OTA_TWS_SAME_TIME_ENABLE
sys_timeout_add(NULL, app_protocol_ota_update_success_reset, 2000); //延时一段时间再reset保证命令已经发送
#endif
} else {
log_info(">>>initiative update failed\n");
update_result_set(UPDATA_DEV_ERR);
__this->update_result = APP_UPDATE_FAILED;
}
} else {
if ((0 == ret_code->stu) && (0 == ret_code->err_code)) {
__this->update_result = APP_UPDATE_SUCC;
/* set_jl_update_flag(1); */
}
}
os_sem_post(&(__this->ota_sem));
break;
}
}
//被动升级请求下一帧数据
int passive_ota_write_callback(void *priv)
{
if (__this->ota_api.ota_request_data) {
__this->ota_api.ota_request_data(NULL, 0, 0);
}
return 0;
}
int passive_ota_set_boot_info_callback(int ret)
{
if (__this->ota_api.ota_report_result) {
__this->ota_api.ota_report_result(ret);
}
if (ret == 0) { //0表示boot info写成功
#if OTA_TWS_SAME_TIME_ENABLE
if (app_protocol_update_tws_api && app_protocol_update_tws_api->tws_ota_result_hdl && !__this->wait_app_reboot) {
app_protocol_update_tws_api->tws_ota_result_hdl(0);
}
#else
sys_timeout_add(NULL, app_protocol_ota_update_success_reset, 2000); //延时一段时间再reset保证命令已经发送
#endif
__this->update_result = APP_UPDATE_SUCC;
} else {
dual_bank_passive_update_exit(NULL);
#if OTA_TWS_SAME_TIME_ENABLE
if (app_protocol_update_tws_api && app_protocol_update_tws_api->tws_ota_err) {
app_protocol_update_tws_api->tws_ota_err(0);
}
__this->update_result = APP_UPDATE_FAILED;
#endif
}
return 0;
}
int passive_ota_crc_result_call_back(int crc_res)
{
if (crc_res) { //校验成功
log_info("crc check succ, write boot_info\n");
u8 update_boot_info_flag, verify_err;
#if OTA_TWS_SAME_TIME_ENABLE
if (app_protocol_update_tws_api && app_protocol_update_tws_api->exit_verify_hdl) {
if (app_protocol_update_tws_api->exit_verify_hdl(&verify_err, &update_boot_info_flag)) {
dual_bank_update_burn_boot_info((int (*)(int))passive_ota_set_boot_info_callback);
} else { //从机写boot_info失败
if (__this->ota_api.ota_report_result) {
__this->ota_api.ota_report_result(APP_CHECK_CRC_FAILED);
}
if (app_protocol_update_tws_api && app_protocol_update_tws_api->tws_ota_err) { //通知从机升级失败
app_protocol_update_tws_api->tws_ota_err(0);
}
__this->update_result = APP_UPDATE_FAILED;
}
} else
#endif
{
dual_bank_update_burn_boot_info((int (*)(int))passive_ota_set_boot_info_callback);
}
} else { //校验失败
if (__this->ota_api.ota_report_result) {
__this->ota_api.ota_report_result(APP_CHECK_CRC_FAILED);
}
#if OTA_TWS_SAME_TIME_ENABLE
if (app_protocol_update_tws_api && app_protocol_update_tws_api->tws_ota_err) { //通知从机升级失败
app_protocol_update_tws_api->tws_ota_err(0);
}
#endif
__this->update_result = APP_UPDATE_FAILED;
//app_protocol_reply_frame_check_result(crc_res);
dual_bank_passive_update_exit(NULL);
}
return 0;
}
int app_protocol_ota_interrupt_by_disconnect(int id)
{
if (check_ota_type_by_protocol_id(id) == INITIATIVE_OTA) {
} else {
#if OTA_TWS_SAME_TIME_ENABLE
if (app_protocol_update_tws_api && app_protocol_update_tws_api->tws_ota_err) {
app_protocol_update_tws_api->tws_ota_err(0);
}
#endif
dual_bank_passive_update_exit(NULL);
}
return 0;
}
int app_protocol_update_success_flag(void)
{
return __this->update_result;
}
int app_protocol_ota_message_handler(int id, int opcode, u8 *data, u32 len)
{
int err_code = UPDATE_RESULT_ERR_NONE;
int ret = 0;
switch (opcode) {
case APP_PROTOCOL_OTA_CHECK:
log_info("APP_PROTOCOL_OTA_CHECK\n");
ota_frame_info *frame_info = data;
dual_bank_passive_update_init(frame_info->frame_crc, frame_info->frame_size, frame_info->max_pkt_len, NULL);
ret = dual_bank_update_allow_check(frame_info->frame_size);
if (ret) {
err_code = UPDATE_RESULT_RESOURCE_LIMIT;
dual_bank_passive_update_exit(NULL);
} else { //for tws sync update init
#if OTA_TWS_SAME_TIME_ENABLE
app_protocol_update_tws_api = get_tws_update_api();
struct __tws_ota_para tws_update_para;
tws_update_para.fm_size = frame_info->frame_size;
tws_update_para.fm_crc16 = frame_info->frame_crc;
tws_update_para.max_pkt_len = frame_info->max_pkt_len;
if (app_protocol_update_tws_api && app_protocol_update_tws_api->tws_ota_start) {
if (app_protocol_update_tws_api->tws_ota_start(&tws_update_para)) {
err_code = UPDATE_RESULT_OTA_TWS_START_ERR;
dual_bank_passive_update_exit(NULL);
}
}
__this->sync_update_first_packet = 1;
#endif
}
break;
case APP_PROTOCOL_OTA_BEGIN:
update_mode_info_t info = {
.type = BLE_APP_UPDATA,
.state_cbk = initiative_ota_state_cbk,
.p_op_api = &initiative_update_op,
.task_en = 1,
};
__this->ota_cancle_flag = 0;
app_active_update_task_init(&info);
break;
case APP_PROTOCOL_OTA_TRANS_DATA:
log_info("APP_PROTOCOL_OTA_TRANS_DATA\n");
if (check_ota_type_by_protocol_id(id) == INITIATIVE_OTA) {
initiative_ota_handle(UPDATA_REV_DATA, data, len);
} else {
#if OTA_TWS_SAME_TIME_ENABLE
if (!__this->sync_update_first_packet) { //第一次传输不需要pend
if (app_protocol_update_tws_api && app_protocol_update_tws_api->tws_ota_data_send_pend) {
if (app_protocol_update_tws_api->tws_ota_data_send_pend()) {
log_info(" UPDATE_ERR_WAIT_TWS_RESPONSE_TIMEOUT\n");
err_code = UPDATE_RESULT_OTA_TWS_NO_RSP;
break;
}
}
}
__this->sync_update_first_packet = 0;
#endif
dual_bank_update_write(data, len, passive_ota_write_callback);
#if OTA_TWS_SAME_TIME_ENABLE
if (app_protocol_update_tws_api && app_protocol_update_tws_api->tws_ota_data_send) {
app_protocol_update_tws_api->tws_ota_data_send(data, len);
}
#endif
}
break;
case APP_PROTOCOL_OTA_GET_APP_VERSION:
u32 fm_version = app_protocol_get_version_by_id(id);
break;
case APP_PROTOCOL_OTA_CHECK_CRC:
if (check_ota_type_by_protocol_id(id) == INITIATIVE_OTA) {
os_sem_pend(&(__this->ota_sem), 0);
err_code = __this->update_result;
} else {
clk_set("sys", 120 * 1000000L); //提升主频加快CRC校验速度
#if OTA_TWS_SAME_TIME_ENABLE
if (app_protocol_update_tws_api && app_protocol_update_tws_api->tws_ota_data_send_pend) { //pend 最后一包数据
if (app_protocol_update_tws_api->tws_ota_data_send_pend()) {
log_info(" UPDATE_ERR_WAIT_TWS_RESPONSE_TIMEOUT\n");
err_code = UPDATE_RESULT_OTA_TWS_NO_RSP;
break;
}
}
if (app_protocol_update_tws_api && app_protocol_update_tws_api->enter_verfiy_hdl) {
if (app_protocol_update_tws_api->enter_verfiy_hdl(NULL)) { //从机校验CRC
log_info("update enter verify err\n");
if (__this->ota_api.ota_report_result) {
__this->ota_api.ota_report_result(APP_CHECK_CRC_FAILED);
}
} else {
log_info("update enter verify succ\n");
dual_bank_update_verify(__this->ota_api.ota_crc_init_hdl, __this->ota_api.ota_crc_calc_hdl, passive_ota_crc_result_call_back);
}
} else
#endif
{
dual_bank_update_verify(__this->ota_api.ota_crc_init_hdl, __this->ota_api.ota_crc_calc_hdl, passive_ota_crc_result_call_back);
}
}
break;
case APP_PROTOCOL_OTA_CANCLE:
__this->ota_cancle_flag = 1;
break;
case APP_PROTOCOL_OTA_REBOOT:
__this->state = 0;
/* #if OTA_TWS_SAME_TIME_ENABLE //同步升级在update lib里进行重启 */
/* g_printf("APP_PROTOCOL_OTA_REBOOT!!!\n"); */
/* #else */
/* cpu_reset(); */
/* #endif */
break;
case APP_PROTOCOL_OTA_PERCENT:
break;
case APP_PROTOCOL_OTA_END:
break;
case APP_PROTOCOL_OTA_SUCCESS:
break;
case APP_PROTOCOL_OTA_FAIL:
break;
}
return err_code;
}
#endif

View File

@ -0,0 +1,28 @@
#ifndef __APP_PROTOCOL_OTA_H__
#define __APP_PROTOCOL_OTA_H__
#include "typedef.h"
#define NO_SUPPORT_OTA 0xff
#define INITIATIVE_OTA 0x01
#define PASSIVE_OTA 0x02
typedef struct app_protocol_ota_type_map_t {
u32 protocol_id;
u8 ota_type;
} app_protocol_ota_type_map;
typedef struct app_protocol_ota_api_t {
u32(*ota_request_data)(void *priv, u32 offset, u16 len);
u32(*ota_report_result)(u8 result);
void (*ota_notify_file_size)(u32 file_size);
void (*ota_crc_init_hdl)(void);
u16(*ota_crc_calc_hdl)(u16 init_crc, u8 *data, u32 len);
} app_protocol_ota_api;
int app_protocol_ota_message_handler(int id, int opcode, u8 *data, u32 len);
void app_protocol_ota_init(app_protocol_ota_api *api, u8 need_wait_app_reboot);
int app_protocol_ota_interrupt_by_disconnect(int id);
int app_protocol_update_success_flag(void);
#endif //__APP_PROTOCOL_OTA_H__

View File

@ -0,0 +1,126 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "app_protocol_api.h"
#include "system/includes.h"
#include "audio_config.h"
#include "app_power_manage.h"
#include "user_cfg.h"
#include "btstack/avctp_user.h"
#include "bt_tws.h"
#if APP_PROTOCOL_TME_CODE
extern void TME_set_edr_connected(u8 flag);
//*********************************************************************************//
// TME认证信息 //
//*********************************************************************************//
//*********************************************************************************//
// TME提示音 //
//*********************************************************************************//
const char *tme_notice_tab[APP_RROTOCOL_TONE_MAX] = {
[APP_RROTOCOL_TONE_SPEECH_KEY_START] = TONE_NORMAL,
};
//*********************************************************************************//
// TME弱函数实现 //
//*********************************************************************************//
//*********************************************************************************//
// TME私有消息处理 //
//*********************************************************************************//
#if 1
extern int le_controller_set_mac(void *addr);
extern int le_controller_get_mac(void *addr);
#if TCFG_USER_TWS_ENABLE
static void tme_tws_rx_from_sibling(u16 cmd, u8 *data, u16 len)
{
#if TCFG_USER_TWS_ENABLE
switch (cmd) {
}
#endif
}
static void tme_update_ble_addr()
{
u8 ble_old_addr[6];
u8 ble_new_addr[6];
u8 comm_addr[6];
printf("%s\n", __func__);
tws_api_get_local_addr(comm_addr);
le_controller_get_mac(ble_old_addr);
lib_make_ble_address(ble_new_addr, comm_addr);
le_controller_set_mac(ble_new_addr); //地址发生变化,更新地址
if (is_tws_master_role() && memcmp(ble_old_addr, ble_new_addr, 6)) {
app_protocol_disconnect(NULL);
app_protocol_ble_adv_switch(0);
app_protocol_ble_adv_switch(1);
}
}
static void tme_bt_tws_event_handler(struct bt_event *bt)
{
int role = bt->args[0];
int phone_link_connection = bt->args[1];
int reason = bt->args[2];
switch (bt->event) {
case TWS_EVENT_CONNECTED:
tme_update_ble_addr();
if (BT_STATUS_WAITINT_CONN != get_bt_connect_status()) {
TME_set_edr_connected(1);
}
break;
case TWS_EVENT_REMOVE_PAIRS:
tme_update_ble_addr();
break;
}
}
#endif
static int tme_bt_status_event_handler(struct bt_event *bt)
{
switch (bt->event) {
case BT_STATUS_SECOND_CONNECTED:
case BT_STATUS_FIRST_CONNECTED:
TME_set_edr_connected(1); //连接过经典蓝牙标志
break;
}
return 0;
}
int tme_sys_event_deal(struct sys_event *event)
{
switch (event->type) {
case SYS_BT_EVENT:
if ((u32)event->arg == SYS_BT_EVENT_TYPE_CON_STATUS) {
tme_bt_status_event_handler(&event->u.bt);
}
#if TCFG_USER_TWS_ENABLE
else if (((u32)event->arg == SYS_BT_EVENT_FROM_TWS)) {
tme_bt_tws_event_handler(&event->u.bt);
}
#endif
break;
}
return 0;
}
struct app_protocol_private_handle_t tme_private_handle = {
/* .tws_rx_from_siblling = tme_tws_rx_from_sibling, */
.sys_event_handler = tme_sys_event_deal,
};
#endif
#endif

View File

@ -0,0 +1,89 @@
#include "adv_adaptive_noise_reduction.h"
#include "syscfg_id.h"
#include "user_cfg_id.h"
#include "rcsp_adv_bluetooth.h"
#if (RCSP_ADV_EN && RCSP_ADV_ANC_VOICE && RCSP_ADV_ADAPTIVE_NOISE_REDUCTION)
#include "audio_anc.h"
/**
* @brief 获取自适应降噪信息开关
*
* @result 1:自适应降噪开 0:自适应降噪关
*/
int get_adaptive_noise_reduction_switch()
{
int sw_result = audio_anc_coeff_mode_get();
return sw_result;
}
/**
* @brief 开启自适应降噪
*/
void set_adaptive_noise_reduction_on()
{
audio_anc_coeff_adaptive_set(1, 1, 1);
}
/**
* @brief 关闭自适应降噪
*/
void set_adaptive_noise_reduction_off()
{
audio_anc_coeff_adaptive_set(0, 1, 1);
}
static u8 adaptive_noise_reduction_reseting = 0; // 重新检测状态1:进行中 0:结束
static u8 adaptive_noise_reduction_reset_result = 0; // 重新检测结果1:失败 0:成功
/**
* @brief 自适应降噪重新检测
*/
void set_adaptive_noise_reduction_reset()
{
audio_anc_mode_ear_adaptive();
adaptive_noise_reduction_reseting = 1;
}
/**
* @brief 获取自适应降噪重新检测状态
*
* @result 1:进行中 0:结束
*/
u8 get_adaptive_noise_reduction_reset_status()
{
return adaptive_noise_reduction_reseting;
}
/**
* @brief 获取自适应降噪重新检测结果
*
* @result 1:失败 0:成功
*/
u8 get_adaptive_noise_reduction_reset_result()
{
return adaptive_noise_reduction_reset_result;
}
/**
* @brief 自适应降噪重新检测结果回调
*/
void set_adaptive_noise_reduction_reset_callback(u8 result)
{
adaptive_noise_reduction_reseting = 0;
if (result != 0) {
// 成功
adaptive_noise_reduction_reset_result = 0;
} else {
// 失败
adaptive_noise_reduction_reset_result = 1;
}
// 通知手机APP
/* JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_ANC_VOICE, NULL, 0); */
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_ADAPTIVE_NOISE_REDUCTION, NULL, 0);
}
#endif

View File

@ -0,0 +1,48 @@
#ifndef __ADV_ADAPTIVE_NOISE_REDUCTION_H__
#define __ADV_ADAPTIVE_NOISE_REDUCTION_H__
#include "le_rcsp_adv_module.h"
/**
* @brief 获取自适应降噪信息开关
*
* @result 1:自适应降噪开 0:自适应降噪关
*/
int get_adaptive_noise_reduction_switch();
/**
* @brief 开启自适应降噪
*/
void set_adaptive_noise_reduction_on();
/**
* @brief 关闭自适应降噪
*/
void set_adaptive_noise_reduction_off();
/**
* @brief 自适应降噪重新检测
*/
void set_adaptive_noise_reduction_reset();
/**
* @brief 获取自适应降噪重新检测状态
*
* @result 1:进行中 0:结束
*/
u8 get_adaptive_noise_reduction_reset_status();
/**
* @brief 获取自适应降噪重新检测结果
*
* @result 1:失败 0:成功
*/
u8 get_adaptive_noise_reduction_reset_result();
/**
* @brief 自适应降噪重新检测结果回调
*/
void set_adaptive_noise_reduction_reset_callback(u8 result);
#endif

View File

@ -0,0 +1,54 @@
#ifndef __ADV_AI_NO_PICK_H__
#define __ADV_AI_NO_PICK_H__
#include "system/includes.h"
typedef enum {
RCSP_AI_NO_PICK_SENSITIVITY_HIGH = 0x00,
RCSP_AI_NO_PICK_SENSITIVITY_LOW = 0x01,
} RCSP_AI_NO_PICK_SENSITIVITY;
typedef enum {
RCSP_AI_NO_PICK_AUTO_CLOSE_TIME_NONE = 0x00, // 不自动关闭
RCSP_AI_NO_PICK_AUTO_CLOSE_TIME_5s = 0x01,
RCSP_AI_NO_PICK_AUTO_CLOSE_TIME_15s = 0x02,
RCSP_AI_NO_PICK_AUTO_CLOSE_TIME_30s = 0x03,
} RCSP_AI_NO_PICK_AUTO_CLOSE_TIME;
/**
* @brief 获取智能免摘开关
*
* @result bool
*/
bool get_ai_no_pick_switch();
/**
* @brief 开启智能免摘
*/
void set_ai_no_pick_switch(bool p_switch);
/**
* @brief 获取智能免摘敏感度
*
* @result RCSP_AI_NO_PICK_SENSITIVITY
*/
RCSP_AI_NO_PICK_SENSITIVITY get_ai_no_pick_sensitivity();
/**
* @brief 设置智能免摘敏感度
*/
void set_ai_no_pick_sensitivity(RCSP_AI_NO_PICK_SENSITIVITY sensitivity);
/**
* @brief 获取智能免摘自动关闭时间
*
* @result RCSP_AI_NO_PICK_AUTO_CLOSE_TIME
*/
RCSP_AI_NO_PICK_AUTO_CLOSE_TIME get_ai_no_pick_auto_close_time();
/**
* @brief 设置智能免摘自动关闭时间
*/
void set_ai_no_pick_auto_close_time(RCSP_AI_NO_PICK_AUTO_CLOSE_TIME time_type);
#endif // __ADV_AI_NO_PICK_H__

View File

@ -0,0 +1,335 @@
#include "app_config.h"
#include "syscfg_id.h"
#include "user_cfg_id.h"
#include "le_rcsp_adv_module.h"
#include "adv_anc_voice.h"
#include "adv_setting_common.h"
#include "rcsp_adv_tws_sync.h"
#include "rcsp_adv_opt.h"
#include "rcsp_adv_bluetooth.h"
#if (RCSP_ADV_EN && RCSP_ADV_ANC_VOICE)
#include "audio_anc.h"
// anc信息mode(1byte/0/1/2) + ( left_max(2byte) + right_max(2byte) + left_cur_val(2byte) + right_cur_val(2byte) ) * 3
static u8 g_anc_info[25] = {0};
extern int get_bt_tws_connect_status();
extern u8 JL_get_cur_bt_channel_sel(void);
static bool check_pos_neg(u8 mode)
{
bool ret = false;
u8 offset = 1 + mode * 8;
#if TCFG_USER_TWS_ENABLE
if ('R' == tws_api_get_local_channel()) {
offset += 2;
}
#endif
s16 val = g_anc_info[offset] << 8 | g_anc_info[offset + 1];
if (val < 0) {
ret = true;
}
return ret;
}
void get_anc_voice_info(u8 *anc_info)
{
memcpy(anc_info, g_anc_info, sizeof(g_anc_info));
}
void set_anc_voice_info(u8 *anc_info)
{
memcpy(g_anc_info, anc_info, sizeof(g_anc_info));
}
static void update_anc_voice_vm_value(u8 *anc_info)
{
u8 anc_vm_info[25] = {-1};
int ret = syscfg_read(CFG_RCSP_ADV_ANC_VOICE_MODE, anc_vm_info, 1);
if (0 != memcmp(anc_vm_info, anc_info, 1)) {
ret = syscfg_write(CFG_RCSP_ADV_ANC_VOICE_MODE, anc_info, 1);
}
ret = syscfg_read(CFG_RCSP_ADV_ANC_VOICE, anc_vm_info + 1, sizeof(anc_vm_info) - 1);
if (0 != memcmp(anc_vm_info + 1, anc_info + 1, sizeof(anc_vm_info) - 1)) {
ret = syscfg_write(CFG_RCSP_ADV_ANC_VOICE, anc_info + 1, sizeof(anc_vm_info) - 1);
}
}
static void anc_voice_sync(u8 *anc_info)
{
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
update_adv_setting(BIT(ATTR_TYPE_ANC_VOICE));
}
#endif
}
static void anc_voice_effect_set(u8 mode, s16 value)
{
static s16 value_old = -1;
#if TCFG_AUDIO_ANC_ENABLE
extern void anc_gain_app_value_set(int app_value);
if (value != value_old) {
/* audio_anc_gain(value, value); */
anc_gain_app_value_set(value);
}
anc_mode_switch(mode + 1, 1);
#endif
value_old = value;
}
static void anc_voice_state_update(void)
{
u8 offset = 0;
u8 mode = g_anc_info[offset++];
offset += mode * 8;
s16 left_max = g_anc_info[offset++] << 8 | g_anc_info[offset++];
s16 right_max = g_anc_info[offset++] << 8 | g_anc_info[offset++];
s16 left_val = g_anc_info[offset++] << 8 | g_anc_info[offset++];
s16 right_val = g_anc_info[offset++] << 8 | g_anc_info[offset++];
#if TCFG_USER_TWS_ENABLE
if ('R' == tws_api_get_local_channel()) {
if (check_pos_neg(mode) && right_val >= right_max) {
anc_voice_effect_set(mode, right_val);
} else if (right_max >= right_val) {
anc_voice_effect_set(mode, right_val);
}
return;
}
#endif
if (check_pos_neg(mode) && left_val >= left_max) {
anc_voice_effect_set(mode, left_val);
} else if (left_max >= left_val) {
anc_voice_effect_set(mode, left_val);
}
}
void deal_anc_voice(u8 *anc_setting, u8 write_vm, u8 tws_sync)
{
u8 anc_info[25] = {0};
if (!anc_setting) {
get_anc_voice_info(anc_info);
} else {
u8 mode = anc_setting[0];
g_anc_info[0] = mode;
memcpy(g_anc_info + 1 + mode * 8, anc_setting + 1, 8);
memcpy(anc_info, g_anc_info, sizeof(anc_info));
}
if (write_vm) {
update_anc_voice_vm_value(anc_info);
}
if (tws_sync) {
anc_voice_sync(anc_info);
}
anc_voice_state_update();
}
#if TCFG_USER_TWS_ENABLE
#define TWS_FUNC_ID_ANC_VOICE_SYNC \
(((u8)('R' + 'C' + 'S' + 'P') << (3 * 8)) | \
((u8)('A' + 'N' + 'C' + 'S') << (2 * 8)) | \
((u8)('V' + 'O' + 'I' + 'C' + 'E') << (1 * 8)) | \
((u8)('S' + 'Y' + 'N' + 'C') << (0 * 8)))
void anc_voice_max_val_swap_sync(u8 *data, u16 len)
{
update_anc_voice_vm_value(g_anc_info);
}
static void anc_voice_state_sync(u8 *data, u16 len)
{
if (NULL == data || 0 == len) {
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_ANC_VOICE, NULL, 0);
return;
}
u8 offset = 9;
// 假如当前是右耳,应该填写左值
// 假如当前是左耳,应该填写右值
if ('L' == tws_api_get_local_channel()) {
offset += 2;
}
// 根据左右耳填充对应的最大值信息
// 降噪(2byte) + 通透(2byte)
memcpy(g_anc_info + offset, data, 2);
memcpy(g_anc_info + offset + 4, data + 4, 2);
offset += 8;
memcpy(g_anc_info + offset, data + 2, 2);
memcpy(g_anc_info + offset + 4, data + 6, 2);
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_ANC_VOICE_MAX_SYNC, NULL, 0);
}
static void adv_anc_voice_tws_func_t(void *data, u16 len, bool rx)
{
if (rx) {
anc_voice_state_sync((u8 *)data, len);
}
}
REGISTER_TWS_FUNC_STUB(adv_tws_sync) = {
.func_id = TWS_FUNC_ID_ANC_VOICE_SYNC,
.func = adv_anc_voice_tws_func_t,
};
#endif
void rcsp_adv_voice_mode_update(u8 mode)
{
u8 anc_info[25] = {0};
get_anc_voice_info(anc_info);
anc_info[0] = mode;
if (mode) {
memcpy(anc_info + 1, anc_info + 1 + mode * 8, 8);
}
deal_anc_voice(anc_info, 1, 0);
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status() && TWS_ROLE_SLAVE == tws_api_get_role()) {
tws_api_send_data_to_sibling(NULL, 0, TWS_FUNC_ID_ANC_VOICE_SYNC);
return;
}
#endif
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_ANC_VOICE, NULL, 0);
}
int anc_voice_setting_sync()
{
int ret = 0;
u8 anc_info[8] = {0};
#if (TCFG_AUDIO_ANC_ENABLE)
/* extern int anc_gain_tab[3]; */
/* u16 noise_reduction = (u16)(16384 & (u16) - 1); // 调用接口获取降噪最大值 */
/* u16 transparent = (u16)(16384 & (u16) - 1); // 调用接口获取通透最大值 */
u16 noise_reduction = 16384; // 调用接口获取降噪最大值
u16 transparent = 16384; // 调用接口获取通透最大值
#else
u16 noise_reduction = 0;
u16 transparent = 0;
#endif
anc_info[0] = ((u8 *)&noise_reduction)[1];
anc_info[1] = ((u8 *)&noise_reduction)[0];
anc_info[2] = ((u8 *)&transparent)[1];
anc_info[3] = ((u8 *)&transparent)[0];
u8 offset = 9;
#if TCFG_USER_TWS_ENABLE
if ('R' == tws_api_get_local_channel()) {
offset += 2;
}
#endif
// 初始值最大和当前值都是同一个值
// 默认是左值
u8 tmp_value = -1;
int result = 0;
if ((result = syscfg_read(CFG_RCSP_ADV_ANC_VOICE_MODE, &tmp_value, sizeof(tmp_value))) != sizeof(tmp_value)) {
tmp_value = offset;
memcpy(g_anc_info + tmp_value, anc_info, 2);
tmp_value += 4;
memcpy(g_anc_info + tmp_value, anc_info, 2);
tmp_value += 4;
memcpy(g_anc_info + tmp_value, anc_info + 2, 2);
tmp_value += 4;
memcpy(g_anc_info + tmp_value, anc_info + 2, 2);
}
#if TCFG_USER_TWS_ENABLE
// 填写当前降噪/通透当前值
memcpy(anc_info + 4, g_anc_info + offset + 4, 2);
memcpy(anc_info + 6, g_anc_info + offset + 8 + 4, 2);
// 把自己的最大值发送给对端
if (get_bt_tws_connect_status()) {
tws_api_send_data_to_sibling(anc_info, sizeof(anc_info), TWS_FUNC_ID_ANC_VOICE_SYNC);
}
#endif
return ret;
}
int anc_voice_setting_init(void)
{
int ret = 1;
u8 anc_mode = -1;
if (syscfg_read(CFG_RCSP_ADV_ANC_VOICE_MODE, &anc_mode, sizeof(anc_mode)) != sizeof(anc_mode)) {
anc_voice_setting_sync();
ret = 0;
}
return ret;
}
// ====================================================
enum {
anc_VOICE_GET_PREP_MSG,
anc_VOICE_SET_CUR_MODE,
anc_VOICE_NOTICE_MSG,
anc_VOICE_GET_CUR_MODE,
};
static void s16_pos_neg_conversion(u8 *data)
{
s16 tmp_val = data[0] << 8 | data[1];
tmp_val = -tmp_val;
data[1] = ((u8 *)&tmp_val)[0];
data[0] = ((u8 *)&tmp_val)[1];
}
u8 anc_voice_info_get(u8 *data, u16 len)
{
u8 offset = 0;
u8 anc_info[25] = {0};
get_anc_voice_info(anc_info);
u8 mode = anc_info[0];
data[offset++] = mode;
memcpy(data + offset, anc_info + 1 + mode * 8, 8);
if (check_pos_neg(mode)) {
for (u8 i = 0; i < 8; i += 2) {
s16_pos_neg_conversion(data + 1 + i);
}
}
offset += 8;
return offset;
}
u8 anc_voice_info_fetch_all_get(u8 *data, u16 len)
{
u8 mode = 0;
u8 offset = 1;
u8 anc_info[25] = {0};
get_anc_voice_info(anc_info);
for (u8 resp_offset = 1; offset < sizeof(anc_info); offset += 8) {
data[resp_offset++] = mode;
memcpy(data + resp_offset, anc_info + offset, 8);
if (check_pos_neg(mode)) {
for (u8 i = 0; i < 8; i += 2) {
s16_pos_neg_conversion(data + 2 + mode * 9 + i);
}
}
resp_offset += 8;
mode++;
}
data[0] = mode;
return len;
}
int anc_voice_info_set(u8 *data, u16 len)
{
int ret = 0;
if (check_pos_neg(data[0])) {
for (u8 i = 0; i < 8; i += 2) {
s16_pos_neg_conversion(data + 1 + i);
}
}
deal_anc_voice(data, 1, 1);
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_ANC_VOICE, NULL, 0);
return ret;
}
#endif

View File

@ -0,0 +1,19 @@
#ifndef __ADV_ANS_VOICE_H__
#define __ADV_ANS_VOICE_H__
#include "le_rcsp_adv_module.h"
int anc_voice_setting_init(void);
int anc_voice_setting_sync(void);
void deal_anc_voice(u8 *anc_setting, u8 write_vm, u8 tws_sync);
void set_anc_voice_info(u8 *anc_info);
void get_anc_voice_info(u8 *anc_info);
u8 anc_voice_info_get(u8 *data, u16 len);
u8 anc_voice_info_fetch_all_get(u8 *data, u16 len);
int anc_voice_info_set(u8 *data, u16 len);
int update_anc_voice_key_opt(void);
void rcsp_adv_voice_mode_update(u8 mode);
#endif

View File

@ -0,0 +1,94 @@
#include "app_config.h"
#include "syscfg_id.h"
#include "user_cfg_id.h"
#include "key_event_deal.h"
#include "le_rcsp_adv_module.h"
#include "adv_anc_voice_key.h"
#include "adv_setting_common.h"
#include "rcsp_adv_tws_sync.h"
#include "rcsp_adv_opt.h"
#include "adv_anc_voice.h"
#if (RCSP_ADV_EN)
/* #if (RCSP_ADV_KEY_SET_ENABLE && TCFG_AUDIO_ANC_ENABLE) */
#if (RCSP_ADV_KEY_SET_ENABLE)
#include "audio_anc.h"
#define COMMON_FUNCTION 0xFF
#define ANC_VOICE_TYPE_MAX 3
static u8 g_anc_voice_key_mode[4] = {0, 0, 0, BIT(ANC_VOICE_TYPE_MAX) - 1};
extern int get_bt_tws_connect_status();
void set_anc_voice_key_mode(u8 *anc_voice_mode)
{
memcpy(g_anc_voice_key_mode, anc_voice_mode, sizeof(g_anc_voice_key_mode));
}
void get_anc_voice_key_mode(u8 *anc_voice_mode)
{
memcpy(anc_voice_mode, g_anc_voice_key_mode, sizeof(g_anc_voice_key_mode));
}
static void update_anc_voice_key_vm_value(u8 *anc_voice_mode)
{
syscfg_write(CFG_RCSP_ADV_ANC_VOICE_KEY, anc_voice_mode, 4);
}
static void anc_voice_key_sync(u8 *key_setting_info)
{
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
update_adv_setting(BIT(ATTR_TYPE_ANC_VOICE_KEY));
}
#endif
}
void deal_anc_voice_key_setting(u8 *anc_key_setting, u8 write_vm, u8 tws_sync)
{
u8 anc_voice_key_mode[4] = {0};
if (!anc_key_setting) {
get_anc_voice_key_mode(anc_voice_key_mode);
} else {
set_anc_voice_key_mode(anc_key_setting);
memcpy(anc_voice_key_mode, g_anc_voice_key_mode, sizeof(g_anc_voice_key_mode));
}
if (write_vm) {
update_anc_voice_key_vm_value(anc_voice_key_mode);
}
if (tws_sync) {
anc_voice_key_sync(anc_voice_key_mode);
}
}
int update_anc_voice_key_opt(void)
{
int ret = 0;
#if (RCSP_ADV_ANC_VOICE)
u32 mask = g_anc_voice_key_mode[0] << 24 | g_anc_voice_key_mode[1] << 16 | g_anc_voice_key_mode[2] << 8 | g_anc_voice_key_mode[3];
// 获取当前处于什么模式
#if TCFG_AUDIO_ANC_ENABLE
u8 cur_mode = anc_mode_get();
#else
u8 cur_mode = ANC_OFF;
#endif
u8 next_mode = cur_mode % ANC_VOICE_TYPE_MAX;
for (; next_mode < ANC_VOICE_TYPE_MAX; next_mode++) {
if (mask & BIT(next_mode)) {
rcsp_adv_voice_mode_update(next_mode % ANC_VOICE_TYPE_MAX);
return ret;
}
}
if (mask & BIT(next_mode % ANC_VOICE_TYPE_MAX)) {
rcsp_adv_voice_mode_update(next_mode % ANC_VOICE_TYPE_MAX);
}
#endif
return ret;
}
#endif
#endif

View File

@ -0,0 +1,12 @@
#ifndef __ADV_ANC_VOICE_KEY_H__
#define __ADV_ANC_VOICE_KEY_H__
#include "le_rcsp_adv_module.h"
void deal_anc_voice_key_setting(u8 *anc_key_setting, u8 write_vm, u8 tws_sync);
void get_anc_voice_key_mode(u8 *anc_voice_mode);
void set_anc_voice_key_mode(u8 *anc_voice_mode);
int update_anc_voice_key_opt(void);
#endif

View File

@ -0,0 +1,67 @@
#include "app_config.h"
#include "user_cfg.h"
#include "syscfg_id.h"
#include "user_cfg_id.h"
#include "le_rcsp_adv_module.h"
#include "adv_bt_name_setting.h"
#include "adv_setting_common.h"
#include "rcsp_adv_tws_sync.h"
#include "rcsp_adv_opt.h"
#if (RCSP_ADV_EN)
#if RCSP_ADV_NAME_SET_ENABLE
extern int get_bt_tws_connect_status();
void adv_edr_name_change_now(void)
{
extern BT_CONFIG bt_cfg;
extern const char *bt_get_local_name();
extern void lmp_hci_write_local_name(const char *name);
memcpy(bt_cfg.edr_name, _s_info.edr_name, LOCAL_NAME_LEN);
lmp_hci_write_local_name(bt_get_local_name());
}
void set_bt_name_setting(u8 *bt_name_setting)
{
memcpy(_s_info.edr_name, bt_name_setting, 32);
}
void get_bt_name_setting(u8 *bt_name_setting)
{
memcpy(bt_name_setting, _s_info.edr_name, 32);
}
// 1、写入VM
static void update_bt_name_vm_value(u8 *bt_name_setting)
{
syscfg_write(CFG_BT_NAME, bt_name_setting, 32);
}
// 2、同步对端
static void bt_name_sync(u8 *bt_name_setting)
{
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
update_adv_setting(BIT(ATTR_TYPE_EDR_NAME));
}
#endif
}
void deal_bt_name_setting(u8 *bt_name_setting, u8 write_vm, u8 tws_sync)
{
u8 bt_name[32] = {0};
if (!bt_name_setting) {
get_bt_name_setting(bt_name);
} else {
memcpy(bt_name, bt_name_setting, 32);
}
if (write_vm) {
update_bt_name_vm_value(bt_name);
}
if (tws_sync) {
bt_name_sync(bt_name);
}
}
#endif
#endif

View File

@ -0,0 +1,12 @@
#ifndef __ADV_BT_NAME_SETTING_H__
#define __ADV_BT_NAME_SETTING_H__
#include "le_rcsp_adv_module.h"
#if RCSP_ADV_NAME_SET_ENABLE
void set_bt_name_setting(u8 *bt_name_setting);
void get_bt_name_setting(u8 *bt_name_setting);
#endif
#endif

View File

@ -0,0 +1,218 @@
#include "app_config.h"
#include "syscfg_id.h"
#include "user_cfg_id.h"
#include "le_rcsp_adv_module.h"
#include "adv_eq_setting.h"
#include "adv_setting_common.h"
#include "rcsp_adv_tws_sync.h"
#include "rcsp_adv_opt.h"
#include "application/audio_eq.h"
#if (RCSP_ADV_EN)
#if RCSP_ADV_EQ_SET_ENABLE
extern int get_bt_tws_connect_status();
extern int eq_mode_get_freq(u8 mode, u16 index);
extern s8 eq_mode_get_gain(u8 mode, u16 index);
extern int eq_mode_set_custom_param(u16 index, int gain);
extern int eq_mode_set(u8 mode);
extern int eq_mode_get_cur(void);
static void eq_setting_info_deal(u8 *eq_info_data)
{
u8 data;
u8 status;
u8 mode;
if (eq_info_data[0] >> 7) {
status = eq_info_data[2];
} else {
status = *(((u8 *)eq_info_data) + 1);
}
mode = eq_info_data[0] & 0x7F;
if (mode < EQ_MODE_CUSTOM) {
eq_mode_set(mode);
} else {
// 自定义修改EQ参数
if (EQ_MODE_CUSTOM == mode) {
if (status != 0x7F) {
u8 i;
for (i = 0; i < EQ_SECTION_MAX; i++) {
if (eq_info_data[0] >> 7) {
data = eq_info_data[i + 2];
} else {
data = eq_info_data[i + 1];
}
eq_mode_set_custom_param(i, (s8)data);
}
}
eq_mode_set(mode);
}
}
}
void set_eq_setting(u8 *eq_setting)
{
u8 i;
u8 eq_setting_mode = eq_setting[0];
if (eq_setting_mode >> 7) {
// 多段eq
for (i = 2; i < eq_setting[1] + 2; i++) {
if ((eq_setting[i] > 12) && (eq_setting[i] < -12)) {
eq_setting[i] = 0;
}
}
} else {
// 10段eq
for (i = 1; i < 11; i++) {
if ((eq_setting[i] > 12) && (eq_setting[i] < -12)) {
eq_setting[i] = 0;
}
}
}
memcpy(_s_info.eq_mode_info, eq_setting, 11);
}
void get_eq_setting(u8 *eq_setting)
{
memcpy(eq_setting, _s_info.eq_mode_info, 11);
}
// 1、写入VM
static void update_eq_vm_value(u8 *eq_setting)
{
u8 status = *(((u8 *)eq_setting) + 1);
syscfg_write(CFG_RCSP_ADV_EQ_MODE_SETTING, eq_setting, 1);
/*自定义修改EQ参数*/
if (EQ_MODE_CUSTOM == (eq_setting[0] & 0x7F)) {
if (eq_setting[0] >> 7) {
// 多段eq
status = eq_setting[2];
}
if (status != 0x7F) {
syscfg_write(CFG_RCSP_ADV_EQ_DATA_SETTING, &eq_setting[1], 10);
}
}
}
// 2、同步对端
static void eq_sync(u8 *eq_setting)
{
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
update_adv_setting(BIT(ATTR_TYPE_EQ_SETTING));
}
#endif
}
void deal_eq_setting(u8 *eq_setting, u8 write_vm, u8 tws_sync)
{
u8 eq_info[11] = {0};
if (!eq_setting) {
get_eq_setting(eq_info);
} else {
u8 status = *(((u8 *)eq_setting) + 1);
/*自定义修改EQ参数*/
if (EQ_MODE_CUSTOM == (eq_setting[0] & 0x7F)) {
if (eq_setting[0] >> 7) {
status = eq_setting[2];
}
if (status != 0x7F) {
memcpy(eq_info, eq_setting, 11);
set_eq_setting(eq_info);
} else {
_s_info.eq_mode_info[0] = eq_setting[0];
get_eq_setting(eq_info);
}
} else {
memcpy(eq_info, eq_setting, 11);
_s_info.eq_mode_info[0] = eq_setting[0];
}
}
if (write_vm) {
update_eq_vm_value(eq_info);
}
if (tws_sync) {
eq_sync(eq_info);
}
eq_setting_info_deal(eq_info);
}
u8 app_get_eq_info(u8 *get_eq_info)
{
u16 i;
get_eq_info[0] = eq_mode_get_cur();
u8 data_len = 1;
if (10 == EQ_SECTION_MAX) {
// 10段eq : mode + gain[10byte]
for (i = 0; i < 10; i++) {
get_eq_info[data_len] = eq_mode_get_gain(get_eq_info[0], i);
data_len++;
}
} else {
// 多段eq : mode + num + value(freq[2byte] + gain[1byte])
get_eq_info[1] = EQ_SECTION_MAX;
data_len++;
for (i = 0; i < EQ_SECTION_MAX; i++) {
get_eq_info[data_len] = eq_mode_get_gain(get_eq_info[0], i);
data_len++;
}
get_eq_info[0] |= (1 << 7);
}
return data_len;
}
u8 app_get_eq_all_info(u8 *get_eq_info)
{
u16 i;
u8 mode = EQ_MODE_NORMAL;
get_eq_info[0] = EQ_SECTION_MAX;
u8 data_len = 1;
// get freq
for (i = 0; i < EQ_SECTION_MAX; i++) {
u16 eq_freq = (u16)(eq_mode_get_freq(mode, i) & ((u16) - 1));
eq_freq = ((((u8 *)&eq_freq)[0] << 8) + ((u8 *)&eq_freq)[1]);
memcpy(get_eq_info + data_len, &eq_freq, sizeof(eq_freq));
data_len += 2;
}
// get gain
for (; mode < EQ_MODE_CUSTOM; mode++) {
get_eq_info[data_len] = mode;
if (10 != EQ_SECTION_MAX) {
get_eq_info[data_len] |= (1 << 7);
}
data_len++;
for (i = 0; i < EQ_SECTION_MAX; i++) {
u8 eq_gain = eq_mode_get_gain(mode, i);
get_eq_info[data_len] = eq_gain;
data_len++;
}
}
// get custom
get_eq_info[data_len] = EQ_MODE_CUSTOM;
if (10 != EQ_SECTION_MAX) {
get_eq_info[data_len] |= (1 << 7);
}
data_len++;
for (i = 0; i < EQ_SECTION_MAX; i++) {
if (10 == EQ_SECTION_MAX) {
get_eq_info[data_len] = _s_info.eq_mode_info[i + 1];
} else {
get_eq_info[data_len] = _s_info.eq_mode_info[i + 2];
}
data_len++;
}
return data_len;
}
#endif
#endif

View File

@ -0,0 +1,20 @@
#ifndef __ADV_EQ_SETTING_H__
#define __ADV_EQ_SETTING_H__
#include "le_rcsp_adv_module.h"
#if defined(RCSP_ADV_EQ_SET_ENABLE) && RCSP_ADV_EQ_SET_ENABLE
struct _EQ_INFO {
u8 mode;
s8 gain_val[10];
};
void set_eq_setting(u8 *eq_setting);
void get_eq_setting(u8 *eq_setting);
void deal_eq_setting(u8 *eq_setting, u8 write_vm, u8 tws_sync);
u8 app_get_eq_info(u8 *get_eq_info);
u8 app_get_eq_all_info(u8 *get_eq_info);
#endif
#endif

View File

@ -0,0 +1,318 @@
#include "app_config.h"
#include "syscfg_id.h"
#include "le_rcsp_adv_module.h"
#include "adv_hearing_aid_setting.h"
#include "rcsp_adv_tws_sync.h"
#include "JL_rcsp_protocol.h"
#include "rcsp_adv_bluetooth.h"
#include "spp_user.h"
#if (RCSP_ADV_EN && RCSP_ADV_ASSISTED_HEARING)
static u8 g_dha_fitting_data[3 + 2 * 4 * DHA_FITTING_CHANNEL_MAX] = {0};
static u8 g_dha_fitting_info[3 + 2 + 2 * DHA_FITTING_CHANNEL_MAX + 1] = {0};
static bool g_aidIsOperating = false;
static u8 g_aidOpCode = -1;
static u8 g_aidOpCode_SN = -1;
extern int tws_api_get_role(void);
extern u8 deal_adv_setting_string_item(u8 *des, u8 *src, u8 src_len, u8 type);
extern u16 get_adv_sync_tws_len(void);
static u16 adv_hearing_aid_convert(u8 *data);
static void hearing_aid_update_handle(u8 *data, u16 data_len)
{
#if (TCFG_AUDIO_HEARING_AID_ENABLE && TCFG_AUDIO_DHA_FITTING_ENABLE)
hearing_aid_fitting_parse(g_dha_fitting_data, data_len);
#endif /*TCFG_AUDIO_HEARING_AID_ENABLE && TCFG_AUDIO_DHA_FITTING_ENABLE*/
}
static void hearing_aid_update(void)
{
// 跟进不同命令类型调用设置函数
printf("%s\n", __func__);
/* u16 data_len = get_adv_sync_tws_len(); */
/* if (sizeof(g_dha_fitting_data) == data_len) { */
/* data_len = adv_hearing_aid_convert(g_dha_fitting_data); */
/* put_buf(g_dha_fitting_data, data_len); */
/* } */
#if ASSISTED_HEARING_CUSTOM_TRASNDATA
// 从机才触发
u16 data_len = get_adv_sync_tws_len();
#else
u16 data_len = adv_hearing_aid_convert(g_dha_fitting_data);
#endif
put_buf(g_dha_fitting_data, data_len);
hearing_aid_update_handle(g_dha_fitting_data, data_len);
}
#pragma pack(1)
struct hearing_aid_playload {
u8 cmd;
u16 data_len;
dha_fitting_info_t data_info;
};
#pragma pack()
void get_dha_fitting_info(u8 *dha_fitting_info)
{
printf("%s\n", __func__);
struct hearing_aid_playload playload;
playload.cmd = DHA_FITTING_CMD_INFO;
// 如果当前是主动拿,就把所有信息返回
// 获取0x50对应的数据
/* u8 tmp_data[] = {0, DHA_FITTING_CHANNEL_MAX, 0x12, 0x21, 0x23, 0x32, 0x34, 0x43, 0x45, 0x54, 0x56, 0x65, 0x67, 0x76}; // 例子 */
/* playload.data_len = sizeof(tmp_data); */
/* memcpy(&playload.data_info, tmp_data, sizeof(tmp_data)); */
// 获取0x50对应的数据
dha_fitting_info_t dha_info;
#if (TCFG_AUDIO_HEARING_AID_ENABLE && TCFG_AUDIO_DHA_FITTING_ENABLE)
playload.data_len = get_hearing_aid_fitting_info(&dha_info);
#endif /*TCFG_AUDIO_HEARING_AID_ENABLE && TCFG_AUDIO_DHA_FITTING_ENABLE*/
memcpy(&playload.data_info, &dha_info, sizeof(dha_info));
memcpy(g_dha_fitting_info, &playload, sizeof(playload));
// 如果当前是从机通知就直接memcpy过去不需要填充前三个头
u16 data_len = adv_hearing_aid_convert(g_dha_fitting_info);
put_buf(g_dha_fitting_info, data_len);
memcpy(dha_fitting_info, g_dha_fitting_info, sizeof(g_dha_fitting_info) - 1);
}
static void hearing_aid_sync(void)
{
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
update_adv_setting(BIT(ATTR_TYPE_ASSISTED_HEARING));
}
#endif
}
static void big_to_little(u8 *data, u8 data_len)
{
u8 tmp_data = 0;
for (u8 i = 0; i < (data_len / 2); i++) {
tmp_data = data[i];
data[i] = data[data_len - i - 1];
data[data_len - i - 1] = tmp_data;
}
}
static u16 adv_hearing_aid_convert(u8 *data)
{
u16 offset = 0;
u16 data_len = 0;
u8 cmd = data[offset++];
dha_fitting_adjust_t *dha_data; // 0x51
dha_fitting_info_t *dha_info; // 0x50
switch (cmd) {
case DHA_FITTING_CMD_INFO:
big_to_little(data + offset, 2);
data_len = data[offset++] << 8 | data[offset++];
dha_info = (dha_fitting_adjust_t *)(data + offset);
offset += 2;
for (; offset < data_len + 3; offset += 2) {
big_to_little(data + offset, 2);
}
break;
case DHA_FITTING_CMD_ADJUST:
data_len = data[offset] << 8 | data[offset + 1];
big_to_little(data + offset, 2);
offset += 2;
dha_data = (dha_fitting_adjust_t *)(data + offset);
offset += 2;
big_to_little((u8 *)&dha_data->freq, sizeof(dha_data->freq));
offset += 2;
big_to_little((u8 *)&dha_data->gain, sizeof(dha_data->gain));
offset += 4;
break;
case DHA_FITTING_CMD_UPDATE:
data_len = data[offset] << 8 | data[offset + 1];
big_to_little(data + offset, 2);
offset += 3;
for (; offset < data_len + 3; offset += 4) {
big_to_little(g_dha_fitting_data + offset, 4);
}
break;
case DHA_FITTING_CMD_STATE:
big_to_little(data + offset, 2);
data_len = data[offset++] << 8 | data[offset++];
offset += 1;
break;
}
if (data_len + 3 == offset) {
return offset;
}
return 0;
}
void set_hearing_aid_setting(u8 *hear_aid_setting)
{
memcpy(g_dha_fitting_data, hear_aid_setting, sizeof(g_dha_fitting_data));
}
void get_hearing_aid_setting(u8 *hear_aid_setting)
{
memcpy(hear_aid_setting, g_dha_fitting_data, sizeof(g_dha_fitting_data));
}
u32 hearing_aid_rcsp_notify(u8 *data, u16 data_len)
{
u32 ret = 0;
u8 *buf = NULL;
if (0 == adv_hearing_aid_convert(data)) {
return -1;
}
buf = zalloc(data_len + 3);
if (NULL == buf) {
return -1;
}
buf[0] = 0xFF;
data_len = add_one_attr(buf + 1, data_len + 2, 0, COMMON_INFO_ATTR_ASSISTED_HEARING, data, data_len);
ret = JL_CMD_send(JL_OPCODE_SYS_INFO_AUTO_UPDATE, buf, data_len + 1, JL_NOT_NEED_RESPOND);
if (buf) {
free(buf);
}
return ret;
}
u32 hearing_aid_rcsp_response(u8 *data, u16 data_len)
{
/*不开辅听功能时不回复app信息*/
#if (TCFG_AUDIO_HEARING_AID_ENABLE && TCFG_AUDIO_DHA_FITTING_ENABLE)
if (get_hearing_aid_state() == 0)
#endif /*(TCFG_AUDIO_HEARING_AID_ENABLE && TCFG_AUDIO_DHA_FITTING_ENABLE)*/
{
return 0;
}
if ((TWS_ROLE_MASTER == tws_api_get_role()) && (g_aidOpCode >= 0) && (g_aidOpCode_SN >= 0)) {
u32 ret = 0;
ret = JL_CMD_response_send(g_aidOpCode, JL_PRO_STATUS_SUCCESS, g_aidOpCode_SN, data, data_len);
g_aidIsOperating = false;
g_aidOpCode = -1;
g_aidOpCode_SN = -1;
return ret;
} else {
return -1;
}
}
void deal_hearing_aid_setting(u8 opCode, u8 opCode_SN, u8 *hear_aid_setting, u8 write_en, u8 type_sync)
{
if (TWS_ROLE_MASTER == tws_api_get_role()) {
set_hearing_aid_operating_flag();
}
if (g_aidIsOperating) {
return;
}
if (TWS_ROLE_MASTER == tws_api_get_role()) {
g_aidIsOperating = true;
g_aidOpCode = opCode;
g_aidOpCode_SN = opCode_SN;
}
if (hear_aid_setting) {
u16 len = hear_aid_setting[1] << 8 | hear_aid_setting[2];
memcpy(g_dha_fitting_data, hear_aid_setting, len + 2);
}
if (type_sync) {
hearing_aid_sync();
}
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
if (TWS_ROLE_MASTER == tws_api_get_role()) {
hearing_aid_update();
} else if (0 == type_sync) {
hearing_aid_update();
}
} else
#endif
{
hearing_aid_update();
}
}
#if ASSISTED_HEARING_CUSTOM_TRASNDATA
static struct spp_operation_t *spp_opt = NULL;
static void app_third_party_spp_rx_cbk(void *priv, u8 *buf, u16 len)
{
app_third_party_hearing_aid_handle(buf, len);
}
void adv_hearing_aid_init(void)
{
spp_get_operation_table(&spp_opt);
if (spp_opt && spp_opt->regist_recieve_cbk) {
spp_opt->regist_recieve_cbk(NULL, app_third_party_spp_rx_cbk);
}
}
int app_third_party_hearing_aid_handle(u8 *data, u16 len)
{
#if TCFG_USER_TWS_ENABLE
u8 *tmp_buf = NULL;
u16 offset = 1;
if (len < sizeof(g_dha_fitting_data)) {
return -1;
}
tmp_buf = zalloc(1 + 1 + len);
if (NULL == tmp_buf) {
return -1;
}
offset += deal_adv_setting_string_item(tmp_buf + offset, data, len, ATTR_TYPE_ASSISTED_HEARING);
tmp_buf[0] = offset;
if (tws_api_get_role() == TWS_ROLE_MASTER) {
tws_api_send_data_to_sibling(tmp_buf, offset, TWS_FUNC_ID_ADV_SETTING_SYNC);
}
if (tmp_buf) {
free(tmp_buf);
}
#endif
// 处理函数
hearing_aid_update_handle(data, len);
return 0;
}
extern int custom_app_send_user_data(u8 *data, u16 len);
int app_third_party_hearing_aid_resp(u8 *data, u16 len)
{
if (custom_app_send_user_data(data, len)) {
if (spp_opt && spp_opt->send_data) {
return spp_opt->send_data(NULL, data, (u32)len);
}
}
return 0;
}
#else
int app_third_party_hearing_aid_handle(u8 *data, u16 len)
{
return 0;
}
int app_third_party_hearing_aid_resp(u8 *data, u16 len)
{
return 0;
}
void adv_hearing_aid_init(void)
{
}
#endif
#endif

View File

@ -0,0 +1,26 @@
#ifndef __ADV_HEARING_AID_SETTING_H__
#define __ADV_HEARING_AID_SETTING_H__
#include "le_rcsp_adv_module.h"
#include "audio_hearing_aid.h"
// 是否使用三方的ble/edr数据传输
#define ASSISTED_HEARING_CUSTOM_TRASNDATA 0
void adv_hearing_aid_init(void);
void set_hearing_aid_setting(u8 *hear_aid_setting);
void get_hearing_aid_setting(u8 *hear_aid_setting);
void deal_hearing_aid_setting(u8 opCode, u8 opCode_SN, u8 *hear_aid_setting, u8 write_en, u8 type_sync);
void get_dha_fitting_info(u8 *dha_fitting_info);
// 主动推数给app
u32 hearing_aid_rcsp_notify(u8 *data, u16 data_len);
// app回复函数
u32 hearing_aid_rcsp_response(u8 *data, u16 data_len);
// 第三方调用函数
int app_third_party_hearing_aid_handle(u8 *data, u16 len);
int app_third_party_hearing_aid_resp(u8 *data, u16 len);
#endif

View File

@ -0,0 +1,18 @@
#ifndef __ADV_HIGH_LOW_VOL__
#define __ADV_HIGH_LOW_VOL__
#include "le_rcsp_adv_module.h"
#if RCSP_ADV_HIGH_LOW_SET
struct _HIGL_LOW_VOL {
int low_vol;
int high_vol;
};
void get_high_low_vol_info(u8 *vol_gain_param);
void set_high_low_vol_info(u8 *vol_gain_param);
void deal_high_low_vol(u8 *vol_gain_data, u8 write_vm, u8 tws_sync);
#endif
#endif

View File

@ -0,0 +1,81 @@
#include "app_config.h"
#include "syscfg_id.h"
#include "user_cfg_id.h"
#include "adv_high_low_vol.h"
#include "adv_setting_common.h"
#include "rcsp_adv_tws_sync.h"
#include "rcsp_adv_opt.h"
#if (RCSP_ADV_EN)
#if RCSP_ADV_HIGH_LOW_SET
static struct _HIGL_LOW_VOL high_low_vol = {
.low_vol = 12,
.high_vol = 12,
};
extern int get_bt_tws_connect_status();
extern int audio_out_eq_spec_set_gain(u8 idx, int gain);
void get_high_low_vol_info(u8 *vol_gain_param)
{
memcpy(vol_gain_param, &high_low_vol, sizeof(struct _HIGL_LOW_VOL));
}
void set_high_low_vol_info(u8 *vol_gain_param)
{
memcpy(&high_low_vol, vol_gain_param, sizeof(struct _HIGL_LOW_VOL));
}
static void update_high_low_vol_vm_value(u8 *vol_gain_param)
{
syscfg_write(CFG_RCSP_ADV_HIGH_LOW_VOL, vol_gain_param, sizeof(struct _HIGL_LOW_VOL));
}
static void high_low_vol_setting_sync(u8 *vol_gain_param)
{
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
update_adv_setting(BIT(ATTR_TYPE_HIGH_LOW_VOL));
}
#endif
}
static void high_low_vol_state_update(void)
{
#if (TCFG_AUDIO_OUT_EQ_ENABLE != 0)
static int low_vol = 0;
static int high_vol = 0;
if (low_vol != high_low_vol.low_vol) {
audio_out_eq_spec_set_gain(0, high_low_vol.low_vol - 12);
low_vol = high_low_vol.low_vol;
}
if (high_vol != high_low_vol.high_vol) {
audio_out_eq_spec_set_gain(1, high_low_vol.high_vol - 12);
high_vol = high_low_vol.high_vol;
}
#endif
}
void deal_high_low_vol(u8 *vol_gain_data, u8 write_vm, u8 tws_sync)
{
int vol_gain_param[2] = {0};
if (!vol_gain_data) {
get_high_low_vol_info((u8 *)vol_gain_param);
} else {
memcpy((u8 *)&vol_gain_param, vol_gain_data, sizeof(vol_gain_param));
set_high_low_vol_info(vol_gain_data);
printf("low %d, high %d\n", vol_gain_param[0], vol_gain_param[1]);
}
if (write_vm) {
update_high_low_vol_vm_value((u8 *)vol_gain_param);
}
if (tws_sync) {
high_low_vol_setting_sync((u8 *)vol_gain_param);
}
high_low_vol_state_update();
}
#endif
#endif

View File

@ -0,0 +1,219 @@
#include "app_config.h"
#include "syscfg_id.h"
#include "user_cfg_id.h"
#include "key_event_deal.h"
#include "le_rcsp_adv_module.h"
#include "adv_key_setting.h"
#include "adv_setting_common.h"
#include "rcsp_adv_tws_sync.h"
#include "rcsp_adv_opt.h"
#include "adv_anc_voice_key.h"
#if (RCSP_ADV_EN)
#if RCSP_ADV_KEY_SET_ENABLE
extern int get_bt_tws_connect_status();
static u8 rcsp_adv_key_event_flag = 0x0;
static void enable_adv_key_event(void)
{
rcsp_adv_key_event_flag = 1;
}
static u8 get_adv_key_event_status(void)
{
return rcsp_adv_key_event_flag;
}
static void disable_adv_key_event(void)
{
rcsp_adv_key_event_flag = 0;
}
void set_key_setting(u8 *key_setting_info)
{
_s_info.key_setting[3 * 0 + 2] = key_setting_info[0];
_s_info.key_setting[3 * 2 + 2] = key_setting_info[1];
_s_info.key_setting[3 * 1 + 2] = key_setting_info[2];
_s_info.key_setting[3 * 3 + 2] = key_setting_info[3];
}
void get_key_setting(u8 *key_setting_info)
{
key_setting_info[0] = _s_info.key_setting[3 * 0 + 2];
key_setting_info[1] = _s_info.key_setting[3 * 2 + 2];
key_setting_info[2] = _s_info.key_setting[3 * 1 + 2];
key_setting_info[3] = _s_info.key_setting[3 * 3 + 2];
}
static void update_key_setting_vm_value(u8 *key_setting_info)
{
syscfg_write(CFG_RCSP_ADV_KEY_SETTING, key_setting_info, 4);
}
static void key_setting_sync(u8 *key_setting_info)
{
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
update_adv_setting(BIT(ATTR_TYPE_KEY_SETTING));
}
#endif
}
void deal_key_setting(u8 *key_setting_info, u8 write_vm, u8 tws_sync)
{
u8 key_setting[4];
if (!key_setting_info) {
get_key_setting(key_setting);
} else {
memcpy(key_setting, key_setting_info, 4);
}
// 1、写入VM
if (write_vm) {
update_key_setting_vm_value(key_setting);
}
// 2、同步对端
if (tws_sync) {
key_setting_sync(key_setting);
}
// 3、更新状态
enable_adv_key_event();
}
#define ADV_POWER_ON_OFF 0
enum ADV_KEY_TYPE {
ADV_KEY_TYPE_NULL = 0x0,
#if ADV_POWER_ON_OFF
ADV_KEY_TYPE_POWER_ON,
ADV_KEY_TYPE_POWER_OFF,
#endif
ADV_KEY_TYPE_PREV = 0x3,
ADV_KEY_TYPE_NEXT,
ADV_KEY_TYPE_PP,
ADV_KEY_TYPE_ANSWER_CALL,
ADV_KEY_TYPE_HANG_UP,
ADV_KEY_TYPE_CALL_BACK,
ADV_KEY_TYPE_INC_VOICE,
ADV_KEY_TYPE_DESC_VOICE,
ADV_KEY_TYPE_TAKE_PHOTO,
ADV_KEY_TYPE_ANC_VOICE = 0xFF,
};
static u8 get_adv_key_opt(u8 key_action, u8 channel)
{
u8 opt;
for (opt = 0; opt < sizeof(_s_info.key_setting); opt += 3) {
if (_s_info.key_setting[opt] == channel &&
_s_info.key_setting[opt + 1] == key_action) {
break;
}
}
if (sizeof(_s_info.key_setting) == opt) {
return -1;
}
switch (_s_info.key_setting[opt + 2]) {
case ADV_KEY_TYPE_NULL:
//opt = KEY_NULL;
opt = ADV_KEY_TYPE_NULL;
break;
#if ADV_POWER_ON_OFF
case ADV_KEY_TYPE_POWER_ON:
opt = KEY_POWER_ON;
break;
case ADV_KEY_TYPE_POWER_OFF:
opt = KEY_RCSP_POWEROFF;
break;
#endif
case ADV_KEY_TYPE_PREV:
opt = KEY_MUSIC_PREV;
break;
case ADV_KEY_TYPE_NEXT:
opt = KEY_MUSIC_NEXT;
break;
case ADV_KEY_TYPE_PP:
opt = KEY_MUSIC_PP;
break;
case ADV_KEY_TYPE_ANSWER_CALL:
opt = KEY_CALL_ANSWER;
break;
case ADV_KEY_TYPE_HANG_UP:
opt = KEY_CALL_HANG_UP;
break;
case ADV_KEY_TYPE_CALL_BACK:
opt = KEY_CALL_LAST_NO;
break;
case ADV_KEY_TYPE_INC_VOICE:
opt = KEY_VOL_UP;
break;
case ADV_KEY_TYPE_DESC_VOICE:
opt = KEY_VOL_DOWN;
break;
case ADV_KEY_TYPE_TAKE_PHOTO:
opt = KEY_HID_CONTROL;
break;
case ADV_KEY_TYPE_ANC_VOICE:
update_anc_voice_key_opt();
opt = KEY_NULL;
break;
}
return opt;
}
void set_key_event_by_rcsp_info(struct sys_event *event, u8 *key_event)
{
if (0 == get_adv_key_event_status()) {
return;
}
u8 key_action = 0;
struct key_event *key = &event->u.key;
switch (key->event) {
case 0:
// 单击
key_action = 0x1;
break;
case 4:
// 双击
key_action = 0x2;
break;
default:
return;
}
#if (TCFG_CHARGESTORE_ENABLE && TCFG_USER_TWS_ENABLE)
u8 channel = tws_api_get_local_channel();
if (get_bt_tws_connect_status()) {
channel = tws_api_get_local_channel();
}
#else
u8 channel = 'U';
#endif
switch (channel) {
case 'U':
case 'L':
channel = (u32) event->arg == KEY_EVENT_FROM_TWS ? 2 : 1;
break;
case 'R':
channel = (u32) event->arg == KEY_EVENT_FROM_TWS ? 1 : 2;
break;
default:
return;
}
key_action = get_adv_key_opt(key_action, channel);
if ((u8) - 1 != key_action) {
*key_event = key_action ? key_action : KEY_NULL;
}
}
#else
void set_key_event_by_rcsp_info(struct sys_event *event, u8 *key_event)
{
return;
}
#endif
#endif

View File

@ -0,0 +1,13 @@
#ifndef __ADV_KEY_SETTING_H__
#define __ADV_KEY_SETTING_H__
#include "le_rcsp_adv_module.h"
#if RCSP_ADV_KEY_SET_ENABLE
void set_key_setting(u8 *key_setting_info);
void get_key_setting(u8 *key_setting_info);
#endif
#endif

View File

@ -0,0 +1,145 @@
#include "app_config.h"
#include "syscfg_id.h"
#include "user_cfg_id.h"
#include "asm/pwm_led.h"
#include "user_cfg.h"
#include "ui_manage.h"
#include "le_rcsp_adv_module.h"
#include "adv_led_setting.h"
#include "adv_setting_common.h"
#include "rcsp_adv_tws_sync.h"
#include "rcsp_adv_opt.h"
#if (RCSP_ADV_EN)
#if RCSP_ADV_LED_SET_ENABLE
enum ADV_LED_TYPE {
ADV_LED_TYPE_ALL_OFF = 0x0,
ADV_LED_TYPE_RED_ON,
ADV_LED_TYPE_BLUE_ON,
ADV_LED_TYPE_RAD_BREATHE,
ADV_LED_TYPE_BLUE_BREATHE,
ADV_LED_TYPE_FAST_FLASH,
ADV_LED_TYPE_SLOW_FLASH,
};
extern STATUS *get_led_config(void);
extern int get_bt_tws_connect_status();
__attribute__((weak))
u8 adv_get_led_status(void)
{
return 1;
}
static u8 adv_led_value_conversion(u8 adv_led_opt)
{
u8 conversion_value = adv_led_opt;
switch (adv_led_opt) {
case ADV_LED_TYPE_ALL_OFF:
conversion_value = PWM_LED_ALL_OFF;
break;
case ADV_LED_TYPE_RED_ON:
conversion_value = PWM_LED1_ON;
break;
case ADV_LED_TYPE_BLUE_ON:
conversion_value = PWM_LED0_ON;
break;
case ADV_LED_TYPE_RAD_BREATHE:
conversion_value = PWM_LED1_BREATHE;
break;
case ADV_LED_TYPE_BLUE_BREATHE:
conversion_value = PWM_LED0_BREATHE;
break;
case ADV_LED_TYPE_FAST_FLASH:
conversion_value = PWM_LED0_LED1_FAST_FLASH;
break;
case ADV_LED_TYPE_SLOW_FLASH:
conversion_value = PWM_LED0_LED1_SLOW_FLASH;
break;
}
return conversion_value;
}
void set_led_setting(u8 *led_setting_info)
{
_s_info.led_status[2 * 0 + 1] = led_setting_info[0];
_s_info.led_status[2 * 1 + 1] = led_setting_info[1];
_s_info.led_status[2 * 2 + 1] = led_setting_info[2];
}
void get_led_setting(u8 *led_setting_info)
{
led_setting_info[0] = _s_info.led_status[2 * 0 + 1];
led_setting_info[1] = _s_info.led_status[2 * 1 + 1];
led_setting_info[2] = _s_info.led_status[2 * 2 + 1];
}
// 1、写入VM
static void update_led_setting_vm_value(u8 *led_setting_info)
{
syscfg_write(CFG_RCSP_ADV_LED_SETTING, led_setting_info, 3);
}
// 2、同步对端
static void led_setting_sync(u8 *led_setting_info)
{
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
update_adv_setting(BIT(ATTR_TYPE_LED_SETTING));
}
#endif
}
// 3、更新状态
void update_led_setting_state(void)
{
u8 led_setting_info[3];
get_led_setting(led_setting_info);
// 直接修改led表
STATUS *p_led = get_led_config();
// 未配对
p_led->bt_init_ok = adv_led_value_conversion(led_setting_info[0]);
p_led->bt_disconnect = adv_led_value_conversion(led_setting_info[0]);
// 未连接
p_led->tws_connect_ok = adv_led_value_conversion(led_setting_info[1]);
// 连接
p_led->bt_connect_ok = adv_led_value_conversion(led_setting_info[2]);
switch (adv_get_led_status()) {
case STATUS_BT_INIT_OK:
case STATUS_BT_DISCONN:
ui_update_status(STATUS_BT_INIT_OK);
break;
case STATUS_BT_TWS_CONN:
ui_update_status(STATUS_BT_TWS_CONN);
break;
case STATUS_PHONE_ACTIV:
case STATUS_PHONE_OUT:
case STATUS_PHONE_INCOME:
case STATUS_BT_CONN:
ui_update_status(STATUS_BT_CONN);
break;
}
}
void deal_led_setting(u8 *led_setting_info, u8 write_vm, u8 tws_sync)
{
u8 led_setting[3];
if (!led_setting_info) {
get_led_setting(led_setting);
} else {
memcpy(led_setting, led_setting_info, 3);
}
if (write_vm) {
update_led_setting_vm_value(led_setting);
}
if (tws_sync) {
led_setting_sync(led_setting);
}
update_led_setting_state();
}
#endif
#endif

View File

@ -0,0 +1,13 @@
#ifndef __ADV_LED_SETTING_H__
#define __ADV_LED_SETTING_H__
#include "le_rcsp_adv_module.h"
#if RCSP_ADV_LED_SET_ENABLE
void set_led_setting(u8 *led_setting_info);
void get_led_setting(u8 *led_setting_info);
#endif
#endif

View File

@ -0,0 +1,155 @@
#include "app_config.h"
#include "syscfg_id.h"
#include "user_cfg_id.h"
#include "le_rcsp_adv_module.h"
#include "adv_mic_setting.h"
#include "adv_setting_common.h"
#include "rcsp_adv_tws_sync.h"
#include "rcsp_adv_opt.h"
#if (RCSP_ADV_EN)
#if RCSP_ADV_MIC_SET_ENABLE
extern void test_esco_role_switch(u8 flag);
extern void tws_conn_switch_role();
extern int get_bt_tws_connect_status();
static void mic_setting_info_deal(u8 mic_info_data)
{
#if TCFG_USER_TWS_ENABLE
u8 channel = tws_api_get_local_channel();
printf("%s, %d\n", __FUNCTION__, channel);
if (tws_api_get_role() == TWS_ROLE_MASTER) {
printf("-----master-----\n");
} else {
printf("-----role-----\n");
}
switch (mic_info_data) {
case 0x01:
if (get_bt_tws_connect_status()) {
printf("-------auto--------\n");
tws_api_auto_role_switch_enable();
}
break;
case 0x02:
if (get_bt_tws_connect_status()) {
if (channel != 'L') {
printf("-------!L--------\n");
tws_api_auto_role_switch_disable();
tws_conn_switch_role();
}
}
break;
case 0x03:
if (get_bt_tws_connect_status()) {
if (channel != 'R') {
printf("-------!R--------\n");
tws_api_auto_role_switch_disable();
tws_conn_switch_role();
}
}
break;
default:
break;
}
#endif
}
void set_mic_setting(u8 mic_setting_info)
{
_s_info.mic_mode = mic_setting_info;
}
u8 get_mic_setting(void)
{
return _s_info.mic_mode;
}
static void update_mic_setting_vm_value(u8 mic_setting_info)
{
syscfg_write(CFG_RCSP_ADV_MIC_SETTING, &mic_setting_info, 1);
}
static void adv_mic_setting_sync(u8 mic_setting_info)
{
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
update_adv_setting(BIT(ATTR_TYPE_MIC_SETTING));
}
#endif
}
void deal_mic_setting(u8 mic_setting_info, u8 write_vm, u8 tws_sync)
{
if (!mic_setting_info) {
mic_setting_info = get_mic_setting();
} else {
set_mic_setting(mic_setting_info);
}
if (write_vm) {
update_mic_setting_vm_value(mic_setting_info);
}
if (tws_sync) {
adv_mic_setting_sync(mic_setting_info);
}
mic_setting_info_deal(mic_setting_info);
}
//通话时,固定mic的位置,mode--esco state
void rcsp_user_mic_fixed_deal(u8 mode)
{
u8 channel = tws_api_get_local_channel();
if (!get_bt_tws_connect_status()) {
return;
}
if (mode == 0) {
test_esco_role_switch(0);
return;
}
if ((tws_api_get_role() == TWS_ROLE_MASTER)
&& (tws_api_get_tws_state() | TWS_STA_ESCO_OPEN)) {
switch (get_mic_setting()) {
case 0x02:
if (get_bt_tws_connect_status()) {
if (channel != 'L') {
printf("mic_sw_l\n");
test_esco_role_switch(1);
}
}
break;
case 0x03:
if (get_bt_tws_connect_status()) {
if (channel != 'R') {
printf("mic_sw_r\n");
test_esco_role_switch(1);
}
}
break;
default:
printf("mic_sw_auto\n");
test_esco_role_switch(0);
break;
}
}
}
#else
void rcsp_user_mic_fixed_deal(u8 mode)
{
return;
}
#endif
#endif

View File

@ -0,0 +1,15 @@
#ifndef __ADV_MIC_SETTING_H__
#define __ADV_MIC_SETTING_H__
#include "le_rcsp_adv_module.h"
#if RCSP_ADV_MIC_SET_ENABLE
void set_mic_setting(u8 mic_setting_info);
u8 get_mic_setting(void);
#endif
void rcsp_user_mic_fixed_deal(u8 mode);
#endif

View File

@ -0,0 +1,447 @@
#include "app_config.h"
#include "syscfg_id.h"
#include "user_cfg_id.h"
#include "le_rcsp_adv_module.h"
#include "adv_setting_common.h"
#include "rcsp_adv_tws_sync.h"
#include "rcsp_adv_opt.h"
#include "adv_music_info_setting.h"
#include "btstack/avctp_user.h"
#include "rcsp_adv_bluetooth.h"
#include "bt_tws.h"
#if (RCSP_ADV_EN)
#if RCSP_ADV_MUSIC_INFO_ENABLE
struct music_info_t {
u8 title_len;
char title[64];
u8 artist_len;
char artist[64];
u8 album_len;
char album[64];
u8 num_len;
char number;
u8 total_len;
char total[2];
u8 genre_len;
char genre[16];
char time[8];
u8 player_state;
u8 player_time_min;
u8 player_time_sec;
u32 curr_player_time;
u8 player_time_en;
u32 total_time;
volatile int get_music_player_timer;
};
struct music_info_t music_info;
void JL_rcsp_event_to_user(u32 type, u8 event, u8 *msg, u8 size);
u8 get_player_time_en(void)
{
return music_info.player_time_en;
}
void set_player_time_en(u8 en)
{
music_info.player_time_en = en;
}
void reset_player_time_en(void)
{
music_player_time_timer_deal(music_info.player_time_en);
}
void music_player_time_deal(void *priv)
{
if (BT_STATUS_PLAYING_MUSIC == get_bt_connect_status()) {
user_send_cmd_prepare(USER_CTRL_AVCTP_OPID_GET_PLAY_TIME, 0, NULL);
}
}
void get_music_info(void)
{
//printf("\nsend music info\n");
user_send_cmd_prepare(USER_CTRL_AVCTP_OPID_GET_MUSIC_INFO, 0, NULL);
}
void btstack_avrcp_ch_creat_ok(void)
{
if (tws_api_get_role() == TWS_ROLE_SLAVE) {
//printf("\n\n\n\nrcsp ge music info\n");
tws_api_sync_call_by_uuid('T', SYNC_CMD_MUSIC_INFO, 300);
} else {
if ((tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED) == 0) {
//printf("\n\n\nno tws rcsp ge music info\n\n");
get_music_info();
}
}
}
char *get_music_title(void)
{
return music_info.title;
}
u8 get_music_title_len(void)
{
return music_info.title_len;
}
char *get_music_artist(void)
{
return music_info.artist;
}
u8 get_music_artist_len(void)
{
return music_info.artist_len;
}
char *get_music_album(void)
{
return music_info.album;
}
u8 get_music_album_len(void)
{
return music_info.album_len;
}
char *get_music_number(void)
{
return &music_info.number;
}
u8 get_music_number_len(void)
{
return music_info.num_len;
}
char *get_music_total(void)
{
return music_info.total;
}
u8 get_music_total_len(void)
{
return music_info.total_len;
}
char *get_music_genre(void)
{
return music_info.genre;
}
u8 get_music_genre_len(void)
{
return music_info.genre_len;
}
u16 get_music_total_time(void)
{
return (music_info.total_time / 1000);
}
u32 get_music_curr_time(void)
{
return music_info.curr_player_time;
/* return (music_info.player_time_min * 60 + music_info.player_time_sec); */
}
u8 bt_music_total_time(u32 time)
{
music_info.total_time = time;
/* printf("get music time %d\n", music_info.total_time); */
return 0;
}
u8 get_music_player_state(void)
{
return music_info.player_state;
}
void rcsp_update_player_state(void)
{
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_PLAYER_STATE, NULL, 0);
}
void bt_status_change(u8 state)
{
if (BT_STATUS_PLAYING_MUSIC == state) {
music_info.player_state = 1;
} else {
music_info.player_state = 0;
}
if ((tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED) == 0) {
rcsp_update_player_state();
} else {
if (tws_api_get_role() == TWS_ROLE_MASTER) {
tws_api_sync_call_by_uuid('T', SYNC_CMD_MUSIC_PLAYER_STATE, 300);
} else {
tws_api_sync_call_by_uuid('T', SYNC_CMD_MUSIC_PLAYER_TIEM_EN, 300);
}
}
}
void stop_get_music_timer(u8 en)
{
if (en) {
music_info.player_time_en = 0;
}
if (music_info.get_music_player_timer) {
sys_timeout_del(music_info.get_music_player_timer);
music_info.get_music_player_timer = 0;
}
}
void music_player_time_timer_deal(u8 en)
{
if (en) {
if (music_info.get_music_player_timer == 0) {
music_info.get_music_player_timer = sys_timer_add(NULL, music_player_time_deal, 800);
}
} else {
if (music_info.get_music_player_timer) {
sys_timer_del(music_info.get_music_player_timer);
music_info.get_music_player_timer = 0;
}
}
}
void music_info_cmd_handle(u8 *p, u16 len)
{
u8 cmd = *p;
u8 *data = p + 1;
switch (cmd) {
case 0x01:
user_send_cmd_prepare(USER_CTRL_AVCTP_OPID_PLAY, 0, NULL);
break;
case 0x02:
user_send_cmd_prepare(USER_CTRL_AVCTP_OPID_PREV, 0, NULL);
break;
case 0x03:
user_send_cmd_prepare(USER_CTRL_AVCTP_OPID_NEXT, 0, NULL);
break;
case 0x04:
music_info.player_time_en = *data;
if (*data) {
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_MUSIC_PLAYER_TIME_TEMER, data, 1);
} else {
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_MUSIC_PLAYER_TIME_TEMER, data, 1);
}
break;
default:
break;
}
}
u32 char_to_hex(char num, u8 ten_num)
{
u32 char_num;
switch (num) {
case '0':
char_num = 0;
break;
case '1':
char_num = 1;
break;
case '2':
char_num = 2;
break;
case '3':
char_num = 3;
break;
case '4':
char_num = 4;
break;
case '5':
char_num = 5;
break;
case '6':
char_num = 6;
break;
case '7':
char_num = 7;
break;
case '8':
char_num = 8;
break;
case '9':
char_num = 9;
break;
default:
char_num = 0;
}
switch (ten_num) {
case 0:
char_num = char_num;
break;
case 1:
char_num = char_num * 10;
break;
case 2:
char_num = char_num * 100;
break;
case 3:
char_num = char_num * 1000;
break;
case 4:
char_num = char_num * 10000;
break;
case 5:
char_num = char_num * 100000;
break;
case 6:
char_num = char_num * 1000000;
break;
case 7:
char_num = char_num * 10000000;
break;
default:
char_num = char_num;
}
return char_num;
}
u32 num_char_to_hex(char *c, len)
{
u32 total_num = 0;
u8 i;
for (i = 0; i < len; i++) {
total_num += char_to_hex(*(c + i), len - i - 1);
}
return total_num;
}
void rcsp_adv_music_info_deal(u8 type, u32 time, u8 *info, u16 len)
{
//printf("info len \n");
//put_buf(info,len);
#if RCSP_ADV_FIND_DEVICE_ENABLE
extern u8 find_device_key_flag_get(void);
if (find_device_key_flag_get()) {
return;
}
#endif
switch (type) {
case 0:
if (time != music_info.total_time) {
/* if(music_info.player_time_en) */
{
music_info.curr_player_time = time;
music_info.player_time_min = time / 1000 / 60;
music_info.player_time_sec = time / 1000 - (music_info.player_time_min * 60);
/* printf("total time %d %d->", music_info.total_time, time); */
/* printf("muisc time %d %d->", music_info.player_time_min, music_info.player_time_sec); */
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_PLAYER_TIME, NULL, 0);
}
}
return;
case 1:
if ((info) && (len)) {
if (len > 64) {
len = 64;
}
music_info.title_len = len;
memcpy(music_info.title, info, len);
}
break;
case 2:
if ((info) && (len)) {
if (len > 64) {
len = 64;
}
music_info.artist_len = len;
memcpy(music_info.artist, info, len);
}
break;
case 3:
if ((info) && (len)) {
if (len > 64) {
len = 64;
}
music_info.album_len = len;
memcpy(music_info.album, info, len);
}
break;
case 4:
if ((info) && (len)) {
len = 1;
music_info.num_len = len;
memcpy(&music_info.number, info, len);
}
break;
case 5:
if ((info) && (len)) {
len = 2;
music_info.total_len = len;
memcpy(music_info.total, info, len);
}
break;
case 6:
if ((info) && (len)) {
if (len > 16) {
len = 16;
}
music_info.genre_len = len;
memcpy(music_info.genre, info, len);
}
break;
case 7:
if ((info) && (len)) {
if (len > 8) {
len = 8;
}
memcpy(music_info.time, info, len);
/* printf("get time %s\n", info); */
/* put_buf(music_info.time, len); */
music_info.total_time = num_char_to_hex(music_info.time, len);
}
break;
default:
break;
}
if (music_info.player_time_en) {
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_MUSIC_INFO, &type, 1);
}
/* os_time_dly(2); */
}
#endif
#endif

View File

@ -0,0 +1,31 @@
#ifndef __ADV_MUSIC_INFO_SETTING_H__
#define __ADV_MUSIC_INFO_SETTING_H__
#include "le_rcsp_adv_module.h"
#if RCSP_ADV_MUSIC_INFO_ENABLE
char *get_music_title(void);
u8 get_music_title_len(void);
char *get_music_artist(void);
u8 get_music_artist_len(void);
char *get_music_album(void);
u8 get_music_album_len(void);
char *get_music_number(void);
u8 get_music_number_len(void);
char *get_music_total(void);
u8 get_music_total_len(void);
char *get_music_genre(void);
u8 get_music_genre_len(void);
u16 get_music_total_time(void);
u32 get_music_curr_time(void);
u8 get_music_player_state(void);
void music_info_cmd_handle(u8 *p, u16 len);
void stop_get_music_timer(u8 en);
extern void music_player_time_timer_deal(u8 en);
u8 get_player_time_en(void);
void set_player_time_en(u8 en);
void rcsp_adv_music_info_deal(u8 type, u32 time, u8 *info, u16 len);
#endif
#endif

View File

@ -0,0 +1,27 @@
#ifndef __ADV_SCENE_NOISE_REDUCTION_H__
#define __ADV_SCENE_NOISE_REDUCTION_H__
#include "system/includes.h"
typedef enum {
RCSP_SCENE_NOISE_REDUCTION_TYPE_INTELLIGENT = 0x00,
RCSP_SCENE_NOISE_REDUCTION_TYPE_MILD = 0x01,
RCSP_SCENE_NOISE_REDUCTION_TYPE_BALANCE = 0x02,
RCSP_SCENE_NOISE_REDUCTION_TYPE_DEEPNESS = 0x03,
} RCSP_SCENE_NOISE_REDUCTION_TYPE;
/**
* @brief 获取场景降噪类型
*
* @result RCSP_SCENE_NOISE_REDUCTION_TYPE
*/
RCSP_SCENE_NOISE_REDUCTION_TYPE get_scene_noise_reduction_type();
/**
* @brief 设置场景降噪类型
*/
void set_scene_noise_reduction_type(RCSP_SCENE_NOISE_REDUCTION_TYPE type);
#endif // __ADV_SCENE_NOISE_REDUCTION_H__

View File

@ -0,0 +1,31 @@
#ifndef __ADV_SETTING_COMMON_H__
#define __ADV_SETTING_COMMON_H__
#include "typedef.h"
#include "event.h"
#if RCSP_ADV_EN
struct t_s_info {
u8 edr_name[32];
u8 key_setting[12];
u8 key_extra_setting[4];
u8 led_status[6];
u8 mic_mode;
u8 work_mode;
u8 eq_mode_info[11];
};
extern struct t_s_info _s_info;
void deal_time_stamp_setting(u32 time_stamp, u8 write_vm, u8 tws_sync);
void deal_bt_name_setting(u8 *bt_name_setting, u8 write_vm, u8 tws_sync);
void deal_key_setting(u8 *key_setting_info, u8 write_vm, u8 tws_sync);
void deal_led_setting(u8 *led_setting_info, u8 write_vm, u8 tws_sync);
void deal_mic_setting(u8 mic_setting_info, u8 write_vm, u8 tws_sync);
void deal_work_setting(u8 work_setting_info, u8 write_vm, u8 tws_sync, u8 poweron);
void adv_setting_init(void);
void update_adv_setting(u16 type);
void update_info_from_adv_vm_info(void);
void modify_bt_name_and_reset(u32 msec);
#endif
#endif

View File

@ -0,0 +1,87 @@
#include "app_config.h"
#include "syscfg_id.h"
#include "user_cfg_id.h"
#include "rcsp_adv_bluetooth.h"
#include "JL_rcsp_protocol.h"
#include "le_rcsp_adv_module.h"
#include "adv_time_stamp_setting.h"
#include "adv_setting_common.h"
#include "rcsp_adv_tws_sync.h"
#include "rcsp_adv_opt.h"
#if (RCSP_ADV_EN)
extern int get_bt_tws_connect_status();
static u32 adv_time_stamp = 0;
u32 get_adv_time_stamp(void)
{
return adv_time_stamp;
}
void set_adv_time_stamp(u32 time_stamp)
{
adv_time_stamp = time_stamp;
}
void sync_setting_by_time_stamp(void)
{
tws_api_send_data_to_sibling((u8 *)&adv_time_stamp, sizeof(adv_time_stamp), TWS_FUNC_ID_TIME_STAMP_SYNC);
}
void deal_sibling_time_stamp_setting_switch(void *data, u16 len)
{
u32 time_stamp = *((u32 *)data);
if (adv_time_stamp > time_stamp) {
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_ADV_SETTING_SYNC, NULL, 0);
}
}
void deal_adv_setting_gain_time_stamp(void)
{
#if TCFG_USER_TWS_ENABLE
extern u8 adv_info_device_request(u8 * buf, u16 len);
static u8 tws_pair = 0;
u8 buf = 2;
u8 ret = 0;
if (get_bt_tws_connect_status()) {
tws_pair = 1;
} else {
if (tws_pair) {
tws_pair = 0;
ret = adv_info_device_request(&buf, sizeof(buf));
}
}
#endif
}
// 1、写入VM
static void update_time_stamp_vm_value(u32 time_stamp)
{
syscfg_write(CFG_RCSP_ADV_TIME_STAMP, (u8 *)&time_stamp, 4);
}
// 2、同步对端
static void adv_time_stamp_sync(u32 time_stamp)
{
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
update_adv_setting(BIT(ATTR_TYPE_TIME_STAMP));
}
#endif
}
void deal_time_stamp_setting(u32 time_stamp, u8 write_vm, u8 tws_sync)
{
if (!time_stamp) {
time_stamp = get_adv_time_stamp();
} else {
set_adv_time_stamp(time_stamp);
}
if (write_vm) {
update_time_stamp_vm_value(time_stamp);
}
if (tws_sync) {
adv_time_stamp_sync(time_stamp);
}
}
#endif

View File

@ -0,0 +1,10 @@
#ifndef __ADV_TIME_STAMP_SETTING_H__
#define __ADV_TIME_STAMP_SETTING_H__
void set_adv_time_stamp(u32 time_stamp);
u32 get_adv_time_stamp(void);
void deal_sibling_time_stamp_setting_switch(void *data, u16 len);
extern void sync_setting_by_time_stamp(void);
void deal_adv_setting_gain_time_stamp(void);
#endif

View File

@ -0,0 +1,18 @@
#ifndef __ADV_VOICE_ENHANCEMENT_MODE_H__
#define __ADV_VOICE_ENHANCEMENT_MODE_H__
#include "system/includes.h"
/**
* @brief 获取人声增强模式开关
*
* @result bool
*/
bool get_voice_enhancement_mode_switch();
/**
* @brief 设置人声增强模式开关
*/
void set_voice_enhancement_mode_switch(bool mode_switch);
#endif // __ADV_VOICE_ENHANCEMENT_MODE_H__

View File

@ -0,0 +1,18 @@
#ifndef __ADV_WIND_NOISE_DETECTION_H__
#define __ADV_WIND_NOISE_DETECTION_H__
#include "system/includes.h"
/**
* @brief 获取风噪检测开关
*
* @result bool
*/
bool get_wind_noise_detection_switch();
/**
* @brief 设置风噪检测开关
*/
void set_wind_noise_detection_switch(bool detection_switch);
#endif // __ADV_WIND_NOISE_DETECTION_H__

View File

@ -0,0 +1,104 @@
#include "app_config.h"
#include "syscfg_id.h"
#include "user_cfg_id.h"
#include "le_rcsp_adv_module.h"
#include "adv_work_setting.h"
#include "adv_setting_common.h"
#include "rcsp_adv_tws_sync.h"
#include "rcsp_adv_opt.h"
#include "os/os_api.h"
#include "btstack/avctp_user.h"
#if (RCSP_ADV_EN)
#if RCSP_ADV_WORK_SET_ENABLE
extern int get_bt_tws_connect_status();
extern void bt_set_low_latency_mode(int enable);
void set_work_setting(u8 work_setting_info)
{
_s_info.work_mode = work_setting_info;
}
u8 get_work_setting(void)
{
return _s_info.work_mode;
}
static void adv_work_setting_vm_value(u8 work_setting_info)
{
/* syscfg_write(CFG_RCSP_ADV_WORK_SETTING, &work_setting_info, 1); */
}
static void adv_work_setting_sync(u8 work_setting_info)
{
#if TCFG_USER_TWS_ENABLE
if (get_bt_tws_connect_status()) {
update_adv_setting(BIT(ATTR_TYPE_WORK_MODE));
}
#endif
}
static void __rcsp_work_set_call(void)
{
//r_f_printf("__rcsp_work_set_call\n");
if (1 == _s_info.work_mode) {
bt_set_low_latency_mode(0);
} else if (2 == _s_info.work_mode) {
bt_set_low_latency_mode(1);
}
}
static void rcsp_work_set_deal(void)
{
int err;
int msg[3];
msg[0] = (int) __rcsp_work_set_call;
msg[1] = 1;
msg[2] = 0;
err = os_taskq_post_type("app_core", Q_CALLBACK, 3, msg);
//r_printf("err %x\n",err);
}
static void update_work_setting_state(void)
{
//r_f_printf("set deal\n");
rcsp_work_set_deal();
}
void deal_work_setting(u8 work_setting_info, u8 write_vm, u8 tws_sync, u8 poweron)
{
if (poweron) {
__rcsp_work_set_call();
} else {
if (0 == work_setting_info) {
work_setting_info = get_work_setting();
} else {
set_work_setting(work_setting_info);
}
if (write_vm) {
adv_work_setting_vm_value(work_setting_info);
}
if (tws_sync) {
adv_work_setting_sync(work_setting_info);
}
update_work_setting_state();
}
}
int ble_vendor_is_slow_state(void)
{
if ((BT_STATUS_PLAYING_MUSIC == get_bt_connect_status()) && (2 == _s_info.work_mode)) {
return 1;
} else {
return 0;
}
}
#endif
#endif

View File

@ -0,0 +1,13 @@
#ifndef __ADV_WORK_SETTING_H__
#define __ADV_WORK_SETTING_H__
#include "le_rcsp_adv_module.h"
#if RCSP_ADV_WORK_SET_ENABLE
void set_work_setting(u8 work_setting_info);
u8 get_work_setting(void);
#endif
#endif

View File

@ -0,0 +1,131 @@
#ifndef __JL_BLUETOOTH_ADV_H__
#define __JL_BLUETOOTH_ADV_H__
#include "app_config.h"
#include "typedef.h"
#include "system/event.h"
#include "le_common.h"
#include "ble_user.h"
#include "spp_user.h"
#if (RCSP_ADV_EN)
void rcsp_init();
void rcsp_dev_select(u8 type);
void function_change_inform(void);
bool common_msg_deal(u32 param, void *priv);
bool ble_msg_deal(u32 param);
bool music_msg_deal(u32 param, void *priv);
bool linein_msg_deal(u32 param);
bool rtc_msg_deal(u32 param);
#if (RCSP_ADV_ASSISTED_HEARING)
void set_hearing_aid_operating_flag();
#endif
void rcsp_exit(void);
u8 rcsp_get_asr_status(void);
u8 get_rcsp_support_new_reconn_flag(void);
enum {
RCSP_BLE,
RCSP_SPP,
};
enum {
ANDROID,
APPLE_IOS,
};
struct JL_AI_VAR {
ble_state_e JL_ble_status;
struct ble_server_operation_t *rcsp_ble;
u8 JL_spp_status;
struct spp_operation_t *rcsp_spp;
volatile u8 speech_state;
u32 feature_mask;
u8 device_type;
u8 phone_platform;
void (*start_speech)(void);
void (*stop_speech)(void);
u8 err_report;
volatile u8 file_browse_lock_flag;
u32 return_msg;
u8 spec_mode;
struct __rcsp_user_var *rcsp_user;
volatile u8 rcsp_run_flag;
u8 ffr_mode;
u16 ffr_time;
volatile u8 wait_asr_end;
u8 new_reconn_flag; //是否支持新的回连方式(进行地址修改)
};
struct _SPEECH_OVER_DEAL {
u8 last_task;
u8 status;
};
extern struct JL_AI_VAR jl_ai_var;
extern struct _SPEECH_OVER_DEAL speech_deal_val;
#define DEVICE_EVENT_FROM_RCSP (('R' << 24) | ('C' << 16) | ('S' << 8) | 'P')
enum RCSP_MSG_T {
MSG_JL_GET_DEV_UPDATE_FILE_INFO_OFFSET,
MSG_JL_INQUIRE_DEVEICE_IF_CAN_UPDATE,
MSG_JL_LOADER_DOWNLOAD_START,
MSG_JL_UPDATE_START,
MSG_JL_ENTER_UPDATE_MODE,
MSG_JL_DEV_DISCONNECT,
MSG_JL_BLE_UPDATE_START,
MSG_JL_SPP_UPDATE_START,
MSG_JL_ADV_SETTING_SYNC,
MSG_JL_ADV_SETTING_UPDATE,
MSG_JL_UPDATE_EQ,
MSG_JL_UPDATE_SEQ,
MSG_JL_SWITCH_DEVICE,
MSG_JL_UPDATE_PLAYER_TIME,
MSG_JL_UPDATE_PLAYER_STATE,
MSG_JL_UPDATE_MUSIC_INFO,
MSG_JL_UPDATE_MUSIC_PLAYER_TIME_TEMER,
MSG_JL_UPDAET_ADV_STATE_INFO,
MSG_JL_REBOOT_DEV,
MSG_JL_FIND_DEVICE_RESUME,
MSG_JL_FIND_DEVICE_STOP,
MSG_JL_UPDATE_ANC_VOICE,
MSG_JL_UPDATE_ANC_VOICE_MAX_SYNC,
MSG_JL_UPDATE_ADAPTIVE_NOISE_REDUCTION,
MSG_JL_UPDATE_AI_NO_PICK,
MSG_JL_UPDATE_SCENE_NOISE_REDUCTION,
MSG_JL_UPDATE_WIND_NOISE_DETECTION,
MSG_JL_UPDATE_VOICE_ENHANCEMENT_MODE,
MSG_JL_TWS_NEED_UPDATE,
};
void JL_rcsp_event_to_user(u32 type, u8 event, u8 *msg, u8 size);
int JL_rcsp_event_handler(struct rcsp_event *rcsp);
void rcsp_tws_auth_sync_deal(void);
extern u8 JL_get_cur_bt_channel_sel(void);
#define SDK_TYPE_AC690X 0x0
#define SDK_TYPE_AC692X 0x1
#define SDK_TYPE_AC693X 0x2
#define SDK_TYPE_AC695X 0x3
#define SDK_TYPE_AC697X 0x4
#if (defined CONFIG_CPU_BR21)
#define RCSP_SDK_TYPE SDK_TYPE_AC692X
#elif (defined CONFIG_CPU_BR22)
#define RCSP_SDK_TYPE SDK_TYPE_AC693X
#elif (defined CONFIG_CPU_BR23)
#define RCSP_SDK_TYPE SDK_TYPE_AC695X
#elif (defined CONFIG_CPU_BR30)
#define RCSP_SDK_TYPE SDK_TYPE_AC697X
#else
#define RCSP_SDK_TYPE SDK_TYPE_AC693X
#endif
#endif
#endif

View File

@ -0,0 +1,70 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "string.h"
#include "JL_rcsp_api.h"
#include "JL_rcsp_protocol.h"
#include "JL_rcsp_packet.h"
#include "spp_user.h"
#include "btstack/avctp_user.h"
#include "system/timer.h"
#include "app_core.h"
#include "user_cfg.h"
#include "asm/pwm_led.h"
#include "ui_manage.h"
#include "key_event_deal.h"
#include "syscfg_id.h"
#include "user_cfg_id.h"
#include "classic/tws_api.h"
#include "event.h"
#include "bt_tws.h"
#include "custom_cfg.h"
#include "app_config.h"
#if (RCSP_ADV_EN)
/* #define RCSP_USER_DEBUG_EN */
#ifdef RCSP_USER_DEBUG_EN
#define rcsp_user_putchar(x) putchar(x)
#define rcsp_user_printf printf
#define rcsp_user_printf_buf(x,len) put_buf(x,len)
#else
#define rcsp_user_putchar(...)
#define rcsp_user_printf(...)
#define rcsp_user_printf_buf(...)
#endif
/// 发送需要回复的自定义命令
u32 rcsp_user_send_resp_cmd(u8 *data, u16 len)
{
u32 ret = 0;
rcsp_user_printf("send resp cmd\n");
rcsp_user_printf_buf(data, len);
ret = JL_CMD_send(JL_OPCODE_CUSTOMER_USER, data, len, 1);
return ret;
}
void rcsp_user_recv_resp(u8 *data, u16 len)
{
///收到固件发出去,APP的回复
rcsp_user_printf("resp resp\n");
rcsp_user_printf_buf(data, len);
}
void rcsp_user_recv_cmd_resp(u8 *data, u16 len)
{
///收到app主动发过来的需要回复的自定义命令
///回复在其他地方已完成,开发不需要单独回复
rcsp_user_printf("user recv cmd:\n");
rcsp_user_printf_buf(data, len);
/* rcsp_user_send_resp_cmd(data, len); */
}
#endif

View File

@ -0,0 +1,17 @@
#ifndef __JL_ADV_CUSTOMER_USER_H__
#define __JL_ADV_CUSTOMER_USER_H__
#include "app_config.h"
#include "typedef.h"
#include "system/event.h"
#include "le_common.h"
#include "spp_user.h"
#if (RCSP_ADV_EN)
void rcsp_user_recv_cmd_resp(u8 *data, u16 len);
void rcsp_user_recv_resp(u8 *data, u16 len);
u32 rcsp_user_send_resp_cmd(u8 *data, u16 len);
#endif
#endif

View File

@ -0,0 +1,495 @@
#include "app_config.h"
#include "syscfg_id.h"
#include "user_cfg_id.h"
#include "le_rcsp_adv_module.h"
#include "rcsp_adv_bluetooth.h"
#include "rcsp_adv_opt.h"
#include "adv_setting_common.h"
#include "rcsp_adv_tws_sync.h"
#include "adv_time_stamp_setting.h"
#include "adv_bt_name_setting.h"
#include "adv_key_setting.h"
#include "adv_led_setting.h"
#include "adv_mic_setting.h"
#include "adv_work_setting.h"
#include "adv_eq_setting.h"
#include "adv_high_low_vol.h"
#include "adv_anc_voice_key.h"
#include "bt_tws.h"
#include "btstack/avctp_user.h"
#include "adv_anc_voice.h"
#include "adv_hearing_aid_setting.h"
#if (RCSP_ADV_EN)
static u16 adv_setting_event_flag = (u16) - 1;
static void set_adv_setting_event_flag(u16 flag)
{
adv_setting_event_flag = flag;
}
static u16 get_adv_setting_event_flag(void)
{
return adv_setting_event_flag;
}
static u8 deal_adv_setting_string_item(u8 *des, u8 *src, u8 src_len, u8 type)
{
des[0] = type;
memcpy(des + 1, src, src_len);
return src_len + sizeof(type);
}
void update_info_from_adv_vm_info(void)
{
if (get_adv_setting_event_flag() & BIT(ATTR_TYPE_TIME_STAMP)) {
deal_time_stamp_setting(0, 1, 0);
}
#if RCSP_ADV_NAME_SET_ENABLE
if (get_adv_setting_event_flag() & BIT(ATTR_TYPE_EDR_NAME)) {
deal_bt_name_setting(NULL, 1, 0);
}
#endif
#if RCSP_ADV_KEY_SET_ENABLE
if (get_adv_setting_event_flag() & BIT(ATTR_TYPE_KEY_SETTING)) {
deal_key_setting(NULL, 1, 0);
}
if (get_adv_setting_event_flag() & BIT(ATTR_TYPE_ANC_VOICE_KEY)) {
deal_anc_voice_key_setting(NULL, 1, 0);
}
#endif
#if RCSP_ADV_LED_SET_ENABLE
if (get_adv_setting_event_flag() & BIT(ATTR_TYPE_LED_SETTING)) {
deal_led_setting(NULL, 1, 0);
}
#endif
#if RCSP_ADV_MIC_SET_ENABLE
if (get_adv_setting_event_flag() & BIT(ATTR_TYPE_MIC_SETTING)) {
deal_mic_setting(0, 1, 0);
}
#endif
#if RCSP_ADV_WORK_SET_ENABLE
if (get_adv_setting_event_flag() & BIT(ATTR_TYPE_WORK_MODE)) {
deal_work_setting(0, 1, 0, 0);
}
#endif
#if RCSP_ADV_EQ_SET_ENABLE
if (get_adv_setting_event_flag() & BIT(ATTR_TYPE_EQ_SETTING)) {
deal_eq_setting(0, 1, 0);
}
#endif
#if RCSP_ADV_HIGH_LOW_SET
if (get_adv_setting_event_flag() & BIT(ATTR_TYPE_HIGH_LOW_VOL)) {
deal_high_low_vol(NULL, 1, 0);
}
#endif
#if (RCSP_ADV_ANC_VOICE)
if (get_adv_setting_event_flag() & BIT(ATTR_TYPE_ANC_VOICE)) {
deal_anc_voice(NULL, 1, 0);
}
#endif
#if (RCSP_ADV_ASSISTED_HEARING)
if (get_adv_setting_event_flag() & BIT(ATTR_TYPE_ASSISTED_HEARING)) {
deal_hearing_aid_setting(-1, -1, NULL, 1, 0);
}
#endif
set_adv_setting_event_flag(0);
}
static u8 adv_read_data_from_vm(u8 syscfg_id, u8 *buf, u8 buf_len)
{
int len = 0;
u8 i = 0;
len = syscfg_read(syscfg_id, buf, buf_len);
if (len > 0) {
for (i = 0; i < buf_len; i++) {
if (buf[i] != 0xff) {
return (buf_len == len);
}
}
}
return 0;
}
void adv_setting_init(void)
{
u32 time_stamp = 0;
if (adv_read_data_from_vm(CFG_RCSP_ADV_TIME_STAMP, (u8 *)&time_stamp, sizeof(time_stamp))) {
set_adv_time_stamp(time_stamp);
//deal_time_stamp_setting(0, 0, 0);
}
#if RCSP_ADV_NAME_SET_ENABLE
u8 bt_name_info[32] = {0};
if (adv_read_data_from_vm(CFG_BT_NAME, bt_name_info, sizeof(bt_name_info))) {
set_bt_name_setting(bt_name_info);
//deal_bt_name_setting(NULL, 0, 0);
}
#endif
#if RCSP_ADV_KEY_SET_ENABLE
u8 key_setting_info[4] = {0};
if (adv_read_data_from_vm(CFG_RCSP_ADV_KEY_SETTING, key_setting_info, sizeof(key_setting_info))) {
set_key_setting(key_setting_info);
deal_key_setting(NULL, 0, 0);
}
u8 key_anc_voice_mode[4] = {0};
if (adv_read_data_from_vm(CFG_RCSP_ADV_ANC_VOICE_KEY, key_anc_voice_mode, sizeof(key_anc_voice_mode))) {
set_anc_voice_key_mode(key_anc_voice_mode);
deal_anc_voice_key_setting(NULL, 0, 0);
}
#endif
#if RCSP_ADV_LED_SET_ENABLE
u8 led_setting_info[3] = {0};
if (adv_read_data_from_vm(CFG_RCSP_ADV_LED_SETTING, led_setting_info, sizeof(led_setting_info))) {
set_led_setting(led_setting_info);
deal_led_setting(NULL, 0, 0);
}
#endif
#if RCSP_ADV_MIC_SET_ENABLE
u8 mic_setting_info = 0;
if (adv_read_data_from_vm(CFG_RCSP_ADV_MIC_SETTING, &mic_setting_info, sizeof(mic_setting_info))) {
set_mic_setting(mic_setting_info);
deal_mic_setting(0, 0, 0);
}
#endif
#if RCSP_ADV_WORK_SET_ENABLE
u8 work_setting_info = 0;
if (adv_read_data_from_vm(CFG_RCSP_ADV_WORK_SETTING, &work_setting_info, sizeof(work_setting_info))) {
set_work_setting(work_setting_info);
deal_work_setting(0, 0, 0, 1);
}
#endif
#if RCSP_ADV_EQ_SET_ENABLE
u8 eq_setting_vm_info[11] = {0};
u8 eq_setting_info[10] = {0};
u8 eq_setting_mode = 0;
u8 i;
if (adv_read_data_from_vm(CFG_RCSP_ADV_EQ_DATA_SETTING, eq_setting_info, sizeof(eq_setting_info))) {
if (adv_read_data_from_vm(CFG_RCSP_ADV_EQ_MODE_SETTING, &eq_setting_mode, sizeof(eq_setting_mode))) {
eq_setting_vm_info[0] = eq_setting_mode;
memcpy(eq_setting_vm_info + 1, eq_setting_info, sizeof(eq_setting_info));
set_eq_setting(eq_setting_vm_info);
deal_eq_setting(NULL, 0, 0);
}
}
#endif
#if RCSP_ADV_HIGH_LOW_SET
u8 high_low_vol_setting[8] = {0};
if (adv_read_data_from_vm(CFG_RCSP_ADV_HIGH_LOW_VOL, high_low_vol_setting, sizeof(high_low_vol_setting))) {
set_high_low_vol_info(high_low_vol_setting);
deal_high_low_vol(NULL, 0, 0);
}
#endif
#if (RCSP_ADV_ANC_VOICE)
u8 anc_voice_setting[25] = {0};
if (anc_voice_setting_init()) {
if (adv_read_data_from_vm(CFG_RCSP_ADV_ANC_VOICE_MODE, anc_voice_setting, 1)) {
if (adv_read_data_from_vm(CFG_RCSP_ADV_ANC_VOICE, anc_voice_setting + 1, sizeof(anc_voice_setting) - 1)) {
set_anc_voice_info(anc_voice_setting);
deal_anc_voice(NULL, 0, 0);
}
}
}
#endif
}
// type : 0 ~ 8
// mode : 0 - 从vm读出并更新全局变量数据 // 1 - 同步
void update_adv_setting(u16 type)
{
u8 offset = 1;
// total_len time name key led mic work eq vol anc anc_voice
u8 adv_setting_to_sync[1 + (4 + 1) + (32 + 1) + (4 + 1) + (3 + 1) + (1 + 1) + (1 + 1) + (11 + 1) + (8 + 1) + (25 + 1) + (4 + 1)] = {0};
memset(adv_setting_to_sync, 0, sizeof(adv_setting_to_sync));
if (type & BIT(ATTR_TYPE_TIME_STAMP)) {
u32 time_stamp = get_adv_time_stamp();
offset += deal_adv_setting_string_item(adv_setting_to_sync + offset, (u8 *)&time_stamp, sizeof(time_stamp), ATTR_TYPE_TIME_STAMP);
}
#if RCSP_ADV_NAME_SET_ENABLE
if (type & BIT(ATTR_TYPE_EDR_NAME)) {
u8 bt_name_info[32] = {0};
get_bt_name_setting(bt_name_info);
offset += deal_adv_setting_string_item(adv_setting_to_sync + offset, bt_name_info, sizeof(bt_name_info), ATTR_TYPE_EDR_NAME);
}
#endif
#if RCSP_ADV_KEY_SET_ENABLE
if (type & BIT(ATTR_TYPE_KEY_SETTING)) {
u8 key_setting_info[4] = {0};
get_key_setting(key_setting_info);
offset += deal_adv_setting_string_item(adv_setting_to_sync + offset, key_setting_info, sizeof(key_setting_info), ATTR_TYPE_KEY_SETTING);
}
if (type & BIT(ATTR_TYPE_ANC_VOICE_KEY)) {
u8 key_anc_voice_mode[4] = {0};
get_anc_voice_key_mode(key_anc_voice_mode);
offset += deal_adv_setting_string_item(adv_setting_to_sync + offset, key_anc_voice_mode, sizeof(key_anc_voice_mode), ATTR_TYPE_ANC_VOICE_KEY);
}
#endif
#if RCSP_ADV_LED_SET_ENABLE
if (type & BIT(ATTR_TYPE_LED_SETTING)) {
u8 led_setting_info[3] = {0};
get_led_setting(led_setting_info);
offset += deal_adv_setting_string_item(adv_setting_to_sync + offset, led_setting_info, sizeof(led_setting_info), ATTR_TYPE_LED_SETTING);
}
#endif
#if RCSP_ADV_MIC_SET_ENABLE
if (type & BIT(ATTR_TYPE_MIC_SETTING)) {
u8 mic_setting_info = get_mic_setting();
offset += deal_adv_setting_string_item(adv_setting_to_sync + offset, &mic_setting_info, sizeof(mic_setting_info), ATTR_TYPE_MIC_SETTING);
}
#endif
#if RCSP_ADV_WORK_SET_ENABLE
if (type & BIT(ATTR_TYPE_WORK_MODE)) {
u8 work_setting_info = get_work_setting();
offset += deal_adv_setting_string_item(adv_setting_to_sync + offset, &work_setting_info, sizeof(work_setting_info), ATTR_TYPE_WORK_MODE);
}
#endif
#if RCSP_ADV_EQ_SET_ENABLE
if (type & BIT(ATTR_TYPE_EQ_SETTING)) {
u8 eq_setting_info[11];
get_eq_setting(eq_setting_info);
offset += deal_adv_setting_string_item(adv_setting_to_sync + offset, eq_setting_info, sizeof(eq_setting_info), ATTR_TYPE_EQ_SETTING);
}
#endif
#if RCSP_ADV_HIGH_LOW_SET
if (type & BIT(ATTR_TYPE_HIGH_LOW_VOL)) {
u8 high_low_vol[8];
get_high_low_vol_info(high_low_vol);
offset += deal_adv_setting_string_item(adv_setting_to_sync + offset, high_low_vol, sizeof(high_low_vol), ATTR_TYPE_HIGH_LOW_VOL);
}
#endif
#if (RCSP_ADV_ANC_VOICE)
if (type & BIT(ATTR_TYPE_ANC_VOICE)) {
u8 anc_voice_info[25];
get_anc_voice_info(anc_voice_info);
offset += deal_adv_setting_string_item(adv_setting_to_sync + offset, anc_voice_info, sizeof(anc_voice_info), ATTR_TYPE_ANC_VOICE);
}
#endif
#if RCSP_ADV_ASSISTED_HEARING
if (((u16) - 1) != type && type & BIT(ATTR_TYPE_ASSISTED_HEARING)) {
u8 dha_fitting_data[3 + 2 * 4 * DHA_FITTING_CHANNEL_MAX];
get_hearing_aid_setting(dha_fitting_data);
offset += deal_adv_setting_string_item(adv_setting_to_sync + offset, dha_fitting_data, sizeof(dha_fitting_data), ATTR_TYPE_ASSISTED_HEARING);
}
#endif
if (offset > 1) {
adv_setting_to_sync[0] = offset;
if (type == ((u16) - 1)) {
tws_api_send_data_to_sibling(adv_setting_to_sync, sizeof(adv_setting_to_sync), TWS_FUNC_ID_ADV_SETTING_SYNC);
#if RCSP_ADV_LED_SET_ENABLE
tws_api_sync_call_by_uuid('T', SYNC_CMD_APP_RESET_LED_UI, 300);
#endif
} else {
if (tws_api_get_role() == TWS_ROLE_MASTER) {
tws_api_send_data_to_sibling(adv_setting_to_sync, sizeof(adv_setting_to_sync), TWS_FUNC_ID_ADV_SETTING_SYNC);
#if RCSP_ADV_LED_SET_ENABLE
tws_api_sync_call_by_uuid('T', SYNC_CMD_APP_RESET_LED_UI, 300);
#endif
}
}
}
}
void deal_sibling_setting(u8 *buf)
{
u8 type;
u8 len = buf[0];
u8 offset = 1;
u8 *data;
u32 time_stamp = 0;
set_adv_setting_event_flag(0);
while (offset < len) {
type = buf[offset++];
data = buf + offset;
switch (type) {
#if RCSP_ADV_NAME_SET_ENABLE
case ATTR_TYPE_EDR_NAME:
set_bt_name_setting(data);
offset += 32;
break;
#endif
#if RCSP_ADV_KEY_SET_ENABLE
case ATTR_TYPE_KEY_SETTING :
set_key_setting(data);
offset += 4;
break;
case ATTR_TYPE_ANC_VOICE_KEY:
set_anc_voice_key_mode(data);
offset += 4;
break;
#endif
#if RCSP_ADV_LED_SET_ENABLE
case ATTR_TYPE_LED_SETTING :
set_led_setting(data);
offset += 3;
break;
#endif
#if RCSP_ADV_MIC_SET_ENABLE
case ATTR_TYPE_MIC_SETTING :
set_mic_setting(*data);
offset += 1;
break;
#endif
#if RCSP_ADV_WORK_SET_ENABLE
case ATTR_TYPE_WORK_MODE :
set_work_setting(*data);
offset += 1;
break;
#endif
#if RCSP_ADV_EQ_SET_ENABLE
case ATTR_TYPE_EQ_SETTING :
/* g_printf("tws eq setting\n"); */
set_eq_setting(data);
offset += 11;
break;
#endif
#if RCSP_ADV_HIGH_LOW_SET
case ATTR_TYPE_HIGH_LOW_VOL:
set_high_low_vol_info(data);
offset += 8;
break;
#endif
#if (RCSP_ADV_ANC_VOICE)
case ATTR_TYPE_ANC_VOICE:
set_anc_voice_info(data);
offset += 25;
break;
#endif
#if (RCSP_ADV_ASSISTED_HEARING)
case ATTR_TYPE_ASSISTED_HEARING:
set_hearing_aid_setting(data);
offset += 3 + 2 * 4 * DHA_FITTING_CHANNEL_MAX;
break;
#endif
case ATTR_TYPE_TIME_STAMP:
time_stamp = (data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24));//*((u32 *)data);
set_adv_time_stamp(time_stamp);
offset += 4;
break;
default:
return;
}
set_adv_setting_event_flag(get_adv_setting_event_flag() | BIT(type));
}
// 发送事件
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_ADV_SETTING_UPDATE, NULL, 0);
}
#if (0)
static void adv_reset_data_to_vm(u8 syscfg_id, u8 *buf, u8 buf_len)
{
u8 res = 0;
res = syscfg_write(syscfg_id, buf, buf_len);
}
u8 rcsp_setting_info_reset() //恢复默认的APP设置
{
printf("%s", __func__);
u32 time_stamp = 0xffffffff;
adv_reset_data_to_vm(CFG_RCSP_ADV_TIME_STAMP, (u8 *)&time_stamp, sizeof(time_stamp));
/* #if RCSP_ADV_NAME_SET_ENABLE */
/* u8 bt_name_info[32] = {0}; */
/* memset(bt_name_info,0xff,32); */
/* adv_reset_data_to_vm(CFG_BT_NAME, bt_name_info, sizeof(bt_name_info)); */
/* #endif */
#if RCSP_ADV_KEY_SET_ENABLE
u8 key_setting_info[4] = {0};
memset(key_setting_info, 0xff, 4);
adv_reset_data_to_vm(CFG_RCSP_ADV_KEY_SETTING, key_setting_info, sizeof(key_setting_info));
#endif
#if RCSP_ADV_LED_SET_ENABLE
u8 led_setting_info[3] = {0};
memset(led_setting_info, 0xff, 3);
adv_reset_data_to_vm(CFG_RCSP_ADV_LED_SETTING, led_setting_info, sizeof(led_setting_info));
#endif
#if RCSP_ADV_MIC_SET_ENABLE
u8 mic_setting_info = 0xff;
adv_reset_data_to_vm(CFG_RCSP_ADV_MIC_SETTING, &mic_setting_info, sizeof(mic_setting_info));
#endif
#if RCSP_ADV_WORK_SET_ENABLE
u8 work_setting_info = 0xff;
adv_reset_data_to_vm(CFG_RCSP_ADV_WORK_SETTING, &work_setting_info, sizeof(work_setting_info));
#endif
#if RCSP_ADV_EQ_SET_ENABLE
u8 eq_setting_info[10] = {0};
u8 eq_setting_mode = 0xff;
memset(eq_setting_info, 0xff, 10);
adv_reset_data_to_vm(CFG_RCSP_ADV_EQ_DATA_SETTING, &eq_setting_info, sizeof(eq_setting_info));
adv_reset_data_to_vm(CFG_RCSP_ADV_EQ_MODE_SETTING, &eq_setting_mode, sizeof(eq_setting_mode));
#endif
return 0;
}
u8 remap_app_chargestore_data_deal(u8 *buf, u8 len)
{
u8 send_buf[30];
u8 ret = 0;
send_buf[0] = buf[0];
//#define CMD_GET_NAME 0xc1
switch (buf[0]) {
case 0x08:
//printf("\n\n\n\n\n\n---------------reset store sys\n");
ret = 1 ;
void bt_tws_remove_pairs();
bt_tws_remove_pairs();
extern u8 rcsp_setting_info_reset();
rcsp_setting_info_reset();
user_send_cmd_prepare(USER_CTRL_DEL_ALL_REMOTE_INFO, 0, NULL);
os_time_dly(60);
cpu_reset();
break;
default:
break;
}
return ret;
}
#endif
#endif

View File

@ -0,0 +1,6 @@
#ifndef __RCSP_ADV_OPT_H__
#define __RCSP_ADV_OPT_H__
void deal_sibling_setting(u8 *buf);
#endif

View File

@ -0,0 +1,105 @@
#include "app_config.h"
#include "rcsp_adv_tws_sync.h"
#include "adv_setting_common.h"
#include "rcsp_adv_opt.h"
#include "adv_time_stamp_setting.h"
#include "rcsp_adv_bluetooth.h"
#include "bt_tws.h"
#if (RCSP_ADV_EN && TCFG_USER_TWS_ENABLE)
static void adv_sync_tws_func_t(void *data, u16 len, bool rx)
{
if (rx) {
deal_sibling_setting((u8 *)data);
}
}
REGISTER_TWS_FUNC_STUB(adv_tws_sync) = {
.func_id = TWS_FUNC_ID_ADV_SETTING_SYNC,
.func = adv_sync_tws_func_t,
};
static void adv_sync_time_stamp_func_t(void *data, u16 len, bool rx)
{
if (rx) {
deal_sibling_time_stamp_setting_switch(data, len);
}
}
REGISTER_TWS_FUNC_STUB(adv_time_stamp_sync) = {
.func_id = TWS_FUNC_ID_TIME_STAMP_SYNC,
.func = adv_sync_time_stamp_func_t,
};
#define TWS_FUNC_ID_ADV_RESET_SYNC \
(((u8)('R' + 'C' + 'S' + 'P') << (3 * 8)) | \
((u8)('A' + 'D' + 'V') << (2 * 8)) | \
((u8)('R' + 'E' + 'S' + 'E' + 'T') << (1 * 8)) | \
((u8)('S' + 'Y' + 'N' + 'C') << (0 * 8)))
static void adv_sync_reset_sync_func_t(int args)
{
extern void cpu_reset();
cpu_reset();
}
TWS_SYNC_CALL_REGISTER(adv_reset_sync) = {
.uuid = TWS_FUNC_ID_ADV_RESET_SYNC,
.func = adv_sync_reset_sync_func_t,
};
void modify_bt_name_and_reset(u32 msec)
{
tws_api_sync_call_by_uuid(TWS_FUNC_ID_ADV_RESET_SYNC, 0, msec);
}
#define TWS_FUNC_ID_ADV_FIND_DEV_SYNC \
(((u8)('A' + 'D' + 'V') << (3 * 8)) | \
((u8)('F' + 'I' + 'N' + 'D') << (2 * 8)) | \
((u8)('D' + 'E' + 'V') << (1 * 8)) | \
((u8)('S' + 'Y' + 'N' + 'C') << (0 * 8)))
static void adv_find_dev_sync_func_t(int args)
{
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_FIND_DEVICE_RESUME, &args, sizeof(args));
}
TWS_SYNC_CALL_REGISTER(adv_find_dev_sync) = {
.uuid = TWS_FUNC_ID_ADV_FIND_DEV_SYNC,
.func = adv_find_dev_sync_func_t,
};
void find_device_sync(u8 *param, u32 msec)
{
int priv = 0;
if (TWS_ROLE_MASTER == tws_api_get_role()) {
memcpy(&priv, param, 3);
tws_api_sync_call_by_uuid(TWS_FUNC_ID_ADV_FIND_DEV_SYNC, priv, msec);
}
}
#define TWS_FUNC_ID_ADV_FIND_DEV_STOP_TIMER_SYNC \
(((u8)('F' + 'I' + 'N' + 'D') << (3 * 8)) | \
((u8)('D' + 'E' + 'V') << (2 * 8)) | \
((u8)('S' + 'T' + 'O' + 'P') << (1 * 8)) | \
((u8)('S' + 'Y' + 'N' + 'C') << (0 * 8)))
static void adv_find_dev_stop_sync_timer_func_t(int args)
{
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_FIND_DEVICE_STOP, &args, sizeof(args));
}
TWS_SYNC_CALL_REGISTER(adv_find_dev_stop_sync) = {
.uuid = TWS_FUNC_ID_ADV_FIND_DEV_STOP_TIMER_SYNC,
.func = adv_find_dev_stop_sync_timer_func_t,
};
void find_devic_stop_timer(u8 *param, u32 msec)
{
int priv = 0;
if (TWS_ROLE_MASTER == tws_api_get_role()) {
memcpy(&priv, param, 3);
tws_api_sync_call_by_uuid(TWS_FUNC_ID_ADV_FIND_DEV_STOP_TIMER_SYNC, priv, msec);
}
}
#endif

View File

@ -0,0 +1,13 @@
#ifndef __RCSP_ADV_TWS_SYNC_H__
#define __RCSP_ADV_TWS_SYNC_H__
#include "classic/tws_api.h"
#define TWS_FUNC_ID_ADV_SETTING_SYNC \
TWS_FUNC_ID('R', 'C', 'S', 'P')
#define TWS_FUNC_ID_TIME_STAMP_SYNC \
TWS_FUNC_ID('R' + 'C' + 'S' + 'P', \
'A' + 'D' + 'V', \
'T' + 'I' + 'M' + 'E', \
'S' + 'T' + 'A' + 'M' + 'P')
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,197 @@
// binary representation
// attribute size in bytes (16), flags(16), handle (16), uuid (16/128), value(...)
#ifndef _LE_SERVER_MODULE_H
#define _LE_SERVER_MODULE_H
#include <stdint.h>
#include "bt_common.h"
#include "audio_anc.h"
#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_ADV_RCSP)
//
// gatt profile include file, generated by jieli gatt_inc_generator.exe
//
static const uint8_t profile_data[] = {
//////////////////////////////////////////////////////
//
// 0x0001 PRIMARY_SERVICE 1800
//
//////////////////////////////////////////////////////
0x0a, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x28, 0x00, 0x18,
/* CHARACTERISTIC, 2a00, READ | WRITE | DYNAMIC, */
// 0x0002 CHARACTERISTIC 2a00 READ | WRITE | DYNAMIC
0x0d, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x28, 0x0a, 0x03, 0x00, 0x00, 0x2a,
// 0x0003 VALUE 2a00 READ | WRITE | DYNAMIC
0x08, 0x00, 0x0a, 0x01, 0x03, 0x00, 0x00, 0x2a,
//////////////////////////////////////////////////////
//
// 0x0004 PRIMARY_SERVICE ae00
//
//////////////////////////////////////////////////////
0x0a, 0x00, 0x02, 0x00, 0x80, 0x00, 0x00, 0x28, 0x00, 0xae,
/* CHARACTERISTIC, ae01, WRITE_WITHOUT_RESPONSE | DYNAMIC, */
// 0x0040 CHARACTERISTIC ae01 WRITE_WITHOUT_RESPONSE | DYNAMIC
0x0d, 0x00, 0x02, 0x00, 0x81, 0x00, 0x03, 0x28, 0x04, 0x82, 0x00, 0x01, 0xae,
// 0x0041 VALUE ae01 WRITE_WITHOUT_RESPONSE | DYNAMIC
0x08, 0x00, 0x04, 0x01, 0x82, 0x00, 0x01, 0xae,
/* CHARACTERISTIC, ae02, NOTIFY, */
// 0x0042 CHARACTERISTIC ae02 NOTIFY
0x0d, 0x00, 0x02, 0x00, 0x83, 0x00, 0x03, 0x28, 0x10, 0x84, 0x00, 0x02, 0xae,
// 0x0043 VALUE ae02 NOTIFY
0x08, 0x00, 0x10, 0x00, 0x84, 0x00, 0x02, 0xae,
// 0x0044 CLIENT_CHARACTERISTIC_CONFIGURATION
0x0a, 0x00, 0x0a, 0x01, 0x85, 0x00, 0x02, 0x29, 0x00, 0x00,
//////////////////////////////////////////////////////
//
// 0x0014 PRIMARY_SERVICE 1812
//
//////////////////////////////////////////////////////
// 0x0a, 0x00, 0x02, 0x00, 0x14, 0x00, 0x00, 0x28, 0x12, 0x18,
#if 0// authentication
//
10, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x28, 0x0A, 0x18, //primary service declaration
13, 0x00, 0x02, 0x00, 0x1B, 0x00, 0x03, 0x28, 0x02, 0x1C, 0x00, 0x50, 0x2A, //characteristic declaration
15, 0x00, 0x02, 0x04, 0x1C, 0x00, 0x50, 0x2A, 0x02, 0x8A, 0x24, 0x66, 0x82, 0x34, 0x36, //PnP ID
#endif
// END
0x00, 0x00,
};
//
// characteristics <--> handles
//
#define ATT_CHARACTERISTIC_2a00_01_VALUE_HANDLE 0x0003
#define ATT_CHARACTERISTIC_ae01_01_VALUE_HANDLE 0x0082
#define ATT_CHARACTERISTIC_ae02_01_VALUE_HANDLE 0x0084
#define ATT_CHARACTERISTIC_ae02_01_CLIENT_CONFIGURATION_HANDLE 0x0085
// #define ATT_CHARACTERISTIC_ae01_01_VALUE_HANDLE 0x0006
// #define ATT_CHARACTERISTIC_ae02_01_VALUE_HANDLE 0x0008
// #define ATT_CHARACTERISTIC_ae02_01_CLIENT_CONFIGURATION_HANDLE 0x0009
// #define ATT_CHARACTERISTIC_ae03_01_VALUE_HANDLE 0x000b
// #define ATT_CHARACTERISTIC_ae04_01_VALUE_HANDLE 0x000d
// #define ATT_CHARACTERISTIC_ae04_01_CLIENT_CONFIGURATION_HANDLE 0x000e
// #define ATT_CHARACTERISTIC_ae05_01_VALUE_HANDLE 0x0010
// #define ATT_CHARACTERISTIC_ae05_01_CLIENT_CONFIGURATION_HANDLE 0x0011
// #define ATT_CHARACTERISTIC_ae10_01_VALUE_HANDLE 0x0013
#define JL_OPCODE_SET_ADV 0xC0
#define JL_OPCODE_GET_ADV 0xC1
#define JL_OPCODE_ADV_DEVICE_NOTIFY 0xC2
#define JL_OPCODE_ADV_NOTIFY_SETTING 0xC3
#define JL_OPCODE_ADV_DEVICE_REQUEST 0xC4
#define ATTR_TYPE_BAT_VALUE (0)
#define ATTR_TYPE_EDR_NAME (1)
#define ATTR_TYPE_KEY_SETTING (2)
#define ATTR_TYPE_LED_SETTING (3)
#define ATTR_TYPE_MIC_SETTING (4)
#define ATTR_TYPE_WORK_MODE (5)
#define ATTR_TYPE_PRODUCT_MESSAGE (6)
#define ATTR_TYPE_TIME_STAMP (7)
#define ATTR_TYPE_EQ_SETTING (8)
#define ATTR_TYPE_HIGH_LOW_VOL (9)
#define ATTR_TYPE_ANC_VOICE_KEY (10)
#define ATTR_TYPE_ANC_VOICE (11)
#define ATTR_TYPE_ASSISTED_HEARING (12)
//rcsp功能模块使能
#define RCSP_ADV_NAME_SET_ENABLE 1
#define RCSP_ADV_KEY_SET_ENABLE 1
#define RCSP_ADV_LED_SET_ENABLE 1
#define RCSP_ADV_MIC_SET_ENABLE 1
#define RCSP_ADV_WORK_SET_ENABLE 1
#if (JL_EARPHONE_APP_EN)
#define RCSP_ADV_EQ_SET_ENABLE 1
#define RCSP_ADV_MUSIC_INFO_ENABLE 1
#define RCSP_ADV_HIGH_LOW_SET 1
#define RCSP_ADV_FIND_DEVICE_ENABLE 1
#define RCSP_ADV_AI_NO_PICK 0 // 智能免摘
#define RCSP_ADV_ASSISTED_HEARING 0 // 辅听注意开启辅听后需要关闭ANC相关功能
#if !RCSP_ADV_ASSISTED_HEARING
#define RCSP_ADV_ANC_VOICE 0 // 主动降噪
#if RCSP_ADV_ANC_VOICE
#define RCSP_ADV_ADAPTIVE_NOISE_REDUCTION 1 // 自适应降噪
#define RCSP_ADV_SCENE_NOISE_REDUCTION 1 // 场景降噪
#define RCSP_ADV_WIND_NOISE_DETECTION 1 // 风噪检测
#define RCSP_ADV_VOICE_ENHANCEMENT_MODE 1 // 人声增强模式
#endif
#endif
#else
#define RCSP_ADV_EQ_SET_ENABLE 0
#define RCSP_ADV_MUSIC_INFO_ENABLE 0
#define RCSP_ADV_HIGH_LOW_SET 0
#define RCSP_ADV_FIND_DEVICE_ENABLE 0
#define RCSP_ADV_ASSISTED_HEARING 0 // 辅听注意开启辅听后需要关闭ANC相关功能
#define RCSP_ADV_ANC_VOICE 0 // 主动降噪
#define RCSP_ADV_ADAPTIVE_NOISE_REDUCTION 0 // 自适应降噪
#define RCSP_ADV_AI_NO_PICK 0 // 智能免摘
#define RCSP_ADV_SCENE_NOISE_REDUCTION 0 // 场景降噪
#define RCSP_ADV_WIND_NOISE_DETECTION 0 // 风噪检测
#define RCSP_ADV_VOICE_ENHANCEMENT_MODE 0 // 人声增强模式
#endif
#define RCSP_ADV_PRODUCT_MSG_ENABLE 1
#if !TCFG_EQ_ENABLE
#undef RCSP_ADV_EQ_SET_ENABLE
#define RCSP_ADV_EQ_SET_ENABLE 0
#endif
#if !ANC_EAR_ADAPTIVE_EN && JL_EARPHONE_APP_EN
#undef RCSP_ADV_ADAPTIVE_NOISE_REDUCTION
#define RCSP_ADV_ADAPTIVE_NOISE_REDUCTION 0 //自适应降噪
#endif
enum {
BT_ADV_ENABLE,
BT_ADV_DISABLE,
BT_ADV_SET_EDR_CON_FLAG,
BT_ADV_SET_BAT_CHARGE_L,
BT_ADV_SET_BAT_CHARGE_R,
BT_ADV_SET_BAT_CHARGE_C,
BT_ADV_SET_BAT_PERCENT_L,
BT_ADV_SET_BAT_PERCENT_R,
BT_ADV_SET_BAT_PERCENT_C,
BT_ADV_SET_NOTIFY_EN,
};
// BT_ADV_SET_EDR_CON_FLAG
#define SECNE_DISMISS (0x00)
#define SECNE_UNCONNECTED (0x01)
#define SECNE_CONNECTED (0x02)
#define SECNE_CONNECTING (0x03)
#define SECNE_CONNECTINLESS (0x04)
#define TWS_FUNC_ID_SEQ_RAND_SYNC (('S' << (3 * 8)) | ('E' << (2 * 8)) | ('Q' << (1 * 8)) | ('\0'))
enum {
TWS_ADV_SEQ_CHANGE = 0,
TWS_VERSON_INFO,
TWS_UPDATE_INFO,
};
extern int bt_ble_adv_ioctl(u32 cmd, u32 priv, u8 mode);
extern void bt_adv_seq_change(void);
void ble_app_disconnect(void);
void bt_ble_rcsp_adv_enable(void);
void bt_ble_rcsp_adv_disable(void);
u8 get_ble_adv_notify(void);
void set_ble_adv_notify(u8 en);
u8 get_connect_flag(void);
void set_connect_flag(u8 value);
void ble_module_enable(u8 en);
#endif
#endif

View File

@ -0,0 +1,91 @@
#include "app_config.h"
#include "app_action.h"
#include "system/includes.h"
#include "spp_user.h"
#include "string.h"
#include "circular_buf.h"
#include "3th_profile_api.h"
#include "bt_common.h"
#if 1
extern void printf_buf(u8 *buf, u32 len);
#define log_info printf
#define log_info_hexdump printf_buf
#else
#define log_info(...)
#define log_info_hexdump(...)
#endif
/* #define DEBUG_ENABLE */
/* #include "debug_log.h" */
/* #include "rcsp_spp_user.h" */
#if (RCSP_ADV_EN)
static struct spp_operation_t *spp_api = NULL;
static u8 spp_state;
int rcsp_spp_send_data(u8 *data, u16 len)
{
if (spp_api) {
return spp_api->send_data(NULL, data, len);
}
return SPP_USER_ERR_SEND_FAIL;
}
int rcsp_spp_send_data_check(u16 len)
{
if (spp_api) {
if (spp_api->busy_state()) {
return 0;
}
}
return 1;
}
static void rcsp_spp_state_cbk(u8 state)
{
spp_state = state;
switch (state) {
case SPP_USER_ST_CONNECT:
log_info("SPP_USER_ST_CONNECT ~~~\n");
set_app_connect_type(TYPE_SPP);
break;
case SPP_USER_ST_DISCONN:
log_info("SPP_USER_ST_DISCONN ~~~\n");
set_app_connect_type(TYPE_NULL);
break;
default:
break;
}
}
static void rcsp_spp_send_wakeup(void)
{
putchar('W');
}
static void rcsp_spp_recieve_cbk(void *priv, u8 *buf, u16 len)
{
log_info("spp_api_rx ~~~\n");
log_info_hexdump(buf, len);
}
void rcsp_spp_init(void)
{
spp_state = 0;
spp_get_operation_table(&spp_api);
spp_api->regist_recieve_cbk(0, rcsp_spp_recieve_cbk);
spp_api->regist_state_cbk(0, rcsp_spp_state_cbk);
spp_api->regist_wakeup_send(NULL, rcsp_spp_send_wakeup);
}
#endif

View File

@ -0,0 +1,42 @@
#ifndef TOMCRYPT_H_
#define TOMCRYPT_H_
// #include <stdio.h>
#include <string.h>
#define HARDWARE_METHOD 0
#ifndef WIN32
// #include "hw_cpu.h"
#undef HARDWARE_METHOD
#define HARDWARE_METHOD 1
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*
@param [in] pt[*1] The plaintext
@param ptlen The length of the plaintext(octets) range: 1~32
@param [in] key[*1] The key for encrypt
@param keylen[*1] The length of the key(octets) range: 1~32
@param [out] mac[*1] output : The Message Authentication Code 16 bytes.
*/
extern void btcon_hash(unsigned char *pt, int ptlen, unsigned char *key, int keylen, unsigned char *mac);
#if HARDWARE_METHOD
extern int yf_aes_start_enc(unsigned char key[16], unsigned char plaintext[16], unsigned char encrypt[16]);
#endif
#ifdef __cplusplus
}
#endif
#endif /* TOMCRYPT_H_ */
/* $Source$ */
/* $Revision$ */
/* $Date$ */

View File

@ -0,0 +1,100 @@
#ifndef __JL_BLUETOOTH_H__
#define __JL_BLUETOOTH_H__
#include "typedef.h"
#include "le_common.h"
#include "spp_user.h"
#include "system/event.h"
#include "rcsp_msg.h"
#include "ble_user.h"
#if RCSP_BTMATE_EN
void rcsp_init();
void rcsp_dev_select(u8 type);
void function_change_inform(void);
bool common_msg_deal(u32 param, void *priv);
bool ble_msg_deal(u32 param);
bool music_msg_deal(u32 param, void *priv);
bool linein_msg_deal(u32 param);
bool rtc_msg_deal(u32 param);
void rcsp_exit(void);
u8 rcsp_get_asr_status(void);
u8 get_rcsp_support_new_reconn_flag(void);
// enum {
// RCSP_BLE,
// RCSP_SPP,
// };
enum {
ANDROID,
APPLE_IOS,
};
struct JL_AI_VAR {
ble_state_e JL_ble_status;
struct ble_server_operation_t *rcsp_ble;
u8 JL_spp_status;
struct spp_operation_t *rcsp_spp;
volatile u8 speech_state;
u32 feature_mask;
u8 device_type;
u8 phone_platform;
void (*start_speech)(void);
void (*stop_speech)(void);
u8 err_report;
volatile u8 file_browse_lock_flag;
u32 return_msg;
u8 spec_mode;
struct __rcsp_user_var *rcsp_user;
volatile u8 rcsp_run_flag;
u8 ffr_mode;
u16 ffr_time;
u16 rcsp_timer_hdl;
volatile u8 wait_asr_end;
u8 new_reconn_flag; //是否支持新的回连方式(进行地址修改)
};
struct _SPEECH_OVER_DEAL {
u8 last_task;
u8 status;
};
extern struct JL_AI_VAR jl_ai_var;
extern struct _SPEECH_OVER_DEAL speech_deal_val;
enum RCSP_MSG_T {
MSG_JL_GET_DEV_UPDATE_FILE_INFO_OFFSET = RCSP_MSG_END,
MSG_JL_INQUIRE_DEVEICE_IF_CAN_UPDATE,
MSG_JL_LOADER_DOWNLOAD_START,
MSG_JL_UPDATE_START,
MSG_JL_ENTER_UPDATE_MODE,
MSG_JL_DEV_DISCONNECT,
MSG_JL_BLE_UPDATE_START,
MSG_JL_SPP_UPDATE_START,
};
bool rcsp_msg_post(RCSP_MSG msg, int argc, ...);
#define SDK_TYPE_AC690X 0x0
#define SDK_TYPE_AC692X 0x1
#define SDK_TYPE_AC693X 0x2
#define SDK_TYPE_AC695X 0x3
#define SDK_TYPE_AC697X 0x4
#if (defined CONFIG_CPU_BR21)
#define RCSP_SDK_TYPE SDK_TYPE_AC692X
#elif (defined CONFIG_CPU_BR22)
#define RCSP_SDK_TYPE SDK_TYPE_AC693X
#elif (defined CONFIG_CPU_BR23)
#define RCSP_SDK_TYPE SDK_TYPE_AC695X
#elif (defined CONFIG_CPU_BR30)
#define RCSP_SDK_TYPE SDK_TYPE_AC697X
#else
#define RCSP_SDK_TYPE SDK_TYPE_AC693X
#endif
#endif
#endif

View File

@ -0,0 +1,13 @@
#ifndef __RCSP_MSG_H__
#define __RCSP_MSG_H__
typedef enum __RCSP_MSG {
RCSP_MSG_UPDATE_EQ = 0,
RCSP_MSG_SET_FMTX_POINT,
RCSP_MSG_BS_END,
RCSP_MSG_BT_SCAN,
RCSP_MSG_END,
} RCSP_MSG;
#endif//__RCSP_MSG_H__

View File

@ -0,0 +1,575 @@
#include "app_config.h"
#include "rcsp_adv_user_update.h"
#if RCSP_UPDATE_EN
#include "uart.h"
#include "system/timer.h"
#include "update.h"
#include "custom_cfg.h"
#include "btstack/avctp_user.h"
#include "JL_rcsp_packet.h"
#include "JL_rcsp_protocol.h"
#include "rcsp_adv_bluetooth.h"
#include "le_rcsp_adv_module.h"
#include "update_loader_download.h"
#include "classic/tws_api.h"
#include "syscfg_id.h"
#if (RCSP_ADV_EN)
#define RCSP_DEBUG_EN
#ifdef RCSP_DEBUG_EN
#define rcsp_putchar(x) putchar(x)
#define rcsp_printf printf
#define rcsp_printf_buf(x,len) printf_buf(x,len)
#else
#define rcsp_putchar(...)
#define rcsp_printf(...)
#define rcsp_printf_buf(...)
#endif
#define DEV_UPDATE_FILE_INFO_OFFEST 0x00//0x40
#define DEV_UPDATE_FILE_INFO_LEN 0x00//(0x10 + VER_INFO_EXT_COUNT * (VER_INFO_EXT_MAX_LEN + 1))
typedef enum {
UPDATA_START = 0x00,
UPDATA_REV_DATA,
UPDATA_STOP,
} UPDATA_BIT_FLAG;
#if 0
static update_file_id_t update_file_id_info = {
.ver[0] = 0xff,
.ver[1] = 0xff,
};
#else
static update_file_ext_id_t update_file_id_info = {
.update_file_id_info.ver[0] = 0xff,
.update_file_id_info.ver[1] = 0xff,
};
#endif
extern const int support_dual_bank_update_en;
extern void JL_ble_disconnect(void);
extern u8 check_le_pakcet_sent_finish_flag(void);
static u8 update_flag = 0;
static u8 tws_need_update = 0; //标志耳机是否需要强制升级
static u8 tws_need_role_switch = 0; //用于tws连接之后版本号不匹配进行role_switch低版本号的作为主机进行强制升级
static u8 disconnect_flag = 0;
u8 get_jl_update_flag(void)
{
printf("get_update_flag:%x\n", update_flag);
return update_flag;
}
void set_jl_update_flag(u8 flag)
{
update_flag = flag;
printf("update_flag:%x\n", update_flag);
}
typedef struct _update_mode_t {
u8 opcode;
u8 opcode_sn;
} update_mode_t;
static update_mode_t update_record_info;
void JL_controller_save_curr_cmd_para(u8 OpCode, u8 OpCode_SN)
{
update_record_info.opcode = OpCode;
update_record_info.opcode_sn = OpCode_SN;
}
void JL_controller_get_curr_cmd_para(u8 *OpCode, u8 *OpCode_SN)
{
*OpCode = update_record_info.opcode;
*OpCode_SN = update_record_info.opcode_sn;
}
static void (*fw_update_block_handle)(u8 state, u8 *buf, u16 len) = NULL;
void register_receive_fw_update_block_handle(void (*handle)(u8 state, u8 *buf, u16 len))
{
fw_update_block_handle = handle;
}
static u16 ble_discon_timeout;
static void ble_discon_timeout_handle(void *priv)
{
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_START, NULL, 0);
}
void JL_rcsp_update_cmd_resp(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len)
{
u8 msg[4];
rcsp_printf("%s\n", __FUNCTION__);
switch (OpCode) {
case JL_OPCODE_GET_DEVICE_UPDATE_FILE_INFO_OFFSET:
if (0 == len) {
msg[0] = OpCode;
msg[1] = OpCode_SN;
rcsp_printf("JL_OPCODE_GET_DEVICE_UPDATE_FILE_INFO_OFFSET\n");
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP,
MSG_JL_GET_DEV_UPDATE_FILE_INFO_OFFSET,
msg,
2);
} else {
rcsp_printf("JL_OPCODE_GET_DEVICE_UPDATE_FILE_INFO_OFFSET ERR\n");
}
break;
case JL_OPCODE_INQUIRE_DEVICE_IF_CAN_UPDATE:
rcsp_printf("JL_OPCODE_INQUIRE_DEVICE_IF_CAN_UPDATE:%x %x\n", len, data[0]);
if (len) {
extern void set_curr_update_type(u8 type);
set_curr_update_type(data[0]);
msg[0] = OpCode;
msg[1] = OpCode_SN;
msg[2] = 0x00;
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP,
MSG_JL_INQUIRE_DEVEICE_IF_CAN_UPDATE,
msg,
3);
}
break;
case JL_OPCODE_EXIT_UPDATE_MODE:
rcsp_printf("JL_OPCODE_EXIT_UPDATE_MODE\n");
break;
case JL_OPCODE_ENTER_UPDATE_MODE:
rcsp_printf("JL_OPCODE_ENTER_UPDATE_MODE\n");
msg[0] = OpCode;
msg[1] = OpCode_SN;
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP,
MSG_JL_ENTER_UPDATE_MODE,
msg,
2);
break;
case JL_OPCODE_SEND_FW_UPDATE_BLOCK:
rcsp_printf("JL_OPCODE_SEND_FW_UPDATE_BLOCK\n");
break;
case JL_OPCODE_GET_DEVICE_REFRESH_FW_STATUS:
rcsp_printf("JL_OPCODE_GET_DEVICE_REFRESH_FW_STATUS\n");
JL_controller_save_curr_cmd_para(OpCode, OpCode_SN);
if (fw_update_block_handle) {
fw_update_block_handle(UPDATA_STOP, NULL, 0);
}
break;
/* case JL_OPCODE_SET_DEVICE_REBOOT: */
/* rcsp_printf("JL_OPCODE_SET_DEVICE_REBOOT\n"); */
/* if (support_dual_bank_update_en) { */
/* cpu_reset(); */
/* } */
/* break; */
default:
break;
}
}
static void JL_rcsp_resp_dev_update_file_info_offest(u8 OpCode, u8 OpCode_SN)
{
u8 data[4 + 2];
u16 update_file_info_offset = DEV_UPDATE_FILE_INFO_OFFEST;
u16 update_file_info_len = DEV_UPDATE_FILE_INFO_LEN;
WRITE_BIG_U32(data + 0, update_file_info_offset);
WRITE_BIG_U16(data + 4, update_file_info_len);
JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, data, sizeof(data));
}
static void JL_resp_inquire_device_if_can_update(u8 OpCode, u8 OpCode_SN, u8 update_sta)
{
u8 data[1];
data[0] = update_sta;
JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, data, sizeof(data));
}
enum {
UPDATE_FLAG_OK,
UPDATE_FLAG_LOW_POWER,
UPDATE_FLAG_FW_INFO_ERR,
UPDATE_FLAG_FW_INFO_CONSISTENT,
UPDATE_FLAG_TWS_DISCONNECT,
};
static u8 judge_remote_version_can_update(void)
{
//extern u16 ex_cfg_get_local_version_info(void);
u16 remote_file_ver = READ_BIG_U16(update_file_id_info.update_file_id_info.ver);
//u16 local_ver = ex_cfg_get_local_version_info();
u16 local_ver = get_vid_pid_ver_from_cfg_file(GET_VID_FROM_EX_CFG);
#if (0 == VER_INFO_EXT_COUNT)
//extern u16 ex_cfg_get_local_pid_info(void);
//extern u16 ex_cfg_get_local_vid_info(void);
//u16 local_pid = ex_cfg_get_local_pid_info();
//u16 local_vid = ex_cfg_get_local_vid_info();
u16 local_pid = get_vid_pid_ver_from_cfg_file(GET_PID_FROM_EX_CFG);
u16 local_vid = get_vid_pid_ver_from_cfg_file(GET_VID_FROM_EX_CFG);
u16 remote_file_pid = READ_BIG_U16(update_file_id_info.update_file_id_info.pid);
u16 remote_file_vid = READ_BIG_U16(update_file_id_info.update_file_id_info.vid);
if (remote_file_ver > local_ver || remote_file_pid != local_pid || remote_file_vid != local_vid) {
return UPDATE_FLAG_FW_INFO_ERR;
}
#else
//extern u32 ex_cfg_get_local_authkey_info(u8 * authkey_data[], u8 * authkey_len);
//extern u32 ex_cfg_get_local_procode_info(u8 * procode_data[], u8 * procode_len);
u8 authkey_len = 0;
u8 *local_authkey_data = NULL;
get_authkey_procode_from_cfg_file(&local_authkey_data, &authkey_len, GET_AUTH_KEY_FROM_EX_CFG);
u8 procode_len = 0;
u8 *local_procode_data = NULL;
get_authkey_procode_from_cfg_file(&local_procode_data, &procode_len, GET_PRO_CODE_FROM_EX_CFG);
//ex_cfg_get_local_authkey_info(&local_authkey_data, &authkey_len);
//ex_cfg_get_local_procode_info(&local_procode_data, &procode_len);
u8 *remote_authkey_data = update_file_id_info.ext;
u8 *remote_procode_data = update_file_id_info.ext + authkey_len + 1;
if (remote_file_ver < local_ver
|| 0 != memcmp(remote_authkey_data, local_authkey_data, authkey_len)
|| 0 != memcmp(remote_procode_data, local_procode_data, procode_len)) {
return UPDATE_FLAG_FW_INFO_ERR;
}
#endif
if (remote_file_ver == local_ver) {
rcsp_printf("remote_file_ver is %x, local_ver is %x, remote_file_ver is similar to local_ver\n", remote_file_ver, local_ver);
return UPDATE_FLAG_FW_INFO_CONSISTENT;
}
return UPDATE_FLAG_OK;
}
static bool check_edr_is_disconnct(void)
{
if (get_curr_channel_state()) {
return TRUE;
} else {
return FALSE;
}
}
static bool check_ble_all_packet_sent(void)
{
if (check_le_pakcet_sent_finish_flag()) {
return TRUE;
} else {
return FALSE;
}
}
static u32 rcsp_update_data_read(void *priv, u32 offset_addr, u16 len)
{
u32 err;
u8 data[4 + 2];
WRITE_BIG_U32(data, offset_addr);
WRITE_BIG_U16(data + 4, len);
err = JL_CMD_send(JL_OPCODE_SEND_FW_UPDATE_BLOCK, data, sizeof(data), JL_NEED_RESPOND);
return err;
}
static JL_ERR JL_controller_resp_get_dev_refresh_fw_status(u8 OpCode, u8 OpCode_SN, u8 result)
{
JL_ERR send_err = JL_ERR_NONE;
u8 data[1];
data[0] = result; //0:sucess 1:fail;
send_err = JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, data, sizeof(data));
return send_err;
}
u32 rcsp_update_status_response(void *priv, u8 status)
{
u8 OpCode;
u8 OpCode_SN;
JL_ERR send_err = JL_ERR_NONE;
JL_controller_get_curr_cmd_para(&OpCode, &OpCode_SN);
//log_info("get cmd para:%x %x\n", OpCode, OpCode_SN);
if (JL_OPCODE_GET_DEVICE_REFRESH_FW_STATUS == OpCode) {
send_err = JL_controller_resp_get_dev_refresh_fw_status(OpCode, OpCode_SN, status);
}
return send_err;
}
void JL_rcsp_update_cmd_receive_resp(void *priv, u8 OpCode, u8 status, u8 *data, u16 len)
{
switch (OpCode) {
case JL_OPCODE_SEND_FW_UPDATE_BLOCK:
if (fw_update_block_handle) {
fw_update_block_handle(UPDATA_REV_DATA, data, len);
}
break;
default:
break;
}
}
static void rcsp_loader_download_result_handle(void *priv, u8 type, u8 cmd)
{
if (UPDATE_LOADER_OK == cmd) {
//JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP,MSG_JL_UPDATE_START,NULL,0);
set_jl_update_flag(1);
if (support_dual_bank_update_en) {
rcsp_printf(">>>rcsp update succ\n");
update_result_set(UPDATA_SUCC);
}
} else {
rcsp_printf(">>>update loader err\n");
/* #if OTA_TWS_SAME_TIME_ENABLE */
/* if((tws_ota_control(OTA_TYPE_GET) == OTA_TWS)) { */
/* tws_ota_stop(OTA_STOP_UPDATE_OVER_ERR); */
/* } */
/* #endif */
//rcsp_db_update_fail_deal();
}
}
extern void register_receive_fw_update_block_handle(void (*handle)(u8 state, u8 *buf, u16 len));
extern void rcsp_update_data_api_register(u32(*data_send_hdl)(void *priv, u32 offset, u16 len), u32(*send_update_handl)(void *priv, u8 state));
extern void rcsp_update_handle(void *buf, int len);
extern void bt_set_low_latency_mode(int enable);
extern void bt_adv_seq_change(void);
extern int bt_tws_poweroff();
extern void bt_wait_phone_connect_control(u8 enable);
extern int tws_api_get_role(void);
extern void tws_cancle_all_noconn();
extern void bt_ble_rcsp_adv_disable(void);
extern void ble_module_enable(u8 en);
extern void bt_ble_rcsp_adv_enable(void);
extern u32 ex_cfg_fill_content_api(void);
extern void update_param_priv_fill(UPDATA_PARM *p, void *priv, u16 priv_len);
u8 rcsp_get_update_flag(void)
{
return tws_need_update;
}
void rcsp_set_update_flag(u8 flag)
{
tws_need_update = flag;
}
u8 rcsp_update_get_role_switch(void)
{
return tws_need_role_switch;
}
void rcsp_update_set_role_switch(u8 sw)
{
tws_need_role_switch = sw;
}
void update_slave_adv_reopen(void)
{
r_printf("slave reopen adv...\n");
ble_module_enable(1);
bt_ble_rcsp_adv_enable();
}
static void rcsp_update_private_param_fill(UPDATA_PARM *p)
{
u32 exif_addr = ex_cfg_fill_content_api();
update_param_priv_fill(p, (void *)&exif_addr, sizeof(exif_addr));
}
static void rcsp_update_before_jump_handle(int type)
{
#if CONFIG_UPDATE_JUMP_TO_MASK
y_printf(">>>[test]:latch reset update\n");
latch_reset();
#if 0
update_close_hw("null");
ram_protect_close();
/* save_spi_port(); */
extern void __BT_UPDATA_JUMP();
y_printf("update jump to __BT_UPDATA ...\n");
/* clk_set("sys", 48 * 1000000L); */
//跳转到uboot加载完,30ms左右(200410_yzb)
__BT_UPDATA_JUMP();
#endif
#else
cpu_reset();
#endif
}
void JL_rcsp_msg_deal(void *hdl, u8 event, u8 *msg)
{
u16 remote_file_version;
u8 can_update_flag = UPDATE_FLAG_FW_INFO_ERR;
switch (event) {
case MSG_JL_GET_DEV_UPDATE_FILE_INFO_OFFSET:
rcsp_printf("MSG_JL_GET_DEV_UPDATE_FILE_INFO_OFFSET\n");
/* extern void linein_mutex_stop(void *priv); */
/* linein_mutex_stop(NULL); */
/* extern void linein_mute(u8 mute); */
/* linein_mute(1); */
JL_rcsp_resp_dev_update_file_info_offest((u8)msg[0], (u8)msg[1]);
break;
case MSG_JL_INQUIRE_DEVEICE_IF_CAN_UPDATE:
rcsp_printf("MSG_JL_INQUIRE_DEVEICE_IF_CAN_UPDATE\n");
#if 0
remote_file_version = READ_BIG_U16(update_file_id_info.update_file_id_info.ver);
rcsp_printf("remote_file_ver:V%d.%d.%d.%d\n",
(remote_file_version & 0xf000) >> 12,
(remote_file_version & 0x0f00) >> 8,
(remote_file_version & 0x00f0) >> 4,
(remote_file_version & 0x000f));
if (0 == remote_file_version) {
can_update_flag = UPDATE_FLAG_OK;
} else {
can_update_flag = judge_remote_version_can_update();
}
if (UPDATE_FLAG_OK == can_update_flag) {
set_jl_update_flag(1);
}
#else
#if OTA_TWS_SAME_TIME_ENABLE
int get_bt_tws_connect_status();
if (get_bt_tws_connect_status() || (!support_dual_bank_update_en)) { //单备份返回成功
can_update_flag = UPDATE_FLAG_OK;
} else {
can_update_flag = UPDATE_FLAG_TWS_DISCONNECT;
}
#else
can_update_flag = UPDATE_FLAG_OK;
#endif //endif OTA_TWS_SAME_TIME_ENABLE
#endif
//todo;judge voltage
JL_resp_inquire_device_if_can_update((u8)msg[0], (u8)msg[1], can_update_flag);
if (0 == support_dual_bank_update_en) {
if (tws_api_get_role() == TWS_ROLE_MASTER) {
g_printf("tws master start update...\n");
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_LOADER_DOWNLOAD_START, NULL, 0);
//需要通知从机进入了升级
u8 data = TWS_UPDATE_INFO;
tws_api_send_data_to_sibling(&data, sizeof(data), TWS_FUNC_ID_SEQ_RAND_SYNC);
} else {
bt_ble_rcsp_adv_disable();
ble_module_enable(0); //关闭广播防止从机被手机误回连
r_printf("slave close adv...\n");
sys_timeout_add(NULL, update_slave_adv_reopen, 1000 * 60); //延迟一分钟再开广播
}
if (RCSP_SPP == JL_get_cur_bt_channel_sel()) {
#if TCFG_USER_TWS_ENABLE
tws_api_detach(TWS_DETACH_BY_LOCAL); //单备份升级断开tws
tws_cancle_all_noconn();
#endif
}
}
break;
case MSG_JL_DEV_DISCONNECT:
if (check_ble_all_packet_sent()) {
rcsp_printf("MSG_JL_DEV_DISCONNECT\n");
JL_ble_disconnect();
if (check_edr_is_disconnct()) {
puts("-need discon edr\n");
user_send_cmd_prepare(USER_CTRL_POWER_OFF, 0, NULL);
}
ble_discon_timeout = sys_timeout_add(NULL, ble_discon_timeout_handle, 1000);
} else {
rcsp_printf("W");
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_DEV_DISCONNECT, NULL, 0);
}
break;
case MSG_JL_LOADER_DOWNLOAD_START:
rcsp_update_data_api_register(rcsp_update_data_read, rcsp_update_status_response);
register_receive_fw_update_block_handle(rcsp_update_handle);
if (RCSP_BLE == get_curr_device_type()) {
rcsp_update_loader_download_init(BLE_APP_UPDATA, rcsp_loader_download_result_handle);
} else if (RCSP_SPP == get_curr_device_type()) {
rcsp_update_loader_download_init(SPP_APP_UPDATA, rcsp_loader_download_result_handle);
}
break;
case MSG_JL_UPDATE_START:
if (check_edr_is_disconnct()) {
rcsp_printf("b");
JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_START, NULL, 0);
break;
}
if (RCSP_BLE == get_curr_device_type()) {
rcsp_printf("BLE_APP_UPDATE\n");
update_mode_api_v2(BLE_APP_UPDATA,
rcsp_update_private_param_fill,
rcsp_update_before_jump_handle);
} else {
rcsp_printf("SPP_APP_UPDATA\n");
update_mode_api_v2(SPP_APP_UPDATA,
rcsp_update_private_param_fill,
rcsp_update_before_jump_handle);
}
break;
case MSG_JL_ENTER_UPDATE_MODE:
rcsp_printf("MSG_JL_ENTER_UPDATE_MODE:%x %x\n", msg[0], msg[1]);
clk_set("sys",96*1000000L);
bt_set_low_latency_mode(0);
if (support_dual_bank_update_en && !tws_api_get_role()) {
u8 status = 0;
JL_CMD_response_send(msg[0], JL_PRO_STATUS_SUCCESS, msg[1], &status, 1);
rcsp_update_data_api_register(rcsp_update_data_read, rcsp_update_status_response);
register_receive_fw_update_block_handle(rcsp_update_handle);
rcsp_update_loader_download_init(DUAL_BANK_UPDATA, rcsp_loader_download_result_handle);
}
break;
default:
break;
}
}
#endif
#else
//以下函数是为了编译通过
void update_slave_adv_reopen(void)
{
printf("%s:NULL", __func__);
}
void rcsp_set_update_flag(u8 flag)
{
printf("%s:NULL", __func__);
}
void rcsp_update_set_role_switch(u8 sw)
{
printf("%s:NULL", __func__);
}
u8 get_jl_update_flag(void)
{
printf("%s:NULL", __func__);
return 0;
}
u8 rcsp_get_update_flag(void)
{
printf("%s:NULL", __func__);
return 0;
}
#endif

View File

@ -0,0 +1,27 @@
#ifndef _RCSP_ADV_USER_UPDATE_H_
#define _RCSP_ADV_USER_UPDATE_H_
//#include "rcsp_protocol.h"
//#include "rcsp_packet.h"
#include "typedef.h"
#define JL_OPCODE_GET_DEVICE_UPDATE_FILE_INFO_OFFSET 0xe1
#define JL_OPCODE_INQUIRE_DEVICE_IF_CAN_UPDATE 0xe2
#define JL_OPCODE_ENTER_UPDATE_MODE 0xe3
#define JL_OPCODE_EXIT_UPDATE_MODE 0xe4
#define JL_OPCODE_SEND_FW_UPDATE_BLOCK 0xe5
#define JL_OPCODE_GET_DEVICE_REFRESH_FW_STATUS 0xe6
#define JL_OPCODE_SET_DEVICE_REBOOT 0xe7
#define JL_OPCODE_NOTIFY_UPDATE_CONENT_SIZE 0xe8
void JL_rcsp_update_cmd_resp(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len);
void JL_rcsp_update_cmd_receive_resp(void *priv, u8 OpCode, u8 status, u8 *data, u16 len);
void JL_rcsp_msg_deal(void *hdl, u8 event, u8 *msg);
u8 get_jl_update_flag(void);
void set_jl_update_flag(u8 flag);
u8 get_curr_device_type(void);
void update_slave_adv_reopen(void);
#endif

View File

@ -0,0 +1,377 @@
//#include "update_lib.h"
#include "update.h"
#include "uart.h"
#include "update_loader_download.h"
#include "system/fs/fs.h"
#include "rcsp_user_update.h"
#include "JL_rcsp_protocol.h"
#include "os/os_error.h"
#include <string.h>
#if OTA_TWS_SAME_TIME_NEW
#include "update_tws_new.h"
#else
#include "update_tws.h"
#endif
#if TCFG_USER_TWS_ENABLE
#include "bt_tws.h"
#endif
#if ((RCSP_ADV_EN || RCSP_BTMATE_EN))
#define LMP_CH_UPDATE_DEBUG_EN 1
#if LMP_CH_UPDATE_DEBUG_EN
#define deg_puts puts
#define deg_printf printf
#else
#define deg_puts(...)
#define deg_printf(...)
#endif
typedef enum __DEVICE_REFRESH_FW_STATUS {
DEVICE_UPDATE_STA_SUCCESS = 0, //升级成功(default)
DEVICE_UPDATE_STA_VERIFY_ERR, //升级完校验代码出错(default)
DEVICE_UPDATE_STA_FAIL, //升级失败(default)
DEVICE_UPDATE_STA_KEY_ERR, //加密key不匹配
DEVICE_UPDATE_STA_FILE_ERR, //升级文件出错
DEVICE_UPDATE_STA_TYPE_ERR, //升级类型出错,仅code_type;
//DEVICE_UPDATE_STA_MAX_ERR,
DEVICE_UPDATE_STA_LOADER_DOWNLOAD_SUCC = 0x80,
} DEVICE_UPDATE_STA;
enum {
BT_UPDATE_OVER = 0,
BT_UPDATE_KEY_ERR,
BT_UPDATE_CONNECT_ERR,
};
typedef enum {
UPDATA_START = 0x00,
UPDATA_REV_DATA,
UPDATA_STOP,
} UPDATA_BIT_FLAG;
typedef struct _rcsp_update_param_t {
u32 state;
u32 read_len;
u32 need_rx_len;
u8 *read_buf;
void (*resume_hdl)(void *priv);
int (*sleep_hdl)(void *priv);
u32(*data_send_hdl)(void *priv, u32 offset, u16 len);
u32(*send_update_status_hdl)(void *priv, u8 state);
u32 file_offset;
u8 seek_type;
} rcsp_update_param_t;
extern void set_jl_update_flag(u8 flag);
extern const int support_dual_bank_update_en;
static rcsp_update_param_t rcsp_update_param;
#define __this (&rcsp_update_param)
static u8 *bt_read_buf = NULL;
static u16 g_bt_read_len = 0;
static u32 rcsp_file_offset = 0;
static u8 rcsp_seek_type = 0;
//NOTE:测试盒的定义和本sdk文件系统的seek_type定义不一样;
enum {
BT_SEEK_SET = 0x01,
BT_SEEK_CUR = 0x02,
BT_SEEK_TYPE_UPDATE_LEN = 0x10,
};
void tws_api_auto_role_switch_disable();
void tws_api_auto_role_switch_enable();
int rcsp_f_seek(void *fp, u8 type, u32 offset)
{
if (type == SEEK_SET) {
__this->file_offset = offset;
__this->seek_type = BT_SEEK_SET;
} else if (type == SEEK_CUR) {
__this->file_offset += offset;
__this->seek_type = BT_SEEK_CUR;
}
/* lib_printf("---------UPDATA_seek type %d, offsize %d----------\n", bt_seek_type, bt_file_offset); */
return 0;//FR_OK;
}
static u16 rcsp_f_stop(u8 err);
#define RETRY_TIMES 3
u8 get_rcsp_connect_status();
u16 rcsp_f_read(void *fp, u8 *buff, u16 len)
{
//printf("===rcsp_read:%x %x\n", __this->file_offset, len);
u8 retry_cnt = 0;
__this->need_rx_len = len;
__this->state = UPDATA_REV_DATA;
__this->read_len = 0;
__this->read_buf = buff;
__RETRY:
if (!get_rcsp_connect_status()) { //如果已经断开连接直接返回-1
return -1;
}
__this->data_send_hdl(fp, __this->file_offset, len);
while (!((0 == __this->state) && (__this->read_len == len))) {
if (__this->sleep_hdl && get_rcsp_connect_status()) {
__this->sleep_hdl(NULL);
} else {
len = -1;
break;
}
if (!((0 == __this->state) && (__this->read_len == len))) {
if (retry_cnt++ > RETRY_TIMES) {
len = (u16) - 1;
break;
} else {
goto __RETRY;
}
}
}
if ((u16) - 1 != len) {
__this->file_offset += len;
}
return len;
}
u16 rcsp_f_open(void)
{
deg_puts(">>>rcsp_f_open\n");
__this->file_offset = 0;
__this->seek_type = BT_SEEK_SET;
return 1;
}
u16 rcsp_send_update_len(u32 update_len)
{
/* while (0 == (bit(updata_start) & bt_updata_get_flag())); */
/* bt_updata_clr_flag(updata_start); //clr flag */
return 1;
}
static u8 update_result_handle(u8 err)
{
u8 res = DEVICE_UPDATE_STA_LOADER_DOWNLOAD_SUCC;
/* #if OTA_TWS_SAME_TIME_ENABLE */
/* tws_api_auto_role_switch_enable(); */
/* #endif */
if (err & UPDATE_RESULT_FLAG_BITMAP) {
switch (err & 0x7f) {
//升级文件错误
case UPDATE_RESULT_FILE_SIZE_ERR:
case UPDATE_RESULT_LOADER_SIZE_ERR:
case UPDATE_RESULT_REMOTE_FILE_HEAD_ERR:
case UPDATE_RESULT_LOCAL_FILE_HEAD_ERR:
case UPDATE_RESULT_FILE_OPERATION_ERR:
case UPDATE_RESULT_NOT_FIND_TARGET_FILE_ERR:
case UPDATE_RESULT_PRODUCT_INFO_NOT_MATCH:
res = DEVICE_UPDATE_STA_FILE_ERR;
break;
//文件内容校验失败
case UPDATE_RESULT_LOADER_VERIFY_ERR:
case UPDATE_RESULT_FLASH_DATA_VERIFY_ERR:
res = DEVICE_UPDATE_STA_VERIFY_ERR;
break;
}
} else if (BT_UPDATE_OVER == err) {
if (support_dual_bank_update_en) {
res = DEVICE_UPDATE_STA_SUCCESS;
} else {
res = DEVICE_UPDATE_STA_LOADER_DOWNLOAD_SUCC;
}
} else if (BT_UPDATE_KEY_ERR == err) {
res = DEVICE_UPDATE_STA_KEY_ERR;
} else {
res = DEVICE_UPDATE_STA_FAIL;
}
return res;
}
static u16 rcsp_f_stop(u8 err)
{
/* while (0 == (bit(updata_start) & bt_updata_get_flag())); */
/* bt_updata_clr_flag(updata_start); //clr flag */
err = update_result_handle(err);
__this->state = UPDATA_STOP;
printf(">>>rcsp_stop:%x\n", __this->state);
if (__this->data_send_hdl) {
__this->data_send_hdl(NULL, 0, 0);
}
while (!(0 == __this->state)) {
if (__this->sleep_hdl && get_rcsp_connect_status()) {
if (__this->sleep_hdl(NULL) == OS_TIMEOUT) {
break;
}
} else {
break;
}
}
if (__this->send_update_status_hdl) {
__this->send_update_status_hdl(NULL, err);
}
return 1;
}
void db_update_notify_fail_to_phone()
{
if (get_rcsp_connect_status()) {
rcsp_f_stop(DEVICE_UPDATE_STA_FAIL);
}
}
__attribute__((weak))
void user_change_ble_conn_param(u8 param_index)
{
}
static int rcsp_notify_update_content_size(void *priv, u32 size)
{
int err;
u8 data[4];
WRITE_BIG_U32(data, size);
user_change_ble_conn_param(0);
deg_printf("send content_size:%x\n", size);
err = JL_CMD_send(JL_OPCODE_NOTIFY_UPDATE_CONENT_SIZE, data, sizeof(data), JL_NEED_RESPOND);
return err;
}
void rcsp_update_handle(u8 state, void *buf, int len)
{
/* deg_puts("R"); */
if (state != __this->state) {
deg_puts(">>>rcsp state err\n");
return;
}
switch (state) {
case UPDATA_REV_DATA:
if (__this->read_buf) {
memcpy(__this->read_buf, buf, len);
__this->read_len = len;
__this->state = 0;
}
break;
case UPDATA_STOP:
__this->state = 0;
break;
}
if (__this->resume_hdl) {
__this->resume_hdl(NULL);
}
}
void rcsp_resume(void)
{
if (__this->resume_hdl) {
__this->resume_hdl(NULL);
}
}
static void rcsp_update_resume_hdl_register(void (*resume_hdl)(void *priv), int (*sleep_hdl)(void *priv))
{
__this->resume_hdl = resume_hdl;
__this->sleep_hdl = sleep_hdl;
}
void rcsp_update_data_api_register(u32(*data_send_hdl)(void *priv, u32 offset, u16 len), u32(*send_update_status_hdl)(void *priv, u8 state))
{
__this->data_send_hdl = data_send_hdl;
__this->send_update_status_hdl = send_update_status_hdl;
}
void rcsp_update_data_api_unregister(void)
{
__this->data_send_hdl = NULL;
__this->send_update_status_hdl = NULL;
}
void rcsp_ch_update_init(void (*resume_hdl)(void *priv), int (*sleep_hdl)(void *priv))
{
deg_puts("------------rcsp_ch_update_init\n");
rcsp_update_resume_hdl_register(resume_hdl, sleep_hdl);
//register_receive_fw_update_block_handle(rcsp_updata_handle);
}
const update_op_api_t rcsp_update_op = {
.ch_init = rcsp_ch_update_init,
.f_open = rcsp_f_open,
.f_read = rcsp_f_read,
.f_seek = rcsp_f_seek,
.f_stop = rcsp_f_stop,
.notify_update_content_size = rcsp_notify_update_content_size,
};
static void rcsp_update_state_cbk(int type, u32 state, void *priv)
{
update_ret_code_t *ret_code = (update_ret_code_t *)priv;
if (ret_code) {
printf("state:%x err:%x\n", ret_code->stu, ret_code->err_code);
}
switch (state) {
case UPDATE_CH_EXIT:
if (UPDATE_DUAL_BANK_IS_SUPPORT()) {
if ((0 == ret_code->stu) && (0 == ret_code->err_code)) {
set_jl_update_flag(1);
printf(">>>rcsp update succ\n");
update_result_set(UPDATA_SUCC);
} else {
update_result_set(UPDATA_DEV_ERR);
printf(">>>rcsp update succ\n");
}
} else {
if ((0 == ret_code->stu) && (0 == ret_code->err_code)) {
set_jl_update_flag(1);
}
}
break;
}
}
void rcsp_update_loader_download_init(int update_type, void (*result_cbk)(void *priv, u8 type, u8 cmd))
{
update_mode_info_t info = {
.type = update_type,
.state_cbk = rcsp_update_state_cbk,
.p_op_api = &rcsp_update_op,
.task_en = 1,
};
app_active_update_task_init(&info);
}
#endif //(OTA_TWS_SAME_TIME_ENABLE && (RCSP_ADV_EN || RCSP_BTMATE_EN))

View File

@ -0,0 +1,564 @@
#include "rcsp_user_update.h"
#include "app_config.h"
#if RCSP_UPDATE_EN
#include "uart.h"
#include "system/timer.h"
#include "update.h"
#include "custom_cfg.h"
#include "btstack/avctp_user.h"
#include "JL_rcsp_packet.h"
#include "JL_rcsp_protocol.h"
#include "rcsp_bluetooth.h"
#include "update_loader_download.h"
#if(TCFG_USER_TWS_ENABLE == 1)
#include "classic/tws_api.h"
#endif
#include "btstack_3th_protocol_user.h"
#if (RCSP_BTMATE_EN)
#define RCSP_DEBUG_EN
#ifdef RCSP_BTMATE_EN
#define rcsp_putchar(x) putchar(x)
#define rcsp_printf printf
#define rcsp_printf_buf(x,len) printf_buf(x,len)
#else
#define rcsp_putchar(...)
#define rcsp_printf(...)
#define rcsp_printf_buf(...)
#endif
#define DEV_UPDATE_FILE_INFO_OFFEST 0x00//0x40
#define DEV_UPDATE_FILE_INFO_LEN 0x00//(0x10 + VER_INFO_EXT_COUNT * (VER_INFO_EXT_MAX_LEN + 1))
typedef enum {
UPDATA_START = 0x00,
UPDATA_REV_DATA,
UPDATA_STOP,
} UPDATA_BIT_FLAG;
typedef struct _update_mode_t {
u8 opcode;
u8 opcode_sn;
} update_mode_t;
extern const int support_dual_bank_update_en;
extern void JL_ble_disconnect(void);
extern void set_curr_update_type(u8 type);
extern u8 check_le_pakcet_sent_finish_flag(void);
extern void register_receive_fw_update_block_handle(void (*handle)(u8 state, u8 *buf, u16 len));
extern void rcsp_update_data_api_register(u32(*data_send_hdl)(void *priv, u32 offset, u16 len), u32(*send_update_handl)(void *priv, u8 state));
extern void rcsp_update_handle(void *buf, int len);
extern u32 ex_cfg_fill_content_api(void);
extern void update_result_set(u16 result);
static u8 rcsp_update_status;
static u8 update_flag = 0;
static u16 ble_discon_timeout;
static void (*fw_update_block_handle)(u8 state, u8 *buf, u16 len) = NULL;
static update_file_ext_id_t update_file_id_info = {
.update_file_id_info.ver[0] = 0xff,
.update_file_id_info.ver[1] = 0xff,
};
static update_mode_t update_record_info;
u8 get_jl_update_flag(void)
{
printf("get_update_flag:%x\n", update_flag);
return update_flag;
}
void set_jl_update_flag(u8 flag)
{
update_flag = flag;
printf("update_flag:%x\n", update_flag);
}
void JL_controller_save_curr_cmd_para(u8 OpCode, u8 OpCode_SN)
{
update_record_info.opcode = OpCode;
update_record_info.opcode_sn = OpCode_SN;
}
void JL_controller_get_curr_cmd_para(u8 *OpCode, u8 *OpCode_SN)
{
*OpCode = update_record_info.opcode;
*OpCode_SN = update_record_info.opcode_sn;
}
void register_receive_fw_update_block_handle(void (*handle)(u8 state, u8 *buf, u16 len))
{
fw_update_block_handle = handle;
}
static void ble_discon_timeout_handle(void *priv)
{
rcsp_msg_post(MSG_JL_UPDATE_START, 0);
}
void JL_rcsp_update_cmd_resp(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len)
{
u8 msg[4];
rcsp_printf("%s\n", __FUNCTION__);
switch (OpCode) {
case JL_OPCODE_GET_DEVICE_UPDATE_FILE_INFO_OFFSET:
if (0 == len) {
rcsp_printf("JL_OPCODE_GET_DEVICE_UPDATE_FILE_INFO_OFFSET\n");
rcsp_msg_post(MSG_JL_GET_DEV_UPDATE_FILE_INFO_OFFSET, 2, OpCode, OpCode_SN);
} else {
rcsp_printf("JL_OPCODE_GET_DEVICE_UPDATE_FILE_INFO_OFFSET ERR\n");
}
break;
case JL_OPCODE_INQUIRE_DEVICE_IF_CAN_UPDATE:
rcsp_printf("JL_OPCODE_INQUIRE_DEVICE_IF_CAN_UPDATE:%x %x\n", len, data[0]);
//if (DEV_UPDATE_FILE_INFO_LEN == len) {
if (len) {
//memcpy((u8 *)&update_file_id_info, data, DEV_UPDATE_FILE_INFO_LEN);
set_curr_update_type(data[0]);
rcsp_msg_post(MSG_JL_INQUIRE_DEVEICE_IF_CAN_UPDATE, 3, OpCode, OpCode_SN, 0x00);
}
break;
case JL_OPCODE_EXIT_UPDATE_MODE:
rcsp_printf("JL_OPCODE_EXIT_UPDATE_MODE\n");
break;
case JL_OPCODE_ENTER_UPDATE_MODE:
rcsp_printf("JL_OPCODE_ENTER_UPDATE_MODE\n");
rcsp_msg_post(MSG_JL_ENTER_UPDATE_MODE, 2, OpCode, OpCode_SN);
break;
case JL_OPCODE_SEND_FW_UPDATE_BLOCK:
rcsp_printf("JL_OPCODE_SEND_FW_UPDATE_BLOCK\n");
break;
case JL_OPCODE_GET_DEVICE_REFRESH_FW_STATUS:
rcsp_printf("JL_OPCODE_GET_DEVICE_REFRESH_FW_STATUS\n");
JL_controller_save_curr_cmd_para(OpCode, OpCode_SN);
if (fw_update_block_handle) {
fw_update_block_handle(UPDATA_STOP, NULL, 0);
}
break;
case JL_OPCODE_SET_DEVICE_REBOOT:
rcsp_printf("JL_OPCODE_SET_DEVICE_REBOOT\n");
if (support_dual_bank_update_en) {
cpu_reset();
}
break;
default:
break;
}
}
static void JL_rcsp_resp_dev_update_file_info_offest(u8 OpCode, u8 OpCode_SN)
{
u8 data[4 + 2];
u16 update_file_info_offset = DEV_UPDATE_FILE_INFO_OFFEST;
u16 update_file_info_len = DEV_UPDATE_FILE_INFO_LEN;
WRITE_BIG_U32(data + 0, update_file_info_offset);
WRITE_BIG_U16(data + 4, update_file_info_len);
JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, data, sizeof(data));
}
static void JL_resp_inquire_device_if_can_update(u8 OpCode, u8 OpCode_SN, u8 update_sta)
{
u8 data[1];
data[0] = update_sta;
JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, data, sizeof(data));
}
enum {
UPDATE_FLAG_OK,
UPDATE_FLAG_LOW_POWER,
UPDATE_FLAG_FW_INFO_ERR,
UPDATE_FLAG_FW_INFO_CONSISTENT,
};
static u8 judge_remote_version_can_update(void)
{
//extern u16 ex_cfg_get_local_version_info(void);
u16 remote_file_ver = READ_BIG_U16(update_file_id_info.update_file_id_info.ver);
//u16 local_ver = ex_cfg_get_local_version_info();
u16 local_ver = get_vid_pid_ver_from_cfg_file(GET_VID_FROM_EX_CFG);
#if (0 == VER_INFO_EXT_COUNT)
//extern u16 ex_cfg_get_local_pid_info(void);
//extern u16 ex_cfg_get_local_vid_info(void);
//u16 local_pid = ex_cfg_get_local_pid_info();
//u16 local_vid = ex_cfg_get_local_vid_info();
u16 local_pid = get_vid_pid_ver_from_cfg_file(GET_PID_FROM_EX_CFG);
u16 local_vid = get_vid_pid_ver_from_cfg_file(GET_VID_FROM_EX_CFG);
u16 remote_file_pid = READ_BIG_U16(update_file_id_info.update_file_id_info.pid);
u16 remote_file_vid = READ_BIG_U16(update_file_id_info.update_file_id_info.vid);
if (remote_file_ver > local_ver || remote_file_pid != local_pid || remote_file_vid != local_vid) {
return UPDATE_FLAG_FW_INFO_ERR;
}
#else
//extern u32 ex_cfg_get_local_authkey_info(u8 * authkey_data[], u8 * authkey_len);
//extern u32 ex_cfg_get_local_procode_info(u8 * procode_data[], u8 * procode_len);
u8 authkey_len = 0;
u8 *local_authkey_data = NULL;
get_authkey_procode_from_cfg_file(&local_authkey_data, &authkey_len, GET_AUTH_KEY_FROM_EX_CFG);
u8 procode_len = 0;
u8 *local_procode_data = NULL;
get_authkey_procode_from_cfg_file(&local_procode_data, &procode_len, GET_PRO_CODE_FROM_EX_CFG);
//ex_cfg_get_local_authkey_info(&local_authkey_data, &authkey_len);
//ex_cfg_get_local_procode_info(&local_procode_data, &procode_len);
u8 *remote_authkey_data = update_file_id_info.ext;
u8 *remote_procode_data = update_file_id_info.ext + authkey_len + 1;
if (remote_file_ver < local_ver
|| 0 != memcmp(remote_authkey_data, local_authkey_data, authkey_len)
|| 0 != memcmp(remote_procode_data, local_procode_data, procode_len)) {
return UPDATE_FLAG_FW_INFO_ERR;
}
#endif
if (remote_file_ver == local_ver) {
rcsp_printf("remote_file_ver is %x, local_ver is %x, remote_file_ver is similar to local_ver\n", remote_file_ver, local_ver);
return UPDATE_FLAG_FW_INFO_CONSISTENT;
}
return UPDATE_FLAG_OK;
}
static bool check_edr_is_disconnct(void)
{
if (get_curr_channel_state()) {
return TRUE;
} else {
return FALSE;
}
}
static bool check_ble_all_packet_sent(void)
{
if (check_le_pakcet_sent_finish_flag()) {
return TRUE;
} else {
return FALSE;
}
}
static u32 rcsp_update_data_read(void *priv, u32 offset_addr, u16 len)
{
u32 err;
u8 data[4 + 2];
WRITE_BIG_U32(data, offset_addr);
WRITE_BIG_U16(data + 4, len);
err = JL_CMD_send(JL_OPCODE_SEND_FW_UPDATE_BLOCK, data, sizeof(data), JL_NEED_RESPOND);
return err;
}
static JL_ERR JL_controller_resp_get_dev_refresh_fw_status(u8 OpCode, u8 OpCode_SN, u8 result)
{
JL_ERR send_err = JL_ERR_NONE;
u8 data[1];
data[0] = result; //0:sucess 1:fail;
send_err = JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, data, sizeof(data));
return send_err;
}
u32 rcsp_update_status_response(void *priv, u8 status)
{
u8 OpCode;
u8 OpCode_SN;
JL_ERR send_err = JL_ERR_NONE;
JL_controller_get_curr_cmd_para(&OpCode, &OpCode_SN);
//log_info("get cmd para:%x %x\n", OpCode, OpCode_SN);
if (JL_OPCODE_GET_DEVICE_REFRESH_FW_STATUS == OpCode) {
send_err = JL_controller_resp_get_dev_refresh_fw_status(OpCode, OpCode_SN, status);
}
return send_err;
}
void JL_rcsp_update_cmd_receive_resp(void *priv, u8 OpCode, u8 status, u8 *data, u16 len)
{
switch (OpCode) {
case JL_OPCODE_SEND_FW_UPDATE_BLOCK:
if (fw_update_block_handle) {
fw_update_block_handle(UPDATA_REV_DATA, data, len);
}
break;
default:
break;
}
}
static void rcsp_loader_download_result_handle(void *priv, u8 type, u8 cmd)
{
if (UPDATE_LOADER_OK == cmd) {
//rcsp_msg(MSG_JL_UPDATE_START, 0);
set_jl_update_flag(1);
if (support_dual_bank_update_en) {
rcsp_printf(">>>rcsp update succ\n");
update_result_set(UPDATA_SUCC);
}
} else {
rcsp_printf(">>>update loader err\n");
#if OTA_TWS_SAME_TIME_ENABLE
if ((tws_ota_control(OTA_TYPE_GET) == OTA_TWS)) {
tws_ota_stop(OTA_STOP_UPDATE_OVER_ERR);
}
#endif
}
}
u32 get_jl_rcsp_update_status()
{
return rcsp_update_status;
}
static void rcsp_update_private_param_fill(UPDATA_PARM *p)
{
u32 exif_addr;
exif_addr = ex_cfg_fill_content_api();
update_param_priv_fill(p, (void *)&exif_addr, sizeof(exif_addr));
}
static void rcsp_update_before_jump_handle(int type)
{
#if CONFIG_UPDATE_JUMP_TO_MASK
y_printf(">>>[test]:latch reset update\n");
latch_reset();
#if 0
update_close_hw("null");
ram_protect_close();
/* save_spi_port(); */
extern void __BT_UPDATA_JUMP();
y_printf("update jump to __BT_UPDATA ...\n");
//跳转到uboot加载完,30ms左右(200410_yzb)
/* clk_set("sys", 48 * 1000000L); */
__BT_UPDATA_JUMP();
#endif
#else
cpu_reset();
#endif
}
void JL_rcsp_msg_deal(RCSP_MSG msg, int argc, int *argv)
{
u16 remote_file_version;
u8 can_update_flag = UPDATE_FLAG_FW_INFO_ERR;
switch (msg) {
case MSG_JL_GET_DEV_UPDATE_FILE_INFO_OFFSET:
rcsp_printf("MSG_JL_GET_DEV_UPDATE_FILE_INFO_OFFSET\n");
rcsp_update_status = 1;
/* extern void linein_mutex_stop(void *priv); */
/* linein_mutex_stop(NULL); */
/* extern void linein_mute(u8 mute); */
/* linein_mute(1); */
if (argc < 2) {
rcsp_printf("err: MSG_JL_GET_DEV_UPDATE_FILE_INFO_OFFSET too few argument, argc is %d\n", argc);
return;
}
JL_rcsp_resp_dev_update_file_info_offest((u8)argv[0], (u8)argv[1]);
break;
case MSG_JL_INQUIRE_DEVEICE_IF_CAN_UPDATE:
rcsp_printf("MSG_JL_INQUIRE_DEVEICE_IF_CAN_UPDATE\n");
if (argc < 2) {
rcsp_printf("err: MSG_JL_INQUIRE_DEVEICE_IF_CAN_UPDATE too few argument, argc is %d\n", argc);
return;
}
#if 0
remote_file_version = READ_BIG_U16(update_file_id_info.update_file_id_info.ver);
rcsp_printf("remote_file_ver:V%d.%d.%d.%d\n",
(remote_file_version & 0xf000) >> 12,
(remote_file_version & 0x0f00) >> 8,
(remote_file_version & 0x00f0) >> 4,
(remote_file_version & 0x000f));
if (0 == remote_file_version) {
can_update_flag = UPDATE_FLAG_OK;
} else {
can_update_flag = judge_remote_version_can_update();
}
if (UPDATE_FLAG_OK == can_update_flag) {
set_jl_update_flag(1);
}
#else
can_update_flag = UPDATE_FLAG_OK;
#endif
//todo;judge voltage
JL_resp_inquire_device_if_can_update((u8)argv[0], (u8)argv[1], can_update_flag);
if (0 == support_dual_bank_update_en) {
rcsp_msg_post(MSG_JL_LOADER_DOWNLOAD_START, 0);
}
break;
case MSG_JL_DEV_DISCONNECT:
if (check_ble_all_packet_sent()) {
rcsp_printf("MSG_JL_DEV_DISCONNECT\n");
JL_ble_disconnect();
if (check_edr_is_disconnct()) {
puts("-need discon edr\n");
user_send_cmd_prepare(USER_CTRL_POWER_OFF, 0, NULL);
}
ble_discon_timeout = sys_timeout_add(NULL, ble_discon_timeout_handle, 1000);
} else {
rcsp_printf("W");
rcsp_msg_post(MSG_JL_DEV_DISCONNECT, 0);
}
break;
case MSG_JL_LOADER_DOWNLOAD_START:
rcsp_update_data_api_register(rcsp_update_data_read, rcsp_update_status_response);
register_receive_fw_update_block_handle(rcsp_update_handle);
if (RCSP_BLE == get_curr_device_type()) {
rcsp_update_loader_download_init(BLE_APP_UPDATA, rcsp_loader_download_result_handle);
} else if (RCSP_SPP == get_curr_device_type()) {
rcsp_update_loader_download_init(SPP_APP_UPDATA, rcsp_loader_download_result_handle);
}
break;
case MSG_JL_UPDATE_START:
if (check_edr_is_disconnct()) {
rcsp_printf("b");
rcsp_msg_post(MSG_JL_UPDATE_START, 0);
break;
}
if (RCSP_BLE == get_curr_device_type()) {
rcsp_printf("BLE_APP_UPDATE\n");
update_mode_api_v2(BLE_APP_UPDATA,
rcsp_update_private_param_fill,
rcsp_update_before_jump_handle);
} else {
rcsp_printf("SPP_APP_UPDATA\n");
update_mode_api_v2(SPP_APP_UPDATA,
rcsp_update_private_param_fill,
rcsp_update_before_jump_handle);
}
/* if (RCSP_BLE == get_curr_device_type()) { */
/* rcsp_printf("BLE_APP_UPDATE\n"); */
/* update_mode_api(BLE_APP_UPDATA); */
/* } else { */
/* rcsp_printf("SPP_APP_UPDATA\n"); */
/* update_mode_api(SPP_APP_UPDATA); */
/* } */
break;
case MSG_JL_ENTER_UPDATE_MODE:
if (argc < 2) {
rcsp_printf("err: MSG_JL_ENTER_UPDATE_MODE too few argument, argc is %d\n", argc);
return;
}
rcsp_printf("MSG_JL_ENTER_UPDATE_MODE:%x %x\n", (u8)argv[0], (u8)argv[1]);
#if(TCFG_USER_TWS_ENABLE == 1)
void tws_cancle_all_noconn();
tws_cancle_all_noconn();
#endif
user_send_cmd_prepare(USER_CTRL_WRITE_CONN_DISABLE, 0, NULL);
user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_DISABLE, 0, NULL);
if (support_dual_bank_update_en) {
u8 status = 0;
JL_CMD_response_send((u8)argv[0], JL_PRO_STATUS_SUCCESS, (u8)argv[1], &status, 1);
rcsp_update_data_api_register(rcsp_update_data_read, rcsp_update_status_response);
register_receive_fw_update_block_handle(rcsp_update_handle);
rcsp_update_loader_download_init(DUAL_BANK_UPDATA, rcsp_loader_download_result_handle);
}
break;
default:
break;
}
}
void rcsp_update_jump_for_hid_device()
{
if (RCSP_BLE == get_curr_device_type()) {
rcsp_printf("BLE_APP_UPDATE\n");
update_mode_api_v2(BLE_APP_UPDATA,
rcsp_update_private_param_fill,
rcsp_update_before_jump_handle);
} else {
rcsp_printf("SPP_APP_UPDATA\n");
update_mode_api_v2(SPP_APP_UPDATA,
rcsp_update_private_param_fill,
rcsp_update_before_jump_handle);
}
}
#endif
static u8 rcsp_update_flag = 0;
void set_rcsp_db_update_status(u8 value)
{
rcsp_update_flag = value;
}
u8 get_rcsp_db_update_status()
{
return rcsp_update_flag;
}
void rcsp_before_enter_db_update_mode() //进入双备份升级前
{
r_printf("%s", __func__);
rcsp_update_flag = 1;
void sys_auto_shut_down_disable(void);
if (get_total_connect_dev() == 0) {
sys_auto_shut_down_disable();
}
#if TCFG_USER_TWS_ENABLE
int tws_api_get_role(void);
if (tws_api_get_role() == TWS_ROLE_SLAVE) {
return;
}
#endif
if (get_total_connect_dev()) { //断开蓝牙连接,断开之后不能让他重新开
/* user_send_cmd_prepare(USER_CTRL_DISCONNECTION_HCI, 0, NULL); */
}
#if TCFG_USER_TWS_ENABLE
extern void tws_cancle_all_noconn();
/* tws_cancle_all_noconn() ; */
#else
user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_DISABLE, 0, NULL);
user_send_cmd_prepare(USER_CTRL_WRITE_CONN_DISABLE, 0, NULL);
#endif
}
extern void sys_auto_shut_down_enable(void);
void rcsp_db_update_fail_deal() //双备份升级失败处理
{
r_printf("%s", __func__);
if (rcsp_update_flag) {
rcsp_update_flag = 0;
if (get_total_connect_dev() == 0) {
sys_auto_shut_down_enable();
}
}
/* cpu_reset(); //升级失败直接复位 */
}
#endif

View File

@ -0,0 +1,25 @@
#ifndef _RCSP_USER_UPDATE_H_
#define _RCSP_USER_UPDATE_H_
//#include "rcsp_protocol.h"
//#include "rcsp_packet.h"
#include "typedef.h"
#define JL_OPCODE_GET_DEVICE_UPDATE_FILE_INFO_OFFSET 0xe1
#define JL_OPCODE_INQUIRE_DEVICE_IF_CAN_UPDATE 0xe2
#define JL_OPCODE_ENTER_UPDATE_MODE 0xe3
#define JL_OPCODE_EXIT_UPDATE_MODE 0xe4
#define JL_OPCODE_SEND_FW_UPDATE_BLOCK 0xe5
#define JL_OPCODE_GET_DEVICE_REFRESH_FW_STATUS 0xe6
#define JL_OPCODE_SET_DEVICE_REBOOT 0xe7
#define JL_OPCODE_NOTIFY_UPDATE_CONENT_SIZE 0xe8
void JL_rcsp_update_cmd_resp(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len);
void JL_rcsp_update_cmd_receive_resp(void *priv, u8 OpCode, u8 status, u8 *data, u16 len);
u8 get_jl_update_flag(void);
void set_jl_update_flag(u8 flag);
u8 get_curr_device_type(void);
#endif

Some files were not shown because too many files have changed in this diff Show More