This commit is contained in:
huxi
2025-12-03 11:12:34 +08:00
parent c23ae4f24c
commit bc195654bf
8163 changed files with 3799544 additions and 92 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,81 @@
// binary representation
// attribute size in bytes (16), flags(16), handle (16), uuid (16/128), value(...)
#ifndef _BLE_FMY_H
#define _BLE_FMY_H
#include <stdint.h>
#include "app_config.h"
#include "ble_user.h"
#include "gatt_common/le_gatt_common.h"
#include "btstack/third_party/fmna/fmna_api.h"
enum {
FY_STATE_UNPAIR = 0,
FY_STATE_NEARBY,
FY_STATE_SEPARATED,
FY_STATE_CONNECTED,
};
enum {
PROFILE_MODE_UNPAIR = 0,
PROFILE_MODE_OWNER,
PROFILE_MODE_NON_OWNER,
PROFILE_MODE_NEARBY,
PROFILE_MODE_SEPARATED,
};
typedef struct {
u8 adv_fmna_state;
u8 profile_mode;
u8 make_new_mac_flag;
u8 sound_onoff;
u16 sound_ctrl_timer_id;
u16 pairing_mode_timer_id;
u8 pairing_mode_enable;
u8 fmna_state;
} fmy_glb_t;
extern fmy_glb_t fmy_global_data;
#define __fydata (&fmy_global_data)
typedef struct {
u8 head_tag;
u8 reset_config;//flag
u8 is_open;
} fmy_vm_t;
typedef struct {
u16 conn_hdl;
u16 timer_id;
u16 interval;
u8 update_flag;
} fmy_conn_info_t;
extern fmy_vm_t fmy_vm_info;
#define __fy_vm (&fmy_vm_info)
extern adv_cfg_t fmy_server_adv_config;
extern uint8_t fmy_battery_level;
//------------------------------------------------------------------
extern const gatt_client_cfg_t fmy_client_init_cfg;
void fmy_client_init(void);
void fmy_client_exit(void);
int fmy_client_search_remote_profile(u16 conn_handle);
int fmy_client_search_remote_stop(u16 conn_handle);
void fmy_ios_services_init(void);
void fmy_ios_services_exit(void);
bool ble_set_make_random_address(u8 random_type);
int fmna_main_start(void);
int fmna_main_exit(void);
void swapX(const uint8_t *src, uint8_t *dst, int len);
bool fmy_check_capabilities_is_enalbe(u8 cap);
void fmy_state_idle_set_active(u8 active);
bool fmy_vm_deal(fmy_vm_t *info, u8 rw_flag);
void fmy_pairing_timeout_start(void);
void fmy_pairing_timeout_stop(void);
//--------------------------------------------------------------------------------
#endif
@@ -0,0 +1,115 @@
// binary representation
// attribute size in bytes (16), flags(16), handle (16), uuid (16/128), value(...)
#ifndef _BLE_FMY_CFG_H
#define _BLE_FMY_CFG_H
#include <stdint.h>
#include "app_config.h"
#include "gatt_common/le_gatt_common.h"
//set token =====================================================
#define TOKEN_ID_PRODUCTION_MODE 0 //0--debug, 1--production
#define UUID_TOKEN_IS_BASE64_MODE 0 //0--hex, 1--base64
#define FMY_FMCA_TEST_MODE 1
#if(TOKEN_ID_PRODUCTION_MODE)
#define FMY_DEBUG_SERVICE_ENABLE 0
#else
#define FMY_DEBUG_SERVICE_ENABLE 1
#endif
//===============================================================
//firmware version config
#define FMY_FW_VERSION_MAJOR_NUMBER 1
#define FMY_FW_VERSION_MINOR_NUMBER 0
#define FMY_FW_VERSION_REVISION_NUMBER 6
// set change mac config
#define FMY_MAC_CHANGE_LOCK 0 // 0--unpair后修改mac1--unpair后不修改mac
// fmy authentication information
static const uint8_t fmy_serial_number[16] = "d12599062d934e86";
static const uint8_t fmy_product_data[8] = {0xBD, 0x56, 0xA0, 0x84, 0x60, 0x84, 0x35, 0xA9};//JL
static const char fmy_Server_Encryption_Key[] = "BJzFrd3QKbdTXTDm5dFtt6jSGxtItVsZ1bEQ6VvzFUXndM9Rjeu+PHFoM+RD8RRHblpLBU42dQcFbjmVzGuWkJY=";
static const char fmy_Signature_Verification_Key[] = "BDNMWnP9Yd82Qz+8aZI245jklBLzwP3E5doLQRh3lRcIcSCIjpeSN3a6SNxRfA+oe5xiqf7paw84QD9mnh5nVWA=";
#if UUID_TOKEN_IS_BASE64_MODE
static const char fmy_token_uuid_char[] = "0d9290f5-2e7d-49b1-9aab-259b93f17e0e";
static const char fmy_token_auth_char[] = "MYG/ME8CAQECAQEERzBFAiEA3hgTtFg2nTHkX4iuG1Mxk/KNUCfKv8XIe85voCqFY3YCIH/hZVR/JanIF3LmEnZrUTDb7CVWew8E+setdWaW5oVxMGwCAQICAQEEZDFiMAkCAWYCAQEEAQIwEAIBZQIBAQQIYWnfhIYBAAAwEQICAMoCAQEECAAAAAAAAAAIMBYCAgDJAgEBBA0yNjI5ODMtMjYzMTg0MBgCAWcCAQEEENzutdJeT04ym3Vw0QXUzZA=";
#else
static const uint8_t fmy_token_uuid_hex[16] = {
0x50, 0xDB, 0x3E, 0xC0, 0xE5, 0xE6, 0x4A, 0xDD, 0xBF, 0x4C, 0x22, 0x27, 0x59, 0xDA, 0xAA, 0x69,
};
static const uint8_t fmy_token_auth_hex[] = {
0x31, 0x81, 0xC0, 0x30, 0x50, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x04, 0x48, 0x30, 0x46, 0x02,
0x21, 0x00, 0xBD, 0x60, 0x02, 0x34, 0xEE, 0x10, 0xA2, 0x13, 0x35, 0x4E, 0x43, 0x16, 0x07, 0xF3,
0xB6, 0x26, 0x56, 0xB4, 0x40, 0xE7, 0x5B, 0xAF, 0x54, 0x43, 0x63, 0x0B, 0x64, 0x6A, 0x77, 0x4E,
0x01, 0x91, 0x02, 0x21, 0x00, 0x94, 0x9B, 0x4C, 0x8C, 0xAB, 0x0E, 0x51, 0x2C, 0xD7, 0x78, 0xF4,
0x08, 0xDB, 0xB1, 0xD9, 0x0A, 0x15, 0x72, 0xB4, 0x22, 0x26, 0x34, 0x1C, 0x83, 0xB8, 0x35, 0x37,
0x96, 0x92, 0xE2, 0xED, 0xD2, 0x30, 0x6C, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x04, 0x64, 0x31,
0x62, 0x30, 0x09, 0x02, 0x01, 0x66, 0x02, 0x01, 0x01, 0x04, 0x01, 0x02, 0x30, 0x10, 0x02, 0x01,
0x65, 0x02, 0x01, 0x01, 0x04, 0x08, 0x18, 0xF1, 0xE3, 0x99, 0x99, 0x01, 0x00, 0x00, 0x30, 0x11,
0x02, 0x02, 0x00, 0xCA, 0x02, 0x01, 0x01, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x30, 0x16, 0x02, 0x02, 0x00, 0xC9, 0x02, 0x01, 0x01, 0x04, 0x0D, 0x33, 0x39, 0x39, 0x39,
0x35, 0x39, 0x2D, 0x39, 0x36, 0x39, 0x31, 0x32, 0x35, 0x30, 0x18, 0x02, 0x01, 0x67, 0x02, 0x01,
0x01, 0x04, 0x10, 0x0B, 0xB8, 0xCE, 0xF9, 0x2C, 0xA7, 0x49, 0x1E, 0xBA, 0xD1, 0x81, 0xC6, 0x52,
0xAC, 0x38, 0xAC, 0x31, 0x81, 0xC0, 0x30, 0x50, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x04, 0x48,
0x30, 0x46, 0x02, 0x21, 0x00, 0xDC, 0x10, 0x8A, 0x5E, 0x35, 0x42, 0x5A, 0x5E, 0x38, 0x0B, 0x64,
0x1B, 0x08, 0xE4, 0x2D, 0xA3, 0x11, 0xCB, 0x48, 0xAF, 0x0C, 0xED, 0xB6, 0xF3, 0x9D, 0x44, 0x4C,
0x1C, 0x88, 0x97, 0xEF, 0xD2, 0x02, 0x21, 0x00, 0x9F, 0x14, 0x51, 0x31, 0xFA, 0x5A, 0x79, 0x90,
0x85, 0xC5, 0xBA, 0xE6, 0xC6, 0x73, 0x63, 0xA0, 0x1C, 0x6E, 0x06, 0xDD, 0xD3, 0x53, 0x5A, 0x50,
0x02, 0x06, 0x79, 0xB7, 0x7E, 0x42, 0x50, 0x14, 0x30, 0x6C, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01,
0x04, 0x64, 0x31, 0x62, 0x30, 0x09, 0x02, 0x01, 0x66, 0x02, 0x01, 0x01, 0x04, 0x01, 0x02, 0x30,
0x10, 0x02, 0x01, 0x65, 0x02, 0x01, 0x01, 0x04, 0x08, 0xDC, 0xAA, 0xF1, 0xD0, 0x99, 0x01, 0x00,
0x00, 0x30, 0x11, 0x02, 0x02, 0x00, 0xCA, 0x02, 0x01, 0x01, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x08, 0x30, 0x16, 0x02, 0x02, 0x00, 0xC9, 0x02, 0x01, 0x01, 0x04, 0x0D, 0x33,
0x39, 0x39, 0x39, 0x35, 0x39, 0x2D, 0x39, 0x36, 0x39, 0x31, 0x32, 0x35, 0x30, 0x18, 0x02, 0x01,
0x67, 0x02, 0x01, 0x01, 0x04, 0x10, 0xAB, 0xFF, 0x22, 0x5A, 0xA0, 0x0F, 0x41, 0x66, 0xAA, 0x49,
0xF0, 0x59, 0xC1, 0x6A, 0xBE, 0x8A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
#endif
#endif
@@ -0,0 +1,874 @@
/*********************************************************************************************
* Filename : .c
* Description :
* Author : JM
* Email : zh-jieli.com
* Last modifiled : 2017-01-17 11:14
* Copyright:(c)JIELI 2011-2016 @ , All Rights Reserved.
*********************************************************************************************/
/* #include "system/app_core.h" */
#include "system/includes.h"
#include "app_config.h"
#include "app_action.h"
#include "btstack/btstack_task.h"
#include "btstack/bluetooth.h"
#include "user_cfg.h"
#include "vm.h"
#include "btcontroller_modules.h"
#include "bt_common.h"
#include "3th_profile_api.h"
#include "le_common.h"
#include "JL_rcsp_api.h"
#include "custom_cfg.h"
#include "btstack/btstack_event.h"
#include "ble_fmy.h"
#include "le/ble_api.h"
#include "ble_fmy_fmna.h"
#include "ble_fmy_profile.h"
#include "system/malloc.h"
#include "ble_fmy_cfg.h"
#include "ble_fmy_ota.h"
#include "app_ble_spp_api.h"
#include "ble_fmy_modet.h"
#include "ui/ui_api.h"
#if (BT_AI_SEL_PROTOCOL & FMNA_EN)
#if 1
#define log_info(x, ...) printf("[BLE_FMY_FMNA]" x "\r\n", ## __VA_ARGS__)
/* #define log_info(x, ...) r_printf("[BLE_FMY_FMNA]" x "\r\n", ## __VA_ARGS__) */
#define log_info_hexdump put_buf
#else
#define log_info(...)
#define log_info_hexdump(...)
#endif
//******************************************************************************************
enum FMY_TEXT_EVENT {
BATTERY_LOW = 69, // 明确设置为70
BATTERY_FULL,
SERIALNUMBER_LOOKUP_OPEN, // 71
SERIALNUMBER_LOOKUP_CLOSE, // 71
PAIRING_OPEN, // 73
};
//******************************************************************************************
extern void *fmy_ble_hdl;
extern void *fmy_second_ble_hdl;
extern ble_state_e fmy_ble_state;
extern adv_cfg_t fmy_server_adv_config;
extern u8 fmy_owner_connect;
#define FMY_DEBUG_TEST_LOW_ADV_TO_FASE 0 //for debug test
#if FMY_DEBUG_TEST_LOW_ADV_TO_FASE
#define FMY_ADV_SLOW_INTERVAL 0xa0 //for test
#else
#define FMY_ADV_SLOW_INTERVAL 0xC80 //fixed 2 seconds,bqb
#endif
#define FMY_ADV_PAIR_TIMEOUT_MS (10*60*1000L) //10 min
// Separated fast advertising is used for UT finding, e.g. aggressive adv.
#define FMY_FMNA_SEPARATED_ADV_FAST_INTERVAL 0x30 /**< Fast advertising interval 30ms (in units of 0.625 ms.) */
#define FMY_FMNA_SEPARATED_ADV_SLOW_INTERVAL FMY_ADV_SLOW_INTERVAL /**< Slow advertising interval 2 seconds (in units of 0.625 ms.) */
// Nearby fast advertising is used for leash break.
#define FMY_FMNA_NEARBY_ADV_FAST_INTERVAL 0x30 /**< Fast advertising interval 30ms (in units of 0.625 ms.) */
#define FMY_FMNA_NEARBY_ADV_SLOW_INTERVAL FMY_ADV_SLOW_INTERVAL /**< Slow advertising interval 2 seconds (in units of 0.625 ms.) */
#define FMY_FMNA_PAIRING_ADV_FAST_INTERVAL 0x30 /**< Fast advertising interval 30ms (in units of 0.625 ms.) */
#define FMY_FMNA_PAIRING_ADV_SLOW_INTERVAL 0x30 /**< Slow advertising interval 30ms (in units of 0.625 ms.) */
static const uint16_t fmna_separated_adv_interval[] = {FMY_FMNA_SEPARATED_ADV_FAST_INTERVAL, FMY_FMNA_SEPARATED_ADV_SLOW_INTERVAL};
static const uint16_t fmna_nearby_adv_interval[] = {FMY_FMNA_NEARBY_ADV_FAST_INTERVAL, FMY_FMNA_NEARBY_ADV_SLOW_INTERVAL};
static const uint16_t fmna_pairing_adv_interval[] = {FMY_FMNA_PAIRING_ADV_FAST_INTERVAL, FMY_FMNA_PAIRING_ADV_SLOW_INTERVAL};
//******************************************************************************************
#define PORT_DIR_OUPUT 0
#define PORT_DIR_INPUT 1
#define PORT_VALUE_HIGH 1
#define PORT_VALUE_LOW 0
#define SOUND_GPIO_PORT IO_PORTA_00
#define PORT_IO_INIT(PORT_IO,DIR) //{gpio_set_die(PORT_IO,1);\
//gpio_set_pull_down(PORT_IO,0);\
//gpio_set_pull_up(PORT_IO,0);\
//gpio_set_direction(PORT_IO,DIR);}
#define PORT_IO_OUPUT(PORT_IO,VALUE) //gpio_set_mode(IO_PORT_SPILT(SOUND_GPIO_PORT), VALUE?PORT_OUTPUT_HIGH:PORT_OUTPUT_LOW);
//gpio_write(PORT_IO,VALUE);
#define PORT_IO_INPUT(PORT_IO) //gpio_read(PORT_IO,0);
#define DEV_OPEN_LED_STATE() //PORT_IO_OUPUT(LED_PAIR_GAPIO_POR,PORT_VALUE_HIGH);
#define DEV_CLOSE_LED_STATE() //PORT_IO_OUPUT(LED_PAIR_GAPIO_POR,PORT_VALUE_LOW);
#define DEV_SOUND_STATE(ON_OFF) //PORT_IO_OUPUT(SOUND_GPIO_PORT, ON_OFF);
#define DEV_SOUND_INIT() //PORT_IO_INIT(SOUND_GPIO_PORT, PORT_DIR_OUPUT);
#define DEV_SOUND_DEINIT() //gpio_set_mode(IO_PORT_SPILT(SOUND_GPIO_PORT),PORT_HIGHZ)//PORT_IO_INIT(SOUND_GPIO_PORT, PORT_DIR_INPUT);
#define SOUND_TICKS_MS (500)
//***********************************************************************************************
static u8 fmy_adv_data[ADV_RSP_PACKET_MAX];//max is 31
static u8 fmy_scan_rsp_data[ADV_RSP_PACKET_MAX];//max is 31
//***********************************************************************************************
extern int fmy_set_adv_enable(u8 enable);
static int fmy_set_adv_mode(uint8_t mode);
static int fmy_get_static_mac(uint8_t *mac);
static int fmy_set_static_mac(uint8_t *mac);
static int fmy_get_battery_level(void);
static int fmy_disconnect(uint16_t conn_handle, uint8_t reason);
static void fmy_pairing_timeout_start(void);
static void fmy_pairing_timeout_stop(void);
static void fmy_test_get_send_sensor_data(void);
extern void update_list_local_addr(u8 *old_local_addr, u8 *new_local_addr);
//-------------------------------------------------------------------------------------
static const fmna_att_handle_t fmna_att_handle_table = {
.pairing_control_point_handle = ATT_CHARACTERISTIC_4F860001_943B_49EF_BED4_2F730304427A_01_VALUE_HANDLE,
.owner_cfg_control_point_handle = ATT_CHARACTERISTIC_4F860002_943B_49EF_BED4_2F730304427A_01_VALUE_HANDLE,
.owner_info_porint_handle = ATT_CHARACTERISTIC_4F860004_943B_49EF_BED4_2F730304427A_01_VALUE_HANDLE,
.non_owner_control_point_handle = ATT_CHARACTERISTIC_4F860003_943B_49EF_BED4_2F730304427A_01_VALUE_HANDLE,
.debug_control_point_handle = ATT_CHARACTERISTIC_4F860005_943B_49EF_BED4_2F730304427A_01_VALUE_HANDLE,
.firmware_update_handle = ATT_CHARACTERISTIC_94110001_6D9B_4225_A4F1_6A4A7F01B0DE_01_VALUE_HANDLE,
};
//============================================================================================
static void fmy_systerm_reset(u32 delay_ticks)
{
if (delay_ticks) {
log_info("delay_reset: %d ticks", delay_ticks);
os_time_dly(delay_ticks);
}
log_info("reset start......");
cpu_reset();
while (1);
}
/*************************************************************************************************/
/*!
* \brief 推送消息到app_core 任务,app处理
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
void fmna_state_machine_event_deal(struct fmna_event *fmna_evt)
{
log_info("fmna_state_machine_event_deal: event=%devt_data= %x,value=%02x,handler= %08x,", (int)fmna_evt->event, (u32)fmna_evt->value, (u32)fmna_evt->event_data, (u32)fmna_evt->handler);
fmna_state_machine_event_handle(fmna_evt);
free(fmna_evt);
}
static int fmy_evnet_post_msg(u8 priv_event, void *evt_data, u32 value, void *handler)
{
int argv[3];
log_info("fmna_app_evnet_post: event=%devt_data= %x,value=%02x,handler= %08x,", priv_event, (u32)evt_data, value, (u32)handler);
struct fmna_event *fmna_evt = zalloc(sizeof(struct fmna_event));;
if (fmna_evt == NULL) {
log_info("fmna_evt zalloc err \n");
return -1;
}
fmna_evt->event = priv_event;
fmna_evt->value = value;
fmna_evt->event_data = evt_data;
fmna_evt->handler = handler;
argv[0] = (int)fmna_state_machine_event_deal;
argv[1] = 1;
argv[2] = (int)fmna_evt;
int ret = os_taskq_post_type("app_core", Q_CALLBACK, 3, argv);
if (ret) {
log_info("fmna_app_evnet_post err \n");
free(fmna_evt);
return -1;
}
return 0;
}
static int fmy_get_static_mac(uint8_t *mac)
{
int ret;
u8 cur_ble_address[6];//high->low
log_info("%s(%d)", __FUNCTION__, __LINE__);
#if FMY_MAC_CHANGE_LOCK
if (!__fydata->make_new_mac_flag) {
ret = syscfg_read(CFG_FMNA_BLE_ADDRESS_INFO, cur_ble_address, 6);
if (ret == 6) {
log_info("get vm address");
memcpy(mac, cur_ble_address, 6);
log_info_hexdump(mac, 6);
return 0;
}
} else {
__fydata->make_new_mac_flag = 0;
}
#endif
log_info("make new address");
log_info("=============make rand address");
cur_ble_address[0] = rand32() | STATIC_ADV_ADDR_TYPE_MASK;
cur_ble_address[1] = rand32();
cur_ble_address[2] = rand32();
cur_ble_address[3] = rand32();
cur_ble_address[4] = rand32();
cur_ble_address[5] = rand32();
memcpy(mac, cur_ble_address, 6);
log_info_hexdump(mac, 6);
#if FMY_MAC_CHANGE_LOCK
log_info("update vm ble address1");
syscfg_write(CFG_FMNA_BLE_ADDRESS_INFO, cur_ble_address, 6);
#endif
return 0;
}
static int fmy_set_static_mac(uint8_t *mac)
{
log_info("%s(%d)", __FUNCTION__, __LINE__);
const u8 empty_mac_addr[6] = {0, 0, 0, 0, 0, 0};
uint8_t new_swap_addr[6];
uint8_t old_swap_addr[6];
ble_set_make_random_address(1);
swapX(mac, new_swap_addr, 6);
void *app_ble_hdl = fmy_ble_hdl;
if (app_ble_get_hdl_con_handle(fmy_ble_hdl) != 0) {
log_info("======second dev adv_enable===");
app_ble_hdl = fmy_second_ble_hdl;
}
//le_controller_set_random_mac(new_swap_addr);
u8 *old_addr = app_ble_adv_addr_get(app_ble_hdl);
if (old_addr) {
swapX(old_addr, old_swap_addr, 6);
}
if (memcmp(mac, old_swap_addr, 6) && memcmp(old_swap_addr, empty_mac_addr, 6)) {
update_list_local_addr(old_swap_addr, mac);
}
app_ble_set_mac_addr(app_ble_hdl, new_swap_addr);
log_info_hexdump(new_swap_addr, 6);
return 0;
}
static int fmy_get_battery_level(void)
{
log_info("%s,bat_lev= %d", __FUNCTION__, fmy_battery_level);
return fmy_battery_level;
}
static int fmy_disconnect(uint16_t conn_handle, uint8_t reason)
{
log_info("%s(%d): %04x,%02x", __FUNCTION__, __LINE__, conn_handle, reason);
if (app_ble_get_hdl_con_handle(fmy_ble_hdl) == conn_handle) {
return app_ble_disconnect(fmy_ble_hdl);
}
if (app_ble_get_hdl_con_handle(fmy_second_ble_hdl) == conn_handle) {
return app_ble_disconnect(fmy_second_ble_hdl);
}
return -1;
// return ble_comm_disconnect_extend(conn_handle, reason);
}
void fmy_state_idle_set_active(u8 active)
{
}
static void fmy_sound_timer_control(void *priv)
{
DEV_SOUND_STATE(__fydata->sound_onoff);
__fydata->sound_onoff = !__fydata->sound_onoff;
}
static int fmy_sound_control(FMNA_SOUND_OP_t op)
{
log_info("func:%s,op= %d", __FUNCTION__, op);
switch (op) {
case FMNA_SOUND_INIT:
DEV_SOUND_INIT();
DEV_SOUND_STATE(PORT_VALUE_LOW);
break;
case FMNA_SOUND_START:
#if TCFG_PWMLED_ENABLE
fmy_state_idle_set_active(true);
#endif
__fydata->sound_onoff = 1;
if (!__fydata->sound_ctrl_timer_id) {
__fydata->sound_ctrl_timer_id = sys_timer_add(NULL, fmy_sound_timer_control, SOUND_TICKS_MS);
}
break;
case FMNA_SOUND_STOP:
#if TCFG_PWMLED_ENABLE
fmy_state_idle_set_active(false);
#endif
if (__fydata->sound_ctrl_timer_id) {
sys_timer_del(__fydata->sound_ctrl_timer_id);
__fydata->sound_ctrl_timer_id = 0;
}
DEV_SOUND_STATE(PORT_VALUE_LOW);
break;
default:
break;
}
return 0;
}
static void fmy_pairing_timeout_handle(void *priv)
{
__fydata->pairing_mode_timer_id = 0;
__fydata->pairing_mode_enable = 0;
if (__fydata->adv_fmna_state == FMNA_SM_PAIR) {
log_info("%s,%d", __FUNCTION__, __LINE__);
fmy_set_adv_enable(0);
}
}
void fmy_pairing_timeout_stop(void)
{
if (__fydata->pairing_mode_timer_id) {
log_info("%s,%d", __FUNCTION__, __LINE__);
sys_timeout_del(__fydata->pairing_mode_timer_id);
__fydata->pairing_mode_timer_id = 0;
}
}
void fmy_pairing_timeout_start(void)
{
log_info("%s,%d", __FUNCTION__, __LINE__);
if (__fydata->pairing_mode_timer_id) {
fmy_pairing_timeout_stop();
}
__fydata->pairing_mode_timer_id = sys_timeout_add(0, fmy_pairing_timeout_handle, FMY_ADV_PAIR_TIMEOUT_MS);
}
void fmy_pairing_restart_adv(void)
{
if (__fydata->adv_fmna_state == FMNA_SM_PAIR && BLE_ST_ADV != fmy_ble_state) {
log_info("%s,%d", __FUNCTION__, __LINE__);
__fydata->pairing_mode_enable = 1;
fmy_set_adv_enable(1);
fmy_pairing_timeout_start();
}
}
void fmy_pairing_reset_address(void)
{
u8 address[6];
ble_state_e cur_state;
log_info("[msg]%s-%d>>>>>>>>>>>__fydata->adv_fmna_state=%d", __FUNCTION__, __LINE__, __fydata->adv_fmna_state);
if (__fydata->adv_fmna_state == FMNA_SM_PAIR) {
log_info("%s,%d", __FUNCTION__, __LINE__);
cur_state = fmy_ble_state;
fmy_set_adv_enable(0);
__fydata->make_new_mac_flag = 1;
fmy_get_static_mac(address);
fmy_set_static_mac(address);
if (BLE_ST_ADV == cur_state) {
fmy_set_adv_enable(1);
}
}
}
/*************************************************************************************************/
/*!
* \brief 组织adv包数据,放入buff
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
static int fmy_set_adv_data(uint8_t fmna_state, uint8_t *fmna_payload, uint8_t size)
{
u8 cnt = 0;
u8 *buf = fmy_adv_data;
switch (fmna_state) {
case FMNA_SM_PAIR:
buf[cnt++] = 3;
buf[cnt++] = 3;
buf[cnt++] = FMY_UUID_SERVICE & 0xff;
buf[cnt++] = (FMY_UUID_SERVICE >> 8);
buf[cnt++] = 3 + size;//3 + size -1;
buf[cnt++] = 0x16;
buf[cnt++] = FMY_UUID_SERVICE & 0xff;
buf[cnt++] = (FMY_UUID_SERVICE >> 8);
break;
case FMNA_SM_NEARBY:
buf[cnt++] = 7;
buf[cnt++] = 0xff;
buf[cnt++] = APPLE_VENDOR_ID & 0xff;
buf[cnt++] = (APPLE_VENDOR_ID >> 8);
break;
case FMNA_SM_SEPARATED:
buf[cnt++] = 0x1E;
buf[cnt++] = 0xff;
buf[cnt++] = APPLE_VENDOR_ID & 0xff;
buf[cnt++] = (APPLE_VENDOR_ID >> 8);
break;
default:
log_info("err_state: fmna_state= %d", fmna_state);
break;
}
__fydata->adv_fmna_state = fmna_state;
memcpy(&buf[cnt], fmna_payload, size);
cnt += size;
log_info("fmy state(%d), adv_data(%d)", fmna_state, cnt);
log_info_hexdump(buf, cnt);
fmy_server_adv_config.adv_data_len = cnt;
fmy_server_adv_config.adv_data = fmy_adv_data;
fmy_server_adv_config.rsp_data_len = 0;
fmy_server_adv_config.rsp_data = fmy_scan_rsp_data;
return 0;
}
/*************************************************************************************************/
/*!
* \brief 配置广播参数
*
* \param [in]
*
* \return
*
* \note 开广播前配置都有效
*/
/*************************************************************************************************/
static int fmy_set_adv_mode(uint8_t mode)
{
if (mode > FMNA_ADV_MODE_SLOW) {
return -1;
}
fmy_server_adv_config.adv_auto_do = 0;
fmy_server_adv_config.adv_type = ADV_IND;
fmy_server_adv_config.adv_channel = ADV_CHANNEL_ALL;
switch (__fydata->adv_fmna_state) {
case FMNA_SM_PAIR:
log_info("FMNA_SM_PAIR");
fmy_server_adv_config.adv_interval = fmna_pairing_adv_interval[mode];
break;
case FMNA_SM_SEPARATED:
log_info("FMNA_SM_SEPARATED");
fmy_server_adv_config.adv_interval = fmna_separated_adv_interval[mode];
break;
case FMNA_SM_NEARBY:
log_info("FMNA_SM_NEARBY");
fmy_server_adv_config.adv_interval = fmna_nearby_adv_interval[mode];
if (app_ble_get_hdl_con_handle(fmy_ble_hdl) != 0) {
log_info("===set_adv second devices===");
fmy_server_adv_config.adv_interval = FMY_FMNA_NEARBY_ADV_SLOW_INTERVAL;
} else {
}
default:
break;
}
log_info("set_adv_mode(%d), adv_fmna_state(%d), adv_interval= %04x, adv_type= %d", mode, __fydata->adv_fmna_state, fmy_server_adv_config.adv_interval, fmy_server_adv_config.adv_type);
return 0;
}
int fmy_set_adv_enable(u8 enable)
{
log_info("%s(%d): %d", __FUNCTION__, __LINE__, enable);
void *app_ble_hdl = fmy_ble_hdl;
if (app_ble_adv_state_get(fmy_second_ble_hdl)) {
log_info("======second dev adv_disable===");
app_ble_hdl = fmy_second_ble_hdl;
} else if (app_ble_get_hdl_con_handle(fmy_ble_hdl) != 0) {
log_info("======second dev adv_enable===");
app_ble_hdl = fmy_second_ble_hdl;
}
if (enable) {
if (!__fy_vm->is_open) {
log_info("fmy is not open, adv is locked!");
return 0;
}
if (__fydata->adv_fmna_state == FMNA_SM_PAIR) {
if (0 == __fydata->pairing_mode_enable) {
log_info("hold Find My network pairing mode!!!");
return 0;
} else {
if (__fydata->pairing_mode_timer_id) {
log_info("reset pairing timer");
fmy_pairing_timeout_stop();
fmy_pairing_timeout_start();
} else {
log_info("start pairing timer");
fmy_pairing_timeout_start();
}
}
} else {
//other state,bonded, default pairing unlock
__fydata->pairing_mode_enable = 1;
}
/* if (ble_comm_dev_get_connected_nums(GATT_ROLE_SERVER)) { */
/* log_info("======second dev adv_enable==="); */
/* } */
/* ble_gatt_server_set_adv_config(&fmy_server_adv_config); */
// if (app_ble_get_hdl_con_handle(app_ble_hdl) == 0) {
app_ble_set_adv_param(app_ble_hdl, \
fmy_server_adv_config.adv_interval, \
fmy_server_adv_config.adv_type, \
fmy_server_adv_config.adv_channel);
app_ble_adv_data_set(app_ble_hdl, \
(u8 *)fmy_server_adv_config.adv_data,
fmy_server_adv_config.adv_data_len);
app_ble_rsp_data_set(app_ble_hdl, \
(u8 *)fmy_server_adv_config.rsp_data,
fmy_server_adv_config.rsp_data_len);
// }
}
if (enable && BLE_ST_ADV == fmy_ble_state) {
log_info("already adv open!!!");
return 0;
}
/* ble_gatt_server_adv_enable(enable); */
if (enable) {
fmy_ble_state = BLE_ST_ADV;
} else {
fmy_ble_state = BLE_ST_IDLE;
}
log_info(">>>> fmy fmy adv:%x %x", (u32)app_ble_hdl, app_ble_get_hdl_con_handle(app_ble_hdl));
//if (enable) {
// if (app_ble_get_hdl_con_handle(app_ble_hdl) == 0) {
// app_ble_adv_enable(app_ble_hdl, enable);
// }
//} else {
app_ble_adv_enable(app_ble_hdl, enable);
//}
log_info("%s(%d): %d", __FUNCTION__, __LINE__, enable);
return 0;
}
static int ble_fmy_att_send_data(u16 conn_handle, u16 att_handle, u8 *data, u16 len, att_op_type_e op_type)
{
log_info("att_send:con_hdl= %04x,att_hdl= %04x,le= %d,op_type= %d", conn_handle, att_handle, len, op_type);
log_info_hexdump(data, len);
if (app_ble_get_hdl_con_handle(fmy_ble_hdl) == conn_handle) {
return app_ble_att_send_data(fmy_ble_hdl, att_handle, data, len, op_type);
}
if (app_ble_get_hdl_con_handle(fmy_second_ble_hdl) == conn_handle) {
return app_ble_att_send_data(fmy_second_ble_hdl, att_handle, data, len, op_type);
}
return -1;
}
/*************************************************************************************************/
/*!
* \brief 断开连接
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
void fmy_test_disconnect(void)
{
log_info("%s", __FUNCTION__);
fmna_connection_disconnect_all();
}
/*************************************************************************************************/
void fmy_test_switch_battery_level(u8 bat_val)
{
fmy_battery_level = bat_val;
log_info("%s, bat= %d", __FUNCTION__, fmy_battery_level);
}
/*
* @brief findmy state callback,状态类别参考FMNA_SM_State_t枚举体
*/
static uint16_t fmy_state_callback(FMNA_SM_State_t fmy_state, const char *state_string)
{
log_info("fmy state change->fmy_state:%s", state_string);
__fydata->fmna_state = fmy_state;
switch (fmy_state) {
case FMNA_SM_CONNECTING:
UI_MSG_POST("SET_CONNECTING_FLAG:a=%4", 1);
break;
case FMNA_SM_FMNA_PAIR_COMPLETE:
log_info("findmy pair success!!");
UI_MSG_POST("PAIR_SUCCESS");
break;
case FMNA_SM_UNPAIR:
// 锁住pairing mode 广播,待重新开启
UI_MSG_POST("UNPAIR_SUCCESS");
fmy_owner_connect = false;
__fydata->pairing_mode_enable = 0;
log_info("findmy unpair success!!");
fmy_owner_info_revert_back();
break;
case FMNA_SM_FMNA_PAIR:
log_info("SM_FMNA_PAIR!!");
break;
default:
break;
}
return 0;
}
//=====================================================================
static const fmna_app_api_t fmna_app_api_table = {
.evnet_post_msg = fmy_evnet_post_msg,
.set_adv_data = fmy_set_adv_data,
.set_adv_mode = fmy_set_adv_mode,
.set_adv_enable = fmy_set_adv_enable,
.get_mac = fmy_get_static_mac,
.set_mac = fmy_set_static_mac,
.att_send_data = ble_fmy_att_send_data,
.get_battery_level = fmy_get_battery_level,
.call_disconnect = fmy_disconnect,
.sound_control = fmy_sound_control,
#if TCFG_GSENSOR_ENABLE && TCFG_P11GSENSOR_EN
.sensor_init = fmy_motion_detection_init,
.sensor_deinit = fmy_motion_detection_deinit,
.motion_deteted = fmy_motion_detection,
#endif
#if FMY_OTA_SUPPORT_CONFIG
.uarp_ota_process = fmy_ota_process,
#else
.uarp_ota_process = NULL,
#endif
.state_callback = fmy_state_callback,
.check_capability = fmy_check_capabilities_is_enalbe,
};
static const char fmy_user_config_path[] = "flash/EXT_RESERVED/FINDMY";//配置区路径(isd_config_rule.c)
static int fmy_set_user_infomation(void)
{
ret_code_t ret = FMY_SUCCESS;
fmna_input_cfg_t input_cfg;
fmna_user_cfg_set_patch(fmy_user_config_path);
fmna_set_product_data(fmy_product_data);
fmna_set_crypto_enc_key_config(fmy_Server_Encryption_Key, fmy_Signature_Verification_Key);
uint8_t *data_ram = zalloc(16 + 1024);
int len;
if (data_ram) {
fmna_user_cfg_set_patch(fmy_user_config_path);
ret = fmna_user_cfg_open();
if (ret == FMY_SUCCESS) {
if (fmna_user_cfg_is_exist()) {
log_info("exist user_cfg info");
goto w_end;
}
//配置区有效,并且为空才写入
input_cfg.serial_number = (uint8_t *)fmy_serial_number;
input_cfg.uuid = data_ram;
input_cfg.token = &data_ram[16];
#if UUID_TOKEN_IS_BASE64_MODE
len = uuid_str_to_hex(fmy_token_uuid_char, input_cfg.uuid);
if (len != 16) {
log_info("err uuid char");
ret = FMY_ERROR_INVALID_DATA;
goto w_end;
}
len = fmna_Base64Decode((char *)fmy_token_auth_char, (char *)input_cfg.token, 1024);
if (len == 0) {
log_info("err token char");
ret = FMY_ERROR_INVALID_DATA;
goto w_end;
}
#else
memcpy(input_cfg.uuid, fmy_token_uuid_hex, 16);
int cpy_len = sizeof(fmy_token_auth_hex);
if (cpy_len > 1024) {
cpy_len = 1024;
}
memcpy(input_cfg.token, fmy_token_auth_hex, sizeof(fmy_token_auth_hex));
#endif
ret = fmna_user_cfg_write(&input_cfg);
}
w_end:
fmna_user_cfg_close();
if (ret == FMY_SUCCESS) {
log_info("set user_cfg succ");
} else {
log_info("set user_cfg fail,%d", ret);
}
free(data_ram);
}
return 0;
}
static void fmy_devices_init(void)
{
// enable fmy sound
DEV_SOUND_INIT();
DEV_SOUND_STATE(PORT_VALUE_LOW);
}
static void fmy_devices_deinit()
{
// disable fmy sound
DEV_SOUND_DEINIT();
fmy_sound_control(FMNA_SOUND_STOP);
}
void fmy_fmna_init(void)
{
log_info("fmna_init: %s,%s", __DATE__, __TIME__);
log_info("production mode= %d, fmy_version= %d", TOKEN_ID_PRODUCTION_MODE,
FMY_FW_VERSION_MAJOR_NUMBER * 100 + FMY_FW_VERSION_MINOR_NUMBER * 10 + FMY_FW_VERSION_REVISION_NUMBER);
fmy_set_user_infomation();
fmna_config_user_vm_rang(CFG_FMNA_SOFTWARE_AUTH_START, CFG_FMNA_SOFTWARE_AUTH_END);
fmna_set_app_api((fmna_app_api_t *)&fmna_app_api_table);
fmna_gatt_set_att_handle_table(&fmna_att_handle_table);
fmna_version_init(FMY_FW_VERSION_MAJOR_NUMBER, FMY_FW_VERSION_MINOR_NUMBER, FMY_FW_VERSION_REVISION_NUMBER);
fmna_main_start();
log_info("reboot fmna state: %d", fmna_get_current_state());
}
int fmy_enable(bool en)
{
// 写开关标志位
__fy_vm->is_open = en;
fmy_vm_deal(__fy_vm, 1);
if (en) {
log_info(">>>>>fmy open");
// 使能fmy外设
fmy_devices_init();
// 处于配对状态就不需要做开关配对广播操作
if (__fydata->adv_fmna_state == FMNA_SM_PAIR) {
return 0;
}
} else {
log_info(">>>>>fmy close");
// 关闭findmy外设
fmy_devices_deinit();
// 如果处于连接状态则需要先断开连接再关广播
if (__fydata->fmna_state == FMNA_SM_CONNECTED) {
fmy_test_disconnect();
return 0;
}
}
// 开关广播操作
return fmy_set_adv_enable(en);
}
// 开关配对广播
void fmy_open_close_pairing_mode(bool en)
{
if (en) {
log_info(">>>fmy start pairing adv");
fmy_pairing_reset_address();
fmy_pairing_restart_adv();
} else {
if (__fydata->adv_fmna_state == FMNA_SM_PAIR) {
log_info(">>>fmy close pairing adv");
__fydata->pairing_mode_enable = 0;
fmy_set_adv_enable(0);
fmy_pairing_timeout_stop();
}
}
}
// 是否配对, 1:已配对 0:未配对
bool fmy_get_pair_state(void)
{
return fmna_connection_is_fmna_paired();
}
// 手动强制解除配对
void fmy_factory_reset(void)
{
log_info(">>>findmy factory reset!");
fmy_sound_control(FMNA_SOUND_STOP);
fmna_factory_reset(NULL);
}
void fmy_key_process(u8 key_event)
{
#if 0//过认证的测试按键,用到的时候在打开需要再iokey.c去配置
switch (key_event) {
case BATTERY_LOW:
fmy_test_switch_battery_level(BAT_STATE_CRITICALLY_LOW);
break;
case SERIALNUMBER_LOOKUP_OPEN:
fmna_paired_serialnumber_lookup_enable(1);
break;
case BATTERY_FULL:
fmy_test_switch_battery_level(BAT_STATE_FULL);
break;
case SERIALNUMBER_LOOKUP_CLOSE:
fmna_paired_serialnumber_lookup_enable(0);
break;
case PAIRING_OPEN:
fmy_enable(1);
fmy_open_close_pairing_mode(1);
break;
}
#endif
}
/* void fmy_key_process(u8 key_event) */
/* { */
/* if (key_event == 64) { // short */
/* printf("fmy key short"); */
/* fmy_open_close_pairing_mode(1); */
/* } else if (key_event == 66) { // long */
/* fmy_factory_reset(); */
/* } */
/* } */
#endif
@@ -0,0 +1,23 @@
#ifndef _BLE_FMY_FMNA_H
#define _BLE_FMY_FMNA_H
int fmy_enable(bool en);
void fmy_open_close_pairing_mode(bool en);
bool fmy_get_pair_state(void);
void fmy_factory_reset(void);
u16 ble_fmy_get_con_handle(void);
void fmna_factory_reset(void *priv);
u16 ble_fmy_get_con_handle(void);
void fmy_suffix_name_set(void);
void fmy_original_name_set(void);
bool fmy_is_owner_pair_set(void);
void fmy_owner_info_revert_back(void);
bool fmy_is_owner_address(uint8_t *addr_in);
#endif
@@ -0,0 +1,73 @@
#include "system/includes.h"
#include "gSensor/gSensor_manage.h"
#include "ble_fmy_modet.h"
#include "user_p11_cmd.h"
#if (TCFG_GSENSOR_ENABLE && TCFG_P11GSENSOR_EN)
#if GSENSOR_PRINTF_ENABLE
#define log_info(x, ...) printf("[FMY_MO_DET]" x "\r\n", ## __VA_ARGS__)
#define log_info_hexdump put_buf
#else
#define log_info(...)
#define log_info_hexdump(...)
#endif
#define SENSOR_DATA_LEN 25 // 需小于传感器采集HZ
// Motion detection config
static char *workbuf = NULL;
static const short fs = 25;
static const float thread = 2.0;
// GET DATA FROM WATCH_SGENSOR_BUF
extern short gsensorbuf[];
static void fmy_motion_detection_print_accel_data(const axis_info_t *accel_data, int size)
{
for (int i = 0; i < size; i++) {
log_info("x: %d, y: %d, z: %d", accel_data[i].x, accel_data[i].y, accel_data[i].z);
}
}
bool fmy_motion_detection(void)
{
axis_info_t accel_data[SENSOR_DATA_LEN] = {0};
memcpy(accel_data, gsensorbuf, SENSOR_DATA_LEN * 2 * 3);
/* fmy_motion_detection_print_accel_data(accel_data, SENSOR_DATA_LEN); */
bool is_moved = run_MotionDetection(workbuf, SENSOR_DATA_LEN, accel_data);
if (is_moved) {
log_info("is moving!!");
} else {
log_info("is static!!");
}
return is_moved;
}
int fmy_motion_detection_init(void)
{
int buff_size = get_DetectionBuf(fs);
workbuf = (char *)malloc(buff_size);
if (workbuf == NULL) {
log_info("workbuf init fail!!");
return -1;
}
init_MotionDet(workbuf, fs, thread);
return 0;
}
int fmy_motion_detection_deinit(void)
{
if (!workbuf) {
log_info("sensor is not init so can not deinit!!");
return 0;
}
free(workbuf);
workbuf = NULL;
return 0;
}
#endif
@@ -0,0 +1,15 @@
#ifndef _FMY_GSENSOR_H
#define _FMY_GSENSOR_H
#define GSENSOR_PRINTF_ENABLE 1
// fmy gsensor api
bool fmy_motion_detection(void);
int fmy_motion_detection_init(void);
int fmy_motion_detection_deinit(void);
// Motion Detection algorithm in MotionDetection.a
int get_DetectionBuf(int fs);
void init_MotionDet(void *ptr, short fs, float thread);
char run_MotionDetection(void *ptr, int len, short *data);
#endif
@@ -0,0 +1,313 @@
/*********************************************************************************************
* Filename : .c
* Description :
* Author : JM
* Email : zh-jieli.com
* Last modifiled : 2017-01-17 11:14
* Copyright:(c)JIELI 2011-2016 @ , All Rights Reserved.
*********************************************************************************************/
/* #include "system/app_core.h" */
#include "system/includes.h"
#include "app_config.h"
#include "app_action.h"
#include "btstack/btstack_task.h"
#include "btstack/bluetooth.h"
#include "user_cfg.h"
#include "vm.h"
#include "btcontroller_modules.h"
#include "bt_common.h"
#include "3th_profile_api.h"
#include "le_common.h"
/* #include "rcsp_bluetooth.h" */
#include "JL_rcsp_api.h"
#include "custom_cfg.h"
#include "btstack/btstack_event.h"
#include "gatt_common/le_gatt_common.h"
#include "ble_fmy.h"
#include "ble_fmy_ota.h"
#include "system/malloc.h"
#include "dual_bank_updata_api.h"
#if (BT_AI_SEL_PROTOCOL & FMNA_EN)
#define rr_printf(x, ...) printf("\e[31m\e[1m" x "\e[0m", ## __VA_ARGS__)
#define gg_printf(x, ...) printf("\e[32m\e[1m" x "\e[0m", ## __VA_ARGS__)
#define yy_printf(x, ...) printf("\e[33m\e[1m" x "\e[0m", ## __VA_ARGS__)
#if 0
#define log_info(x, ...) printf("[FMY_OTA]" x "\r\n", ## __VA_ARGS__)
#define log_error(x, ...) printf("[FMY_OTA_ERR]" x "\r\n", ## __VA_ARGS__)
#define log_info_hexdump put_buf
#else
#define log_info(...)
#define log_error(...)
#define log_info_hexdump(...)
#endif
#define OTA_WRITE_FLASH_SIZE (1024)
typedef struct {
u32 old_sys_clk;
u32 file_size;
u32 version;
u32 recv_size;
u16 ota_packet_num;
volatile u8 ota_state;
u8 res_byte;
volatile u32 buff_size;
u8 buff[OTA_WRITE_FLASH_SIZE + 32];
} fmy_ota_t;
static fmy_ota_t *fmy_ota;
#define FMY_OTA_IS_ENABLE() (fmy_ota != NULL)
//--------------------------------------------------------------------------------------------
static void fmy_ota_set_state(u8 state);
extern u8 dual_bank_update_verify_without_crc(int (*verify_result_hdl)(int calc_crc));
//--------------------------------------------------------------------------------------------
extern u32 dual_bank_passive_update_exit(void *priv);
extern void set_ota_status(u8 stu);
static int fmy_ota_init(void)
{
log_info("%s", __FUNCTION__);
dual_bank_passive_update_exit(NULL);
if (!fmy_ota) {
fmy_ota = malloc(sizeof(fmy_ota_t));
}
if (fmy_ota) {
memset(fmy_ota, 0, sizeof(fmy_ota_t));
set_ota_status(1);
fmy_state_idle_set_active(true);
return FMNA_OTA_OP_SUCC;
}
log_error("%s malloc fail", __FUNCTION__);
return FMNA_OTA_OP_MALLOC_FAIL;
}
static int fmy_ota_exit(void)
{
log_info("%s", __FUNCTION__);
dual_bank_passive_update_exit(NULL);
set_ota_status(0);
if (fmy_ota) {
local_irq_disable();
free(fmy_ota);
fmy_ota = NULL;
local_irq_enable();
}
fmy_ota_set_state(FMY_OTA_STATE_IDLE);
fmy_state_idle_set_active(false);
return FMNA_OTA_OP_SUCC;
}
static void fmy_ota_set_state(u8 state)
{
if (FMY_OTA_IS_ENABLE()) {
fmy_ota->ota_state = state;
}
}
u8 fmy_ota_get_state(void)
{
if (FMY_OTA_IS_ENABLE()) {
return fmy_ota->ota_state;
}
return FMY_OTA_STATE_IDLE;
}
static void fmy_ota_reset(void *priv)
{
log_info("cpu_reset!");
cpu_reset();
}
static int fmy_ota_boot_info_cb(int err)
{
log_info("fmy_ota_boot_info_cb:%d", err);
if (err == 0) {
sys_timeout_add(NULL, fmy_ota_reset, 2000);
} else {
log_error("update head fail");
}
return 0;
}
static int fmy_clk_resume(int priv)
{
/* clk_set("sys", fmy_ota->old_sys_clk); //恢复时钟 */
return 0;
}
//传输写入结束
extern u32 dual_bank_update_burn_boot_info(int (*burn_boot_info_result_hdl)(int err));
static int fmy_ota_write_complete(void)
{
int status = FMNA_OTA_OP_SUCC;
//把最后一次OTA_DATA的信号量pend到再开始校验
/* fmy_ota->old_sys_clk = clk_get("sys"); */
/* clk_set("sys", 96 * 1000000L); //提升系统时钟提高校验速度 */
if (dual_bank_update_verify_without_crc(fmy_clk_resume) == 0) {
log_info("update succ");
fmy_ota_set_state(FMY_OTA_STATE_IDLE);
dual_bank_update_burn_boot_info(fmy_ota_boot_info_cb);
} else {
log_error("update fail");
status = FMNA_OTA_OP_CRC_FAIL;
}
set_ota_status(0);
return status;
}
//每一笔数据写入的回调
static int fmy_update_write_cb(void *priv)
{
int err = (int)priv;
log_info("flash write %d bytes Complete,err %d", fmy_ota->buff_size, err);
if (err) {
fmy_ota_set_state(FMY_OTA_STATE_WRITE_ERROR);
}
fmy_ota->buff_size = 0;
return 0;
}
extern u32 dual_bank_passive_update_init(u32 fw_crc, u32 fw_size, u16 max_pkt_len, void *priv);
extern u32 dual_bank_update_allow_check(u32 fw_size);
extern u32 dual_bank_update_write(void *data, u16 len, int (*write_complete_cb)(void *priv));
int fmy_ota_process(uarp_cmd_type_t cmd_type, u8 *recv_data, u32 recv_len)
{
int ret;
int status = FMNA_OTA_OP_SUCC;
log_info("cmd_type= %d,len= %d", cmd_type, recv_len);
if (!FMY_OTA_SUPPORT_CONFIG) {
log_error("OTA config err!");
return FMNA_OTA_OP_OTHER_ERR;
}
if (false == fmy_check_capabilities_is_enalbe(FMY_CAPABILITY_SUPPORTS_FW_UPDATE_SERVICE)) {
log_error("OTA not support!");
return FMNA_OTA_OP_INIT_FAIL;
}
if (!FMY_OTA_IS_ENABLE() && cmd_type != FMNA_UARP_OTA_REQ) {
log_error("OTA not running!");
return FMNA_OTA_OP_INIT_FAIL;
}
switch (cmd_type) {
case FMNA_UARP_OTA_REQ:
status = fmy_ota_init();
if (status == FMNA_OTA_OP_SUCC) {
fmy_ota_set_state(FMY_OTA_STATE_REQ);
fmy_ota->version = little_endian_read_32(recv_data, 0);
log_info("OTA_REQ,version= %08x", fmy_ota->version);
}
//升级开始前对flash解保护
extern int norflash_set_write_protect(u32 enable);
norflash_set_write_protect(0);
break;
case FMNA_UARP_OTA_FILE_INFO:
fmy_ota_set_state(FMY_OTA_STATE_CHECK_FILESIZE);
fmy_ota->file_size = little_endian_read_32(recv_data, 0);
log_info("OTA_FILE_INFO file_size= %d", fmy_ota->file_size);
/* log_info("task:%s", os_current_task()); */
ret = dual_bank_passive_update_init(0, fmy_ota->file_size, OTA_WRITE_FLASH_SIZE, NULL);
if (0 == ret) {
ret = dual_bank_update_allow_check(fmy_ota->file_size);
if (ret) {
log_error("check err: %d", ret);
status = FMNA_OTA_OP_NO_SPACE;
}
} else {
log_error("init err: %d", ret);
status = FMNA_OTA_OP_INIT_FAIL;
}
break;
case FMNA_UARP_OTA_DATA: {
if (fmy_ota_get_state() == FMY_OTA_STATE_WRITE_ERROR) {
ret = 1;
goto write_end;
}
int wait_cnt = 200;//wait flash write complete, timeout is 2 second
while (wait_cnt && fmy_ota->buff_size >= OTA_WRITE_FLASH_SIZE) {
putchar('&');
wait_cnt--;
os_time_dly(1);
}
if (fmy_ota->buff_size && wait_cnt == 0) {
ret = 2;
goto write_end;
}
fmy_ota_set_state(FMY_OTA_STATE_WRITE_DATA);
fmy_ota->ota_packet_num++;
fmy_ota->recv_size += recv_len;
memcpy(fmy_ota->buff, recv_data, recv_len);
fmy_ota->buff_size += recv_len;
log_info("OTA_DATA: file_size= %d,recv_size= %d,packet_num= %d,frame_size= %d", \
fmy_ota->file_size, fmy_ota->recv_size, fmy_ota->ota_packet_num, fmy_ota->buff_size);
log_info_hexdump(fmy_ota->buff, 32);
ret = dual_bank_update_write(fmy_ota->buff, fmy_ota->buff_size, fmy_update_write_cb);
write_end:
if (ret) {
log_error("dual_write err %d", ret);
status = FMNA_OTA_OP_WRITE_FAIL;
/* fmy_ota_boot_info_cb(0);//to reset */
}
}
break;
case FMNA_UARP_OTA_END:
log_info("OTA_END");
fmy_ota_set_state(FMY_OTA_STATE_COMPLETE);
status = fmy_ota_write_complete();
break;
case FMNA_UARP_OTA_DISCONNECT:
log_info("OTA_DISCONNECT");
if (fmy_ota_get_state() != FMY_OTA_STATE_IDLE) {
log_error("OTA fail");
/* fmy_ota_boot_info_cb(0); //to reset */
}
status = fmy_ota_exit();
break;
default:
log_error("unknow uarp cmd");
break;
}
if (status) {
log_error("ota_process err= %d", status);
fmy_ota_exit();
}
return status;
}
#endif
@@ -0,0 +1,21 @@
#ifndef __BLE_FMY_OTA_H__
#define __BLE_FMY_OTA_H__
#include "typedef.h"
#include "btstack/third_party/fmna/fmna_api.h"
#define FMY_OTA_SUPPORT_CONFIG (CONFIG_DB_UPDATE_DATA_GENERATE_EN&&CONFIG_DOUBLE_BANK_ENABLE)
enum {
FMY_OTA_STATE_IDLE = 0,
FMY_OTA_STATE_REQ,
FMY_OTA_STATE_CHECK_FILESIZE,
FMY_OTA_STATE_WRITE_DATA,
FMY_OTA_STATE_COMPLETE,
FMY_OTA_STATE_WRITE_ERROR,
};
int fmy_ota_process(uarp_cmd_type_t cmd_type, u8 *recv_data, u32 recv_len);
u8 fmy_ota_get_state(void);
#endif
@@ -0,0 +1,292 @@
// binary representation
// attribute size in bytes (16), flags(16), handle (16), uuid (16/128), value(...)
#ifndef _BLE_FMY_PROFILE_H
#define _BLE_FMY_PROFILE_H
#include <stdint.h>
#include "app_config.h"
/******************************************************************************
//gatt_profile.cfg
PRIMARY_SERVICE, 1800
CHARACTERISTIC, 2a00, READ | DYNAMIC,
PRIMARY_SERVICE, 1801
//CHARACTERISTIC, 2a05, INDICATE,
PRIMARY_SERVICE, 1804
CHARACTERISTIC, 2a07, READ | DYNAMIC,
//The Accessory information service
PRIMARY_SERVICE, 87290102-3C51-43B1-A1A9-11B9DC38478B
//ProductData
CHARACTERISTIC, 6AA50001-6352-4D57-A7B4-003A416FBB0B, READ | DYNAMIC,
//ManufacturerName
CHARACTERISTIC, 6AA50002-6352-4D57-A7B4-003A416FBB0B, READ | DYNAMIC,
//ModelName
CHARACTERISTIC, 6AA50003-6352-4D57-A7B4-003A416FBB0B, READ | DYNAMIC,
//AccessoryCategory
CHARACTERISTIC, 6AA50005-6352-4D57-A7B4-003A416FBB0B, READ | DYNAMIC,
//AccessoryCapabilities
CHARACTERISTIC, 6AA50006-6352-4D57-A7B4-003A416FBB0B, READ | DYNAMIC,
//FirmwareVersion
CHARACTERISTIC, 6AA50007-6352-4D57-A7B4-003A416FBB0B, READ | DYNAMIC,
//FindMyVersion
CHARACTERISTIC, 6AA50008-6352-4D57-A7B4-003A416FBB0B, READ | DYNAMIC,
//BatteryType
CHARACTERISTIC, 6AA50009-6352-4D57-A7B4-003A416FBB0B, READ | DYNAMIC,
//BatteryLevel
CHARACTERISTIC, 6AA5000A-6352-4D57-A7B4-003A416FBB0B, READ | DYNAMIC,
//set handle start 0x0080
//GATT_HANDLE_BEGIN, 0080
//unbond,The Find My network service
PRIMARY_SERVICE, FD44
//Pairing Control Point
CHARACTERISTIC, 4F860001-943B-49EF-BED4-2F730304427A, WRITE | INDICATE | DYNAMIC,
//bond,Owner,The Find My network service
//Configuration Control Point
CHARACTERISTIC, 4F860002-943B-49EF-BED4-2F730304427A, WRITE | INDICATE | DYNAMIC,
//Non Owner Control Point
CHARACTERISTIC, 4F860003-943B-49EF-BED4-2F730304427A, WRITE | INDICATE | DYNAMIC,
//Non Paired && Pairedowner Information Control Point
CHARACTERISTIC, 4F860004-943B-49EF-BED4-2F730304427A, WRITE | INDICATE | DYNAMIC,
//Debug Control Point
CHARACTERISTIC, 4F860005-943B-49EF-BED4-2F730304427A, WRITE | INDICATE | DYNAMIC,
//firmware update service
PRIMARY_SERVICE, FD43
CHARACTERISTIC, 94110001-6D9B-4225-A4F1-6A4A7F01B0DE, WRITE | INDICATE | DYNAMIC,
//for test
//PRIMARY_SERVICE, a0abe2fa-bb45-462c-87c7-5970d3e6e849
//CHARACTERISTIC, a0abe2fa-bb45-462c-87c7-5970d3e6e849, WRITE | DYNAMIC
******************************************************************************/
//----------------------------------------------------------------------------------------------------------
//
// gatt profile include file, generated by jieli gatt_inc_generator.exe
//
static const uint8_t findmy_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 1801
//
//////////////////////////////////////////////////////
0x0a, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x28, 0x01, 0x18,
//////////////////////////////////////////////////////
//
// 0x0005 PRIMARY_SERVICE 1804
//
//////////////////////////////////////////////////////
0x0a, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x28, 0x04, 0x18,
/* CHARACTERISTIC, 2a07, READ | DYNAMIC, */
// 0x0006 CHARACTERISTIC 2a07 READ | DYNAMIC
0x0d, 0x00, 0x02, 0x00, 0x06, 0x00, 0x03, 0x28, 0x02, 0x07, 0x00, 0x07, 0x2a,
// 0x0007 VALUE 2a07 READ | DYNAMIC
0x08, 0x00, 0x02, 0x01, 0x07, 0x00, 0x07, 0x2a,
//////////////////////////////////////////////////////
//
// 0x0008 PRIMARY_SERVICE 87290102-3C51-43B1-A1A9-11B9DC38478B
//
//////////////////////////////////////////////////////
0x18, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x28, 0x8b, 0x47, 0x38, 0xdc, 0xb9, 0x11, 0xa9, 0xa1, 0xb1, 0x43, 0x51, 0x3c, 0x02, 0x01, 0x29, 0x87,
/* CHARACTERISTIC, 6AA50001-6352-4D57-A7B4-003A416FBB0B, READ | DYNAMIC, */
// 0x0009 CHARACTERISTIC 6AA50001-6352-4D57-A7B4-003A416FBB0B READ | DYNAMIC
0x1b, 0x00, 0x02, 0x00, 0x09, 0x00, 0x03, 0x28, 0x02, 0x0a, 0x00, 0x0b, 0xbb, 0x6f, 0x41, 0x3a, 0x00, 0xb4, 0xa7, 0x57, 0x4d, 0x52, 0x63, 0x01, 0x00, 0xa5, 0x6a,
// 0x000a VALUE 6AA50001-6352-4D57-A7B4-003A416FBB0B READ | DYNAMIC
0x16, 0x00, 0x02, 0x03, 0x0a, 0x00, 0x0b, 0xbb, 0x6f, 0x41, 0x3a, 0x00, 0xb4, 0xa7, 0x57, 0x4d, 0x52, 0x63, 0x01, 0x00, 0xa5, 0x6a,
/* CHARACTERISTIC, 6AA50002-6352-4D57-A7B4-003A416FBB0B, READ | DYNAMIC, */
// 0x000b CHARACTERISTIC 6AA50002-6352-4D57-A7B4-003A416FBB0B READ | DYNAMIC
0x1b, 0x00, 0x02, 0x00, 0x0b, 0x00, 0x03, 0x28, 0x02, 0x0c, 0x00, 0x0b, 0xbb, 0x6f, 0x41, 0x3a, 0x00, 0xb4, 0xa7, 0x57, 0x4d, 0x52, 0x63, 0x02, 0x00, 0xa5, 0x6a,
// 0x000c VALUE 6AA50002-6352-4D57-A7B4-003A416FBB0B READ | DYNAMIC
0x16, 0x00, 0x02, 0x03, 0x0c, 0x00, 0x0b, 0xbb, 0x6f, 0x41, 0x3a, 0x00, 0xb4, 0xa7, 0x57, 0x4d, 0x52, 0x63, 0x02, 0x00, 0xa5, 0x6a,
/* CHARACTERISTIC, 6AA50003-6352-4D57-A7B4-003A416FBB0B, READ | DYNAMIC, */
// 0x000d CHARACTERISTIC 6AA50003-6352-4D57-A7B4-003A416FBB0B READ | DYNAMIC
0x1b, 0x00, 0x02, 0x00, 0x0d, 0x00, 0x03, 0x28, 0x02, 0x0e, 0x00, 0x0b, 0xbb, 0x6f, 0x41, 0x3a, 0x00, 0xb4, 0xa7, 0x57, 0x4d, 0x52, 0x63, 0x03, 0x00, 0xa5, 0x6a,
// 0x000e VALUE 6AA50003-6352-4D57-A7B4-003A416FBB0B READ | DYNAMIC
0x16, 0x00, 0x02, 0x03, 0x0e, 0x00, 0x0b, 0xbb, 0x6f, 0x41, 0x3a, 0x00, 0xb4, 0xa7, 0x57, 0x4d, 0x52, 0x63, 0x03, 0x00, 0xa5, 0x6a,
/* CHARACTERISTIC, 6AA50005-6352-4D57-A7B4-003A416FBB0B, READ | DYNAMIC, */
// 0x000f CHARACTERISTIC 6AA50005-6352-4D57-A7B4-003A416FBB0B READ | DYNAMIC
0x1b, 0x00, 0x02, 0x00, 0x0f, 0x00, 0x03, 0x28, 0x02, 0x10, 0x00, 0x0b, 0xbb, 0x6f, 0x41, 0x3a, 0x00, 0xb4, 0xa7, 0x57, 0x4d, 0x52, 0x63, 0x05, 0x00, 0xa5, 0x6a,
// 0x0010 VALUE 6AA50005-6352-4D57-A7B4-003A416FBB0B READ | DYNAMIC
0x16, 0x00, 0x02, 0x03, 0x10, 0x00, 0x0b, 0xbb, 0x6f, 0x41, 0x3a, 0x00, 0xb4, 0xa7, 0x57, 0x4d, 0x52, 0x63, 0x05, 0x00, 0xa5, 0x6a,
/* CHARACTERISTIC, 6AA50006-6352-4D57-A7B4-003A416FBB0B, READ | DYNAMIC, */
// 0x0011 CHARACTERISTIC 6AA50006-6352-4D57-A7B4-003A416FBB0B READ | DYNAMIC
0x1b, 0x00, 0x02, 0x00, 0x11, 0x00, 0x03, 0x28, 0x02, 0x12, 0x00, 0x0b, 0xbb, 0x6f, 0x41, 0x3a, 0x00, 0xb4, 0xa7, 0x57, 0x4d, 0x52, 0x63, 0x06, 0x00, 0xa5, 0x6a,
// 0x0012 VALUE 6AA50006-6352-4D57-A7B4-003A416FBB0B READ | DYNAMIC
0x16, 0x00, 0x02, 0x03, 0x12, 0x00, 0x0b, 0xbb, 0x6f, 0x41, 0x3a, 0x00, 0xb4, 0xa7, 0x57, 0x4d, 0x52, 0x63, 0x06, 0x00, 0xa5, 0x6a,
/* CHARACTERISTIC, 6AA50007-6352-4D57-A7B4-003A416FBB0B, READ | DYNAMIC, */
// 0x0013 CHARACTERISTIC 6AA50007-6352-4D57-A7B4-003A416FBB0B READ | DYNAMIC
0x1b, 0x00, 0x02, 0x00, 0x13, 0x00, 0x03, 0x28, 0x02, 0x14, 0x00, 0x0b, 0xbb, 0x6f, 0x41, 0x3a, 0x00, 0xb4, 0xa7, 0x57, 0x4d, 0x52, 0x63, 0x07, 0x00, 0xa5, 0x6a,
// 0x0014 VALUE 6AA50007-6352-4D57-A7B4-003A416FBB0B READ | DYNAMIC
0x16, 0x00, 0x02, 0x03, 0x14, 0x00, 0x0b, 0xbb, 0x6f, 0x41, 0x3a, 0x00, 0xb4, 0xa7, 0x57, 0x4d, 0x52, 0x63, 0x07, 0x00, 0xa5, 0x6a,
/* CHARACTERISTIC, 6AA50008-6352-4D57-A7B4-003A416FBB0B, READ | DYNAMIC, */
// 0x0015 CHARACTERISTIC 6AA50008-6352-4D57-A7B4-003A416FBB0B READ | DYNAMIC
0x1b, 0x00, 0x02, 0x00, 0x15, 0x00, 0x03, 0x28, 0x02, 0x16, 0x00, 0x0b, 0xbb, 0x6f, 0x41, 0x3a, 0x00, 0xb4, 0xa7, 0x57, 0x4d, 0x52, 0x63, 0x08, 0x00, 0xa5, 0x6a,
// 0x0016 VALUE 6AA50008-6352-4D57-A7B4-003A416FBB0B READ | DYNAMIC
0x16, 0x00, 0x02, 0x03, 0x16, 0x00, 0x0b, 0xbb, 0x6f, 0x41, 0x3a, 0x00, 0xb4, 0xa7, 0x57, 0x4d, 0x52, 0x63, 0x08, 0x00, 0xa5, 0x6a,
/* CHARACTERISTIC, 6AA50009-6352-4D57-A7B4-003A416FBB0B, READ | DYNAMIC, */
// 0x0017 CHARACTERISTIC 6AA50009-6352-4D57-A7B4-003A416FBB0B READ | DYNAMIC
0x1b, 0x00, 0x02, 0x00, 0x17, 0x00, 0x03, 0x28, 0x02, 0x18, 0x00, 0x0b, 0xbb, 0x6f, 0x41, 0x3a, 0x00, 0xb4, 0xa7, 0x57, 0x4d, 0x52, 0x63, 0x09, 0x00, 0xa5, 0x6a,
// 0x0018 VALUE 6AA50009-6352-4D57-A7B4-003A416FBB0B READ | DYNAMIC
0x16, 0x00, 0x02, 0x03, 0x18, 0x00, 0x0b, 0xbb, 0x6f, 0x41, 0x3a, 0x00, 0xb4, 0xa7, 0x57, 0x4d, 0x52, 0x63, 0x09, 0x00, 0xa5, 0x6a,
/* CHARACTERISTIC, 6AA5000A-6352-4D57-A7B4-003A416FBB0B, READ | DYNAMIC, */
// 0x0019 CHARACTERISTIC 6AA5000A-6352-4D57-A7B4-003A416FBB0B READ | DYNAMIC
0x1b, 0x00, 0x02, 0x00, 0x19, 0x00, 0x03, 0x28, 0x02, 0x1a, 0x00, 0x0b, 0xbb, 0x6f, 0x41, 0x3a, 0x00, 0xb4, 0xa7, 0x57, 0x4d, 0x52, 0x63, 0x0a, 0x00, 0xa5, 0x6a,
// 0x001a VALUE 6AA5000A-6352-4D57-A7B4-003A416FBB0B READ | DYNAMIC
0x16, 0x00, 0x02, 0x03, 0x1a, 0x00, 0x0b, 0xbb, 0x6f, 0x41, 0x3a, 0x00, 0xb4, 0xa7, 0x57, 0x4d, 0x52, 0x63, 0x0a, 0x00, 0xa5, 0x6a,
//////////////////////////////////////////////////////
//
// 0x001b PRIMARY_SERVICE FD44
//
//////////////////////////////////////////////////////
0x0a, 0x00, 0x02, 0x00, 0x1b, 0x00, 0x00, 0x28, 0x44, 0xfd,
/* CHARACTERISTIC, 4F860001-943B-49EF-BED4-2F730304427A, WRITE | INDICATE | DYNAMIC, */
// 0x001c CHARACTERISTIC 4F860001-943B-49EF-BED4-2F730304427A WRITE | INDICATE | DYNAMIC
0x1b, 0x00, 0x02, 0x00, 0x1c, 0x00, 0x03, 0x28, 0x28, 0x1d, 0x00, 0x7a, 0x42, 0x04, 0x03, 0x73, 0x2f, 0xd4, 0xbe, 0xef, 0x49, 0x3b, 0x94, 0x01, 0x00, 0x86, 0x4f,
// 0x001d VALUE 4F860001-943B-49EF-BED4-2F730304427A WRITE | INDICATE | DYNAMIC
0x16, 0x00, 0x28, 0x03, 0x1d, 0x00, 0x7a, 0x42, 0x04, 0x03, 0x73, 0x2f, 0xd4, 0xbe, 0xef, 0x49, 0x3b, 0x94, 0x01, 0x00, 0x86, 0x4f,
// 0x001e CLIENT_CHARACTERISTIC_CONFIGURATION
0x0a, 0x00, 0x0a, 0x01, 0x1e, 0x00, 0x02, 0x29, 0x00, 0x00,
/* CHARACTERISTIC, 4F860002-943B-49EF-BED4-2F730304427A, WRITE | INDICATE | DYNAMIC, */
// 0x001f CHARACTERISTIC 4F860002-943B-49EF-BED4-2F730304427A WRITE | INDICATE | DYNAMIC
0x1b, 0x00, 0x02, 0x00, 0x1f, 0x00, 0x03, 0x28, 0x28, 0x20, 0x00, 0x7a, 0x42, 0x04, 0x03, 0x73, 0x2f, 0xd4, 0xbe, 0xef, 0x49, 0x3b, 0x94, 0x02, 0x00, 0x86, 0x4f,
// 0x0020 VALUE 4F860002-943B-49EF-BED4-2F730304427A WRITE | INDICATE | DYNAMIC
0x16, 0x00, 0x28, 0x03, 0x20, 0x00, 0x7a, 0x42, 0x04, 0x03, 0x73, 0x2f, 0xd4, 0xbe, 0xef, 0x49, 0x3b, 0x94, 0x02, 0x00, 0x86, 0x4f,
// 0x0021 CLIENT_CHARACTERISTIC_CONFIGURATION
0x0a, 0x00, 0x0a, 0x01, 0x21, 0x00, 0x02, 0x29, 0x00, 0x00,
/* CHARACTERISTIC, 4F860003-943B-49EF-BED4-2F730304427A, WRITE | INDICATE | DYNAMIC, */
// 0x0022 CHARACTERISTIC 4F860003-943B-49EF-BED4-2F730304427A WRITE | INDICATE | DYNAMIC
0x1b, 0x00, 0x02, 0x00, 0x22, 0x00, 0x03, 0x28, 0x28, 0x23, 0x00, 0x7a, 0x42, 0x04, 0x03, 0x73, 0x2f, 0xd4, 0xbe, 0xef, 0x49, 0x3b, 0x94, 0x03, 0x00, 0x86, 0x4f,
// 0x0023 VALUE 4F860003-943B-49EF-BED4-2F730304427A WRITE | INDICATE | DYNAMIC
0x16, 0x00, 0x28, 0x03, 0x23, 0x00, 0x7a, 0x42, 0x04, 0x03, 0x73, 0x2f, 0xd4, 0xbe, 0xef, 0x49, 0x3b, 0x94, 0x03, 0x00, 0x86, 0x4f,
// 0x0024 CLIENT_CHARACTERISTIC_CONFIGURATION
0x0a, 0x00, 0x0a, 0x01, 0x24, 0x00, 0x02, 0x29, 0x00, 0x00,
/* CHARACTERISTIC, 4F860004-943B-49EF-BED4-2F730304427A, WRITE | INDICATE | DYNAMIC, */
// 0x0025 CHARACTERISTIC 4F860004-943B-49EF-BED4-2F730304427A WRITE | INDICATE | DYNAMIC
0x1b, 0x00, 0x02, 0x00, 0x25, 0x00, 0x03, 0x28, 0x28, 0x26, 0x00, 0x7a, 0x42, 0x04, 0x03, 0x73, 0x2f, 0xd4, 0xbe, 0xef, 0x49, 0x3b, 0x94, 0x04, 0x00, 0x86, 0x4f,
// 0x0026 VALUE 4F860004-943B-49EF-BED4-2F730304427A WRITE | INDICATE | DYNAMIC
0x16, 0x00, 0x28, 0x03, 0x26, 0x00, 0x7a, 0x42, 0x04, 0x03, 0x73, 0x2f, 0xd4, 0xbe, 0xef, 0x49, 0x3b, 0x94, 0x04, 0x00, 0x86, 0x4f,
// 0x0027 CLIENT_CHARACTERISTIC_CONFIGURATION
0x0a, 0x00, 0x0a, 0x01, 0x27, 0x00, 0x02, 0x29, 0x00, 0x00,
/* CHARACTERISTIC, 4F860005-943B-49EF-BED4-2F730304427A, WRITE | INDICATE | DYNAMIC, */
// 0x0028 CHARACTERISTIC 4F860005-943B-49EF-BED4-2F730304427A WRITE | INDICATE | DYNAMIC
0x1b, 0x00, 0x02, 0x00, 0x28, 0x00, 0x03, 0x28, 0x28, 0x29, 0x00, 0x7a, 0x42, 0x04, 0x03, 0x73, 0x2f, 0xd4, 0xbe, 0xef, 0x49, 0x3b, 0x94, 0x05, 0x00, 0x86, 0x4f,
// 0x0029 VALUE 4F860005-943B-49EF-BED4-2F730304427A WRITE | INDICATE | DYNAMIC
0x16, 0x00, 0x28, 0x03, 0x29, 0x00, 0x7a, 0x42, 0x04, 0x03, 0x73, 0x2f, 0xd4, 0xbe, 0xef, 0x49, 0x3b, 0x94, 0x05, 0x00, 0x86, 0x4f,
// 0x002a CLIENT_CHARACTERISTIC_CONFIGURATION
0x0a, 0x00, 0x0a, 0x01, 0x2a, 0x00, 0x02, 0x29, 0x00, 0x00,
//////////////////////////////////////////////////////
//
// 0x002b PRIMARY_SERVICE FD43
//
//////////////////////////////////////////////////////
0x0a, 0x00, 0x02, 0x00, 0x2b, 0x00, 0x00, 0x28, 0x43, 0xfd,
/* CHARACTERISTIC, 94110001-6D9B-4225-A4F1-6A4A7F01B0DE, WRITE | INDICATE | DYNAMIC, */
// 0x002c CHARACTERISTIC 94110001-6D9B-4225-A4F1-6A4A7F01B0DE WRITE | INDICATE | DYNAMIC
0x1b, 0x00, 0x02, 0x00, 0x2c, 0x00, 0x03, 0x28, 0x28, 0x2d, 0x00, 0xde, 0xb0, 0x01, 0x7f, 0x4a, 0x6a, 0xf1, 0xa4, 0x25, 0x42, 0x9b, 0x6d, 0x01, 0x00, 0x11, 0x94,
// 0x002d VALUE 94110001-6D9B-4225-A4F1-6A4A7F01B0DE WRITE | INDICATE | DYNAMIC
0x16, 0x00, 0x28, 0x03, 0x2d, 0x00, 0xde, 0xb0, 0x01, 0x7f, 0x4a, 0x6a, 0xf1, 0xa4, 0x25, 0x42, 0x9b, 0x6d, 0x01, 0x00, 0x11, 0x94,
// 0x002e CLIENT_CHARACTERISTIC_CONFIGURATION
0x0a, 0x00, 0x0a, 0x01, 0x2e, 0x00, 0x02, 0x29, 0x00, 0x00,
// END
0x00, 0x00,
};
//
// characteristics <--> handles
//
#define ATT_CHARACTERISTIC_2a00_01_VALUE_HANDLE 0x0003
#define ATT_CHARACTERISTIC_2a07_01_VALUE_HANDLE 0x0007
#define ATT_CHARACTERISTIC_6AA50001_6352_4D57_A7B4_003A416FBB0B_01_VALUE_HANDLE 0x000a
#define ATT_CHARACTERISTIC_6AA50002_6352_4D57_A7B4_003A416FBB0B_01_VALUE_HANDLE 0x000c
#define ATT_CHARACTERISTIC_6AA50003_6352_4D57_A7B4_003A416FBB0B_01_VALUE_HANDLE 0x000e
#define ATT_CHARACTERISTIC_6AA50005_6352_4D57_A7B4_003A416FBB0B_01_VALUE_HANDLE 0x0010
#define ATT_CHARACTERISTIC_6AA50006_6352_4D57_A7B4_003A416FBB0B_01_VALUE_HANDLE 0x0012
#define ATT_CHARACTERISTIC_6AA50007_6352_4D57_A7B4_003A416FBB0B_01_VALUE_HANDLE 0x0014
#define ATT_CHARACTERISTIC_6AA50008_6352_4D57_A7B4_003A416FBB0B_01_VALUE_HANDLE 0x0016
#define ATT_CHARACTERISTIC_6AA50009_6352_4D57_A7B4_003A416FBB0B_01_VALUE_HANDLE 0x0018
#define ATT_CHARACTERISTIC_6AA5000A_6352_4D57_A7B4_003A416FBB0B_01_VALUE_HANDLE 0x001a
#define ATT_CHARACTERISTIC_4F860001_943B_49EF_BED4_2F730304427A_01_VALUE_HANDLE 0x001d
#define ATT_CHARACTERISTIC_4F860001_943B_49EF_BED4_2F730304427A_01_CLIENT_CONFIGURATION_HANDLE 0x001e
#define ATT_CHARACTERISTIC_4F860002_943B_49EF_BED4_2F730304427A_01_VALUE_HANDLE 0x0020
#define ATT_CHARACTERISTIC_4F860002_943B_49EF_BED4_2F730304427A_01_CLIENT_CONFIGURATION_HANDLE 0x0021
#define ATT_CHARACTERISTIC_4F860003_943B_49EF_BED4_2F730304427A_01_VALUE_HANDLE 0x0023
#define ATT_CHARACTERISTIC_4F860003_943B_49EF_BED4_2F730304427A_01_CLIENT_CONFIGURATION_HANDLE 0x0024
#define ATT_CHARACTERISTIC_4F860004_943B_49EF_BED4_2F730304427A_01_VALUE_HANDLE 0x0026
#define ATT_CHARACTERISTIC_4F860004_943B_49EF_BED4_2F730304427A_01_CLIENT_CONFIGURATION_HANDLE 0x0027
#define ATT_CHARACTERISTIC_4F860005_943B_49EF_BED4_2F730304427A_01_VALUE_HANDLE 0x0029
#define ATT_CHARACTERISTIC_4F860005_943B_49EF_BED4_2F730304427A_01_CLIENT_CONFIGURATION_HANDLE 0x002a
#define ATT_CHARACTERISTIC_94110001_6D9B_4225_A4F1_6A4A7F01B0DE_01_VALUE_HANDLE 0x002d
#define ATT_CHARACTERISTIC_94110001_6D9B_4225_A4F1_6A4A7F01B0DE_01_CLIENT_CONFIGURATION_HANDLE 0x002e
//整理服务UUID的范围
#define UNPAIR_CONTROL_START_HANDLE (ATT_CHARACTERISTIC_4F860001_943B_49EF_BED4_2F730304427A_01_VALUE_HANDLE - 1)
#define UNPAIR_CONTROL_END_HANDLE (ATT_CHARACTERISTIC_4F860001_943B_49EF_BED4_2F730304427A_01_CLIENT_CONFIGURATION_HANDLE)
#define CFG_CONTROL_START_HANDLE (ATT_CHARACTERISTIC_4F860002_943B_49EF_BED4_2F730304427A_01_VALUE_HANDLE - 1)
#define CFG_CONTROL_END_HANDLE (ATT_CHARACTERISTIC_4F860002_943B_49EF_BED4_2F730304427A_01_CLIENT_CONFIGURATION_HANDLE)
#define NON_OWNER_CONTROL_START_HANDLE (ATT_CHARACTERISTIC_4F860003_943B_49EF_BED4_2F730304427A_01_VALUE_HANDLE - 1)
#define NON_OWNER_CONTROL_END_HANDLE (ATT_CHARACTERISTIC_4F860003_943B_49EF_BED4_2F730304427A_01_CLIENT_CONFIGURATION_HANDLE)
#define PAIRED_OWNER_INFO_START_HANDLE (ATT_CHARACTERISTIC_4F860004_943B_49EF_BED4_2F730304427A_01_VALUE_HANDLE - 1)
#define PAIRED_OWNER_INFO_END_HANDLE (ATT_CHARACTERISTIC_4F860004_943B_49EF_BED4_2F730304427A_01_CLIENT_CONFIGURATION_HANDLE)
#define DEBUG_CONTROL_START_HANDLE (ATT_CHARACTERISTIC_4F860005_943B_49EF_BED4_2F730304427A_01_VALUE_HANDLE - 1)
#define DEBUG_CONTROL_END_HANDLE (ATT_CHARACTERISTIC_4F860005_943B_49EF_BED4_2F730304427A_01_CLIENT_CONFIGURATION_HANDLE)
#define FW_UPDATE_START_HANDLE (ATT_CHARACTERISTIC_94110001_6D9B_4225_A4F1_6A4A7F01B0DE_01_VALUE_HANDLE - 2)
#define FW_UPDATE_END_HANDLE (ATT_CHARACTERISTIC_94110001_6D9B_4225_A4F1_6A4A7F01B0DE_01_CLIENT_CONFIGURATION_HANDLE)
#endif