commponent bt:add the wechat airsync profile to the project

1. add the wx_airsync_prf.h which have been define the sturcter data has been
used for the wechat airsync profile database
2. add the wx_airsync_prf.c file
3. add the app_airsync_md5.c file
4. add the app_airsync_prf.c
5. add epb.c file
6. add epb_mmbp.c
7. add mpbledemo2.c
8. add wechar_crc.c
9  add wechat_aes.c
10. add app_airsync_md5.h
11. add app_airsync_prf.h
12. add app_wechat_util.h
13. add epb.h
14. add epb_mmbp.h
15 add mpbledemo2.h
16 add wechar_crc.h
17 add wechat_aes.h
This commit is contained in:
yulong 2016-10-11 05:43:36 -04:00
parent bde768f13c
commit 849ba39544
30 changed files with 3653 additions and 37 deletions

View file

@ -26,9 +26,13 @@
#include "bta_api.h"
#include "bta_gatt_api.h"
#include "bta_gatts_int.h"
#include "button_pro.h"
#include "prf_defs.h"
#if (BUT_PROFILE_CFG)
#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
tBUTTON_CB_ENV button_cb_env;
@ -54,7 +58,10 @@ static void button_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
{
tBTA_GATTS_RSP rsp;
tBT_UUID uuid = {LEN_UUID_16, {ATT_SVC_BUTTON}};
tBUT_INST *p_inst = &button_cb_env.button_inst;
UINT8 net_event = 0xff;
UINT8 len = 0;
UINT8 *p_rec_data = NULL;
//LOG_ERROR("p_data->status = %x\n",p_data->status);
//if(p_data->status != BTA_GATT_OK){
// LOG_ERROR("button profile register failed\n");
@ -91,6 +98,32 @@ static void button_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
case BTA_GATTS_WRITE_EVT:
BTA_GATTS_SendRsp(p_data->req_data.conn_id,p_data->req_data.trans_id,
p_data->req_data.status,NULL);
LOG_ERROR("Received button data:");
for(int i = 0; i < p_data->req_data.p_data->write_req.len; i++){
LOG_ERROR("%x",p_data->req_data.p_data->write_req.value[i]);
}
LOG_ERROR("\n");
if(p_data->req_data.p_data->write_req.handle == button_cb_env.button_inst.but_wirt_hdl){
if(p_data->req_data.p_data->write_req.value[0] == 0xFF){
net_event = RECEIVE_NET_PASSWD_EVT;
len = p_data->req_data.p_data->write_req.len - 1;
p_rec_data = &p_data->req_data.p_data->write_req.value[1];
LOG_ERROR("RECEIVE_NET_PASSWD_EVT\n");
}else if(p_data->req_data.p_data->write_req.value[0] == 0xEE){
net_event = RECEIVE_NET_SSD_EVT;
len = p_data->req_data.p_data->write_req.len - 1;
p_rec_data = &p_data->req_data.p_data->write_req.value[1];
LOG_ERROR("RECEIVE_NET_SSD_EVT\n");
}else{
net_event = 0xff;
len = p_data->req_data.p_data->write_req.len;
p_rec_data = p_data->req_data.p_data->write_req.value;
}
// button_msg_notify(len,p_rec_data);
(*p_inst->p_cback)(button_cb_env.button_inst.app_id,net_event,len,p_rec_data);
}
break;
case BTA_GATTS_CONF_EVT:
@ -285,9 +318,10 @@ BOOLEAN button_env_clcb_dealloc(UINT16 conn_id)
** Description Initializa the GATT Service for button profiles.
**
*******************************************************************************/
tGATT_STATUS button_init (void)
tGATT_STATUS button_init (tBU_CBACK *call_back)
{
tBT_UUID app_uuid = {LEN_UUID_16,{ATT_SVC_BUTTON}};
if(button_cb_env.enabled)
{
@ -299,6 +333,12 @@ tGATT_STATUS button_init (void)
memset(&button_cb_env,0,sizeof(tBUTTON_CB_ENV));
}
if(call_back != NULL)
{
button_cb_env.button_inst.p_cback = call_back;
}
/* register the button profile to the BTA_GATTS module*/
BTA_GATTS_AppRegister(&app_uuid,button_profile_cb);
@ -324,3 +364,5 @@ void button_msg_notify(UINT8 len, UINT8 *button_msg)
BTA_GATTS_HandleValueIndication (conn_id, attr_id, len,
button_msg, rsp);
}
#endif ///BUT_PROFILE_CFG

View file

@ -11,7 +11,9 @@
*
****************************************************************************************
*/
#include "prf_defs.h"
#if (BUT_PROFILE_CFG)
#include "bt_target.h"
#include "gatt_api.h"
#include "gattdefs.h"
@ -34,11 +36,18 @@
#define BUT_MAX_STRING_DATA 7
typedef void (tBU_CBACK)(UINT8 app_id, UINT8 event, UINT8 len, UINT8 *data);
#ifndef BUT_MAX_INT_NUM
#define BUT_MAX_INT_NUM 4
#endif
enum
{
RECEIVE_NET_PASSWD_EVT,
RECEIVE_NET_SSD_EVT,
RECEIVE_EVT_MAX
};
/// button Service Attributes Indexes
enum
@ -79,6 +88,8 @@ typedef struct
UINT16 but_wirt_hdl;
UINT16 but_ntf_hdl;
UINT16 but_cfg_hdl;
tBU_CBACK *p_cback;
}tBUT_INST;
@ -102,9 +113,10 @@ UINT16 button_env_find_conn_id_by_bd_adddr(BD_ADDR bda);
BOOLEAN button_env_clcb_dealloc(UINT16 conn_id);
tGATT_STATUS button_init(void);
tGATT_STATUS button_init(tBU_CBACK *call_back);
void button_msg_notify(UINT8 len, UINT8 *button_msg);
extern tBUTTON_CB_ENV button_cb_env;
#endif ///BUT_PROFILE_CFG

View file

@ -0,0 +1,115 @@
/**
****************************************************************************************
*
* @file wx_airsync_prf.h
*
* @brief Application entry point
*
* Copyright (C) Espressif 2016
* Created by Yulong at 2016/9/29
*
*
****************************************************************************************
*/
#include "prf_defs.h"
#if (WX_AIRSYNC_CFG)
#include "bt_target.h"
#include "gatt_api.h"
#include "gattdefs.h"
/// Maximum Transmission Unit
#define ATT_DEFAULT_MTU (23)
#define BLE_WECHAT_MAX_DATA_LEN (ATT_DEFAULT_MTU - 3)
//define the key serivce uuid
#define ATT_SVC_AIRSYNC 0xFEE7
//define the airsync Char uuid
#define ATT_CHAR_AIRSYNC_WIT 0xFEC7
#define ATT_CHAR_AIRSYBC_NTF 0xFEC8
#define ATT_CHAR_AIRSYNC_READ 0xFEC9
typedef void (tAIRSYNC_CBACK)(UINT8 app_id, UINT8 event, UINT8 len, UINT8 *data);
/// WX AirSync Service Attributes Indexes
enum
{
WX_IDX_SVC,
WX_IDX_AIRSYNC_WIT_CHAR,
WX_IDX_AIRSYNC_WIT_VAL,
WX_IDX_AIRSYNC_NTF_CHAR,
WX_IDX_AIRSYNC_NTF_VAL,
WX_IDX_AIRSYNC_READ_CHAR,
WX_IDX_AIRSYNC_READ_VAL,
WX_IDX_AIRSYNC_NTF_CFG,
KEY_IDX_NB,
};
typedef struct
{
BD_ADDR remote_bda;
BOOLEAN need_rsp;
UINT16 clt_cfg;
}tAirSync_WRITE_DATA;
typedef struct
{
BOOLEAN in_use;
BOOLEAN congest;
UINT16 conn_id;
BOOLEAN connected;
BD_ADDR remote_bda;
UINT32 trans_id;
UINT8 cur_srvc_id;
}tAirSync_CLCB;
typedef struct
{
UINT8 app_id;
UINT16 airsync_wirt_hdl;
UINT16 airsync_ntf_hdl;
UINT16 airsync_read_hdl;
UINT16 airsync_cfg_hdl;
tAIRSYNC_CBACK *p_cback;
}tAirSync_INST;
/* service engine control block */
typedef struct
{
tAirSync_CLCB clcb; /* connection link*/
tGATT_IF gatt_if;
BOOLEAN enabled;
BOOLEAN is_primery;
tAirSync_INST airsync_inst;
UINT8 inst_id;
}tAIRSYNC_CB_ENV;
void AirSync_CreateService(void);
tAirSync_CLCB *airsync_env_clcb_alloc (UINT16 conn_id, BD_ADDR remote_bda);
UINT16 AirSync_env_find_conn_id_by_bd_adddr(BD_ADDR bda);
BOOLEAN AirSync_env_clcb_dealloc(UINT16 conn_id);
tGATT_STATUS AirSync_Init(tAIRSYNC_CBACK *call_back);
void AirSync_msg_notify(UINT8 len, UINT8 *button_msg);
extern tAIRSYNC_CB_ENV airsync_cb_env;
#endif ///WX_AIRSYNC_CFG

View file

@ -0,0 +1,286 @@
/**
****************************************************************************************
*
* @file wx_airsync_prf.c
*
* @brief Application entry point
*
* Copyright (C) Espressif 2016
* Created by Yulong at 2016/9/29
*
*
****************************************************************************************
*/
#include "wx_airsync_prf.h"
#if (WX_AIRSYNC_CFG)
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <stdio.h>
#include "bt_target.h"
#include "bt_trace.h"
#include "bt_types.h"
#include "gatt_api.h"
#include "bta_api.h"
#include "bta_gatt_api.h"
#include "bta_gatts_int.h"
tAIRSYNC_CB_ENV airsync_cb_env;
/*****************************************************************************
** Constants
*****************************************************************************/
static void airsync_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data);
/*******************************************************************************
**
** Function airsync_profile_cb
**
** Description the callback function after the profile has been register to the BTA manager module
**
** Returns NULL
**
*******************************************************************************/
static void airsync_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
{
tBTA_GATTS_RSP rsp;
tBT_UUID uuid = {LEN_UUID_16, {ATT_SVC_AIRSYNC}};
tAirSync_INST *p_inst = &airsync_cb_env.airsync_inst;
LOG_ERROR("airsync profile cb event = %x\n",event);
switch(event)
{
case BTA_GATTS_REG_EVT:
if(p_data->reg_oper.status != BTA_GATT_OK)
{
LOG_ERROR("button profile register failed\n");
}
airsync_cb_env.gatt_if = p_data->reg_oper.server_if;
airsync_cb_env.enabled = true;
if(p_data->reg_oper.uuid.uu.uuid16 == ATT_SVC_AIRSYNC)
{
AirSync_CreateService();
}
break;
case BTA_GATTS_READ_EVT:
if(airsync_cb_env.clcb.connected && airsync_cb_env.enabled){
//tBTA_GATTS_RSP rsp;
memset(&rsp,0,sizeof(tBTA_GATTS_API_RSP));
rsp.attr_value.handle = p_data->req_data.p_data->read_req.handle;
rsp.attr_value.len = 2;
BTA_GATTS_SendRsp(p_data->req_data.conn_id,p_data->req_data.trans_id,
p_data->req_data.status,&rsp);
}
break;
case BTA_GATTS_WRITE_EVT:
if(airsync_cb_env.clcb.connected && airsync_cb_env.enabled){
BTA_GATTS_SendRsp(p_data->req_data.conn_id,p_data->req_data.trans_id,
p_data->req_data.status,NULL);
}
break;
case BTA_GATTS_CONF_EVT:
break;
case BTA_GATTS_CREATE_EVT:
uuid.uu.uuid16 = ATT_CHAR_AIRSYNC_WIT;
airsync_cb_env.clcb.cur_srvc_id= p_data->create.service_id;
airsync_cb_env.is_primery = p_data->create.is_primary;
//start the airsync service after created
BTA_GATTS_StartService(p_data->create.service_id,BTA_GATT_TRANSPORT_LE);
//add the frist airsync characteristic --> write characteristic
BTA_GATTS_AddCharacteristic(airsync_cb_env.clcb.cur_srvc_id,&uuid,
(GATT_PERM_WRITE|GATT_PERM_READ),
(GATT_CHAR_PROP_BIT_READ|GATT_CHAR_PROP_BIT_WRITE));
break;
case BTA_GATTS_ADD_CHAR_EVT:
if(p_data->add_result.char_uuid.uu.uuid16 == ATT_CHAR_AIRSYNC_WIT)
{
uuid.uu.uuid16 = ATT_CHAR_AIRSYBC_NTF;
//tBTA_GATT_PERM perm = GATT_PERM_READ;
//tBTA_GATT_CHAR_PROP prop = (GATT_CHAR_PROP_BIT_READ|GATT_CHAR_PROP_BIT_NOTIFY);
//save the att handle to the env
airsync_cb_env.airsync_inst.airsync_wirt_hdl = p_data->add_result.attr_id;
//add the second airsync characteristic --> Notify characteristic
BTA_GATTS_AddCharacteristic(airsync_cb_env.clcb.cur_srvc_id,&uuid,
GATT_PERM_READ,(GATT_CHAR_PROP_BIT_READ|GATT_CHAR_PROP_BIT_INDICATE));
}else if(p_data->add_result.char_uuid.uu.uuid16 == ATT_CHAR_AIRSYBC_NTF){
//tBTA_GATT_PERM perm = (GATT_PERM_WRITE|GATT_PERM_WRITE);
uuid.uu.uuid16 = GATT_UUID_CHAR_CLIENT_CONFIG;
airsync_cb_env.airsync_inst.airsync_ntf_hdl = p_data->add_result.attr_id;
BTA_GATTS_AddCharDescriptor (airsync_cb_env.clcb.cur_srvc_id,
(GATT_PERM_WRITE|GATT_PERM_WRITE),
&uuid);
uuid.uu.uuid16 = ATT_CHAR_AIRSYNC_READ;
//add the third airsync characteristic --> Read characteristic
BTA_GATTS_AddCharacteristic(airsync_cb_env.clcb.cur_srvc_id,&uuid,
GATT_PERM_READ,
GATT_CHAR_PROP_BIT_READ);
}else if(p_data->add_result.char_uuid.uu.uuid16 == ATT_CHAR_AIRSYNC_READ){
airsync_cb_env.airsync_inst.airsync_read_hdl = p_data->add_result.attr_id;
}
break;
case BTA_GATTS_ADD_CHAR_DESCR_EVT:
if(p_data->add_result.char_uuid.uu.uuid16 == GATT_UUID_CHAR_CLIENT_CONFIG)
{
airsync_cb_env.airsync_inst.airsync_cfg_hdl = p_data->add_result.attr_id;
}
break;
case BTA_GATTS_CONNECT_EVT:
//set the connection flag to true
airsync_env_clcb_alloc(p_data->conn.conn_id, p_data->conn.remote_bda);
break;
case BTA_GATTS_DISCONNECT_EVT:
//set the connection flag to true
airsync_cb_env.clcb.connected = false;
break;
case BTA_GATTS_OPEN_EVT:
break;
case BTA_GATTS_CLOSE_EVT:
if(airsync_cb_env.clcb.connected && (airsync_cb_env.clcb.conn_id == p_data->conn.conn_id))
{
//set the connection channal congested flag to true
airsync_cb_env.clcb.congest = p_data->congest.congested;
}
break;
case BTA_GATTS_LISTEN_EVT:
break;
case BTA_GATTS_CONGEST_EVT:
//set the congest flag
airsync_cb_env.clcb.congest = p_data->congest.congested;
break;
default:
break;
}
}
/*******************************************************************************
**
** Function AirSync_CreateService
**
** Description Create a Service for the airsync profile
**
** Returns NULL
**
*******************************************************************************/
void AirSync_CreateService(void)
{
tBTA_GATTS_IF server_if ;
tBT_UUID uuid = {LEN_UUID_16, {ATT_SVC_AIRSYNC}};
UINT16 num_handle = KEY_IDX_NB;
UINT8 inst = 0x00;
server_if = airsync_cb_env.gatt_if;
airsync_cb_env.inst_id = inst;
BTA_GATTS_CreateService(server_if,&uuid,inst,num_handle,true);
}
/*******************************************************************************
**
** Function airsync_env_clcb_alloc
**
** Description The function allocates a GATT profile connection link control block
**
** Returns NULL if not found. Otherwise pointer to the connection link block.
**
*******************************************************************************/
tAirSync_CLCB *airsync_env_clcb_alloc (UINT16 conn_id, BD_ADDR remote_bda)
{
tAirSync_CLCB *p_clcb = NULL;
p_clcb = &airsync_cb_env.clcb;
if(!p_clcb->in_use)
{
p_clcb->in_use = TRUE;
p_clcb->conn_id = conn_id;
LOG_ERROR("p_clcb->conn_id = %x\n",conn_id);
p_clcb->connected = TRUE;
memcpy(p_clcb->remote_bda,remote_bda,BD_ADDR_LEN);
}
return p_clcb;
}
/*******************************************************************************
**
** Function airsync_env_find_conn_id_by_bd_adddr
**
** Description The function searches all LCB with macthing bd address
**
** Returns total number of clcb found.
**
*******************************************************************************/
UINT16 airsync_env_find_conn_id_by_bd_adddr(BD_ADDR remote_bda)
{
UINT8 i_clcb;
tAirSync_CLCB *p_clcb = NULL;
for(i_clcb = 0, p_clcb = &airsync_cb_env.clcb; i_clcb < 1; i_clcb++, p_clcb++)
{
if(p_clcb->in_use && p_clcb->connected &&memcmp(p_clcb->remote_bda,remote_bda,BD_ADDR_LEN))
{
return p_clcb->conn_id;
}
}
return GATT_INVALID_CONN_ID;
}
/*******************************************************************************
**
** Function airsync_init
**
** Description Initializa the GATT Service for airsync profiles.
**
*******************************************************************************/
tGATT_STATUS AirSync_Init(tAIRSYNC_CBACK *call_back)
{
tBT_UUID app_uuid = {LEN_UUID_16,{ATT_SVC_AIRSYNC}};
if(airsync_cb_env.enabled)
{
LOG_ERROR("airsync svc already initaliezd\n");
return GATT_ERROR;
}
else
{
memset(&airsync_cb_env,0,sizeof(tAIRSYNC_CB_ENV));
}
if(call_back != NULL)
{
airsync_cb_env.airsync_inst.p_cback = call_back;
}
/* register the airsync profile to the BTA_GATTS module*/
BTA_GATTS_AppRegister(&app_uuid,airsync_profile_cb);
airsync_cb_env.enabled = TRUE;
return GATT_SUCCESS;
}
#endif ///WX_AIRSYNC_CFG

View file

@ -13,9 +13,9 @@
*/
#include <string.h>
#include "hid_le_prf.h"
#include "prf_defs.h"
#include "bta_gatt_api.h"
#if (HIDD_LE_PROFILE_CFG)
tHIDD_LE_ENV hidd_le_env;
tBT_UUID char_info_uuid = {LEN_UUID_16, {CHAR_HID_INFO_UUID}};
@ -26,8 +26,6 @@ tBT_UUID char_kb_in_report_uuid = {LEN_UUID_16, {CHAR_BOOT_KB_IN_REPORT_UUID}};
tBT_UUID char_kb_out_report_uuid = {LEN_UUID_16,{CHAR_BOOT_KB_OUT_REPORT_UUID}};
tBT_UUID char_mouse_in_report_uuid = {LEN_UUID_16,{CHAR_BOOT_MOUSE_IN_REPORT_UUID}};
/// Full HID device Database Description - Used to add attributes into the database
const tCHAR_DESC hids_char_db[HIDD_LE_CHAR_MAX] =
{
@ -296,5 +294,6 @@ tGATT_STATUS hidd_le_init (void)
}
#endif ///HIDD_LE_PROFILE_CFG

View file

@ -12,12 +12,15 @@
****************************************************************************************
*/
#include "prf_defs.h"
#if (HIDD_LE_PROFILE_CFG)
#include "bta_gatts_int.h"
#include "bta_api.h"
#include "gatt_api.h"
/// Maximal number of HIDS that can be added in the DB
#ifndef USE_ONE_HIDS_INSTANCE
#define HIDD_LE_NB_HIDS_INST_MAX (2)
@ -214,5 +217,7 @@ enum
tGATT_STATUS hidd_le_init (void);
#endif ///HIDD_LE_PROFILE_CFG

View file

@ -11,6 +11,8 @@
*
****************************************************************************************
*/
#ifndef PRF_DEFS_H_
#define PRF_DEFS_H_
#include "bta_api.h"
#include "bta_gattc_int.h"
@ -24,6 +26,9 @@
#define ATT_UUID_128_LEN 0x0010
#define ATT_UUID_32_LEN 0x0004
#define WX_AIRSYNC_CFG 1
#define BUT_PROFILE_CFG 0
#define HIDD_LE_PROFILE_CFG 0
/*
* Type Definition
@ -626,5 +631,5 @@ enum {
};
#endif ///PRF_DEFS_H_

View file

@ -88,11 +88,11 @@ tBTM_STATUS BTM_BleGetEnergyInfo(tBTM_BLE_ENERGY_INFO_CBACK *p_ener_cback)
BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
BTM_TRACE_EVENT("BTM_BleGetEnergyInfo");
BTM_TRACE_EVENT("BTM_BleGetEnergyInfo\n");
if (0 == cmn_ble_vsc_cb.energy_support)
{
BTM_TRACE_ERROR("Controller does not support get energy info");
BTM_TRACE_ERROR("Controller does not support get energy info\n");
return BTM_ERR_PROCESSING;
}

@ -1 +1 @@
Subproject commit bcbc35215c6d87279da4b87a74d3360c537d6724
Subproject commit 6c9a6de656262113a0aab63907d6871a64e00fae

@ -1 +1 @@
Subproject commit a1e5f8b953c7934677ba7a6ed0a6dd2da0e6bd0f
Subproject commit f6d558367a08b6c9b18c2de515bd0a6740d2c45c

@ -1 +1 @@
Subproject commit 197ba605fe0c05e16bf4c5ec07b726adc8d86abc
Subproject commit 7c84dd433512bac80e4c01c569e42b4fe76646a7

View file

@ -14,12 +14,14 @@
#include "bt_app_common.h"
#include "controller.h"
//#include "prf_defs.h"
#include "hash_map.h"
#include "hash_functions.h"
#include "alarm.h"
#include "app_button.h"
//#include "app_button.h"
#if (BUT_PROFILE_CFG)
#include "button_pro.h"
#endif ///BUT_PROFILE_CFG
#include "thread.h"
#include "bt_app_common.h"
#include "dis_api.h"
@ -64,12 +66,17 @@ static void bt_app_task_handler(void *arg)
if (e->sig == 0xff) {
fixed_queue_process(bta_app_msg_queue);
fixed_queue_process(bt_app_general_alarm_queue);
}else if(e->sig == BUTTON_PRESS_EVT){
LOG_ERROR("button_press_event come in,button_value=%x\n",e->par);
button_msg[1] = e->par;
button_msg_notify(2,button_msg);
}
osi_free(e);
#if (BUT_PROFILE_CFG)
else if(e->sig == BUTTON_PRESS_EVT){
LOG_ERROR("button_press_event come in,button_value=%x\n",e->par);
button_msg[1] = e->par;
button_msg_notify(2,button_msg);
}
#endif ///BUT_PROFILE_CFG
}
}
}
@ -187,7 +194,7 @@ void bt_app_task_start_up(void)
return;
error_exit:
LOG_ERROR("%s Unable to allocate resources for bt_app", __func__);
LOG_ERROR("%s Unable to allocate resources for bt_app\n", __func__);
bt_app_task_shut_down();
}
@ -320,7 +327,7 @@ void bt_app_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_sec)
alarm = hash_map_get(bt_app_general_alarm_hash_map, p_tle);
pthread_mutex_unlock(&bt_app_general_alarm_lock);
if (alarm == NULL) {
LOG_ERROR("%s Unable to create alarm", __func__);
LOG_ERROR("%s Unable to create alarm\n", __func__);
return;
}
@ -364,6 +371,10 @@ static void bt_app_general_alarm_process(TIMER_LIST_ENT *p_tle)
// bt_test_start_inquiry();
/*set connectable,discoverable, pairable and paired only modes of local device*/
tBTA_DM_DISC disc_mode = BTA_DM_BLE_GENERAL_DISCOVERABLE;
tBTA_DM_CONN conn_mode = BTA_DM_BLE_CONNECTABLE;
//BTA_DmSetVisibility(disc_mode, conn_mode, (UINT8)BTA_DM_NON_PAIRABLE, (UINT8)BTA_DM_CONN_ALL);
gatts_server_test();
//gattc_client_test();

View file

@ -0,0 +1,124 @@
/**
****************************************************************************************
*
* @file app_airsync_md5.h
*
* @brief Application airsync md5 generation Entry Point
*
* Copyright (C) ESPRESSIF 2016
* Created by Yulong at 2016/10/9
*
****************************************************************************************
*/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "gki.h"
#include "app_airsync_md5.h"
const uint32_t X[4][2] = {{0, 1}, {1, 5}, {5, 3}, {0, 7}};
const uint32_t S[4][4] = {{ 7, 12, 17, 22 },{ 5, 9 , 14, 20 },{ 4, 11, 16, 23 },{ 6, 10, 15, 21 }};
uint32_t F( uint32_t X, uint32_t Y, uint32_t Z )
{
return ( X & Y ) | ( ~X & Z );
}
uint32_t G( uint32_t X, uint32_t Y, uint32_t Z )
{
return ( X & Z ) | ( Y & ~Z );
}
uint32_t H( uint32_t X, uint32_t Y, uint32_t Z )
{
return X ^ Y ^ Z;
}
uint32_t I( uint32_t X, uint32_t Y, uint32_t Z )
{
return Y ^ ( X | ~Z );
}
// rotates x left s bits.
uint32_t rotate_left( uint32_t x, uint32_t s )
{
return ( x << s ) | ( x >> ( 32 - s ) );
}
// Pre-processin
uint32_t count_padding_bits ( uint32_t length )
{
// uint32_t div = length * BITS / BLOCK_SIZE;
uint32_t mod = length * BITS % BLOCK_SIZE;
uint32_t c_bits;
if ( mod == 0 )
{
c_bits = MOD_SIZE;
}
else
{
c_bits = ( MOD_SIZE + BLOCK_SIZE - mod ) % BLOCK_SIZE;
}
return c_bits / BITS;
}
MD5String append_padding_bits ( char * argv )
{
uint32_t msg_length = strlen ( argv );
uint32_t bit_length = count_padding_bits ( msg_length );
uint64_t app_length = msg_length * BITS;
MD5String string;
string.str = (char *)GKI_getbuf(msg_length + bit_length + APP_SIZE / BITS);
strncpy ( string.str, argv, msg_length );
memset ( string.str + msg_length, 0, bit_length );
string.str [ msg_length ] = SINGLE_ONE_BIT;
memmove ( string.str + msg_length + bit_length, (char *)&app_length, sizeof( uint64_t ) );
string.len = msg_length + bit_length + sizeof( uint64_t );
return string;
}
int32_t wechat_md5 (char *argv, uint8_t *md5_32)
{
MD5String string;
uint32_t w[16];
uint32_t chain[4];
uint32_t state[4];
uint32_t ( *auxi[ 4 ])( uint32_t, uint32_t, uint32_t ) = { F, G, H, I };
int sIdx;
int wIdx;
string = append_padding_bits ( argv );
chain[0] = A;
chain[1] = B;
chain[2] = C;
chain[3] = D;
for (uint32_t j = 0; j < string.len; j += BLOCK_SIZE / BITS)
{
memmove ( (char *)w, string.str + j, BLOCK_SIZE / BITS );
memmove ( state, chain, sizeof(chain) );
for ( uint8_t roundIdx = 0; roundIdx < 4; roundIdx++ )
{
wIdx = X[ roundIdx ][ 0 ];
sIdx = 0;
for (uint8_t i = 0; i < 16; i++ )
{
state[sIdx] = state [(sIdx + 1)%4] + rotate_left( state[sIdx] +(*auxi[ roundIdx])( state[(sIdx+1) % 4],
state[(sIdx+2) % 4],
state[(sIdx+3) % 4]) + w[ wIdx ] + (uint32_t)floor((1ULL << 32) * fabs(sin( roundIdx * 16 + i + 1 )) ),
S[ roundIdx ][ i % 4 ]);
sIdx = ( sIdx + 3 ) % 4;
wIdx = ( wIdx + X[ roundIdx ][ 1 ] ) & 0xF;
}
}
chain[ 0 ] += state[ 0 ];
chain[ 1 ] += state[ 1 ];
chain[ 2 ] += state[ 2 ];
chain[ 3 ] += state[ 3 ];
}
memmove ( md5_32 + 0, (char *)&chain[0], sizeof(uint32_t) );
memmove ( md5_32 + 4, (char *)&chain[1], sizeof(uint32_t) );
memmove ( md5_32 + 8, (char *)&chain[2], sizeof(uint32_t) );
memmove ( md5_32 + 12, (char *)&chain[3], sizeof(uint32_t) );
free(string.str);
string.str = NULL;
return EXIT_SUCCESS;
}

View file

@ -0,0 +1,154 @@
/**
****************************************************************************************
*
* @file app_airsync_prf.c
*
* @brief Application Security Entry Point
*
* Copyright (C) ESPRESSIF 2016
* Created by Yulong at 2016/9/30
*
****************************************************************************************
*/
#include "app_airsync_prf.h"
#include "wx_airsync_prf.h"
#include "app_wechat_util.h"
#include "gki.h"
#include "mpbledemo2.h"
/*****************************************************************************
* data handle
*****************************************************************************/
data_info g_send_data;
static data_info g_rcv_data;
data_handler *pDataHandler;
static void airsync_process_msgreceive_cb(UINT8 app_id,
UINT8 conn_id,uint8_t *pData, uint16_t length);
///function for register all products
static void register_all_products(void)
{
REGISTER(mpbledemo2);
// could register more products if defined
}
void app_wechat_init(void)
{
register_all_products();
data_handler_init(&m_mpbledemo2_handler,PRODUCT_TYPE_MPBLEDEMO2);
m_mpbledemo2_handler->m_data_init_func();
m_mpbledemo2_handler->m_data_init_peripheral_func();
app_wechat_SetDatahandler(m_mpbledemo2_handler);
}
int ble_wechat_indicate_data_chunk(void)
{
uint16_t chunk_len = 0;
chunk_len = g_send_data.len - g_send_data.offset;
chunk_len = chunk_len > BLE_WECHAT_MAX_DATA_LEN?BLE_WECHAT_MAX_DATA_LEN:chunk_len;
if(chunk_len == 0)
{
app_wechat_datahandler()->m_data_free_func(g_send_data.data,g_send_data.len);
g_send_data.data = NULL;
g_send_data.len = 0;
g_send_data.offset = 0;
return 0;
}
g_send_data.offset += chunk_len;
return 1;
}
/*******************************************************************************
**
** Function airsync_msgreceive_cb
**
** Description the callback function after the airsync profile have been
** receive the data from the peer device
** parms appid:the appid have been register to the gatt database
** conn_id:the current connection index
** msg_val:the airsync value receive from peer device
** Returns NULL
**
*******************************************************************************/
static void airsync_process_msgreceive_cb(UINT8 app_id,
UINT8 conn_id,uint8_t *pData, uint16_t length)
{
int error_code;
int chunk_size = 0;
if(length <= BLE_WECHAT_MAX_DATA_LEN)
{
if(g_rcv_data.len == 0)
{
BpFixHead *fix_head = (BpFixHead *)pData;
g_rcv_data.len = ntohs(fix_head->nLength);
g_rcv_data.offset = 0;
g_rcv_data.data = (uint8_t *)GKI_getbuf(g_rcv_data.len);
}
chunk_size = g_rcv_data.len - g_rcv_data.offset;
chunk_size = chunk_size < length ? chunk_size : length;
memcpy(g_rcv_data.data + g_rcv_data.offset, pData, chunk_size);
g_rcv_data.offset += chunk_size;
if (g_rcv_data.len <= g_rcv_data.offset)
{
error_code = app_wechat_datahandler()->m_data_consume_func(g_rcv_data.data, g_rcv_data.len);
app_wechat_datahandler()->m_data_free_func(g_rcv_data.data,g_rcv_data.len);
wechat_error_chack(app_wechat_datahandler(), error_code);
g_rcv_data.len = 0;
g_rcv_data.offset = 0;
app_wechat_datahandler()->m_data_main_process_func();
}
}
}
void app_wechat_SetDatahandler(data_handler* pHandler)
{
pDataHandler = pHandler;
}
bool ble_wechat_is_last_data_sent_out(void)
{
return (g_send_data.len == 0 && g_send_data.offset == 0 ) || \
(g_send_data.len != 0 && g_send_data.len == g_send_data.offset);
}
//device sent data on the indicate characteristic
int ble_wechat_indicate_data(uint8_t *data, int len)
{
if(data == NULL || len == 0)
{
return 0;
}
if(!ble_wechat_is_last_data_sent_out())
{
return 0;
}
g_send_data.data = data;
g_send_data.len = len;
g_send_data.offset = 0;
return (ble_wechat_indicate_data_chunk());
}
data_handler *app_wechat_datahandler(void)
{
return pDataHandler;
}

View file

@ -0,0 +1,408 @@
// epb.c
// WeChat Embedded Proto Buffer
//
// Created by harlliu@tencent.com on 14-02-15.
// Copyright 2014 Tencent. All rights reserved.
//
// Version : 1.0.2
#include <string.h>
#include "epb.h"
#define __LITTLE_ENDIAN__ 1 //Need Test
typedef enum {
WIRETYPE_VARINT = 0,
WIRETYPE_FIXED64 = 1,
WIRETYPE_LENGTH_DELIMITED = 2,
WIRETYPE_FIXED32 = 5
} WireType;
#define CONTINUOUS_MASK 0x80
#define WIRETYPE_MASK 0x07
static int epb_get_varint32_bits(const uint8_t *data, int len, uint32_t *value);
inline static int sizeof_tag(uint16_t tag)
{
return ((tag&0xff00) == 0) ? 1 : 2; //TODO:Tag more then two bytes
}
static uint16_t epb_get_wire_type(uint16_t tag) {
uint16_t wire_type = tag & WIRETYPE_MASK;
if ((tag>>8) != 0)
wire_type = (tag>>8) & WIRETYPE_MASK;
return wire_type;
}
static int epb_get_value_length(const uint8_t *data, int len, uint32_t wire_type)
{
int offset = 0;
switch(wire_type) {
case WIRETYPE_VARINT:
while ((data[offset++]&CONTINUOUS_MASK)!=0 && offset<len);
break;
case WIRETYPE_FIXED64:
offset += 8;
break;
case WIRETYPE_LENGTH_DELIMITED:
{
int32_t l = 0;
offset += epb_get_varint32_bits(data+offset, len-offset, (uint32_t *)&l);
offset += l;
}
break;
case WIRETYPE_FIXED32:
offset += 4;
break;
default:
return -1;
}
return offset;
}
static int epb_get_tag_value_offset(const uint8_t *data, int len, uint16_t tag)
{
int offset = 0;
uint32_t p_tag;
while (offset < len) {
p_tag = data[offset++];
while ((data[offset-1]&CONTINUOUS_MASK)!=0 && offset<len) {
p_tag = (p_tag<<8)|(data[offset++]&0x7f); //TODO:Tag more then two bytes
}
if (p_tag == tag)
return offset;
uint32_t wire_type = epb_get_wire_type(p_tag);
int ret = epb_get_value_length(data+offset, len-offset, wire_type);
if (ret < 0) {
offset++;
continue;
}
offset += ret;
}
return -1;
}
static int epb_get_varint32_bits(const uint8_t *data, int len, uint32_t *value)
{
int offset = 0;
uint32_t p_value = data[offset++] & 0x7F;
while ((data[offset-1]&CONTINUOUS_MASK) != 0) {
if (offset >= len)
return -1;
if (offset >= 5)
break;
p_value |= ((uint32_t)data[offset]&0x7F) << (offset*7);
++offset;
}
*value = p_value;
return offset;
}
static uint32_t epb_get_fixed32_bits(const uint8_t *data, int len)
{
if(len < 4)
return 0;
uint32_t value = 0;
#ifdef __LITTLE_ENDIAN__
memcpy(&value, data, sizeof(uint32_t));
#else
value = (data[3]<<24)|(data[2]<<16)|(data[1]<<8)|data[0];
#endif
return value;
}
void epb_unpack_init(Epb *e, const uint8_t *buf, int len)
{
e->unpack_buf = buf;
e->buf_len = len;
}
bool epb_has_tag(Epb *e, uint16_t tag)
{
int offset = epb_get_tag_value_offset(e->unpack_buf, e->buf_len, tag);
if (offset < 0)
return false;
else
return true;
}
uint32_t epb_get_uint32(Epb *e, uint16_t tag)
{
int offset = epb_get_tag_value_offset(e->unpack_buf, e->buf_len, tag);
if (offset < 0)
return 0;
uint32_t value = 0;
epb_get_varint32_bits(e->unpack_buf+offset, e->buf_len-offset, &value);
return value;
}
int32_t epb_get_int32(Epb *e, uint16_t tag)
{
return epb_get_uint32(e, tag);
}
int32_t epb_get_sint32(Epb *e, uint16_t tag)
{
uint32_t value = epb_get_uint32(e, tag);
if (value&1)
return -(value>>1) - 1;
else
return value>>1;
}
bool epb_get_bool(Epb *e, uint16_t tag)
{
return epb_get_uint32(e, tag);
}
int epb_get_enum(Epb *e, uint16_t tag)
{
return epb_get_uint32(e, tag);
}
const uint8_t *epb_get_bytes(Epb *e, uint16_t tag, int *len)
{
int offset = epb_get_tag_value_offset(e->unpack_buf, e->buf_len, tag);
if (offset < 0)
return NULL;
uint32_t l;
offset += epb_get_varint32_bits(e->unpack_buf+offset, e->buf_len-offset, &l);
*len = (int)l;
return e->unpack_buf+offset;
}
const char *epb_get_string(Epb *e, uint16_t tag, int *len)
{
return (char *)epb_get_bytes(e, tag, len);
}
const Message *epb_get_message(Epb *e, uint16_t tag, int *len)
{
return (Message *)epb_get_bytes(e, tag, len);
}
uint32_t epb_get_fixed32(Epb *e, uint16_t tag)
{
int offset = epb_get_tag_value_offset(e->unpack_buf, e->buf_len, tag);
if (offset < 0)
return 0;
return epb_get_fixed32_bits(e->unpack_buf+offset, e->buf_len-offset);
}
int32_t epb_get_sfixed32(Epb *e, uint16_t tag)
{
return epb_get_fixed32(e, tag);
}
float epb_get_float(Epb *e, uint16_t tag)
{
uint32_t bits = epb_get_fixed32(e, tag);
return *(float *)&bits;
}
/*
epb pack functions
*/
inline static int epb_pack_buf_remain(Epb *e)
{
return e->buf_len - e->buf_offset;
}
static int epb_pack_tag(Epb *e, uint16_t tag)
{
int tag_len = sizeof_tag(tag);
if (epb_pack_buf_remain(e) >= tag_len) {
uint8_t *buf = e->pack_buf + e->buf_offset;
if (tag_len == 2) //TODO
*(buf++) = 0xff&(tag>>8);
*buf = 0xff&tag;
e->buf_offset += tag_len;
return tag_len;
}
return -1;
}
static int epb_pack_varint32_bits(Epb *e, uint32_t value)
{
uint8_t buf[5] = {0};
int i = 0;
do {
buf[i] = value&0x7f;
if (i-1 >= 0)
buf[i-1] |= 0x80;
value = value >> 7;
++i;
} while (value!=0 && i<5);
if (epb_pack_buf_remain(e) >= i) {
memcpy(e->pack_buf+e->buf_offset, buf, i);
e->buf_offset += i;
return i;
}
return -1;
}
void epb_pack_init(Epb *e, uint8_t *buf, int len)
{
e->pack_buf = buf;
e->buf_len = len;
e->buf_offset = 0;
}
int epb_get_packed_size(Epb *e)
{
return e->buf_offset;
}
int epb_set_uint32(Epb *e, uint16_t tag, uint32_t value)
{
int len = 0;
int ret = epb_pack_tag(e, tag);
if (ret < 0) return ret;
len += ret;
ret = epb_pack_varint32_bits(e, value);
if (ret < 0) return ret;
len += ret;
return len;
}
int epb_set_int32(Epb *e, uint16_t tag, int32_t value)
{
return epb_set_uint32(e, tag, value);
}
int epb_set_sint32(Epb *e, uint16_t tag, int32_t value)
{
uint32_t v = (value << 1) ^ (value >> 31);
return epb_set_uint32(e, tag, v);
}
int epb_set_bool(Epb *e, uint16_t tag, bool value)
{
return epb_set_uint32(e, tag, value);
}
int epb_set_enum(Epb *e, uint16_t tag, int value)
{
return epb_set_uint32(e, tag, value);
}
static int epb_set_fixed32_bits(Epb *e, uint32_t value)
{
if (epb_pack_buf_remain(e) >= 4) {
#ifdef __LITTLE_ENDIAN__
memcpy(e->pack_buf+e->buf_offset, &value, 4);
#else
uint8_t *data = (uint8_t *)&value;
for (int i=0; i<4; i++) {
*(e->pack_buf+e->buf_offset+i) = data[4-i];
}
#endif
e->buf_offset += 4;
return 4;
}
return -1;
}
static int epb_pack_length_delimited(Epb *e, const uint8_t *data, int len)
{
if (epb_pack_buf_remain(e) >= len) {
memcpy(e->pack_buf + e->buf_offset, data, len);
e->buf_offset += len;
return len;
}
return -1;
}
int epb_set_bytes(Epb *e, uint16_t tag, const uint8_t *data, int length)
{
int len = 0;
int ret = epb_pack_tag(e, tag);
if (ret < 0) return ret;
len += ret;
ret = epb_pack_varint32_bits(e, length);
if (ret < 0) return ret;
len += ret;
ret = epb_pack_length_delimited(e, data, length);
if (ret < 0) return ret;
len += ret;
return len;
}
int epb_set_string(Epb *e, uint16_t tag, const char *data, int len)
{
return epb_set_bytes(e, tag, (const uint8_t *)data, len);
}
int epb_set_message(Epb *e, uint16_t tag, const Message *data, int len)
{
return epb_set_bytes(e, tag, data, len);
}
int epb_set_fixed32(Epb *e, uint16_t tag, uint32_t value)
{
int len = 0;
int ret = epb_pack_tag(e, tag);
if (ret < 0) return ret;
len += ret;
ret = epb_set_fixed32_bits(e, value);
if (ret < 0) return ret;
len += ret;
return len;
}
int epb_set_sfixed32(Epb *e, uint16_t tag, int32_t value)
{
return epb_set_fixed32(e, tag, value);
}
int epb_set_float(Epb *e, uint16_t tag, float value)
{
uint32_t v = *(uint32_t *)&value;
return epb_set_fixed32(e, tag, v);
}
int epb_varint32_pack_size(uint16_t tag, uint32_t value, bool is_signed)
{
if (is_signed)
value = (value << 1) ^ (value >> 31);
int i = 0;
do {
value = value >> 7;
++i;
} while (value!=0 && i<5);
return sizeof_tag(tag) + i;
}
int epb_fixed32_pack_size(uint16_t tag)
{
return sizeof_tag(tag) + 4;
}
int epb_length_delimited_pack_size(uint16_t tag, int len)
{
return epb_varint32_pack_size(tag, len, false) + len;
}

View file

@ -0,0 +1,559 @@
// epb_MmBp.c
// WeChat Embedded Proto Buffer
//
// Generated by harlliu@tencent.com on 14-11-26.
// Copyright 2014 Tencent. All rights reserved.
//
// Version : 1.0.4
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "epb_MmBp.h"
#include "gki.h"
#define TAG_BaseResponse_ErrCode 0x08
#define TAG_BaseResponse_ErrMsg 0x12
#define TAG_AuthRequest_BaseRequest 0x0a
#define TAG_AuthRequest_Md5DeviceTypeAndDeviceId 0x12
#define TAG_AuthRequest_ProtoVersion 0x18
#define TAG_AuthRequest_AuthProto 0x20
#define TAG_AuthRequest_AuthMethod 0x28
#define TAG_AuthRequest_AesSign 0x32
#define TAG_AuthRequest_MacAddress 0x3a
#define TAG_AuthRequest_TimeZone 0x52
#define TAG_AuthRequest_Language 0x5a
#define TAG_AuthRequest_DeviceName 0x62
#define TAG_AuthResponse_BaseResponse 0x0a
#define TAG_AuthResponse_AesSessionKey 0x12
#define TAG_InitRequest_BaseRequest 0x0a
#define TAG_InitRequest_RespFieldFilter 0x12
#define TAG_InitRequest_Challenge 0x1a
#define TAG_InitResponse_BaseResponse 0x0a
#define TAG_InitResponse_UserIdHigh 0x10
#define TAG_InitResponse_UserIdLow 0x18
#define TAG_InitResponse_ChalleangeAnswer 0x20
#define TAG_InitResponse_InitScence 0x28
#define TAG_InitResponse_AutoSyncMaxDurationSecond 0x30
#define TAG_InitResponse_UserNickName 0x5a
#define TAG_InitResponse_PlatformType 0x60
#define TAG_InitResponse_Model 0x6a
#define TAG_InitResponse_Os 0x72
#define TAG_InitResponse_Time 0x78
#define TAG_InitResponse_TimeZone 0x8001
#define TAG_InitResponse_TimeString 0x8a01
#define TAG_SendDataRequest_BaseRequest 0x0a
#define TAG_SendDataRequest_Data 0x12
#define TAG_SendDataRequest_Type 0x18
#define TAG_SendDataResponse_BaseResponse 0x0a
#define TAG_SendDataResponse_Data 0x12
#define TAG_RecvDataPush_BasePush 0x0a
#define TAG_RecvDataPush_Data 0x12
#define TAG_RecvDataPush_Type 0x18
#define TAG_SwitchViewPush_BasePush 0x0a
#define TAG_SwitchViewPush_SwitchViewOp 0x10
#define TAG_SwitchViewPush_ViewId 0x18
#define TAG_SwitchBackgroudPush_BasePush 0x0a
#define TAG_SwitchBackgroudPush_SwitchBackgroundOp 0x10
int epb_base_request_pack_size(BaseRequest *request)
{
int pack_size = 0;
return pack_size;
}
int epb_pack_base_request(BaseRequest *request, uint8_t *buf, int buf_len)
{
Epb epb;
epb_pack_init(&epb, buf, buf_len);
return epb_get_packed_size(&epb);
}
BaseResponse *epb_unpack_base_response(const uint8_t *buf, int buf_len)
{
Epb epb;
epb_unpack_init(&epb, buf, buf_len);
if (!epb_has_tag(&epb, TAG_BaseResponse_ErrCode)) {
return NULL;
}
BaseResponse *response = (BaseResponse *)GKI_getbuf(sizeof(BaseResponse));
memset(response, 0, sizeof(BaseResponse));
response->err_code = epb_get_int32(&epb, TAG_BaseResponse_ErrCode);
if (epb_has_tag(&epb, TAG_BaseResponse_ErrMsg)) {
response->err_msg.str = epb_get_string(&epb, TAG_BaseResponse_ErrMsg, &response->err_msg.len);
response->has_err_msg = true;
}
return response;
}
void epb_unpack_base_response_free(BaseResponse *response)
{
GKI_freebuf(response);
}
BasePush *epb_unpack_base_push(const uint8_t *buf, int buf_len)
{
Epb epb;
epb_unpack_init(&epb, buf, buf_len);
BasePush *push = (BasePush *)GKI_getbuf(sizeof(BasePush));
memset(push, 0, sizeof(BasePush));
return push;
}
void epb_unpack_base_push_free(BasePush *push)
{
GKI_freebuf(push);
}
int epb_auth_request_pack_size(AuthRequest *request)
{
int pack_size = 0;
int len = 0;
len = epb_base_request_pack_size(request->base_request);
pack_size += epb_length_delimited_pack_size(TAG_AuthRequest_BaseRequest, len);
if (request->has_md5_device_type_and_device_id) {
pack_size += epb_length_delimited_pack_size(TAG_AuthRequest_Md5DeviceTypeAndDeviceId, request->md5_device_type_and_device_id.len);
}
pack_size += epb_varint32_pack_size(TAG_AuthRequest_ProtoVersion, request->proto_version, false);
pack_size += epb_varint32_pack_size(TAG_AuthRequest_AuthProto, request->auth_proto, false);
pack_size += epb_varint32_pack_size(TAG_AuthRequest_AuthMethod, request->auth_method, false);
if (request->has_aes_sign) {
pack_size += epb_length_delimited_pack_size(TAG_AuthRequest_AesSign, request->aes_sign.len);
}
if (request->has_mac_address) {
pack_size += epb_length_delimited_pack_size(TAG_AuthRequest_MacAddress, request->mac_address.len);
}
if (request->has_time_zone) {
pack_size += epb_length_delimited_pack_size(TAG_AuthRequest_TimeZone, request->time_zone.len);
}
if (request->has_language) {
pack_size += epb_length_delimited_pack_size(TAG_AuthRequest_Language, request->language.len);
}
if (request->has_device_name) {
pack_size += epb_length_delimited_pack_size(TAG_AuthRequest_DeviceName, request->device_name.len);
}
return pack_size;
}
int epb_pack_auth_request(AuthRequest *request, uint8_t *buf, int buf_len)
{
Epb epb;
epb_pack_init(&epb, buf, buf_len);
int ret;
int tmp_len;
uint8_t *tmp;
tmp_len = epb_base_request_pack_size(request->base_request);
tmp = (uint8_t *)GKI_getbuf(tmp_len);
ret = epb_pack_base_request(request->base_request, tmp, tmp_len);
if (ret < 0) {
GKI_freebuf(tmp);
return ret;
}
ret = epb_set_message(&epb, TAG_AuthRequest_BaseRequest, tmp, tmp_len);
GKI_freebuf(tmp);
if (ret < 0) return ret;
if (request->has_md5_device_type_and_device_id) {
ret = epb_set_bytes(&epb, TAG_AuthRequest_Md5DeviceTypeAndDeviceId, request->md5_device_type_and_device_id.data, request->md5_device_type_and_device_id.len);
if (ret < 0) return ret;
}
ret = epb_set_int32(&epb, TAG_AuthRequest_ProtoVersion, request->proto_version);
if (ret < 0) return ret;
ret = epb_set_int32(&epb, TAG_AuthRequest_AuthProto, request->auth_proto);
if (ret < 0) return ret;
ret = epb_set_enum(&epb, TAG_AuthRequest_AuthMethod, request->auth_method);
if (ret < 0) return ret;
if (request->has_aes_sign) {
ret = epb_set_bytes(&epb, TAG_AuthRequest_AesSign, request->aes_sign.data, request->aes_sign.len);
if (ret < 0) return ret;
}
if (request->has_mac_address) {
ret = epb_set_bytes(&epb, TAG_AuthRequest_MacAddress, request->mac_address.data, request->mac_address.len);
if (ret < 0) return ret;
}
if (request->has_time_zone) {
ret = epb_set_string(&epb, TAG_AuthRequest_TimeZone, request->time_zone.str, request->time_zone.len);
if (ret < 0) return ret;
}
if (request->has_language) {
ret = epb_set_string(&epb, TAG_AuthRequest_Language, request->language.str, request->language.len);
if (ret < 0) return ret;
}
if (request->has_device_name) {
ret = epb_set_string(&epb, TAG_AuthRequest_DeviceName, request->device_name.str, request->device_name.len);
if (ret < 0) return ret;
}
return epb_get_packed_size(&epb);
}
AuthResponse *epb_unpack_auth_response(const uint8_t *buf, int buf_len)
{
Epb epb;
epb_unpack_init(&epb, buf, buf_len);
const uint8_t *tmp;
int tmp_len;
if (!epb_has_tag(&epb, TAG_AuthResponse_BaseResponse)) {
return NULL;
}
if (!epb_has_tag(&epb, TAG_AuthResponse_AesSessionKey)) {
return NULL;
}
AuthResponse *response = (AuthResponse *)GKI_getbuf(sizeof(AuthResponse));
memset(response, 0, sizeof(AuthResponse));
tmp = epb_get_message(&epb, TAG_AuthResponse_BaseResponse, &tmp_len);
response->base_response = epb_unpack_base_response(tmp, tmp_len);
if (response->base_response == NULL) {
GKI_freebuf(response);
return NULL;
}
response->aes_session_key.data = epb_get_bytes(&epb, TAG_AuthResponse_AesSessionKey, &response->aes_session_key.len);
return response;
}
void epb_unpack_auth_response_free(AuthResponse *response)
{
epb_unpack_base_response_free(response->base_response);
GKI_freebuf(response);
}
int epb_init_request_pack_size(InitRequest *request)
{
int pack_size = 0;
int len = 0;
len = epb_base_request_pack_size(request->base_request);
pack_size += epb_length_delimited_pack_size(TAG_InitRequest_BaseRequest, len);
if (request->has_resp_field_filter) {
pack_size += epb_length_delimited_pack_size(TAG_InitRequest_RespFieldFilter, request->resp_field_filter.len);
}
if (request->has_challenge) {
pack_size += epb_length_delimited_pack_size(TAG_InitRequest_Challenge, request->challenge.len);
}
return pack_size;
}
int epb_pack_init_request(InitRequest *request, uint8_t *buf, int buf_len)
{
Epb epb;
epb_pack_init(&epb, buf, buf_len);
int ret;
int tmp_len;
uint8_t *tmp;
tmp_len = epb_base_request_pack_size(request->base_request);
tmp = (uint8_t *)GKI_getbuf(tmp_len);
ret = epb_pack_base_request(request->base_request, tmp, tmp_len);
if (ret < 0) {
GKI_freebuf(tmp);
return ret;
}
ret = epb_set_message(&epb, TAG_InitRequest_BaseRequest, tmp, tmp_len);
GKI_freebuf(tmp);
if (ret < 0) return ret;
if (request->has_resp_field_filter) {
ret = epb_set_bytes(&epb, TAG_InitRequest_RespFieldFilter, request->resp_field_filter.data, request->resp_field_filter.len);
if (ret < 0) return ret;
}
if (request->has_challenge) {
ret = epb_set_bytes(&epb, TAG_InitRequest_Challenge, request->challenge.data, request->challenge.len);
if (ret < 0) return ret;
}
return epb_get_packed_size(&epb);
}
InitResponse *epb_unpack_init_response(const uint8_t *buf, int buf_len)
{
Epb epb;
epb_unpack_init(&epb, buf, buf_len);
const uint8_t *tmp;
int tmp_len;
if (!epb_has_tag(&epb, TAG_InitResponse_BaseResponse)) {
return NULL;
}
if (!epb_has_tag(&epb, TAG_InitResponse_UserIdHigh)) {
return NULL;
}
if (!epb_has_tag(&epb, TAG_InitResponse_UserIdLow)) {
return NULL;
}
InitResponse *response = (InitResponse *)GKI_getbuf(sizeof(InitResponse));
memset(response, 0, sizeof(InitResponse));
tmp = epb_get_message(&epb, TAG_InitResponse_BaseResponse, &tmp_len);
response->base_response = epb_unpack_base_response(tmp, tmp_len);
if (response->base_response == NULL) {
GKI_freebuf(response);
return NULL;
}
response->user_id_high = epb_get_uint32(&epb, TAG_InitResponse_UserIdHigh);
response->user_id_low = epb_get_uint32(&epb, TAG_InitResponse_UserIdLow);
if (epb_has_tag(&epb, TAG_InitResponse_ChalleangeAnswer)) {
response->challeange_answer = epb_get_uint32(&epb, TAG_InitResponse_ChalleangeAnswer);
response->has_challeange_answer = true;
}
if (epb_has_tag(&epb, TAG_InitResponse_InitScence)) {
response->init_scence = (EmInitScence)epb_get_enum(&epb, TAG_InitResponse_InitScence);
response->has_init_scence = true;
}
if (epb_has_tag(&epb, TAG_InitResponse_AutoSyncMaxDurationSecond)) {
response->auto_sync_max_duration_second = epb_get_uint32(&epb, TAG_InitResponse_AutoSyncMaxDurationSecond);
response->has_auto_sync_max_duration_second = true;
}
if (epb_has_tag(&epb, TAG_InitResponse_UserNickName)) {
response->user_nick_name.str = epb_get_string(&epb, TAG_InitResponse_UserNickName, &response->user_nick_name.len);
response->has_user_nick_name = true;
}
if (epb_has_tag(&epb, TAG_InitResponse_PlatformType)) {
response->platform_type = (EmPlatformType)epb_get_enum(&epb, TAG_InitResponse_PlatformType);
response->has_platform_type = true;
}
if (epb_has_tag(&epb, TAG_InitResponse_Model)) {
response->model.str = epb_get_string(&epb, TAG_InitResponse_Model, &response->model.len);
response->has_model = true;
}
if (epb_has_tag(&epb, TAG_InitResponse_Os)) {
response->os.str = epb_get_string(&epb, TAG_InitResponse_Os, &response->os.len);
response->has_os = true;
}
if (epb_has_tag(&epb, TAG_InitResponse_Time)) {
response->time = epb_get_int32(&epb, TAG_InitResponse_Time);
response->has_time = true;
}
if (epb_has_tag(&epb, TAG_InitResponse_TimeZone)) {
response->time_zone = epb_get_int32(&epb, TAG_InitResponse_TimeZone);
response->has_time_zone = true;
}
if (epb_has_tag(&epb, TAG_InitResponse_TimeString)) {
response->time_string.str = epb_get_string(&epb, TAG_InitResponse_TimeString, &response->time_string.len);
response->has_time_string = true;
}
return response;
}
void epb_unpack_init_response_free(InitResponse *response)
{
epb_unpack_base_response_free(response->base_response);
GKI_freebuf((void *)response);
}
int epb_send_data_request_pack_size(SendDataRequest *request)
{
int pack_size = 0;
int len = 0;
len = epb_base_request_pack_size(request->base_request);
pack_size += epb_length_delimited_pack_size(TAG_SendDataRequest_BaseRequest, len);
pack_size += epb_length_delimited_pack_size(TAG_SendDataRequest_Data, request->data.len);
if (request->has_type) {
pack_size += epb_varint32_pack_size(TAG_SendDataRequest_Type, request->type, false);
}
return pack_size;
}
int epb_pack_send_data_request(SendDataRequest *request, uint8_t *buf, int buf_len)
{
Epb epb;
epb_pack_init(&epb, buf, buf_len);
int ret;
int tmp_len;
uint8_t *tmp;
tmp_len = epb_base_request_pack_size(request->base_request);
tmp = (uint8_t *)GKI_getbuf(tmp_len);
ret = epb_pack_base_request(request->base_request, tmp, tmp_len);
if (ret < 0) {
GKI_freebuf(tmp);
return ret;
}
ret = epb_set_message(&epb, TAG_SendDataRequest_BaseRequest, tmp, tmp_len);
GKI_freebuf(tmp);
if (ret < 0) return ret;
ret = epb_set_bytes(&epb, TAG_SendDataRequest_Data, request->data.data, request->data.len);
if (ret < 0) return ret;
if (request->has_type) {
ret = epb_set_enum(&epb, TAG_SendDataRequest_Type, request->type);
if (ret < 0) return ret;
}
return epb_get_packed_size(&epb);
}
SendDataResponse *epb_unpack_send_data_response(const uint8_t *buf, int buf_len)
{
Epb epb;
epb_unpack_init(&epb, buf, buf_len);
const uint8_t *tmp;
int tmp_len;
if (!epb_has_tag(&epb, TAG_SendDataResponse_BaseResponse)) {
return NULL;
}
SendDataResponse *response = (SendDataResponse *)GKI_getbuf(sizeof(SendDataResponse));
memset(response, 0, sizeof(SendDataResponse));
tmp = epb_get_message(&epb, TAG_SendDataResponse_BaseResponse, &tmp_len);
response->base_response = epb_unpack_base_response(tmp, tmp_len);
if (response->base_response == NULL) {
GKI_freebuf(response);
return NULL;
}
if (epb_has_tag(&epb, TAG_SendDataResponse_Data)) {
response->data.data = epb_get_bytes(&epb, TAG_SendDataResponse_Data, &response->data.len);
response->has_data = true;
}
return response;
}
void epb_unpack_send_data_response_free(SendDataResponse *response)
{
epb_unpack_base_response_free(response->base_response);
GKI_freebuf(response);
}
RecvDataPush *epb_unpack_recv_data_push(const uint8_t *buf, int buf_len)
{
Epb epb;
epb_unpack_init(&epb, buf, buf_len);
const uint8_t *tmp;
int tmp_len;
if (!epb_has_tag(&epb, TAG_RecvDataPush_BasePush)) {
return NULL;
}
if (!epb_has_tag(&epb, TAG_RecvDataPush_Data)) {
return NULL;
}
RecvDataPush *push = (RecvDataPush *)GKI_getbuf(sizeof(RecvDataPush));
memset(push, 0, sizeof(RecvDataPush));
tmp = epb_get_message(&epb, TAG_RecvDataPush_BasePush, &tmp_len);
push->base_push = epb_unpack_base_push(tmp, tmp_len);
if (push->base_push == NULL) {
GKI_freebuf(push);
return NULL;
}
push->data.data = epb_get_bytes(&epb, TAG_RecvDataPush_Data, &push->data.len);
if (epb_has_tag(&epb, TAG_RecvDataPush_Type)) {
push->type = (EmDeviceDataType)epb_get_enum(&epb, TAG_RecvDataPush_Type);
push->has_type = true;
}
return push;
}
void epb_unpack_recv_data_push_free(RecvDataPush *push)
{
epb_unpack_base_push_free(push->base_push);
push->base_push = NULL;
GKI_freebuf(push);
}
SwitchViewPush *epb_unpack_switch_view_push(const uint8_t *buf, int buf_len)
{
Epb epb;
epb_unpack_init(&epb, buf, buf_len);
const uint8_t *tmp;
int tmp_len;
if (!epb_has_tag(&epb, TAG_SwitchViewPush_BasePush)) {
return NULL;
}
if (!epb_has_tag(&epb, TAG_SwitchViewPush_SwitchViewOp)) {
return NULL;
}
if (!epb_has_tag(&epb, TAG_SwitchViewPush_ViewId)) {
return NULL;
}
SwitchViewPush *push = (SwitchViewPush *)GKI_getbuf(sizeof(SwitchViewPush));
memset(push, 0, sizeof(SwitchViewPush));
tmp = epb_get_message(&epb, TAG_SwitchViewPush_BasePush, &tmp_len);
push->base_push = epb_unpack_base_push(tmp, tmp_len);
if (push->base_push == NULL) {
GKI_freebuf(push);
return NULL;
}
push->switch_view_op = (EmSwitchViewOp)epb_get_enum(&epb, TAG_SwitchViewPush_SwitchViewOp);
push->view_id = (EmViewId)epb_get_enum(&epb, TAG_SwitchViewPush_ViewId);
return push;
}
void epb_unpack_switch_view_push_free(SwitchViewPush *push)
{
epb_unpack_base_push_free(push->base_push);
GKI_freebuf(push);
}
SwitchBackgroudPush *epb_unpack_switch_backgroud_push(const uint8_t *buf, int buf_len)
{
Epb epb;
epb_unpack_init(&epb, buf, buf_len);
const uint8_t *tmp;
int tmp_len;
if (!epb_has_tag(&epb, TAG_SwitchBackgroudPush_BasePush)) {
return NULL;
}
if (!epb_has_tag(&epb, TAG_SwitchBackgroudPush_SwitchBackgroundOp)) {
return NULL;
}
SwitchBackgroudPush *push = (SwitchBackgroudPush *)GKI_getbuf(sizeof(SwitchBackgroudPush));
memset(push, 0, sizeof(SwitchBackgroudPush));
tmp = epb_get_message(&epb, TAG_SwitchBackgroudPush_BasePush, &tmp_len);
push->base_push = epb_unpack_base_push(tmp, tmp_len);
if (push->base_push == NULL) {
GKI_freebuf(push);
return NULL;
}
push->switch_background_op = (EmSwitchBackgroundOp)epb_get_enum(&epb, TAG_SwitchBackgroudPush_SwitchBackgroundOp);
return push;
}
void epb_unpack_switch_backgroud_push_free(SwitchBackgroudPush *push)
{
epb_unpack_base_push_free(push->base_push);
GKI_freebuf(push);
}

View file

@ -0,0 +1,579 @@
/*
* WeChat mpbledemo2
*
* author by anqiren 2014/12/02 V1.0bat
*
**/
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include "app_airsync_prf.h"
#include "wechat_aes.h"
#include "epb_MmBp.h"
#include "wechar_crc.h"
#include "app_wechat_util.h"
#include "app_airsync_md5.h"
#include "mpbledemo2.h"
#include "gki.h"
mpbledemo2_info m_info = {CMD_NULL, {NULL, 0}};
#if defined EAM_md5AndNoEnrypt || EAM_md5AndAesEnrypt
uint8_t md5_type_and_id[16];
#endif
uint8_t challeange[CHALLENAGE_LENGTH] = {0x11,0x22,0x33,0x44}; //为了方便这里填了一组确定的数组,使用过程中请自行生成随机数
mpbledemo2_state mpbledemo2Sta = {false, false, false, false, false, false,0,0,0};
const uint8_t key[16] = DEVICE_KEY;
uint8_t session_key[32] = {0};
data_handler *m_mpbledemo2_handler = NULL;
uint8_t isLightOn;
/**** NOTIFICATION BITS ***********/
uint8_t FirstNotificationBit ;
uint8_t SecondNotificationBit;
//static void mpbledemo2_handleCmdFromServer(BleDemo2CmdID cmd, uint8_t *ptrData, uint32_t lengthInByte);
/**@brief Function for the light initialization.
*
* @details Initializes all lights used by this application.
*/
int32_t mpbledemo2_get_md5(void)
{
int32_t error_code = 0;
#if defined EAM_md5AndNoEnrypt || EAM_md5AndAesEnrypt
char device_type[] = DEVICE_TYPE;
char device_id[] = DEVICE_ID;
char argv[sizeof(DEVICE_TYPE) + sizeof(DEVICE_ID) - 1];
memcpy(argv,device_type,sizeof(DEVICE_TYPE));
/*when add the DEVICE_ID to DEVICE_TYPE, the offset shuld -1 to overwrite '\0' at the end of DEVICE_TYPE */
memcpy(argv + sizeof(DEVICE_TYPE)-1,device_id,sizeof(DEVICE_ID));
error_code = wechat_md5(argv, md5_type_and_id);
#endif
return error_code;
}
void mpbledemo2_reset()
{
mpbledemo2Sta.auth_send = false;
mpbledemo2Sta.auth_state = false;
mpbledemo2Sta.indication_state = false;
mpbledemo2Sta.init_send = false;
mpbledemo2Sta.init_state = false;
mpbledemo2Sta.send_data_seq = 0;
mpbledemo2Sta.push_data_seq = 0;
mpbledemo2Sta.seq = 0;
}
int32_t mpbledemo2_init(void)
{
mpbledemo2_reset();
return (mpbledemo2_get_md5());
}
void mpbledemo2_indication_state(bool isEnable)
{
mpbledemo2Sta.indication_state = isEnable;
if (false == isEnable)
{
mpbledemo2Sta.auth_send = false;
}
}
int32_t device_auth()
{
if (m_mpbledemo2_handler == NULL) {
m_mpbledemo2_handler = get_handler_by_type(PRODUCT_TYPE_MPBLEDEMO2);
}
uint8_t *data = NULL;
uint32_t len = 0;
ARGS_ITEM_SET(mpbledemo2_info, m_mpbledemo2_handler->m_data_produce_args, cmd, CMD_AUTH);
m_mpbledemo2_handler->m_data_produce_func(m_mpbledemo2_handler->m_data_produce_args, &data, &len);
if(data == NULL)
{
return errorCodeProduce;
}
//sent data
ble_wechat_indicate_data(data, len);
return 0;
}
int32_t device_init()
{
uint8_t *data = NULL;
uint32_t len = 0;
ARGS_ITEM_SET(mpbledemo2_info, m_mpbledemo2_handler->m_data_produce_args, cmd, CMD_INIT);
m_mpbledemo2_handler->m_data_produce_func(m_mpbledemo2_handler->m_data_produce_args, &data, &len);
if(data == NULL)
{
return errorCodeProduce;
}
//sent data
ble_wechat_indicate_data(data, len);
return 0;
}
void mpbledemo2_main_process()
{
int error_code = 0;
if((mpbledemo2Sta.indication_state) && (!mpbledemo2Sta.auth_state) && (!mpbledemo2Sta.auth_send) )
{
error_code = device_auth();
if (0 == error_code)
{
mpbledemo2Sta.auth_send = true;
}
}
if((mpbledemo2Sta.auth_state) && (!mpbledemo2Sta.init_state) && (!mpbledemo2Sta.init_send))
{
error_code = device_init();
if (0 == error_code)
{
mpbledemo2Sta.init_send = true;
}
}
}
void mpbledemo2_data_free_func(uint8_t *data, uint32_t len)
{
if(data)
{
GKI_freebuf(data);
data = NULL;
}
}
void mpbledemo2_data_produce_func(void *args, uint8_t **r_data, uint32_t *r_len)
{
static uint16_t bleDemoHeadLen = sizeof(BlueDemoHead);
mpbledemo2_info *info = (mpbledemo2_info *)args;
BaseRequest basReq = {NULL};
static uint8_t fix_head_len = sizeof(BpFixHead);
BpFixHead fix_head = {0xFE, 1, 0, htons(ECI_req_auth), 0};
mpbledemo2Sta.seq++;
switch (info->cmd)
{
case CMD_AUTH:
{
#if defined EAM_md5AndAesEnrypt
uint8_t deviceid[] = DEVICE_ID;
static uint32_t seq = 0x00000001; //
uint32_t ran = 0x11223344; //为了方便起见这里放了一个固定值做为随机数,在使用时请自行生成随机数。
ran = t_htonl(ran);
seq = t_htonl(seq);
uint8_t id_len = strlen(DEVICE_ID);
uint8_t* data = GKI_getbuf(id_len+8);
if(!data){return;}
memcpy(data,deviceid,id_len);
memcpy(data+id_len,(uint8_t*)&ran,4);
memcpy(data+id_len+4,(uint8_t*)&seq,4);
uint32_t crc = crc32(0, data, id_len+8);
crc = t_htonl(crc);
memset(data,0x00,id_len+8);
memcpy(data,(uint8_t*)&ran,4);
memcpy(data+4,(uint8_t*)&seq,4);
memcpy(data+8,(uint8_t*)&crc,4);
uint8_t CipherText[16];
AES_Init(key);
AES_Encrypt_PKCS7 (data, CipherText, 12, key);
if(data){GKI_freebuf(data);data = NULL;}
AuthRequest authReq = {&basReq, true,{md5_type_and_id, MD5_TYPE_AND_ID_LENGTH},
PROTO_VERSION, AUTH_PROTO, (EmAuthMethod)AUTH_METHOD, true ,
{CipherText, CIPHER_TEXT_LENGTH}, false, {NULL, 0}, false, {NULL, 0}, false,
{NULL, 0},true,{DEVICE_ID,sizeof(DEVICE_ID)}};
seq++;
#endif
#if defined EAM_macNoEncrypt
static uint8_t mac_address[MAC_ADDRESS_LENGTH];
//get_mac_addr(mac_address);
AuthRequest authReq = {&basReq, false,{NULL, 0}, PROTO_VERSION, AUTH_PROTO, (EmAuthMethod)AUTH_METHOD, false,{NULL, 0}, true, {mac_address, MAC_ADDRESS_LENGTH}, false, {NULL, 0}, false, {NULL, 0},true,{DEVICE_ID,sizeof(DEVICE_ID)}};
#endif
#if defined EAM_md5AndNoEnrypt
AuthRequest authReq = {&basReq, true,{md5_type_and_id, MD5_TYPE_AND_ID_LENGTH}, PROTO_VERSION, (EmAuthMethod)AUTH_PROTO, (EmAuthMethod)AUTH_METHOD, false ,{NULL, 0}, false, {NULL, 0}, false, {NULL, 0}, false, {NULL, 0},true,{DEVICE_ID,sizeof(DEVICE_ID)}};
#endif
*r_len = epb_auth_request_pack_size(&authReq) + fix_head_len;
*r_data = (uint8_t *)GKI_getbuf(*r_len);
if(!(*r_data)){return;}
if(epb_pack_auth_request(&authReq, *r_data+fix_head_len, *r_len-fix_head_len)<0)
{
*r_data = NULL;
return;
}
fix_head.nCmdId = htons(ECI_req_auth);
fix_head.nLength = htons(*r_len);
fix_head.nSeq = htons(mpbledemo2Sta.seq);
memcpy(*r_data, &fix_head, fix_head_len);
return ;
}
case CMD_INIT:
{
//has challeange
InitRequest initReq = {&basReq,false, {NULL, 0},true, {challeange, CHALLENAGE_LENGTH}};
*r_len = epb_init_request_pack_size(&initReq) + fix_head_len;
#if defined EAM_md5AndAesEnrypt
uint8_t length = *r_len;
uint8_t *p = GKI_getbuf(AES_get_length( *r_len-fix_head_len));
if(!p){return;}
*r_len = AES_get_length( *r_len-fix_head_len)+fix_head_len;
#endif
//pack data
*r_data = (uint8_t *)GKI_getbuf(*r_len);
if(!(*r_data)){return;}
if(epb_pack_init_request(&initReq, *r_data+fix_head_len, *r_len-fix_head_len)<0)
{*r_data = NULL;return;}
//encrypt body
#if defined EAM_md5AndAesEnrypt
AES_Init(session_key);
AES_Encrypt_PKCS7(*r_data+fix_head_len,p,length-fix_head_len,session_key);//原始数据长度
memcpy(*r_data + fix_head_len, p, *r_len-fix_head_len);
if(p)GKI_freebuf(p);
#endif
fix_head.nCmdId = htons(ECI_req_init);
fix_head.nLength = htons(*r_len);
fix_head.nSeq = htons(mpbledemo2Sta.seq);
memcpy(*r_data, &fix_head, fix_head_len);
return ;
}
case CMD_SENDDAT:
{
BlueDemoHead *bleDemoHead = (BlueDemoHead*)GKI_getbuf(bleDemoHeadLen+info->send_msg.len);
if (!bleDemoHead)
{
return;
}
// header of sent data
bleDemoHead->m_magicCode[0] = MPBLEDEMO2_MAGICCODE_H;
bleDemoHead->m_magicCode[1] = MPBLEDEMO2_MAGICCODE_L;
bleDemoHead->m_version = htons(MPBLEDEMO2_VERSION);
bleDemoHead->m_totalLength = htons(bleDemoHeadLen + info->send_msg.len);
bleDemoHead->m_cmdid = htons(sendTextReq);
bleDemoHead->m_seq = htons(mpbledemo2Sta.seq);
bleDemoHead->m_errorCode = 0;
/*connect body and head.*/
/*turn to uint8_t* befort offset.*/
memcpy((uint8_t*)bleDemoHead + bleDemoHeadLen, info->send_msg.str, info->send_msg.len);
SendDataRequest sendDatReq =
{
&basReq,
{ (uint8_t*) bleDemoHead, (bleDemoHeadLen + info->send_msg.len)}, // define the data content wrapped in epb
false, // no type, the data is directly sent to vendor server
(EmDeviceDataType)NULL
};
*r_len = epb_send_data_request_pack_size(&sendDatReq) + fix_head_len;
#if defined EAM_md5AndAesEnrypt
uint16_t length = *r_len;
uint8_t *p = GKI_getbuf(AES_get_length( *r_len-fix_head_len));
if(!p){return;}
*r_len = AES_get_length( *r_len-fix_head_len)+fix_head_len;
#endif
*r_data = (uint8_t *)GKI_getbuf(*r_len);
if(!(*r_data)){return;}
if(epb_pack_send_data_request(&sendDatReq, *r_data+fix_head_len, *r_len-fix_head_len)<0)
{
*r_data = NULL;
#if defined EAM_md5AndAesEnrypt
if(p){GKI_freebuf(p);
p = NULL;}
#endif
return;
}
#if defined EAM_md5AndAesEnrypt
//encrypt body
AES_Init(session_key);
AES_Encrypt_PKCS7(*r_data+fix_head_len,p,length-fix_head_len,session_key);//原始数据长度
memcpy(*r_data + fix_head_len, p, *r_len-fix_head_len);
if(p){GKI_freebuf(p); p = NULL;}
#endif
// header of epb
fix_head.nCmdId = htons(ECI_req_sendData);
fix_head.nLength = htons(*r_len);
fix_head.nSeq = htons(mpbledemo2Sta.seq);
memcpy(*r_data, &fix_head, fix_head_len);
if(bleDemoHead){GKI_freebuf(bleDemoHead);bleDemoHead = NULL;}
// increase sequence by 1
mpbledemo2Sta.send_data_seq++;
return ;
}
}
}
int mpbledemo2_data_consume_func(uint8_t *data, uint32_t len)
{
BpFixHead *fix_head = (BpFixHead *)data;
uint8_t fix_head_len = sizeof(BpFixHead);
switch(ntohs(fix_head->nCmdId))
{
case ECI_none:
{
}
break;
case ECI_resp_auth:
{
AuthResponse* authResp;
authResp = epb_unpack_auth_response(data+fix_head_len,len-fix_head_len);
if(authResp->base_response)
{
if(authResp->base_response->err_code == 0)
{
mpbledemo2Sta.auth_state = true;
}
else
{
int32_t returnedErrCode = authResp->base_response->err_code;
epb_unpack_auth_response_free(authResp);
return returnedErrCode;
}
}
#if defined EAM_md5AndAesEnrypt // get sessionkey
if(authResp->aes_session_key.len)
{
AES_Init(key);
AES_Decrypt(session_key,authResp->aes_session_key.data,authResp->aes_session_key.len,key);
}
#endif
epb_unpack_auth_response_free(authResp);
}
break;
case ECI_resp_sendData:
{
#if defined EAM_md5AndAesEnrypt
uint32_t length = len- fix_head_len;//加密后数据长度
uint8_t *p = GKI_getbuf (length);
if(!p){ if(data)GKI_freebuf(data);data = NULL; return 0;}
AES_Init(session_key);
//解密数据
AES_Decrypt(p,data+fix_head_len,len- fix_head_len,session_key);
uint8_t temp;
temp = p[length - 1];//算出填充长度
len = len - temp;//取加密前数据总长度
memcpy(data + fix_head_len, p ,length -temp);//把明文放回
if(p){GKI_freebuf(p);p = NULL;}
#endif
SendDataResponse *sendDataResp;
sendDataResp = epb_unpack_send_data_response(data+fix_head_len,len-fix_head_len);
if (!sendDataResp)
{
return errorCodeUnpackSendDataResp;
}
if(sendDataResp->base_response->err_code)
{
epb_unpack_send_data_response_free(sendDataResp);
return sendDataResp->base_response->err_code;
}
epb_unpack_send_data_response_free(sendDataResp);
}
break;
case ECI_resp_init:
{
FirstNotificationBit = 0;
SecondNotificationBit = 0;
#if defined EAM_md5AndAesEnrypt
uint32_t length = len- fix_head_len; //加密后数据长度
uint8_t *p = GKI_getbuf (length);
if(!p){if(data)GKI_freebuf(data);data = NULL; return 0;}
AES_Init(session_key);
//解密数据
AES_Decrypt(p,data+fix_head_len,len- fix_head_len,session_key);
uint8_t temp;
temp = p[length - 1]; //算出填充长度
len = len - temp; //取加密前数据总长度
memcpy(data + fix_head_len, p ,length -temp); //把明文放回
if(p){GKI_freebuf(p);p = NULL;}
#endif
InitResponse *initResp = epb_unpack_init_response(data+fix_head_len, len-fix_head_len);
if(!initResp)
{
return errorCodeUnpackInitResp;
}
if(initResp->base_response)
{
if(initResp->base_response->err_code == 0)
{
if(initResp->has_challeange_answer)
{
if(crc32(0,challeange,CHALLENAGE_LENGTH) == initResp->challeange_answer)
{
mpbledemo2Sta.init_state = true;
}
}
else mpbledemo2Sta.init_state = true;
mpbledemo2Sta.wechats_switch_state = true;
}
else
{
epb_unpack_init_response_free(initResp);
return initResp->base_response->err_code;
}
}
epb_unpack_init_response_free(initResp);
}
break;
case ECI_push_recvData:
{
#if defined EAM_md5AndAesEnrypt
uint32_t length = len- fix_head_len;//加密后数据长度
uint8_t *p = GKI_getbuf (length);
if(!p){if(data)GKI_freebuf(data); data =NULL; return 0;}
AES_Init(session_key);
//解密数据
AES_Decrypt(p,data+fix_head_len,len- fix_head_len,session_key);
uint8_t temp;
temp = p[length - 1];//算出填充长度
len = len - temp;//取加密前数据总长度
memcpy(data + fix_head_len, p ,length -temp);//把明文放回
if(p){GKI_freebuf(p);p = NULL;}
#endif
RecvDataPush *recvDatPush;
recvDatPush = epb_unpack_recv_data_push(data+fix_head_len, len-fix_head_len);
if(!recvDatPush)
{
return errorCodeUnpackRecvDataPush;
}
BlueDemoHead *bledemohead = (BlueDemoHead*)recvDatPush->data.data;
// ble demo command handle
epb_unpack_recv_data_push_free(recvDatPush);
mpbledemo2Sta.push_data_seq++;
}
break;
case ECI_push_switchView:
{
mpbledemo2Sta.wechats_switch_state = !mpbledemo2Sta.wechats_switch_state;
#if defined EAM_md5AndAesEnrypt
uint32_t length = len- fix_head_len;//加密后数据长度
uint8_t *p = GKI_getbuf (length);
if(!p){if(data)GKI_freebuf(data);data = NULL; return 0;}
AES_Init(session_key);
//解密数据
AES_Decrypt(p,data+fix_head_len,len- fix_head_len,session_key);
uint8_t temp;
temp = p[length - 1];//算出填充长度
len = len - temp;//取加密前数据总长度
memcpy(data + fix_head_len, p ,length -temp);//把明文放回
if(p){GKI_freebuf(p);p = NULL;}
#endif
SwitchViewPush *swichViewPush;
swichViewPush = epb_unpack_switch_view_push(data+fix_head_len,len-fix_head_len);
if(!swichViewPush)
{
return errorCodeUnpackSwitchViewPush;
}
epb_unpack_switch_view_push_free(swichViewPush);
}
break;
case ECI_push_switchBackgroud:
{
#if defined EAM_md5AndAesEnrypt
uint32_t length = len- fix_head_len;//加密后数据长度
uint8_t *p = GKI_getbuf (length);
if(!p){if(data)GKI_freebuf(data);data = NULL; return 0;}
AES_Init(session_key);
//解密数据
AES_Decrypt(p,data+fix_head_len,len- fix_head_len,session_key);
uint8_t temp;
temp = p[length - 1];//算出填充长度
len = len - temp;//取加密前数据总长度
memcpy(data + fix_head_len, p ,length -temp);//把明文放回
if(data){GKI_freebuf(p);p = NULL;}
#endif
SwitchBackgroudPush *switchBackgroundPush = epb_unpack_switch_backgroud_push(data+fix_head_len,len-fix_head_len);
if(! switchBackgroundPush)
{
return errorCodeUnpackSwitchBackgroundPush;
}
epb_unpack_switch_backgroud_push_free(switchBackgroundPush);
}
break;
case ECI_err_decode:
break;
default:
{
}
break;
}
return 0;
}
void mpbledemo2_data_error_func(int error_code)
{
if(error_code)
{
//NVIC_SystemReset();
}
}
data_handler mpbledemo2_data_handler = {
.m_product_type = PRODUCT_TYPE_MPBLEDEMO2,
.m_data_produce_func = &mpbledemo2_data_produce_func,
.m_data_free_func = &mpbledemo2_data_free_func,
.m_data_consume_func = &mpbledemo2_data_consume_func,
.m_data_error_func = &mpbledemo2_data_error_func,
.m_data_init_peripheral_func = NULL,
.m_data_init_func = &mpbledemo2_init,
.m_data_main_process_func = &mpbledemo2_main_process,
.m_data_button_handler_func = NULL,
.m_data_produce_args = &m_info,
.next = NULL
};
// send data to wechat server
int32_t mpbledemo2_sendData(uint8_t* ptrData, uint32_t lengthInByte)
{
uint8_t *data = NULL;
uint32_t len = 0;
ARGS_ITEM_SET(mpbledemo2_info, m_mpbledemo2_handler->m_data_produce_args, cmd, CMD_SENDDAT);
ARGS_ITEM_SET(mpbledemo2_info, m_mpbledemo2_handler->m_data_produce_args, send_msg.len, lengthInByte);
ARGS_ITEM_SET(mpbledemo2_info, m_mpbledemo2_handler->m_data_produce_args, send_msg.str, (const char *)ptrData);
m_mpbledemo2_handler->m_data_produce_func(m_mpbledemo2_handler->m_data_produce_args, &data, &len);
if(data == NULL)
{
return errorCodeProduce;
}
ble_wechat_indicate_data(data, len);
return 0;
}

View file

@ -0,0 +1,44 @@
// crc32.c
// WeChat Embedded
//
// Created by harlliu on 14-03-03.
// Copyright 2014 Tencent. All rights reserved.
//
#include <stdio.h>
#include "wechar_crc.h"
#define DO1(buf) crc = crc_table(((int)crc ^ (*buf++)) & 0xff) ^ (crc >> 8);
#define DO2(buf) DO1(buf); DO1(buf);
#define DO4(buf) DO2(buf); DO2(buf);
#define DO8(buf) DO4(buf); DO4(buf);
static uint32_t crc_table(uint32_t index)
{
uint32_t c = index;
uint32_t poly = 0xedb88320L;
int k;
for (k = 0; k < 8; k++)
c = c & 1 ? poly ^ (c >> 1) : c >> 1;
return c;
}
uint32_t crc32(uint32_t crc, const uint8_t *buf, int len)
{
if (buf == NULL) return 0L;
crc = crc ^ 0xffffffffL;
while (len >= 8)
{
DO8(buf);
len -= 8;
}
if (len) do {
DO1(buf);
} while (--len);
return crc ^ 0xffffffffL;
}

View file

@ -0,0 +1,443 @@
///////////////////////////////////////////////////////////////////////////////
// 文 件 名wechat_aes.c
// 描 述AES加密算法
// 创 建 人Liangbofu
// 创建日期2009-07-17
///////////////////////////////////////////////////////////////////////////////
#include "wechat_aes.h"
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
// 为了能针对C51进行优化并且又使代码可用于ARM和PC等环境
// 在非C51环境没有定义__C51__下需要把C51特定的关键字定义为空
#ifndef __C51__
#define code
#define data
#define idata
#define xdata
#define pdata
typedef unsigned char BOOL;
#else
typedef bit BOOL;
#endif
#define Nk (AES_KEY_LENGTH / 32) // 以“字”4字节为单位的密钥长度
#define Nb 4 // 以“字”4字节为单位的加解密数据块大小固定为4
// Nr加密的轮数
#if AES_KEY_LENGTH == 128
#define Nr 10
#elif AES_KEY_LENGTH == 192
#define Nr 12
#elif AES_KEY_LENGTH == 256
#define Nr 14
#else
#error AES_KEY_LENGTH must be 128, 192 or 256 BOOLs!
#endif
// GF(28) 多项式
#define BPOLY 0x1B // Lower 8 BOOLs of (x^8 + x^4 + x^3 + x + 1), ie. (x^4 + x^3 + x + 1).
// AES子密钥表当密钥长度为128位时占用176字节空间
static xdata unsigned char g_roundKeyTable[4*Nb*(Nr+1)];
// 加密用的SBox
static code const unsigned char SBox[256] =
{
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
};
// 解密用的SBox
static code const unsigned char InvSBox[256] =
{
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
};
///////////////////////////////////////////////////////////////////////////////
// 函数名: RotationWord
// 描述: 对一个“字”数据进行循环右移。
// 输入参数: pWord -- 要右移的4字节数据。
// 输出参数: pWord -- 右移后的4字节数据。
// 返回值: 无。
///////////////////////////////////////////////////////////////////////////////
static void RotationWord(unsigned char *pWord)
{
unsigned char temp = pWord[0];
pWord[0] = pWord[1];
pWord[1] = pWord[2];
pWord[2] = pWord[3];
pWord[3] = temp;
}
///////////////////////////////////////////////////////////////////////////////
// 函数名: XorBytes
// 描述: 批量异或两组数据。
// 输入参数: pData1 -- 要异或的第一组数据。
// pData1 -- 要异或的第二组数据。
// nCount -- 要异或的数据长度。
// 输出参数: pData1 -- 异或后的结果。
// 返回值: 无。
///////////////////////////////////////////////////////////////////////////////
static void XorBytes(unsigned char *pData1, const unsigned char *pData2, unsigned char nCount)
{
unsigned char i;
for (i = 0; i < nCount; i++)
{
pData1[i] ^= pData2[i];
}
}
///////////////////////////////////////////////////////////////////////////////
// 函数名: AddRoundKey
// 描述: 把 中间状态数据 加上异或子密钥数据长度为16字节。
// 输入参数: pState -- 状态数据。
// pRoundKey -- 子密钥数据。
// 输出参数: pState -- 加上子密钥后的状态数据。
// 返回值: 无。
///////////////////////////////////////////////////////////////////////////////
// static void AddRoundKey(unsigned char *pState, const unsigned char *pRoundKey)
// {
// XorBytes(pState, pRoundKey, 4*Nb);
// }
// AddRoundKey的宏形式比函数形式可以节省4字节的data数据
#define AddRoundKey(pState, pRoundKey) \
XorBytes((pState), (pRoundKey), 4*Nb)
///////////////////////////////////////////////////////////////////////////////
// 函数名: SubBytes
// 描述: 通过S盒子置换状态数据。
// 输入参数: pState -- 状态数据。
// nCount -- 状态数据长度。
// bInvert -- 是否使用反向S盒子解密时使用
// 输出参数: pState -- 置换后的状态数据。
// 返回值: 无。
///////////////////////////////////////////////////////////////////////////////
static void SubBytes(unsigned char *pState, unsigned char nCount, BOOL bInvert)
{
unsigned char i;
const unsigned char code *pSBox = bInvert ? InvSBox : SBox;
for (i = 0; i < nCount; i++)
{
pState[i] = pSBox[pState[i]];
}
}
///////////////////////////////////////////////////////////////////////////////
// 函数名: ShiftRows
// 描述: 把状态数据移行。
// 输入参数: pState -- 状态数据。
// bInvert -- 是否反向移行(解密时使用)。
// 输出参数: pState -- 移行后的状态数据。
// 返回值: 无。
///////////////////////////////////////////////////////////////////////////////
static void ShiftRows(unsigned char *pState, BOOL bInvert)
{
// 注意:状态数据以列形式存放!
unsigned char r; // row
unsigned char c; // column
unsigned char temp;
unsigned char rowData[4];
for (r = 1; r < 4; r++)
{
// 备份一行数据
for (c = 0; c < 4; c++)
{
rowData[c] = pState[r + 4*c];
}
temp = bInvert ? (4 - r) : r;
for (c = 0; c < 4; c++)
{
pState[r + 4*c] = rowData[(c + temp) % 4];
}
}
}
///////////////////////////////////////////////////////////////////////////////
// 函数名: GfMultBy02
// 描述: 在GF(28)域的 乘2 运算。
// 输入参数: num -- 乘数。
// 输出参数: 无。
// 返回值: num乘以2的结果。
///////////////////////////////////////////////////////////////////////////////
static unsigned char GfMultBy02(unsigned char num)
{
if ((num & 0x80) == 0)
{
num = num << 1;
}
else
{
num = (num << 1) ^ BPOLY;
}
return num;
}
///////////////////////////////////////////////////////////////////////////////
// 函数名: MixColumns
// 描述: 混合状态各列数据。
// 输入参数: pState -- 状态数据。
// bInvert -- 是否反向混合(解密时使用)。
// 输出参数: pState -- 混合列后的状态数据。
// 返回值: 无。
///////////////////////////////////////////////////////////////////////////////
static void MixColumns(unsigned char *pState, BOOL bInvert)
{
unsigned char i;
unsigned char temp;
unsigned char a0Pa2_M4; // 4(a0 + a2)
unsigned char a1Pa3_M4; // 4(a1 + a3)
unsigned char result[4];
for (i = 0; i < 4; i++, pState += 4)
{
// b0 = 2a0 + 3a1 + a2 + a3
// = (a0 + a1 + a2 + a3) + 2(a0 + a1) + a0
temp = pState[0] ^ pState[1] ^ pState[2] ^ pState[3];
result[0] = temp ^ pState[0] ^ GfMultBy02((unsigned char) (pState[0] ^ pState[1]));
result[1] = temp ^ pState[1] ^ GfMultBy02((unsigned char) (pState[1] ^ pState[2]));
result[2] = temp ^ pState[2] ^ GfMultBy02((unsigned char) (pState[2] ^ pState[3]));
result[3] = temp ^ pState[3] ^ GfMultBy02((unsigned char) (pState[3] ^ pState[0]));
if (bInvert)
{
// b0' = 14a0 + 11a1 + 13a2 + 9a3
// = (a0 + a1 + a2 + a3) + 2(a0 + a1) + a0 这部分为b0
// + 2(4(a0 + a2) + 4(a1 + a3))
// + 4(a0 + a2)
a0Pa2_M4 = GfMultBy02(GfMultBy02((unsigned char) (pState[0] ^ pState[2])));
a1Pa3_M4 = GfMultBy02(GfMultBy02((unsigned char) (pState[1] ^ pState[3])));
temp = GfMultBy02((unsigned char) (a0Pa2_M4 ^ a1Pa3_M4));
result[0] ^= temp ^ a0Pa2_M4;
result[1] ^= temp ^ a1Pa3_M4;
result[2] ^= temp ^ a0Pa2_M4;
result[3] ^= temp ^ a1Pa3_M4;
}
memcpy(pState, result, 4);
}
}
///////////////////////////////////////////////////////////////////////////////
// 函数名: BlockEncrypt
// 描述: 对单块数据加密。
// 输入参数: pState -- 状态数据。
// 输出参数: pState -- 加密后的状态数据。
// 返回值: 无。
///////////////////////////////////////////////////////////////////////////////
static void BlockEncrypt(unsigned char *pState)
{
unsigned char i;
AddRoundKey(pState, g_roundKeyTable);
for (i = 1; i <= Nr; i++) // i = [1, Nr]
{
SubBytes(pState, 4*Nb, 0);
ShiftRows(pState, 0);
if (i != Nr)
{
MixColumns(pState, 0);
}
AddRoundKey(pState, &g_roundKeyTable[4*Nb*i]);
}
// 为了节省代码,合并到循化执行
// SubBytes(pState, 4*Nb);
// ShiftRows(pState, 0);
// AddRoundKey(pState, &g_roundKeyTable[4*Nb*Nr]);
}
///////////////////////////////////////////////////////////////////////////////
// 函数名: BlockDecrypt
// 描述: 对单块数据解密。
// 输入参数: pState -- 状态数据。
// 输出参数: pState -- 解密后的状态数据。
// 返回值: 无。
///////////////////////////////////////////////////////////////////////////////
static void BlockDecrypt(unsigned char *pState)
{
unsigned char i;
AddRoundKey(pState, &g_roundKeyTable[4*Nb*Nr]);
for (i = Nr; i > 0; i--) // i = [Nr, 1]
{
ShiftRows(pState, 1);
SubBytes(pState, 4*Nb, 1);
AddRoundKey(pState, &g_roundKeyTable[4*Nb*(i-1)]);
if (i != 1)
{
MixColumns(pState, 1);
}
}
}
///////////////////////////////////////////////////////////////////////////////
// 函数名: AES_Init
// 描述: 初始化,在此执行扩展密钥操作。
// 输入参数: pKey -- 原始密钥,其长度必须为 AES_KEY_LENGTH/8 字节。
// 输出参数: 无。
// 返回值: 无。
///////////////////////////////////////////////////////////////////////////////
void AES_Init(const void *pKey)
{
// 扩展密钥
unsigned char i;
unsigned char *pRoundKey;
unsigned char Rcon[4] = {0x01, 0x00, 0x00, 0x00};
memcpy(g_roundKeyTable, pKey, 4*Nk);
pRoundKey = &g_roundKeyTable[4*Nk];
for (i = Nk; i < Nb*(Nr+1); pRoundKey += 4, i++)
{
memcpy(pRoundKey, pRoundKey - 4, 4);
if (i % Nk == 0)
{
RotationWord(pRoundKey);
SubBytes(pRoundKey, 4, 0);
XorBytes(pRoundKey, Rcon, 4);
Rcon[0] = GfMultBy02(Rcon[0]);
}
else if (Nk > 6 && i % Nk == Nb)
{
SubBytes(pRoundKey, 4, 0);
}
XorBytes(pRoundKey, pRoundKey - 4*Nk, 4);
}
}
unsigned int AES_get_length(unsigned int length)
{
return ((length>>4) + 1)<<4;
}
//////////////////////////////////////////////////////////////////////////
// 函数名: AES_Encrypt
// 描述: 加密数据
// 输入参数: pPlainText -- 明文即需加密的数据其长度为nDataLen字节。
// nDataLen -- 数据长度,以字节为单位
// pIV -- 初始化向量如果使用ECB模式可设为NULL。
// 输出参数: pCipherText -- 密文即由明文加密后的数据可以与pPlainText相同。
// 返回值: 无。
//////////////////////////////////////////////////////////////////////////
unsigned int AES_Encrypt_PKCS7(const unsigned char *pPlainText, unsigned char *pCipherText,
unsigned int nDataLen, const unsigned char *pIV)
{
unsigned int i;
//长度调整
unsigned int length = nDataLen;
nDataLen = ((nDataLen>>4) + 1)<<4;
uint8_t p=(Nb<<2)-(length%(Nb<<2));
if (pPlainText != pCipherText){memcpy(pCipherText,pPlainText,length);}
//填充
unsigned char temp[16];
memset(temp,p,16);
if(length<nDataLen)
{
memcpy(pCipherText + length,temp,nDataLen - length);
}
if(length == nDataLen)
{
memcpy(pCipherText + length,temp,16);
}
for (i = nDataLen/(4*Nb); i > 0 ; i--, pCipherText += 4*Nb)
{
#if AES_MODE == AES_MODE_CBC
XorBytes(pCipherText, pIV, 4*Nb);
#endif
BlockEncrypt(pCipherText);
pIV = pCipherText;
}
return(nDataLen);
}
//////////////////////////////////////////////////////////////////////////
// 函数名: AES_Decrypt
// 描述: 解密数据
// 输入参数: pCipherText -- 密文即需解密的数据其长度为nDataLen字节。
// nDataLen -- 数据长度以字节为单位必须为AES_KEY_LENGTH/8的整倍数。
// pIV -- 初始化向量如果使用ECB模式可设为NULL。
// 输出参数: pPlainText -- 明文即由密文解密后的数据可以与pCipherText相同。
// 返回值: 无。
//////////////////////////////////////////////////////////////////////////
void AES_Decrypt(unsigned char *pPlainText, const unsigned char *pCipherText,
unsigned int nDataLen, const unsigned char *pIV)
{
unsigned int i;
if (pPlainText != pCipherText)
{
memcpy(pPlainText, pCipherText, nDataLen);
}
// 从最后一块数据开始解密这样不用开辟空间来保存IV
pPlainText += nDataLen - 4*Nb;
for (i = nDataLen/(4*Nb); i > 0 ; i--, pPlainText -= 4*Nb)
{
BlockDecrypt(pPlainText);
#if AES_MODE == AES_MODE_CBC
if (i == 1)
{// 最后一块数据
XorBytes(pPlainText, pIV, 4*Nb);
}
else
{
XorBytes(pPlainText, pPlainText - 4*Nb, 4*Nb);
}
#endif
}
}

View file

@ -12,6 +12,8 @@
#include <stdbool.h>
#include <stdio.h>
#include "prf_defs.h"
#include "bta_api.h"
#include "bta_gatt_api.h"
#include "controller.h"
@ -23,10 +25,16 @@
#include "dis_api.h"
#include "bt_app_common.h"
//#include "app_button.h"
//#include "button_pro.h"
//#include "prf_defs.h"
#include "wx_airsync_prf.h"
#include "button_pro.h"
#include "hid_le_prf.h"
#include "prf_defs.h"
//
#include "hcimsgs.h"
#include "bt_app_defs.h"
@ -45,12 +53,20 @@ static unsigned char BASE_UUID[16] = {
};
UINT16 ijiazu_uuid = 0xffff;
UINT16 wechat_uuid = 0xfee7;
tBTA_BLE_SERVICE ijiazu_service = {
0x01, //only one service in the ijiazu button profile
false,
&ijiazu_uuid
}; /* 16 bits services */
tBTA_BLE_SERVICE wechat_service = {
0x01, //only one service in the ijiazu button profile
false,
&wechat_uuid
}; /* 16 bits services */
UINT8 beacon_manu[25] = {0x4c, 0x00,0x02, 0x15, 0xfd, 0xa5, 0x06, 0x93, 0xa4, 0xe2,
0x4f, 0xb1, 0xaf, 0xcf, 0xc6, 0xeb, 0x07, 0x64, 0x78, 0x25,
@ -58,8 +74,9 @@ UINT8 beacon_manu[25] = {0x4c, 0x00,0x02, 0x15, 0xfd, 0xa5, 0x06, 0x93, 0xa4, 0x
//UINT8 ijiazu_manu[17] = {0xff,0x20,0x14,0x07,0x22,0x00,0x02,0x5B,0x00,0x33,0x49,0x31,0x30,0x4a,0x30,0x30,0x31};
UINT8 ijiazu_manu[17] = {0xff,0x20,0x14,0x07,0x22,0x00,0x02,0x5B,0x00,0x33,0x49,0x31,0x30,0x4a,0x30,0x30,0x31};
UINT8 wechat_manu[] = {0x00,0x00,0x18,0xfe,0x34,0x6a,0x86,0x2e};
tBTA_BLE_MANU p_ijiazu_manu = {sizeof(ijiazu_manu),ijiazu_manu}; /* manufacturer data */
tBTA_BLE_MANU p_wechat_manu = {sizeof(wechat_manu),wechat_manu};
BD_ADDR rand_ijiazu_addr = {0x00,0x02,0x5B,0x00,0x32,0x55};
@ -104,6 +121,50 @@ tESP_BLE_ADV_DATA ijiazu_adv_data[ADV_SCAN_IDX_MAX] =
}
};
tESP_BLE_ADV_DATA wechat_adv_data[ADV_SCAN_IDX_MAX] =
{
[BLE_ADV_DATA_IDX] = {
.adv_name = NULL,
{
{0,0},
NULL, //no manufature data to be setting in the ijiazu adervetisiing datas
&wechat_service,
NULL, //the 128 bits service uuid set to null(not used)
NULL, //the 32 bits Service UUID set to null(not used)
NULL, //16 bits services Solicitation UUIDs set to null(not used)
NULL, //List of 32 bit Service Solicitation UUIDs set to null(not used)
NULL, //List of 128 bit Service Solicitation UUIDs set to null(not used)
NULL, //proprietary data set to null(not used)
NULL, //service data set not null(no service data to be sent)
0x0200, //device type : generic display
BTA_DM_GENERAL_DISC, // General discoverable.
0xFE //the tx power value,defult value is 0
},
},
[BLE_SCAN_RSP_DATA_IDX] = {
.adv_name = "wechat_demo",
{
{0,0},
&p_wechat_manu,
NULL,
NULL, //the 128 bits service uuid set to null(not used)
NULL, //the 32 bits Service UUID set to null(not used)
NULL, //16 bits services Solicitation UUIDs set to null(not used)
NULL, //List of 32 bit Service Solicitation UUIDs set to null(not used)
NULL, //List of 128 bit Service Solicitation UUIDs set to null(not used)
NULL, //proprietary data set to null(not used)
NULL, //service data set not null(no service data to be sent)
0x0000, //device type : generic display
0x00, // General discoverable.
0x00}, //the tx power value,defult value is 0
}
};
#if (BUT_PROFILE_CFG)
static void SimpleDataCallBack(UINT8 app_id, UINT8 event, UINT8 len, UINT8 *p_data);
#endif
typedef struct {
uint8_t uu[16];
@ -180,10 +241,19 @@ static void bta_gatts_set_adv_data_cback(tBTA_STATUS call_status)
bas_register();
/*instantiate the driver for button profile*/
//app_button_init();
#if (BUT_PROFILE_CFG)
/*instantiate a button service*/
//button_init();
button_init(SimpleDataCallBack);
#endif ///BUT_PROFILE_CFG
#if (HIDD_LE_PROFILE_CFG)
/*instantiate a hid device service*/
hidd_le_init();
#endif ///HIDD_LE_PROFILE_CFG
#if (WX_AIRSYNC_CFG)
AirSync_Init(NULL);
#endif ///WX_AIRSYNC_CFG
/*start advetising*/
// BTA_GATTS_Listen(server_if, true, NULL);
}
@ -202,10 +272,10 @@ void bta_gatts_callback(tBTA_GATTS_EVT event, tBTA_GATTS* p_data)
LOG_ERROR("set advertising parameters\n");
//set the advertising data to the btm layer
ESP_AppBleConfigadvData(&ijiazu_adv_data[BLE_ADV_DATA_IDX],
ESP_AppBleConfigadvData(&wechat_adv_data[BLE_ADV_DATA_IDX],
bta_gatts_set_adv_data_cback);
//set the adversting data to the btm layer
ESP_AppBleSetScanRsp(&ijiazu_adv_data[BLE_SCAN_RSP_DATA_IDX],NULL);
ESP_AppBleSetScanRsp(&wechat_adv_data[BLE_SCAN_RSP_DATA_IDX],NULL);
}
break;
@ -227,6 +297,25 @@ void bta_gatts_callback(tBTA_GATTS_EVT event, tBTA_GATTS* p_data)
}
#if (BUT_PROFILE_CFG)
static void SimpleDataCallBack(UINT8 app_id, UINT8 event, UINT8 len, UINT8 *p_data)
{
LOG_ERROR("the event value is:%x\n",event);
switch(event)
{
case RECEIVE_NET_PASSWD_EVT:
LOG_ERROR("Received the network passwork");
break;
case RECEIVE_NET_SSD_EVT:
LOG_ERROR("Received the network SSID");
break;
default:
break;
}
}
#endif ///BUT_PROFILE_CFG
static void ble_server_appRegister(void)
{
bt_uuid_t uuid;

View file

@ -12,9 +12,10 @@ COMPONENT_SRCDIRS := \
app_client_profiles/battery_c \
app_client_profiles \
app_profiles/app_sample_button \
app_profiles/app_WX_airsync \
app_profiles \
app_project
app_project
CFLAGS += -Wno-error=unused-label -Wno-error=return-type -Wno-error=missing-braces -Wno-error=pointer-sign -Wno-error=parentheses -I./include

View file

@ -0,0 +1,47 @@
/**
****************************************************************************************
*
* @file app_airsync_md5.h
*
* @brief Application airsync md5 generation head Entry Point
*
* Copyright (C) ESPRESSIF 2016
* Created by Yulong at 2016/10/9
*
****************************************************************************************
*/
#ifndef __APP_AIRSYNC_MD5__
#define __APP_AIRSYNC_MD5__
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#define SINGLE_ONE_BIT 0x80
#define BLOCK_SIZE 512
#define MOD_SIZE 448
#define APP_SIZE 64
#define BITS 8
// MD5 Chaining Variable
#define A 0x67452301UL
#define B 0xEFCDAB89UL
#define C 0x98BADCFEUL
#define D 0x10325476UL
typedef struct
{
char *str;
uint32_t len;
}MD5String;
int32_t wechat_md5 ( char *argv, uint8_t *md5_32);
#endif /// __APP_AIRSYNC_MD5__

View file

@ -0,0 +1,41 @@
/**
****************************************************************************************
*
* @file app_airsync_prf.h
*
* @brief Application Security Entry Point
*
* Copyright (C) ESPRESSIF 2016
* Created by Yulong at 2016/9/30
*
****************************************************************************************
*/
#ifndef _APP_AIRSYNC_PRF_H__
#define _APP_AIRSYNC_PRF_H__
#include "app_wechat_util.h"
#include <stdint.h>
#include <stdbool.h>
#define MAGIC_NUMBER 0xFE
/**
****************************************************************************************
* @brief Create Wechat Database
*
****************************************************************************************
*/
void app_wechat_create_db(void);
void app_wechat_SetDatahandler(data_handler* pHandler);
int ble_wechat_indicate_data(uint8_t *data, int len);
int ble_wechat_indicate_data_chunk(void);
void ble_wechat_process_received_data(uint8_t* pData, uint32_t length);
data_handler* app_wechat_datahandler(void);
bool ble_wechat_is_last_data_sent_out(void);
#endif ///_APP_AIRSYNC_PRF_H__

View file

@ -0,0 +1,81 @@
#ifndef __APP_WECHAT_UTIL_H__
#define __APP_WECHAT_UTIL_H__
#include <stdint.h>
#include <string.h>
#define PRODUCT_TYPE_UNKNOWN 0
#define PRODUCT_TYPE_MPBLEDEMO2 1
typedef void (*data_produce_func)(void *args, uint8_t **r_data, uint32_t *r_len);
typedef void (*data_free_func)(uint8_t *data, uint32_t len);
typedef int (*data_consume_func)(uint8_t *data, uint32_t len);
typedef void (*data_error_func)(int error_code);
typedef int32_t (*data_button_handler_func)(uint8_t pin_no);
typedef void (*data_main_process_func)(void);
typedef int32_t (*data_init_func)(void);
typedef int32_t (*data_init_peripheral_func)(void);
typedef struct data_handler{
int m_product_type;
data_produce_func m_data_produce_func;
data_free_func m_data_free_func;
data_consume_func m_data_consume_func;
data_error_func m_data_error_func;
data_init_peripheral_func m_data_init_peripheral_func;
data_init_func m_data_init_func;
data_main_process_func m_data_main_process_func;
data_button_handler_func m_data_button_handler_func;
void *m_data_produce_args;
struct data_handler *next;
} data_handler;
extern data_handler first_handler;
#define REGISTER(NAME) \
do { \
data_handler *tmp = &NAME##_data_handler; \
tmp->next = first_handler.next; \
first_handler.next = tmp; \
} while(0)
#define ARGS_ITEM_SET(ARGS_TYPE, ARGS_POINTER, ITEM_NAME, ITEM_VALUE) \
do { \
ARGS_TYPE *tmp = (ARGS_TYPE *)(ARGS_POINTER); \
tmp->ITEM_NAME = (ITEM_VALUE); \
} while(0)
typedef struct
{
unsigned char bMagicNumber;
unsigned char bVer;
unsigned short nLength;
unsigned short nCmdId;
unsigned short nSeq;
} BpFixHead;
/*
* TYPE DEFINITIONS
****************************************************************************************
*/
typedef struct
{
uint8_t *data;
uint16_t len;
uint16_t offset;
} data_info;
data_handler* get_handler_by_type(int type);
unsigned short htons(unsigned short val);
unsigned short ntohs(unsigned short val);
unsigned long t_htonl(unsigned long h);
unsigned long t_ntohl(unsigned long n);
void wechat_error_chack(data_handler *p_data_handler, int error_code);
void data_handler_init(data_handler** p_data_handler, uint8_t product_type);
#endif ///__APP_WECHAT_UTIL_H__

View file

@ -0,0 +1,110 @@
// epb.h
// MicroMessenger
//
// Created by harlliu@tencent.com on 14-02-15.
// Copyright 2014 Tencent. All rights reserved.
//
// Version : 1.0.2
#ifndef __EPB_H__
#define __EPB_H__
#include <stdint.h>
#include <stdbool.h>
typedef struct
{
uint8_t *data;
int len;
} Bytes;
typedef struct
{
const uint8_t *data;
int len;
} CBytes;
typedef struct
{
char *str;
int len;
} String;
typedef struct
{
const char *str;
int len;
} CString;
typedef uint8_t Message;
typedef struct
{
const uint8_t *unpack_buf;
uint8_t *pack_buf;
int buf_len;
int buf_offset;
} Epb;
/*
* embeded protobuf unpack functions
*/
void epb_unpack_init(Epb *e, const uint8_t *buf, int len);
bool epb_has_tag(Epb *e, uint16_t tag);
//Varint
int32_t epb_get_int32(Epb *e, uint16_t tag);
uint32_t epb_get_uint32(Epb *e, uint16_t tag);
int32_t epb_get_sint32(Epb *e, uint16_t tag);
bool epb_get_bool(Epb *e, uint16_t tag);
int epb_get_enum(Epb *e, uint16_t tag);
//Length Delimited
const char *epb_get_string(Epb *e, uint16_t tag, int *len);
const uint8_t *epb_get_bytes(Epb *e, uint16_t tag, int *len);
const Message *epb_get_message(Epb *e, uint16_t tag, int *len);
//Length Delimited Packed Repeadted Field
//TODO
//Fixed32
uint32_t epb_get_fixed32(Epb *e, uint16_t tag);
int32_t epb_get_sfixed32(Epb *e, uint16_t tag);
float epb_get_float(Epb *e, uint16_t tag);
/*
* embeded protobuf pack functions
*/
void epb_pack_init(Epb *e, uint8_t *buf, int len);
int epb_get_packed_size(Epb *e);
//Varint
int epb_set_int32(Epb *e, uint16_t tag, int32_t value);
int epb_set_uint32(Epb *e, uint16_t tag, uint32_t value);
int epb_set_sint32(Epb *e, uint16_t tag, int32_t value);
int epb_set_bool(Epb *e, uint16_t tag, bool value);
int epb_set_enum(Epb *e, uint16_t tag, int value);
//Length Delimited
int epb_set_string(Epb *e, uint16_t tag, const char *data, int len);
int epb_set_bytes(Epb *e, uint16_t tag, const uint8_t *data, int len);
int epb_set_message(Epb *e, uint16_t tag, const Message *data, int len);
//Length Delimited Packed Repeadted Field
//TODO
//Fixed32
int epb_set_fixed32(Epb *e, uint16_t tag, uint32_t value);
int epb_set_sfixed32(Epb *e, uint16_t tag, int32_t value);
int epb_set_float(Epb *e, uint16_t tag, float value);
//Pack size
int epb_varint32_pack_size(uint16_t tag, uint32_t value, bool is_signed);
int epb_fixed32_pack_size(uint16_t tag);
int epb_length_delimited_pack_size(uint16_t tag, int len);
#endif

View file

@ -0,0 +1,241 @@
// epb_MmBp.h
// WeChat Embedded Proto Buffer
//
// Generated by harlliu@tencent.com on 14-11-26.
// Copyright 2014 Tencent. All rights reserved.
//
// Version : 1.0.4
#ifndef __EPB_MMBP_H__
#define __EPB_MMBP_H__
#include "epb.h"
typedef enum
{
ECI_none = 0,
ECI_req_auth = 10001,
ECI_req_sendData = 10002,
ECI_req_init = 10003,
ECI_resp_auth = 20001,
ECI_resp_sendData = 20002,
ECI_resp_init = 20003,
ECI_push_recvData = 30001,
ECI_push_switchView = 30002,
ECI_push_switchBackgroud = 30003,
ECI_err_decode = 29999
} EmCmdId;
typedef enum
{
EEC_system = -1,
EEC_needAuth = -2,
EEC_sessionTimeout = -3,
EEC_decode = -4,
EEC_deviceIsBlock = -5,
EEC_serviceUnAvalibleInBackground = -6,
EEC_deviceProtoVersionNeedUpdate = -7,
EEC_phoneProtoVersionNeedUpdate = -8,
EEC_maxReqInQueue = -9,
EEC_userExitWxAccount = -10
} EmErrorCode;
typedef enum
{
EAM_md5 = 1,
EAM_macNoEncrypt = 2
} EmAuthMethod;
typedef enum
{
EIRFF_userNickName = 0x1,
EIRFF_platformType = 0x2,
EIRFF_model = 0x4,
EIRFF_os = 0x8,
EIRFF_time = 0x10,
EIRFF_timeZone = 0x20,
EIRFF_timeString = 0x40
} EmInitRespFieldFilter;
typedef enum
{
EIS_deviceChat = 1,
EIS_autoSync = 2
} EmInitScence;
typedef enum
{
EPT_ios = 1,
EPT_andriod = 2,
EPT_wp = 3,
EPT_s60v3 = 4,
EPT_s60v5 = 5,
EPT_s40 = 6,
EPT_bb = 7
} EmPlatformType;
typedef enum
{
EDDT_manufatureSvr = 0,
EDDT_wxWristBand = 1,
EDDT_wxDeviceHtmlChatView = 10001
} EmDeviceDataType;
typedef enum
{
ESVO_enter = 1,
ESVO_exit = 2
} EmSwitchViewOp;
typedef enum
{
EVI_deviceChatView = 1,
EVI_deviceChatHtmlView = 2
} EmViewId;
typedef enum
{
ESBO_enterBackground = 1,
ESBO_enterForground = 2,
ESBO_sleep = 3
} EmSwitchBackgroundOp;
typedef struct
{
void *none;
} BaseRequest;
typedef struct
{
int32_t err_code;
bool has_err_msg;
CString err_msg;
} BaseResponse;
typedef struct
{
void *none;
} BasePush;
typedef struct
{
BaseRequest *base_request;
bool has_md5_device_type_and_device_id;
Bytes md5_device_type_and_device_id;
int32_t proto_version;
int32_t auth_proto;
EmAuthMethod auth_method;
bool has_aes_sign;
Bytes aes_sign;
bool has_mac_address;
Bytes mac_address;
bool has_time_zone;
String time_zone;
bool has_language;
String language;
bool has_device_name;
String device_name;
} AuthRequest;
typedef struct
{
BaseResponse *base_response;
CBytes aes_session_key;
} AuthResponse;
typedef struct
{
BaseRequest *base_request;
bool has_resp_field_filter;
Bytes resp_field_filter;
bool has_challenge;
Bytes challenge;
} InitRequest;
typedef struct
{
BaseResponse *base_response;
uint32_t user_id_high;
uint32_t user_id_low;
bool has_challeange_answer;
uint32_t challeange_answer;
bool has_init_scence;
EmInitScence init_scence;
bool has_auto_sync_max_duration_second;
uint32_t auto_sync_max_duration_second;
bool has_user_nick_name;
CString user_nick_name;
bool has_platform_type;
EmPlatformType platform_type;
bool has_model;
CString model;
bool has_os;
CString os;
bool has_time;
int32_t time;
bool has_time_zone;
int32_t time_zone;
bool has_time_string;
CString time_string;
} InitResponse;
typedef struct
{
BaseRequest *base_request;
Bytes data;
bool has_type;
EmDeviceDataType type;
} SendDataRequest;
typedef struct
{
BaseResponse *base_response;
bool has_data;
CBytes data;
} SendDataResponse;
typedef struct
{
BasePush *base_push;
CBytes data;
bool has_type;
EmDeviceDataType type;
} RecvDataPush;
typedef struct
{
BasePush *base_push;
EmSwitchViewOp switch_view_op;
EmViewId view_id;
} SwitchViewPush;
typedef struct
{
BasePush *base_push;
EmSwitchBackgroundOp switch_background_op;
} SwitchBackgroudPush;
BaseResponse *epb_unpack_base_response(const uint8_t *buf, int buf_len);
void epb_unpack_base_response_free(BaseResponse *response);
int epb_auth_request_pack_size(AuthRequest *request);
int epb_pack_auth_request(AuthRequest *request, uint8_t *buf, int buf_len);
AuthResponse *epb_unpack_auth_response(const uint8_t *buf, int buf_len);
void epb_unpack_auth_response_free(AuthResponse *response);
int epb_init_request_pack_size(InitRequest *request);
int epb_pack_init_request(InitRequest *request, uint8_t *buf, int buf_len);
InitResponse *epb_unpack_init_response(const uint8_t *buf, int buf_len);
void epb_unpack_init_response_free(InitResponse *response);
int epb_send_data_request_pack_size(SendDataRequest *request);
int epb_pack_send_data_request(SendDataRequest *request, uint8_t *buf, int buf_len);
SendDataResponse *epb_unpack_send_data_response(const uint8_t *buf, int buf_len);
void epb_unpack_send_data_response_free(SendDataResponse *response);
RecvDataPush *epb_unpack_recv_data_push(const uint8_t *buf, int buf_len);
void epb_unpack_recv_data_push_free(RecvDataPush *push);
SwitchViewPush *epb_unpack_switch_view_push(const uint8_t *buf, int buf_len);
void epb_unpack_switch_view_push_free(SwitchViewPush *push);
SwitchBackgroudPush *epb_unpack_switch_backgroud_push(const uint8_t *buf, int buf_len);
void epb_unpack_switch_backgroud_push_free(SwitchBackgroudPush *push);
#endif

View file

@ -0,0 +1,132 @@
#ifndef __MPBLEDEMO2_H__
#define __MPBLEDEMO2_H__
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include "epb_MmBp.h"
#include "app_airsync_prf.h"
#define CMD_NULL 0
#define CMD_AUTH 1
#define CMD_INIT 2
#define CMD_SENDDAT 3
#define DEVICE_TYPE "gh_b57f1be552dd"
#define DEVICE_ID "gh_b57f1be552dd_8ecc3b117f8c05112638289b0952c797" //"wechat_dialog"
#define PROTO_VERSION 0x010004
#define AUTH_PROTO 1
#define MAC_ADDRESS_LENGTH 6
//#define EAM_md5AndNoEnrypt 1
#define EAM_md5AndAesEnrypt 1
//#define EAM_macNoEncrypt 2
#define DEVICE_KEY {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
#ifdef EAM_macNoEncrypt
#define AUTH_METHOD EAM_macNoEncrypt
#define MD5_TYPE_AND_ID_LENGTH 0
#define CIPHER_TEXT_LENGTH 0
#endif
#ifdef EAM_md5AndAesEnrypt
#define AUTH_METHOD EAM_md5AndAesEnrypt
#define MD5_TYPE_AND_ID_LENGTH 16
#define CIPHER_TEXT_LENGTH 16
#endif
#ifdef EAM_md5AndNoEnrypt
#define AUTH_METHOD EAM_md5AndNoEnrypt
#define MD5_TYPE_AND_ID_LENGTH 16
#define CIPHER_TEXT_LENGTH 0
#endif
#define CHALLENAGE_LENGTH 4
#define MPBLEDEMO2_MAGICCODE_H 0xfe
#define MPBLEDEMO2_MAGICCODE_L 0xcf
#define MPBLEDEMO2_VERSION 0x01
#define SEND_HELLO_WECHAT "Hello, WeChat!"
/* Hardware Resources define */
#define MPBLEDEMO2_LIGHT 19
#define MPBLEDEMO2_BUTTON_1 17
typedef enum
{
errorCodeUnpackAuthResp = 0x9990,
errorCodeUnpackInitResp = 0x9991,
errorCodeUnpackSendDataResp = 0x9992,
errorCodeUnpackCtlCmdResp = 0x9993,
errorCodeUnpackRecvDataPush = 0x9994,
errorCodeUnpackSwitchViewPush = 0x9995,
errorCodeUnpackSwitchBackgroundPush = 0x9996,
errorCodeUnpackErrorDecode = 0x9997,
} mpbledemo2UnpackErrorCode;
typedef enum
{
errorCodeProduce = 0x9980,
} mpbledemo2PackErrorCode;
// command ID between device and vendor server
typedef enum
{
sendTextReq = 0x01,
sendTextResp = 0x1001,
openLightPush = 0x2001,
closeLightPush = 0x2002,
} BleDemo2CmdID;
typedef struct
{
uint8_t m_magicCode[2];
uint16_t m_version;
uint16_t m_totalLength;
uint16_t m_cmdid;
uint16_t m_seq;
uint16_t m_errorCode;
} BlueDemoHead;
typedef struct
{
int cmd;
CString send_msg;
} mpbledemo2_info;
typedef struct
{
bool wechats_switch_state; //公众账号切换到前台的状态
bool indication_state;
bool auth_state;
bool init_state;
bool auth_send;
bool init_send;
unsigned short send_data_seq;
unsigned short push_data_seq;
unsigned short seq;
}mpbledemo2_state;
typedef void (*mpbledemo2_handler_func)(uint8_t *ptrData, uint32_t lengthInByte);
typedef struct
{
BleDemo2CmdID commandCode;
mpbledemo2_handler_func handler;
} MPBLEDEMO2_RECEIVED_CMD_HANDLER_T;
extern data_handler mpbledemo2_data_handler;
extern data_handler *m_mpbledemo2_handler;
extern void mpbledemo2_reset(void);
extern void mpbledemo2_indication_state(bool isEnable);
extern int32_t mpbledemo2_sendData(uint8_t* ptrData, uint32_t lengthInByte);
#endif

View file

@ -0,0 +1,24 @@
// crc32.h
// WeChat Embedded
//
// Created by harlliu on 14-03-03.
// Copyright 2014 Tencent. All rights reserved.
//
#ifndef __CRC32_H__
#define __CRC32_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
uint32_t crc32(uint32_t crc, const uint8_t *buf, int len);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,69 @@
///////////////////////////////////////////////////////////////////////////////
// 文 件 名AES.h
// 描 述AES加密算法
// 创 建 人Liangbofu
// 创建日期2009-07-17
///////////////////////////////////////////////////////////////////////////////
#ifndef __WECHAT_AES_H
#define __WECHAT_AES_H
#ifdef __cplusplus
extern "C" {
#endif
// 以bit为单位的密钥长度只能为 128192 和 256 三种
#define AES_KEY_LENGTH 128
// 加解密模式
#define AES_MODE_ECB 0 // 电子密码本模式(一般模式)
#define AES_MODE_CBC 1 // 密码分组链接模式
#define AES_MODE AES_MODE_CBC
///////////////////////////////////////////////////////////////////////////////
// 函数名: AES_Init
// 描述: 初始化,在此执行扩展密钥操作。
// 输入参数: pKey -- 原始密钥,其长度必须为 AES_KEY_LENGTH/8 字节。
// 输出参数: 无。
// 返回值: 无。
///////////////////////////////////////////////////////////////////////////////
void AES_Init(const void *pKey);
//////////////////////////////////////////////////////////////////////////
// 函数名: AES_Encrypt
// 描述: 加密数据
// 输入参数: pPlainText -- 明文即需加密的数据其长度为nDataLen字节。
// nDataLen -- 数据长度以字节为单位必须为AES_KEY_LENGTH/8的整倍数。
// pIV -- 初始化向量如果使用ECB模式可设为NULL。
// 输出参数: pCipherText -- 密文即由明文加密后的数据可以与pPlainText相同。
// 返回值: 无。
//////////////////////////////////////////////////////////////////////////
void AES_Encrypt(const unsigned char *pPlainText, unsigned char *pCipherText,
unsigned int nDataLen, const unsigned char *pIV);
//////////////////////////////////////////////////////////////////////////
// 函数名: AES_Decrypt
// 描述: 解密数据
// 输入参数: pCipherText -- 密文即需解密的数据其长度为nDataLen字节。
// nDataLen -- 数据长度以字节为单位必须为AES_KEY_LENGTH/8的整倍数。
// pIV -- 初始化向量如果使用ECB模式可设为NULL。
// 输出参数: pPlainText -- 明文即由密文解密后的数据可以与pCipherText相同。
// 返回值: 无。
//////////////////////////////////////////////////////////////////////////
void AES_Decrypt(unsigned char *pPlainText, const unsigned char *pCipherText,
unsigned int nDataLen, const unsigned char *pIV);
//对数据进行解密操作成功返回1失败返回0
unsigned char app_data_encode_aes(char *input, char *output, unsigned short *slen);
unsigned char app_data_decode_aes(unsigned char *input, char *output, unsigned short *slen);
unsigned int AES_Encrypt_PKCS7(const unsigned char *pPlainText, unsigned char *pCipherText,
unsigned int nDataLen, const unsigned char *pIV);
unsigned int AES_get_length(unsigned int length);
void AES_free(unsigned char* p);
#ifdef __cplusplus
}
#endif
#endif // __WECHAT_AES_H

View file

@ -1,10 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "bt.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "string.h"
extern void bte_main_boot_entry(void *);
@ -19,9 +15,8 @@ void pingTask(void *pvParameters)
}
}
void app_main()
void bt_app_main()
{
bt_controller_init();
xTaskCreatePinnedToCore(&pingTask, "pingTask", 2048, NULL, 5, NULL, 0);
bt_app_task_start_up();
bte_main_boot_entry(bt_app_core_start);