demo工程暂存 优化菜单界面UI和功能

This commit is contained in:
2024-04-29 16:32:24 +08:00
commit 330cd25cf1
3310 changed files with 2163318 additions and 0 deletions

View File

@ -0,0 +1,360 @@
/**
* Copyright (c) 2019, Freqchip
*
* All rights reserved.
*
* AMS client profile. protocol websit:
* https://developer.apple.com/library/archive/documentation/CoreBluetooth/Reference/AppleMediaService_Reference/Specification/Specification.html
*
*/
/*
* INCLUDES (包含头文件)
*/
#include <stdio.h>
#include <string.h>
#include "gap_api.h"
#include "gatt_api.h"
#include "gatt_sig_uuid.h"
#include "sys_utils.h"
#include "AMS_client.h"
/*
* MACROS (宏定义)
*/
#define REMOTE_CMD_UUID {0xc2, 0x51, 0xca, 0xf7, 0x56, 0x0e, 0xdf, 0xb8, \
0x8a, 0x4a, 0xb1, 0x57, 0xd8,0x81, 0x3c, 0x9b}
#define ENT_UPDATE_UUID {0x02, 0xc1, 0x96, 0xba, 0x92, 0xbb, 0x0c, 0x9a, \
0x1f, 0x41, 0x8d, 0x80, 0xce,0xab, 0x7c, 0x2f}
#define ENT_ATT_UUID {0xd7, 0xd5, 0xbb, 0x70, 0xa8, 0xa3, 0xab, 0xa6, \
0xd8, 0x46, 0xab, 0x23, 0x8c,0xf3, 0xb2, 0xc6}
/*
* CONSTANTS (常量定义)
*/
/*
* TYPEDEFS (类型定义)
*/
/*
* GLOBAL VARIABLES (全局变量)
*/
/*
* LOCAL VARIABLES (本地变量)
*/
static void AMS_gatt_write_cmd(uint8_t conidx,enum ams_att_idx att_idx,uint8_t *p_data, uint16_t len);
static void AMS_gatt_write_req(uint8_t conidx,enum ams_att_idx att_idx,uint8_t *p_data, uint16_t len);
static void AMS_gatt_read(uint8_t conidx,enum ams_att_idx att_idx);
static uint8_t cmd_id_mask;
static uint8_t AMS_client_conidx;
uint8_t AMS_client_id;
/*********************************************************************
* Profile Attributes - Table
* 每一项都是一个characteristic attribute对应的UUID的定义。
* 第一个是UUID的长度
* 每二个是UUID的值。
*/
const gatt_uuid_t AMS_att_tb[] =
{
[AMS_ATT_IDX_REMOTE_CMD] = { UUID_SIZE_16, REMOTE_CMD_UUID}, //write_req, ntf
[AMS_ATT_IDX_ENT_UPDATE] = { UUID_SIZE_16, ENT_UPDATE_UUID}, //write_req, ntf
[AMS_ATT_IDX_ENT_ATT] = { UUID_SIZE_16, ENT_ATT_UUID}, // read, write_req
};
void AMS_recv_entity_info(uint8_t conidx,uint8_t *p_data, uint16_t len)
{
/*
user get subscribed entity info here
*/
switch(p_data[0])
{
case ENTI_ID_PLAYER:
break;
case ENTI_ID_QUEUE:
break;
case ENTI_ID_TRACK:
if(p_data[2] & ENTI_UPDATE_FLAG_TRUNCATED)
{
co_printf("truncated\r\n");
}
if(p_data[1] ==TRACK_ATT_ID_ARTIST)
{
//show_utf8_string(&rsp[3],len -3);
}
else if(p_data[1] ==TRACK_ATT_ID_ALBUM)
{
//show_utf8_string(&rsp[3],len -3);
}
else if(p_data[1] ==TRACK_ATT_ID_TITLE)
{
//show_utf8_string(&rsp[3],len -3);
if(p_data[2] & ENTI_UPDATE_FLAG_TRUNCATED)
ams_subscribe_entity_att(ENTI_ID_TRACK,BIT(TRACK_ATT_ID_TITLE));
}
else if(p_data[1] ==TRACK_ATT_ID_DURATION)
{
// 0x32,0x38,0x35,0x2E,0x32,0x33,0x34, ==> 285.234 sec
//show_ascii_string(&rsp[3],len -3); //floating value.
}
break;
}
}
/*********************************************************************
* @fn AMS_gatt_msg_handler
*
* @brief Device information gatt message handler.
*
*
* @param p_msg - messages from GATT layer.
*
* @return none.
*/
uint16_t AMS_gatt_msg_handler(gatt_msg_t *p_msg)
{
co_printf("CCC:%x,att_idx[%d]\r\n",p_msg->msg_evt,p_msg->att_idx);
switch(p_msg->msg_evt)
{
case GATTC_MSG_NTF_REQ:
{
if(p_msg->att_idx == AMS_ATT_IDX_REMOTE_CMD)
{
//recv which commands is support by current music. one byte respresent one command
//refer to enum remote_cmd
show_reg(p_msg->param.msg.p_msg_data,p_msg->param.msg.msg_len,1);
uint8_t *value = p_msg->param.msg.p_msg_data;
AMS_client_conidx = p_msg->conn_idx;
cmd_id_mask = 0;
for(uint8_t i = 0; i< p_msg->param.msg.msg_len; i++) //update cmd_id_mask
cmd_id_mask |= (1<<(value[i]));
}
else if(p_msg->att_idx == AMS_ATT_IDX_ENT_UPDATE)
{
show_reg(p_msg->param.msg.p_msg_data,p_msg->param.msg.msg_len,1);
AMS_recv_entity_info(p_msg->conn_idx,p_msg->param.msg.p_msg_data, p_msg->param.msg.msg_len);
}
}
break;
case GATTC_MSG_READ_IND:
{
;
}
break;
case GATTC_MSG_CMP_EVT:
{
co_printf("op:%d done\r\n",p_msg->param.op.operation);
if(p_msg->param.op.operation == GATT_OP_PEER_SVC_REGISTERED)
{
uint16_t att_handles[3];
memcpy(att_handles,p_msg->param.op.arg,6);
show_reg((uint8_t *)att_handles,6,1);
if(att_handles[3] != 0)
{
gatt_client_enable_ntf_t ntf_enable;
ntf_enable.conidx = p_msg->conn_idx;
ntf_enable.client_id = AMS_client_id;
ntf_enable.att_idx = AMS_ATT_IDX_ENT_UPDATE;
gatt_client_enable_ntf(ntf_enable);
ntf_enable.att_idx = AMS_ATT_IDX_REMOTE_CMD;
gatt_client_enable_ntf(ntf_enable);
}
}
else if(p_msg->param.op.operation == GATT_OP_WRITE_REQ && p_msg->att_idx == AMS_ATT_IDX_ENT_ATT)
AMS_gatt_read(AMS_client_conidx,AMS_ATT_IDX_ENT_ATT);
}
break;
case GATTC_MSG_LINK_LOST:
if(p_msg->conn_idx == AMS_client_conidx)
AMS_client_conidx = 0xff;
break;
default:
break;
}
return 0;
}
/*********************************************************************
* @fn AMS_gatt_write_cmd
*
* @brief Write(without response) data to peer.
*
*
* @param conidx - link idx.
* att_idx - attribute idx,refer to enum ams_att_idx.
* p_data - pointer to buffer, its value will be sent.
* len - buffer len.
*
* @return none.
*/
void AMS_gatt_write_cmd(uint8_t conidx,enum ams_att_idx att_idx,uint8_t *p_data, uint16_t len)
{
gatt_client_write_t write;
write.conidx = conidx;
write.client_id = AMS_client_id;
write.att_idx = att_idx;
write.p_data = p_data;
write.data_len = len;
gatt_client_write_cmd(write);
}
/*********************************************************************
* @fn AMS_gatt_write_req
*
* @brief Write(with response) data to peer.
*
*
* @param conidx - link idx.
* att_idx - attribute idx,refer to enum ams_att_idx.
* p_data - pointer to buffer, its value will be sent.
* len - buffer len.
*
* @return none.
*/
void AMS_gatt_write_req(uint8_t conidx,enum ams_att_idx att_idx,uint8_t *p_data, uint16_t len)
{
gatt_client_write_t write;
write.conidx = conidx;
write.client_id = AMS_client_id;
write.att_idx = att_idx;
write.p_data = p_data;
write.data_len = len;
gatt_client_write_req(write);
}
/*********************************************************************
* @fn AMS_gatt_read
*
* @brief Read data from peer. read result will be update from GATT_EVENT: GATTC_MSG_READ_IND
*
*
* @param conidx - link idx.
* att_idx - attribute idx,refer to enum ams_att_idx.
*
* @return none.
*/
void AMS_gatt_read(uint8_t conidx,enum ams_att_idx att_idx)
{
gatt_client_read_t read;
read.conidx = conidx;
read.client_id = AMS_client_id;
read.att_idx = att_idx;
gatt_client_read(read);
}
/*********************************************************************
* @fn batt_gatt_add_service
*
* @brief Simple Profile add GATT service function.
* 添加GATT service到ATT的数据库里面。
*
* @param None.
*
*
* @return None.
*/
void AMS_gatt_add_client(void)
{
gatt_client_t client;
client.p_att_tb = AMS_att_tb;
client.att_nb = AMS_ATT_IDX_MAX;
client.gatt_msg_handler = AMS_gatt_msg_handler;
AMS_client_id = gatt_add_client(&client);
}
/***********************************Usage Example****************************************/
/*********************************************************************
* @fn ams_subscribe_entity_update
*
* @brief subscribe some entity info.
* call this function to subscribe what you are intrested.
* After att_idx: AMS_ATT_IDX_ENT_UPDATE is ntf enabled, call this func
*
* @param id - entity id. refer to enum entity_id_values
* att_id_bits - each bit represent each att_id, multi bits can be set to represent multi att_id is selected
*
* @return None.
* example: subscribe TRACK informations.
* ams_subscribe_entity_update(ENTI_ID_TRACK
* ,BIT(TRACK_ATT_ID_ARTIST)|BIT(TRACK_ATT_ID_ALBUM)|BIT(TRACK_ATT_ID_TITLE)|BIT(TRACK_ATT_ID_DURATION));
*
*/
void ams_subscribe_entity_update(enum entity_id_values id,uint8_t att_id_bits)
{
//you can subscribe one or more entity ids. and one or more att_ids.
uint8_t value[5];
uint8_t idx = 0;
value[idx++] = id;
for(uint8_t i=0; i<4; i++)
{
if(att_id_bits & BIT(i))
{
value[idx++] = i;
}
}
AMS_gatt_write_req(AMS_client_conidx,AMS_ATT_IDX_ENT_UPDATE,value,idx);
}
/*********************************************************************
* @fn ams_subscribe_entity_update
*
* @brief subscribe some entity info.
* call this function only when entity update response is truncated.
*
* @param id - entity id. refer to enum entity_id_values
* att_id_bit - each bit represent each att_id. but only one bit is allowed to be set
*
* @return None.
* example: subscribe TRACK & TRACK_ATT_ID_TITLE informations.
* ams_subscribe_entity_att(ENTI_ID_TRACK,BIT(TRACK_ATT_ID_TITLE));
*
*/
void ams_subscribe_entity_att(enum entity_id_values id,uint8_t att_id_bit)
{
uint8_t value[2];
value[0] = id;
for(uint8_t i=0; i<4; i++)
{
if(att_id_bit & BIT(i))
value[1] = i;
}
AMS_gatt_write_req(AMS_client_conidx,AMS_ATT_IDX_ENT_ATT,value,2);
}
/*********************************************************************
* @fn ams_control
*
* @brief send control cmd to apple, and control current music .
* After att_idx: AMS_ATT_IDX_REMOTE_CMD is ntf enabled, call this func
*
* @param cmd - command id, refet to enum remote_cmd.
*
* @return none.
*/
void ams_crtl_cmd(enum remote_cmd cmd)
{
uint8_t value = cmd;
if(cmd_id_mask & (1<<cmd))
AMS_gatt_write_req(AMS_client_conidx,AMS_ATT_IDX_REMOTE_CMD,&value,1);
}
/***********/

View File

@ -0,0 +1,191 @@
/**
* Copyright (c) 2019, Freqchip
*
* All rights reserved.
*
*
*/
#ifndef AMS_CLIENT_H
#define AMS_CLIENT_H
/*
* INCLUDES (<28><><EFBFBD><EFBFBD>ͷ<EFBFBD>ļ<EFBFBD>)
*/
#include <stdio.h>
#include <stdint.h>
#include "gap_api.h"
#include "gatt_api.h"
#include "gatt_sig_uuid.h"
#include "sys_utils.h"
/*
* MACROS (<28><EFBFBD><EAB6A8>)
*/
#define AMS_SVC_UUID "\xdc\xf8\x55\xad\x02\xc5\xf4\x8e\x3a\x43\x36\x0f\x2b\x50\xd3\x89"
/*
* CONSTANTS (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
*/
/*
* TYPEDEFS (<28><><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>)
*/
enum ams_att_idx
{
AMS_ATT_IDX_REMOTE_CMD, //47
AMS_ATT_IDX_ENT_UPDATE, //51
AMS_ATT_IDX_ENT_ATT, //55
AMS_ATT_IDX_MAX,
};
enum remote_cmd
{
CMD_ID_PLAY,
CMD_ID_PAUSE,
CMD_ID_TOGGLE_PLAY_PAUSE,
CMD_ID_NEXT_TRACK,
CMD_ID_PRE_TRACK,
CMD_ID_VOL_UP,
CMD_ID_VOL_DOWN,
CMD_ID_ADV_REPEAT_MODE,
CMD_ID_ADV_SHUFFLE_MODE,
CMD_ID_SKIP_FORWARD,
CMD_ID_SKIP_BACKWARD,
CMD_ID_LIKE_TRACK,
CMD_ID_DISLIKE_TRACK,
CMD_ID_BOOKMARK_TRACK,
};
enum entity_id_values
{
ENTI_ID_PLAYER,
ENTI_ID_QUEUE,
ENTI_ID_TRACK,
};
#define ENTI_UPDATE_FLAG_TRUNCATED (1<<0)
enum player_att_id_values
{
PLAYER_ATT_ID_NAME,
PLAYER_ATT_ID_PLAYBACK_INFO,
PLAYER_ATT_ID_VOL,
};
enum queue_att_id_values
{
QUEUE_ATT_ID_INDEX,
QUEUE_ATT_ID_COUNT,
QUEUE_ATT_ID_SHUFFLE_MODE,
QUEUE_ATT_ID_REPEAT_MODE,
};
enum track_att_id_values
{
TRACK_ATT_ID_ARTIST,
TRACK_ATT_ID_ALBUM,
TRACK_ATT_ID_TITLE,
TRACK_ATT_ID_DURATION,
};
enum shuffle_mode
{
SHUFFLE_MODE_OFF,
SHUFFLE_MODE_ONE,
SHUFFLE_MODE_ALL,
};
enum repeat_mode
{
REPEAT_MODE_OFF,
REPEAT_MODE_ONE,
REPEAT_MODE_ALL,
};
/*
* GLOBAL VARIABLES (ȫ<>ֱ<EFBFBD><D6B1><EFBFBD>)
*/
extern uint8_t AMS_client_id;
/*
* LOCAL VARIABLES (<28><><EFBFBD>ر<EFBFBD><D8B1><EFBFBD>)
*/
/*
* PUBLIC FUNCTIONS (ȫ<>ֺ<EFBFBD><D6BA><EFBFBD>)
*/
/*********************************************************************
* @fn AMS_gatt_add_client
*
* @brief AMS Profile add GATT client function.
* <20><><EFBFBD><EFBFBD>AMS GATT client<6E><74>ATT<54><54><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><DDBF><EFBFBD><EFBFBD>
*
* @param None.
*
*
* @return None.
*/
void AMS_gatt_add_client(void);
/*********************************************************************
* @fn ams_subscribe_entity_update
*
* @brief subscribe some entity info.
* call this function to subscribe what you are intrested.
* After att_idx: AMS_ATT_IDX_ENT_UPDATE is ntf enabled, call this func
*
* @param id - entity id. refer to enum entity_id_values
* att_id_bits - each bit represent each att_id, multi bits can be set to represent multi att_id is selected
*
* @return None.
* example: subscribe TRACK informations.
* ams_subscribe_entity_update(ENTI_ID_TRACK
* ,BIT(TRACK_ATT_ID_ARTIST)|BIT(TRACK_ATT_ID_ALBUM)|BIT(TRACK_ATT_ID_TITLE)|BIT(TRACK_ATT_ID_DURATION));
*
*/
void ams_subscribe_entity_update(enum entity_id_values id,uint8_t att_id_bits);
/*********************************************************************
* @fn ams_subscribe_entity_update
*
* @brief subscribe some entity info.
* call this function only when entity update response is truncated.
*
* @param id - entity id. refer to enum entity_id_values
* att_id_bit - each bit represent each att_id. but only one bit is allowed to be set
*
* @return None.
* example: subscribe TRACK & TRACK_ATT_ID_TITLE informations.
* ams_subscribe_entity_att(ENTI_ID_TRACK,BIT(TRACK_ATT_ID_TITLE));
*
*/
void ams_subscribe_entity_att(enum entity_id_values id,uint8_t att_id_bit);
/*********************************************************************
* @fn ams_control
*
* @brief send control cmd to apple, and control current music .
* After att_idx: AMS_ATT_IDX_REMOTE_CMD is ntf enabled, call this func
*
* @param cmd - command id, refet to enum remote_cmd.
*
* @return none.
* example: control iphone to play next track.
* ams_crtl_cmd(CMD_ID_NEXT_TRACK);
*
*/
void ams_crtl_cmd(enum remote_cmd cmd);
#endif

View File

@ -0,0 +1,36 @@
https://developer.apple.com/library/archive/documentation/CoreBluetooth/Reference/AppleMediaService_Reference/Specification/Specification.html
ʹ<EFBFBD>ò<EFBFBD><EFBFBD>
1 AMS_client.c&h <20>ļ<EFBFBD>·<EFBFBD><C2B7><EFBFBD><EFBFBD>\components\ble\profiles\ble_AMS
1 <20><><EFBFBD><EFBFBD><EFBFBD>ں<EFBFBD><DABA><EFBFBD>void user_entry_after_ble_init(void) <20>ڵ<EFBFBD><DAB5><EFBFBD> AMS_gatt_add_client();
2 case GAP_EVT_SLAVE_CONNECT: slave<76><65>ɫ<EFBFBD><C9AB><EFBFBD>ӳɹ<D3B3><C9B9><EFBFBD><EFBFBD>¼<EFBFBD><C2BC>ص<EFBFBD><D8B5>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD>
gap_security_req(event->param.slave_connect.conidx); <20><><EFBFBD>м<EFBFBD><D0BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
3 <20><>case GAP_SEC_EVT_SLAVE_ENCRYPT: slave<76><65>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɵ<EFBFBD><C9B5>¼<EFBFBD><C2BC>ص<EFBFBD><D8B5>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>´<EFBFBD><C2B4>룬ɨ<EBA3AC><C9A8>AMS<4D>ķ<EFBFBD><C4B7><EFBFBD><EFBFBD><EFBFBD>
gatt_discovery_peer_svc(AMS_client_id,event->param.slave_connect.conidx,16,AMS_SVC_UUID);
4 AMS_Client.c <20>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD>ĵط<C4B5><D8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void AMS_recv_entity_info(uint8_t conidx,uint8_t *p_data, uint16_t len)
5 AMS_recv_entity_info<66><6F><EFBFBD><EFBFBD><EFBFBD>ڣ<EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD>˶<EFBFBD><CBB6>ĵ<EFBFBD>ENTI_ID_TRACK <20><><EFBFBD>ĸ<EFBFBD><C4B8><EFBFBD><EFBFBD>ԵĴ<D4B5><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߡ<EFBFBD>ר<EFBFBD><D7A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD>ͣ<EFBFBD><CDA3>û<EFBFBD><C3BB><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> asm_subscribe_entity_update() <20><><EFBFBD>Ķ<EFBFBD>Ӧ<EFBFBD><D3A6>entity֮<79><D6AE><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1>
ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD>ڱ仯<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Բ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͡<EFBFBD>
6 Ҫ<><D2AA><EFBFBD>Ƹ<EFBFBD><C6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ţ<EFBFBD>ʹ<EFBFBD>ú<EFBFBD><C3BA><EFBFBD>ams_crtl_cmd()<29><><EFBFBD>С<EFBFBD>
7 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD>ݹ<EFBFBD><DDB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݱ<EFBFBD><DDB1>ضϣ<D8B6><CFA3><EFBFBD><EFBFBD>Ե<EFBFBD><D4B5><EFBFBD>ams_subscribe_entity_att(...)<29><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡijһ<C4B3><D2BB><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2>
8 <20><><EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD>ams<6D><73><EFBFBD>Կ<EFBFBD><D4BF>Ʒ<EFBFBD>ios<6F>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֲ<EFBFBD><D6B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E7A3BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
a) <20><><EFBFBD>ӽ<EFBFBD><D3BD><EFBFBD><EFBFBD>󣬰<EFBFBD><F3A3ACB0>°<EFBFBD><C2B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڰ<EFBFBD><DAB0><EFBFBD><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>´<EFBFBD><C2B4><EFBFBD>ĸ<EFBFBD><C4B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߡ<EFBFBD>ר<EFBFBD><D7A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>
ams_subscribe_entity_update(ENTI_ID_TRACK ,BIT(TRACK_ATT_ID_ARTIST)|BIT(TRACK_ATT_ID_ALBUM)|BIT(TRACK_ATT_ID_TITLE)|BIT(TRACK_ATT_ID_DURATION)); AMS_recv_entity_info(...) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD>˶<EFBFBD><CBB6>ĵĸ<C4B5><C4B8><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2>ÿ<EFBFBD>е<EFBFBD><D0B5><EFBFBD>һ<EFBFBD>׸<EFBFBD>ʱ<EFBFBD><CAB1>ios<6F><73><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Щ<EFBFBD><D0A9><EFBFBD>ݡ<EFBFBD>
b) <20><><EFBFBD>ӽ<EFBFBD><D3BD><EFBFBD><EFBFBD>󣬰<EFBFBD><F3A3ACB0>°<EFBFBD><C2B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڰ<EFBFBD><DAB0><EFBFBD><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>´<EFBFBD><C2B4><EFBFBD><EBB2A5><EFBFBD><EFBFBD>һ<EFBFBD>׸衣
ams_crtl_cmd(CMD_ID_NEXT_TRACK);
c) AMS_recv_entity_info(...) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD>˶<EFBFBD><CBB6>ĵĸ<C4B5><C4B8><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD>п<EFBFBD><D0BF><EFBFBD><EFBFBD><EFBFBD>Ϣ̫<CFA2><CCAB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݱ<EFBFBD><DDB1>ضϵ<D8B6><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E6B4A6>
else if(p_data[1] ==TRACK_ATT_ID_TITLE)
{
//show_utf8_string(&rsp[3],len -3);
if(p_data[2] & ENTI_UPDATE_FLAG_TRUNCATED)
ams_subscribe_entity_att(ENTI_ID_TRACK,BIT(TRACK_ATT_ID_TITLE));
}

View File

@ -0,0 +1,426 @@
/**
* Copyright (c) 2019, Freqchip
*
* All rights reserved.
*
* ANCS client profile. protocol websit:
* https://developer.apple.com/library/archive/documentation/CoreBluetooth/Reference/AppleNotificationCenterServiceSpecification
* /Specification/Specification.html#//apple_ref/doc/uid/TP40013460-CH1-SW14
*
*/
/*
* INCLUDES (<28><><EFBFBD><EFBFBD>ͷ<EFBFBD>ļ<EFBFBD>)
*/
#include <stdio.h>
#include <string.h>
#include "gap_api.h"
#include "gatt_api.h"
#include "gatt_sig_uuid.h"
#include "sys_utils.h"
#include "ANCS_client.h"
#include "driver_plf.h"
/*
* MACROS (<28><EFBFBD><EAB6A8>)
*/
/*
* CONSTANTS (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
*/
/*
* TYPEDEFS (<28><><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>)
*/
/*
* GLOBAL VARIABLES (ȫ<>ֱ<EFBFBD><D6B1><EFBFBD>)
*/
/*
* LOCAL VARIABLES (<28><><EFBFBD>ر<EFBFBD><D8B1><EFBFBD>)
*/
uint8_t ANCS_client_id;
#define CTL_POINT_UUID {0xd9, 0xd9, 0xaa, 0xfd, 0xbd, 0x9b, 0x21, 0x98, \
0xa8, 0x49, 0xe1, 0x45, 0xf3,0xd8, 0xd1, 0x69}
#define NTF_SRC_UUID {0xbd, 0x1d, 0xa2, 0x99, 0xe6, 0x25, 0x58, 0x8c, \
0xd9, 0x42, 0x01, 0x63, 0x0d,0x12, 0xbf, 0x9f}
#define DATA_SRC_UUID {0xfb, 0x7b, 0x7c, 0xce, 0x6a, 0xb3, 0x44, 0xbe, \
0xb5, 0x4b, 0xd6, 0x24, 0xe9,0xc6, 0xea, 0x22}
/*********************************************************************
* Profile Attributes - Table
* ÿһ<C3BF><EFBFBD><EEB6BC>һ<EFBFBD><D2BB>characteristic attribute<74><65>Ӧ<EFBFBD><D3A6>UUID<49>Ķ<EFBFBD><C4B6>
* <20><>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>UUID<49>ij<EFBFBD><C4B3>ȣ<EFBFBD>
* ÿ<><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>UUID<49><44>ֵ<EFBFBD><D6B5>
*/
const gatt_uuid_t ANCS_att_tb[] =
{
[ANCS_ATT_IDX_CTL_POINT] = { UUID_SIZE_16, CTL_POINT_UUID},
[ANCS_ATT_IDX_NTF_SRC] = { UUID_SIZE_16, NTF_SRC_UUID},
[ANCS_ATT_IDX_DATA_SRC] = { UUID_SIZE_16, DATA_SRC_UUID},
};
static uint16_t ANCS_hdl_cache[3] = {0};
uint32_t call_notification_uid ;
uint32_t social_notification_uid ;
#define EVENT_ID_NOTIFICATION_ADD (0) /**< The arrival of a new iOS notification on the NP */
#define EVENT_ID_NOTIFICATION_MODIFIED (1) /**< The modification of an iOS notification on the NP */
#define EVENT_ID_NOTIFICATION_REMOVED (2) /**< The removal of an iOS notification on the NP */
#define EVENT_ID_NOTIFICATION_RESERVED (0xff)
#define EVT_FLAG_SILENT BIT(0)
#define EVT_FLAG_IMPORTANT BIT(1)
#define EVT_FLAG_PRE_EXSITING BIT(2)
#define EVT_FLAG_POSITIVE BIT(3)
#define EVT_FLAG_NEGATIVE BIT(4)
#define CATGRY_ID_OTHER (0)
#define CATGRY_ID_INCOMING_CALL (1)
#define CATGRY_ID_MISS_CALL (2)
#define CATGRY_ID_VOICE_MAIL (3)
#define CATGRY_ID_SOCIAL (4)
#define CATGRY_ID_SCHEDULE (5)
#define CATGRY_ID_EMAIL (6)
#define CATGRY_ID_NEWS (7)
#define CATGRY_ID_HEALTH (8)
#define CATGRY_ID_BUSINESS (9)
#define CATGRY_ID_LOCATION (10)
#define CATGRY_ID_ENTERTAINMENT (11)
__PACKED struct ancs_ntf_src
{
uint8_t event_id;
uint8_t event_flags;
uint8_t category_id;
uint8_t category_cnt;
uint32_t ntf_uid;
}GCC_PACKED;
#define NTF_ATT_ID_APPLE 0
#define NTF_ATT_ID_TITLE 1
#define NTF_ATT_ID_SUBTITLE 2
#define NTF_ATT_ID_MSG 3
#define NTF_ATT_ID_MSG_SIZE 4
#define NTF_ATT_ID_DATE 5
#define NTF_ATT_ID_POSITIVE_ACT 6
#define NTF_ATT_ID_NEGATIVE_ACT 7
void ANCS_recv_ntf_src(uint8_t conidx,uint8_t *p_data, uint16_t len)
{
if(len != 8)
goto _exit;
struct ancs_ntf_src *ntf_src = (struct ancs_ntf_src *)p_data;
co_printf("event_id:%d,event_flags:%x,category_id:%d,category_cnt:%d,ntf_uid:%x\r\n",ntf_src->event_id
,ntf_src->event_flags,ntf_src->category_id,ntf_src->category_cnt,ntf_src->ntf_uid);
if( (ntf_src->category_id == CATGRY_ID_SOCIAL
|| ntf_src->category_id == CATGRY_ID_OTHER
|| ntf_src->category_id == CATGRY_ID_INCOMING_CALL
|| ntf_src->category_id == CATGRY_ID_EMAIL) &&
((ntf_src->event_flags & EVT_FLAG_PRE_EXSITING) != 0x04))
{
if(ntf_src->category_id == CATGRY_ID_INCOMING_CALL)
call_notification_uid = ntf_src->ntf_uid;
if(ntf_src->category_id == CATGRY_ID_SOCIAL)
social_notification_uid = ntf_src->ntf_uid;
if(ntf_src->category_id == CATGRY_ID_MISS_CALL)
co_printf("Miss call !\r\n");
if(ntf_src->event_id != EVENT_ID_NOTIFICATION_REMOVED)
{
co_printf("Send RSP\r\n");
uint16_t max_att_len = gatt_get_mtu(conidx)-3;
uint8_t rsp[19];
uint8_t i = 0;
rsp[i++] = ANCS_CMD_ID_GET_NOTIFICATION_ATTR; //cmd id
*(uint32_t *)(rsp + i) = ntf_src->ntf_uid; //ntf_uid
i+=4;
rsp[i++] = NTF_ATT_ID_APPLE;
rsp[i++] = NTF_ATT_ID_TITLE;
rsp[i++] = (max_att_len & 0xff);
rsp[i++] = (max_att_len & 0xff00)>>8;
rsp[i++] = NTF_ATT_ID_SUBTITLE;
rsp[i++] = (max_att_len & 0xff);
rsp[i++] = (max_att_len & 0xff00)>>8;
rsp[i++] = NTF_ATT_ID_MSG;
rsp[i++] = (max_att_len & 0xff);
rsp[i++] = (max_att_len & 0xff00)>>8;
rsp[i++] = NTF_ATT_ID_MSG_SIZE;
rsp[i++] = NTF_ATT_ID_DATE;
rsp[i++] = NTF_ATT_ID_POSITIVE_ACT;
rsp[i++] = NTF_ATT_ID_NEGATIVE_ACT;
ANCS_gatt_write_req(conidx,ANCS_ATT_IDX_CTL_POINT,rsp,sizeof(rsp));
}
}
_exit:
;
}
enum ntf_msg_type_t
{
WEIXIN,
MOBILE_SMS,
MOBILE_PHONE,
QQ,
};
void ANCS_recv_data_src(uint8_t conidx,uint8_t *p_data, uint16_t len)
{
uint8_t *str = NULL;
uint16_t str_len = 0;
enum ntf_msg_type_t msg_type = 0;
uint16_t i = 0;
uint16_t data_len = 0;
uint8_t event_id = p_data[i++];
uint32_t uid = *(uint32_t *)(p_data + i);
i+=4;
co_printf("evt_id:%d,uid:%x,len:%d\r\n",event_id,uid,len);
while(i < len)
{
switch(p_data[i++])
{
case NTF_ATT_ID_APPLE:
data_len = *(uint16_t *)(p_data + i);
i+=2;
//show_reg(p_data + i,data_len,1);
if( memcmp(p_data+i,"com.tencent.xin",strlen("com.tencent.xin"))==0 )
msg_type = WEIXIN;
else if( memcmp(p_data+i,"com.apple.MobileSMS",strlen("com.apple.MobileSMS"))==0 )
msg_type = MOBILE_SMS;
else if( memcmp(p_data+i,"com.apple.mobilephone",strlen("com.apple.mobilephone"))==0 )
msg_type = MOBILE_PHONE;
else if( memcmp(p_data+i,"com.tencent.mqq",strlen("com.tencent.mqq"))==0 )
msg_type = QQ;
else if( memcmp(p_data+i,"com.tencent.qq",strlen("com.tencent.qq"))==0 )
msg_type = QQ;
co_printf("NTF_ATT_ID_APPLE,msg_type:%d,len:%d\r\n",msg_type,data_len);
i+=data_len;
break;
case NTF_ATT_ID_TITLE: //UTF-8
data_len = *(uint16_t *)(p_data + i);
co_printf("NTF_ATT_ID_TITLE,len:%d\r\n",data_len);
i+=2;
show_utf8_hex(p_data + i,data_len,1);
//str = (uint8_t *)(p_data + i);
//str_len += data_len;
i+=data_len;
break;
case NTF_ATT_ID_SUBTITLE: //UTF-8
data_len = *(uint16_t *)(p_data + i);
co_printf("NTF_ATT_ID_SUBTITLE,len:%d\r\n",data_len);
i+=2;
show_utf8_hex(p_data + i,data_len,1);
i+=data_len;
break;
case NTF_ATT_ID_MSG: //UTF-8
data_len = *(uint16_t *)(p_data + i);
co_printf("NTF_ATT_ID_MSG,len:%d\r\n",data_len);
i+=2;
show_utf8_hex(p_data + i,data_len,1);
//str = (uint8_t *)(p_data + i);
//str_len += data_len;
i+=data_len;
break;
case NTF_ATT_ID_MSG_SIZE: //ASCII
data_len = *(uint16_t *)(p_data + i);
co_printf("NTF_ATT_ID_MSG_SIZE,len:%d\r\n",data_len);
i+=2;
show_reg(p_data + i,data_len,1);
i+=data_len;
break;
case NTF_ATT_ID_DATE: //ASCII
data_len = *(uint16_t *)(p_data + i);
co_printf("NTF_ATT_ID_DATE,len:%d\r\n",data_len);
i+=2;
show_reg(p_data + i,data_len,1);
i+=data_len;
break;
case NTF_ATT_ID_POSITIVE_ACT: //UTF-8
data_len = *(uint16_t *)(p_data + i);
co_printf("NTF_ATT_ID_POSITIVE_ACT,len:%d\r\n",data_len);
i+=2;
show_utf8_hex(p_data + i,data_len,1);
i+=data_len;
break;
case NTF_ATT_ID_NEGATIVE_ACT: //UTF-8
data_len = *(uint16_t *)(p_data + i);
co_printf("NTF_ATT_ID_NEGATIVE_ACT,len:%d\r\n",data_len);
i+=2;
show_utf8_hex(p_data + i,data_len,1);
i+=data_len;
break;
default:
co_printf("ERRR\r\n");
break;
}
}
*(str + str_len) = 0;
if(msg_type == 0)
{
//ui_show_phone_call(3000,str);
}
else
{
//ui_show_chinese_str(msg_type,3000,str);
}
}
/*********************************************************************
* @fn dis_gatt_msg_handler
*
* @brief Device information gatt message handler.
*
*
* @param p_msg - messages from GATT layer.
*
* @return none.
*/
uint16_t ANCS_gatt_msg_handler(gatt_msg_t *p_msg)
{
co_printf("CCC:%x\r\n",p_msg->msg_evt);
switch(p_msg->msg_evt)
{
case GATTC_MSG_NTF_REQ:
{
if(p_msg->att_idx == ANCS_ATT_IDX_CTL_POINT)
{
;
}
else if(p_msg->att_idx == ANCS_ATT_IDX_NTF_SRC)
{
ANCS_recv_ntf_src(p_msg->conn_idx,p_msg->param.msg.p_msg_data,p_msg->param.msg.msg_len);
}
else if(p_msg->att_idx == ANCS_ATT_IDX_DATA_SRC)
{
ANCS_recv_data_src(p_msg->conn_idx,p_msg->param.msg.p_msg_data,p_msg->param.msg.msg_len);
}
}
break;
case GATTC_MSG_READ_IND:
{
;
}
break;
case GATTC_MSG_CMP_EVT:
{
co_printf("op:%d done\r\n",p_msg->param.op.operation);
if(p_msg->param.op.operation == GATT_OP_PEER_SVC_REGISTERED)
{
memcpy(ANCS_hdl_cache,p_msg->param.op.arg,6);
show_reg((uint8_t *)ANCS_hdl_cache,6,1);
gatt_client_enable_ntf_t ntf_enable;
ntf_enable.conidx = p_msg->conn_idx;
ntf_enable.client_id = ANCS_client_id;
ntf_enable.att_idx = ANCS_ATT_IDX_NTF_SRC;
gatt_client_enable_ntf(ntf_enable);
ntf_enable.att_idx = ANCS_ATT_IDX_DATA_SRC;
gatt_client_enable_ntf(ntf_enable);
}
}
break;
default:
break;
}
return 0;
}
/*********************************************************************
* @fn batt_gatt_notify
*
* @brief Send batt level notification to peer.
*
*
* @param conidx - link idx.
* batt_level - battery energy percentage.
*
* @return none.
*/
void ANCS_gatt_write_cmd(uint8_t conidx,enum ancs_att_idx att_idx,uint8_t *p_data, uint16_t len)
{
gatt_client_write_t write;
write.conidx = conidx;
write.client_id = ANCS_client_id;
write.att_idx = att_idx;
write.p_data = p_data;
write.data_len = len;
gatt_client_write_cmd(write);
}
void ANCS_gatt_write_req(uint8_t conidx,enum ancs_att_idx att_idx,uint8_t *p_data, uint16_t len)
{
gatt_client_write_t write;
write.conidx = conidx;
write.client_id = ANCS_client_id;
write.att_idx = att_idx;
write.p_data = p_data;
write.data_len = len;
gatt_client_write_req(write);
}
void ANCS_gatt_read(uint8_t conidx,enum ancs_att_idx att_idx)
{
gatt_client_read_t read;
read.conidx = conidx;
read.client_id = ANCS_client_id;
read.att_idx = att_idx;
gatt_client_read(read);
}
void ANCS_perform_ntf_act(uint8_t conidx, uint32_t notification_uid, enum ancs_act_id action_id)
{
if(ANCS_hdl_cache[ANCS_ATT_IDX_CTL_POINT])
{
uint8_t rsp[12];
uint8_t i = 0;
rsp[i++] = ANCS_CMD_ID_PERFORM_NOTIFICATION_ACTION; //cmd id
*(uint32_t *)(rsp + i) = notification_uid; //ntf_uid
i+=4;
rsp[i++] = action_id;
ANCS_gatt_write_req(conidx,ANCS_ATT_IDX_CTL_POINT,rsp,i);
}
}
/*********************************************************************
* @fn batt_gatt_add_service
*
* @brief Simple Profile add GATT service function.
* <20><><EFBFBD><EFBFBD>GATT service<63><65>ATT<54><54><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><DDBF><EFBFBD><EFBFBD>
*
* @param None.
*
*
* @return None.
*/
void ANCS_gatt_add_client(void)
{
gatt_client_t client;
client.p_att_tb = ANCS_att_tb;
client.att_nb = ANCS_ATT_IDX_MAX;
client.gatt_msg_handler = ANCS_gatt_msg_handler;
ANCS_client_id = gatt_add_client(&client);
}

View File

@ -0,0 +1,128 @@
/**
* Copyright (c) 2019, Freqchip
*
* All rights reserved.
*
*
*/
#ifndef ANCS_CLIENT_H
#define ANCS_CLIENT_H
/*
* INCLUDES (<28><><EFBFBD><EFBFBD>ͷ<EFBFBD>ļ<EFBFBD>)
*/
#include <stdio.h>
#include <string.h>
#include "gap_api.h"
#include "gatt_api.h"
#include "gatt_sig_uuid.h"
/*
* MACROS (<28><EFBFBD><EAB6A8>)
*/
#define ANCS_SVC_UUID "\xd0\x00\x2d\x12\x1e\x4b\x0f\xa4\x99\x4e\xce\xb5\x31\xf4\x05\x79"
/*
* CONSTANTS (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
*/
/*
* TYPEDEFS (<28><><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>)
*/
enum ancs_att_idx
{
ANCS_ATT_IDX_CTL_POINT, //18
ANCS_ATT_IDX_NTF_SRC, //27
ANCS_ATT_IDX_DATA_SRC, //33
ANCS_ATT_IDX_MAX,
};
/** @brief ANCS client control command id*/
enum ancs_cmd_id
{
ANCS_CMD_ID_GET_NOTIFICATION_ATTR = 0,
ANCS_CMD_ID_GET_APP_ATTR = 1,
ANCS_CMD_ID_PERFORM_NOTIFICATION_ACTION = 2,
ANCS_CMD_ID_RESERVED = 255
};
/** @brief ANCS action id state */
enum ancs_act_id
{
ANCS_ACT_ID_POSITIVE = 0,
ANCS_ACT_ID_NEGATIVE = 1,
ANCS_ACT_ID_RESERVED = 255
};
/*
* GLOBAL VARIABLES (ȫ<>ֱ<EFBFBD><D6B1><EFBFBD>)
*/
//current call msg uid
extern uint32_t call_notification_uid ;
//current call social msg uid
extern uint32_t social_notification_uid ;
/*
* LOCAL VARIABLES (<28><><EFBFBD>ر<EFBFBD><D8B1><EFBFBD>)
*/
/*
* PUBLIC FUNCTIONS (ȫ<>ֺ<EFBFBD><D6BA><EFBFBD>)
*/
extern uint8_t ANCS_client_id;
/*********************************************************************
* @fn ANCS_gatt_add_client
*
* @brief Create battery server.
*
* @param None.
*
* @return None.
*/
void ANCS_gatt_add_client(void);
/*********************************************************************
* @fn ANCS_perform_ntf_act
*
* @brief execute positive or negative action for current ancs msg, ex: call or social msg.
*
*
* @param conidx - link idx.
* notification_uid - current ancs msg uid. call_notification_uid, or social_notification_uid.
* action_id - postive or negative.
*
* @return none.
*/
void ANCS_perform_ntf_act(uint8_t conidx, uint32_t notification_uid, enum ancs_act_id action_id);
/*********************************************************************
* @fn ANCS_gatt_write_cmd
*
* @brief Send batt level notification to peer, and update batt level
*
*
* @param conidx - link idx.
* att_idx - index in client profile uuid table .
* p_data - pointer to the buff which will be sent.
* len - buff len.
*
* @return none.
*/
void ANCS_gatt_write_cmd(uint8_t conidx,enum ancs_att_idx att_idx,uint8_t *p_data, uint16_t len);
void ANCS_gatt_write_req(uint8_t conidx,enum ancs_att_idx att_idx,uint8_t *p_data, uint16_t len);
void ANCS_gatt_read(uint8_t conidx,enum ancs_att_idx att_idx);
#endif

View File

@ -0,0 +1,25 @@
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD>https://developer.apple.com/library/archive/documentation/CoreBluetooth/Reference/AppleNotificationCenterServiceSpecification/Specification/Specification.html#//apple_ref/doc/uid/TP40013460-CH1-SW14
ʹ<EFBFBD>ò<EFBFBD><EFBFBD>
1 ANCS_client.c&h <20>ļ<EFBFBD>·<EFBFBD>磺\components\ble\profiles\ble_ANCS
1 <20><><EFBFBD><EFBFBD><EFBFBD>ں<EFBFBD><DABA><EFBFBD>void user_entry_after_ble_init(void) <20>ڵ<EFBFBD><DAB5><EFBFBD> ANCS_gatt_add_client();
2 case GAP_EVT_SLAVE_CONNECT: slave<76><65>ɫ<EFBFBD><C9AB><EFBFBD>ӳɹ<D3B3><C9B9><EFBFBD><EFBFBD>¼<EFBFBD><C2BC>ص<EFBFBD><D8B5>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD>
gap_security_req(event->param.slave_connect.conidx); <20><><EFBFBD>м<EFBFBD><D0BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
3 <20><>case GAP_SEC_EVT_SLAVE_ENCRYPT: slave<76><65>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɵ<EFBFBD><C9B5>¼<EFBFBD><C2BC>ص<EFBFBD><D8B5>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>´<EFBFBD><C2B4>룬ɨ<EBA3AC><C9A8>ANCS<43>ķ<EFBFBD><C4B7><EFBFBD><EFBFBD><EFBFBD>
gatt_discovery_peer_svc(ANCS_client_id,event->param.slave_connect.conidx,16,ANCS_SVC_UUID);
4 ANCS_Client.c <20>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD>ĵط<C4B5><D8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void ANCS_recv_ntf_src(uint8_t conidx,uint8_t *p_data, uint16_t len);
void ANCS_recv_data_src(uint8_t conidx,uint8_t *p_data, uint16_t len);
<EFBFBD><EFBFBD>1<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾiosҪ<EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD><EFBFBD><EFBFBD>Ϣuid<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD>ĸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>id<EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>2<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾios<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>id<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣϸ<EFBFBD>ڡ<EFBFBD>Ĭ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>8<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>id<EFBFBD><EFBFBD>
5 ANCS_recv_data_src<72><63><EFBFBD><EFBFBD><EFBFBD>ڣ<EFBFBD><DAA3><EFBFBD>ʾ<EFBFBD><CABE>Ϣϸ<CFA2>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD>utf-8 <20><>ascii<69><69><EFBFBD>μ<EFBFBD>ע<EFBFBD>͡<EFBFBD>
6 ÿ<>ε<EFBFBD><CEB5><EFBFBD>Ϣ<EFBFBD>ᴫNTF_ATT_ID_POSITIVE_ACT <20><> NTF_ATT_ID_NEGATIVE_ACT<43><54><EFBFBD><EFBFBD>ʾִ<CABE><D6B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD>Ľ<EFBFBD><C4BD><EFBFBD><EFBFBD><EFBFBD>
ִ<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ANCS_perform_ntf_act<63>Ե<EFBFBD>ǰ<EFBFBD><C7B0>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ANCS_perform_ntf_act(0,call_notification_uid,ANCS_ACT_ID_POSITIVE); <20><><EFBFBD>Խ<EFBFBD><D4BD><EFBFBD><EFBFBD><EFBFBD><E7BBB0>
ANCS_perform_ntf_act(0,call_notification_uid,ANCS_ACT_ID_NEGATIVE); <20><><EFBFBD>ԹҶϵ绰<CFB5><E7BBB0>

View File

@ -0,0 +1,381 @@
/**
* Copyright (c) 2019, Freqchip
*
* All rights reserved.
*
* AMS client profile. protocol websit:
* https://developer.apple.com/library/archive/documentation/CoreBluetooth/Reference/AppleMediaService_Reference/Specification/Specification.html
*
*/
/*
* INCLUDES (<28><><EFBFBD><EFBFBD>ͷ<EFBFBD>ļ<EFBFBD>)
*/
#include <stdio.h>
#include <string.h>
#include "gap_api.h"
#include "gatt_api.h"
#include "gatt_sig_uuid.h"
#include "AMS_client.h"
#include "ANCS_AMS_client.h"
#include "FreeRTOS.h"
#include "timers.h"
/*
* MACROS (<28><EFBFBD><EAB6A8>)
*/
#define REMOTE_CMD_UUID {0xc2, 0x51, 0xca, 0xf7, 0x56, 0x0e, 0xdf, 0xb8, \
0x8a, 0x4a, 0xb1, 0x57, 0xd8,0x81, 0x3c, 0x9b}
#define ENT_UPDATE_UUID {0x02, 0xc1, 0x96, 0xba, 0x92, 0xbb, 0x0c, 0x9a, \
0x1f, 0x41, 0x8d, 0x80, 0xce,0xab, 0x7c, 0x2f}
#define ENT_ATT_UUID {0xd7, 0xd5, 0xbb, 0x70, 0xa8, 0xa3, 0xab, 0xa6, \
0xd8, 0x46, 0xab, 0x23, 0x8c,0xf3, 0xb2, 0xc6}
/*
* CONSTANTS (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
*/
#define BIT(x) (1<<(x))
/*
* TYPEDEFS (<28><><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>)
*/
/*
* GLOBAL VARIABLES (ȫ<>ֱ<EFBFBD><D6B1><EFBFBD>)
*/
/*
* LOCAL VARIABLES (<28><><EFBFBD>ر<EFBFBD><D8B1><EFBFBD>)
*/
static void AMS_gatt_write_cmd(uint8_t conidx,enum ancs_ams_att_idx att_idx,uint8_t *p_data, uint16_t len);
static void AMS_gatt_write_req(uint8_t conidx,enum ancs_ams_att_idx att_idx,uint8_t *p_data, uint16_t len);
static void AMS_gatt_read(uint8_t conidx,enum ancs_ams_att_idx att_idx);
static uint8_t cmd_id_mask;
uint8_t AMS_client_conidx;
uint8_t AMS_client_id;
/*********************************************************************
* Profile Attributes - Table
* ÿһ<C3BF><EFBFBD><EEB6BC>һ<EFBFBD><D2BB>characteristic attribute<74><65>Ӧ<EFBFBD><D3A6>UUID<49>Ķ<EFBFBD><C4B6>
* <20><>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>UUID<49>ij<EFBFBD><C4B3>ȣ<EFBFBD>
* ÿ<><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>UUID<49><44>ֵ<EFBFBD><D6B5>
*/
const gatt_uuid_t AMS_att_tb[] =
{
[AMS_ATT_IDX_REMOTE_CMD] = { UUID_SIZE_16, REMOTE_CMD_UUID}, //write_req, ntf
[AMS_ATT_IDX_ENT_UPDATE] = { UUID_SIZE_16, ENT_UPDATE_UUID}, //write_req, ntf
[AMS_ATT_IDX_ENT_ATT] = { UUID_SIZE_16, ENT_ATT_UUID}, // read, write_req
};
static void show_reg(uint8_t *data,uint32_t len,uint8_t dbg_on)
{
uint32_t i=0;
if(len == 0 || (dbg_on==0)) return;
for(; i<len; i++)
{
printf("0x%02X,",data[i]);
}
printf("\r\n");
}
static TimerHandle_t ams_timer = NULL;
void ams_test_timer_ctrl(TimerHandle_t timerhandle)
{
printf("enter ams start timer\r\n");
ams_subscribe_entity_update(ENTI_ID_TRACK,BIT(TRACK_ATT_ID_ARTIST)|BIT(TRACK_ATT_ID_ALBUM)|BIT(TRACK_ATT_ID_TITLE)|BIT(TRACK_ATT_ID_DURATION));
}
void start_ams_test_timer(void)
{
// taskENTER_CRITICAL();//?????
ams_timer = xTimerCreate((const char *)"OneLoadTimer",
(TickType_t)1000 / portTICK_PERIOD_MS,//
(UBaseType_t)pdFALSE,//??
NULL,//ID
(TimerCallbackFunction_t)ams_test_timer_ctrl);
// taskEXIT_CRITICAL();//?????
// vTaskDelete(NULL);
printf("timer task create success\r\n");
// xTimerStop(ams_timer, portMAX_DELAY);
// xTimerChangePeriod(ams_timer, 1000 / portTICK_PERIOD_MS, 0);
xTimerStart(ams_timer, portMAX_DELAY);
// os_timer_init(&ams_test_t,ams_test_timer_ctrl,NULL);
// os_timer_start(&ams_test_t,1000,0);
}
void AMS_recv_entity_info(uint8_t conidx,uint8_t *p_data, uint16_t len)
{
/*
user get subscribed entity info here
*/
show_reg(p_data,len,1);
switch(p_data[0])
{
case ENTI_ID_PLAYER:
break;
case ENTI_ID_QUEUE:
break;
case ENTI_ID_TRACK:
if(p_data[2] & ENTI_UPDATE_FLAG_TRUNCATED)
{
printf("truncated\r\n");
}
if(p_data[1] ==TRACK_ATT_ID_ARTIST)
{
//show_utf8_string(&rsp[3],len -3);
}
else if(p_data[1] ==TRACK_ATT_ID_ALBUM)
{
//show_utf8_string(&rsp[3],len -3);
}
else if(p_data[1] ==TRACK_ATT_ID_TITLE)
{
//show_utf8_string(&rsp[3],len -3);
if(p_data[2] & ENTI_UPDATE_FLAG_TRUNCATED)
ams_subscribe_entity_att(ENTI_ID_TRACK,BIT(TRACK_ATT_ID_TITLE));
}
else if(p_data[1] ==TRACK_ATT_ID_DURATION)
{
// 0x32,0x38,0x35,0x2E,0x32,0x33,0x34, ==> 285.234 sec
//show_ascii_string(&rsp[3],len -3); //floating value.
}
break;
}
}
/*********************************************************************
* @fn AMS_gatt_msg_handler
*
* @brief Device information gatt message handler.
*
*
* @param p_msg - messages from GATT layer.
*
* @return none.
*/
uint16_t AMS_gatt_msg_handler(struct gatt_msg *p_msg)
{
printf("AMS_msg,evt:%d,att_idx[%d]\r\n",p_msg->msg_evt,p_msg->att_idx);
switch(p_msg->msg_evt)
{
case GATTC_MSG_NTF_REQ:
{
if(p_msg->att_idx == AMS_ATT_IDX_REMOTE_CMDx)
{
//recv which commands is support by current music. one byte respresent one command
//refer to enum remote_cmd
show_reg(p_msg->param.gatt_data.p_msg_data,p_msg->param.gatt_data.msg_len,1);
uint8_t *value = p_msg->param.gatt_data.p_msg_data;
AMS_client_conidx = p_msg->conn_idx;
cmd_id_mask = 0;
for(uint8_t i = 0; i< p_msg->param.gatt_data.msg_len; i++) //update cmd_id_mask
cmd_id_mask |= (1<<(value[i]));
}
else if(p_msg->att_idx == AMS_ATT_IDX_ENT_UPDATEx)
{
//show_reg(p_msg->param.msg.p_msg_data,p_msg->param.msg.msg_len,1);
AMS_recv_entity_info(p_msg->conn_idx,p_msg->param.gatt_data.p_msg_data, p_msg->param.gatt_data.msg_len);
}
}
break;
case GATTC_MSG_READ_IND:
{
;
}
break;
case GATTC_MSG_CMP_EVT:
{
printf("ams op:%d done\r\n",p_msg->param.gatt_op_cmp.operation);
if(p_msg->param.gatt_op_cmp.operation == GATT_OP_PEER_SVC_REGISTERED)
{
uint16_t att_handles[6];
memcpy(att_handles,p_msg->param.gatt_op_cmp.arg,12);
show_reg((uint8_t *)att_handles,12,1);
gatt_client_enable_event_t ntf_enable;
ntf_enable.conidx = p_msg->conn_idx;
ntf_enable.client_id = AMS_client_id;
ntf_enable.att_idx = AMS_ATT_IDX_ENT_UPDATEx;
gatt_client_enable_ntf_ind(&ntf_enable, ENABLE_TYPE_NTF);
ntf_enable.att_idx = AMS_ATT_IDX_REMOTE_CMDx;
gatt_client_enable_ntf_ind(&ntf_enable, ENABLE_TYPE_NTF);
ams_subscribe_entity_update(ENTI_ID_TRACK,BIT(TRACK_ATT_ID_ARTIST)|BIT(TRACK_ATT_ID_ALBUM)|BIT(TRACK_ATT_ID_TITLE)|BIT(TRACK_ATT_ID_DURATION));
//start_ams_test_timer();
}
else if(p_msg->param.gatt_op_cmp.operation == GATT_OP_WRITE_REQ && p_msg->att_idx == AMS_ATT_IDX_ENT_ATTx)
AMS_gatt_read(AMS_client_conidx,AMS_ATT_IDX_ENT_ATTx);
}
break;
case GATTC_MSG_LINK_LOST:
if(p_msg->conn_idx == AMS_client_conidx)
AMS_client_conidx = 0xff;
break;
default:
break;
}
return 0;
}
/*********************************************************************
* @fn AMS_gatt_write_cmd
*
* @brief Write(without response) data to peer.
*
*
* @param conidx - link idx.
* att_idx - attribute idx,refer to enum ams_att_idx.
* p_data - pointer to buffer, its value will be sent.
* len - buffer len.
*
* @return none.
*/
void AMS_gatt_write_cmd(uint8_t conidx,enum ancs_ams_att_idx att_idx,uint8_t *p_data, uint16_t len)
{
struct gatt_client_write_param write;
write.conidx = conidx;
write.client_id = AMS_client_id;
write.att_idx = att_idx;
write.p_data = p_data;
write.data_len = len;
gatt_client_write_cmd(&write);
}
/*********************************************************************
* @fn AMS_gatt_write_req
*
* @brief Write(with response) data to peer.
*
*
* @param conidx - link idx.
* att_idx - attribute idx,refer to enum ams_att_idx.
* p_data - pointer to buffer, its value will be sent.
* len - buffer len.
*
* @return none.
*/
void AMS_gatt_write_req(uint8_t conidx,enum ancs_ams_att_idx att_idx,uint8_t *p_data, uint16_t len)
{
struct gatt_client_write_param write;
write.conidx = conidx;
write.client_id = AMS_client_id;
write.att_idx = att_idx;
write.p_data = p_data;
write.data_len = len;
gatt_client_write_req(&write);
}
/*********************************************************************
* @fn AMS_gatt_read
*
* @brief Read data from peer. read result will be update from GATT_EVENT: GATTC_MSG_READ_IND
*
*
* @param conidx - link idx.
* att_idx - attribute idx,refer to enum ams_att_idx.
*
* @return none.
*/
void AMS_gatt_read(uint8_t conidx,enum ancs_ams_att_idx att_idx)
{
struct gatt_client_read_param read;
read.conidx = conidx;
read.client_id = AMS_client_id;
read.att_idx = att_idx;
gatt_client_read(&read);
}
/***********************************Usage Example****************************************/
/*********************************************************************
* @fn ams_subscribe_entity_update
*
* @brief subscribe some entity info.
* call this function to subscribe what you are intrested.
* After att_idx: AMS_ATT_IDX_ENT_UPDATE is ntf enabled, call this func
*
* @param id - entity id. refer to enum entity_id_values
* att_id_bits - each bit represent each att_id, multi bits can be set to represent multi att_id is selected
*
* @return None.
* example: subscribe TRACK informations.
* ams_subscribe_entity_update(ENTI_ID_TRACK
* ,BIT(TRACK_ATT_ID_ARTIST)|BIT(TRACK_ATT_ID_ALBUM)|BIT(TRACK_ATT_ID_TITLE)|BIT(TRACK_ATT_ID_DURATION));
*
*/
void ams_subscribe_entity_update(enum entity_id_values id,uint8_t att_id_bits)
{
//you can subscribe one or more entity ids. and one or more att_ids.
uint8_t value[5];
uint8_t idx = 0;
value[idx++] = id;
for(uint8_t i=0; i<4; i++)
{
if(att_id_bits & BIT(i))
{
value[idx++] = i;
}
}
AMS_gatt_write_req(AMS_client_conidx,AMS_ATT_IDX_ENT_UPDATEx,value,idx);
}
/*********************************************************************
* @fn ams_subscribe_entity_update
*
* @brief subscribe some entity info.
* call this function only when entity update response is truncated.
*
* @param id - entity id. refer to enum entity_id_values
* att_id_bit - each bit represent each att_id. but only one bit is allowed to be set
*
* @return None.
* example: subscribe TRACK & TRACK_ATT_ID_TITLE informations.
* ams_subscribe_entity_att(ENTI_ID_TRACK,BIT(TRACK_ATT_ID_TITLE));
*
*/
void ams_subscribe_entity_att(enum entity_id_values id,uint8_t att_id_bit)
{
uint8_t value[2];
value[0] = id;
for(uint8_t i=0; i<4; i++)
{
if(att_id_bit & BIT(i))
value[1] = i;
}
AMS_gatt_write_req(AMS_client_conidx,AMS_ATT_IDX_ENT_ATTx,value,2);
}
/*********************************************************************
* @fn ams_control
*
* @brief send control cmd to apple, and control current music .
* After att_idx: AMS_ATT_IDX_REMOTE_CMD is ntf enabled, call this func
*
* @param cmd - command id, refet to enum remote_cmd.
*
* @return none.
*/
void ams_crtl_cmd(enum remote_cmd cmd)
{
uint8_t value = cmd;
if(cmd_id_mask & (1<<cmd))
AMS_gatt_write_req(AMS_client_conidx,AMS_ATT_IDX_REMOTE_CMDx,&value,1);
}
/***********/

View File

@ -0,0 +1,190 @@
/**
* Copyright (c) 2019, Freqchip
*
* All rights reserved.
*
*
*/
#ifndef AMS_CLIENT_H
#define AMS_CLIENT_H
/*
* INCLUDES (<28><><EFBFBD><EFBFBD>ͷ<EFBFBD>ļ<EFBFBD>)
*/
#include <stdio.h>
#include <stdint.h>
#include "gap_api.h"
#include "gatt_api.h"
#include "gatt_sig_uuid.h"
/*
* MACROS (<28><EFBFBD><EAB6A8>)
*/
#define AMS_SVC_UUID "\xdc\xf8\x55\xad\x02\xc5\xf4\x8e\x3a\x43\x36\x0f\x2b\x50\xd3\x89"
/*
* CONSTANTS (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
*/
/*
* TYPEDEFS (<28><><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>)
*/
enum ams_att_idx
{
AMS_ATT_IDX_REMOTE_CMD, //47
AMS_ATT_IDX_ENT_UPDATE, //51
AMS_ATT_IDX_ENT_ATT, //55
AMS_ATT_IDX_MAX,
};
enum remote_cmd
{
CMD_ID_PLAY,
CMD_ID_PAUSE,
CMD_ID_TOGGLE_PLAY_PAUSE,
CMD_ID_NEXT_TRACK,
CMD_ID_PRE_TRACK,
CMD_ID_VOL_UP,
CMD_ID_VOL_DOWN,
CMD_ID_ADV_REPEAT_MODE,
CMD_ID_ADV_SHUFFLE_MODE,
CMD_ID_SKIP_FORWARD,
CMD_ID_SKIP_BACKWARD,
CMD_ID_LIKE_TRACK,
CMD_ID_DISLIKE_TRACK,
CMD_ID_BOOKMARK_TRACK,
};
enum entity_id_values
{
ENTI_ID_PLAYER,
ENTI_ID_QUEUE,
ENTI_ID_TRACK,
};
#define ENTI_UPDATE_FLAG_TRUNCATED (1<<0)
enum player_att_id_values
{
PLAYER_ATT_ID_NAME,
PLAYER_ATT_ID_PLAYBACK_INFO,
PLAYER_ATT_ID_VOL,
};
enum queue_att_id_values
{
QUEUE_ATT_ID_INDEX,
QUEUE_ATT_ID_COUNT,
QUEUE_ATT_ID_SHUFFLE_MODE,
QUEUE_ATT_ID_REPEAT_MODE,
};
enum track_att_id_values
{
TRACK_ATT_ID_ARTIST,
TRACK_ATT_ID_ALBUM,
TRACK_ATT_ID_TITLE,
TRACK_ATT_ID_DURATION,
};
enum shuffle_mode
{
SHUFFLE_MODE_OFF,
SHUFFLE_MODE_ONE,
SHUFFLE_MODE_ALL,
};
enum repeat_mode
{
REPEAT_MODE_OFF,
REPEAT_MODE_ONE,
REPEAT_MODE_ALL,
};
/*
* GLOBAL VARIABLES (ȫ<>ֱ<EFBFBD><D6B1><EFBFBD>)
*/
extern uint8_t AMS_client_id;
/*
* LOCAL VARIABLES (<28><><EFBFBD>ر<EFBFBD><D8B1><EFBFBD>)
*/
/*
* PUBLIC FUNCTIONS (ȫ<>ֺ<EFBFBD><D6BA><EFBFBD>)
*/
/*********************************************************************
* @fn AMS_gatt_add_client
*
* @brief AMS Profile add GATT client function.
* <20><><EFBFBD><EFBFBD>AMS GATT client<6E><74>ATT<54><54><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><DDBF><EFBFBD><EFBFBD>
*
* @param None.
*
*
* @return None.
*/
void AMS_gatt_add_client(void);
/*********************************************************************
* @fn ams_subscribe_entity_update
*
* @brief subscribe some entity info.
* call this function to subscribe what you are intrested.
* After att_idx: AMS_ATT_IDX_ENT_UPDATE is ntf enabled, call this func
*
* @param id - entity id. refer to enum entity_id_values
* att_id_bits - each bit represent each att_id, multi bits can be set to represent multi att_id is selected
*
* @return None.
* example: subscribe TRACK informations.
* ams_subscribe_entity_update(ENTI_ID_TRACK
* ,BIT(TRACK_ATT_ID_ARTIST)|BIT(TRACK_ATT_ID_ALBUM)|BIT(TRACK_ATT_ID_TITLE)|BIT(TRACK_ATT_ID_DURATION));
*
*/
void ams_subscribe_entity_update(enum entity_id_values id,uint8_t att_id_bits);
/*********************************************************************
* @fn ams_subscribe_entity_update
*
* @brief subscribe some entity info.
* call this function only when entity update response is truncated.
*
* @param id - entity id. refer to enum entity_id_values
* att_id_bit - each bit represent each att_id. but only one bit is allowed to be set
*
* @return None.
* example: subscribe TRACK & TRACK_ATT_ID_TITLE informations.
* ams_subscribe_entity_att(ENTI_ID_TRACK,BIT(TRACK_ATT_ID_TITLE));
*
*/
void ams_subscribe_entity_att(enum entity_id_values id,uint8_t att_id_bit);
/*********************************************************************
* @fn ams_control
*
* @brief send control cmd to apple, and control current music .
* After att_idx: AMS_ATT_IDX_REMOTE_CMD is ntf enabled, call this func
*
* @param cmd - command id, refet to enum remote_cmd.
*
* @return none.
* example: control iphone to play next track.
* ams_crtl_cmd(CMD_ID_NEXT_TRACK);
*
*/
void ams_crtl_cmd(enum remote_cmd cmd);
#endif

View File

@ -0,0 +1,523 @@
/**
* Copyright (c) 2019, Freqchip
*
* All rights reserved.
*
* ANCS client profile. protocol websit:
* https://developer.apple.com/library/archive/documentation/CoreBluetooth/Reference/AppleNotificationCenterServiceSpecification
* /Specification/Specification.html#//apple_ref/doc/uid/TP40013460-CH1-SW14
*
*/
/*
* INCLUDES (°üº¬Í·Îļþ)
*/
#include <stdio.h>
#include <string.h>
#include "gap_api.h"
#include "gatt_api.h"
#include "gatt_sig_uuid.h"
#include "ANCS_AMS_client.h"
#include "AMS_client.h"
#include "system_fr30xx.h"
#define ANCS_LOG printf
/*
* MACROS (ºê¶¨Òå)
*/
/*
* CONSTANTS (³£Á¿¶¨Òå)
*/
#define BIT(x) (1<<(x))
/*
* TYPEDEFS (ÀàÐͶ¨Òå)
*/
/*
* GLOBAL VARIABLES (È«¾Ö±äÁ¿)
*/
/*
* LOCAL VARIABLES (±¾µØ±äÁ¿)
*/
uint8_t ANCS_AMS_client_id;
#define CTL_POINT_UUID {0xd9, 0xd9, 0xaa, 0xfd, 0xbd, 0x9b, 0x21, 0x98, \
0xa8, 0x49, 0xe1, 0x45, 0xf3,0xd8, 0xd1, 0x69}
#define NTF_SRC_UUID {0xbd, 0x1d, 0xa2, 0x99, 0xe6, 0x25, 0x58, 0x8c, \
0xd9, 0x42, 0x01, 0x63, 0x0d,0x12, 0xbf, 0x9f}
#define DATA_SRC_UUID {0xfb, 0x7b, 0x7c, 0xce, 0x6a, 0xb3, 0x44, 0xbe, \
0xb5, 0x4b, 0xd6, 0x24, 0xe9,0xc6, 0xea, 0x22}
/*************AMS UUID************/
#define REMOTE_CMD_UUIDx {0xc2, 0x51, 0xca, 0xf7, 0x56, 0x0e, 0xdf, 0xb8, \
0x8a, 0x4a, 0xb1, 0x57, 0xd8,0x81, 0x3c, 0x9b}
#define ENT_UPDATE_UUIDx {0x02, 0xc1, 0x96, 0xba, 0x92, 0xbb, 0x0c, 0x9a, \
0x1f, 0x41, 0x8d, 0x80, 0xce,0xab, 0x7c, 0x2f}
#define ENT_ATT_UUIDx {0xd7, 0xd5, 0xbb, 0x70, 0xa8, 0xa3, 0xab, 0xa6, \
0xd8, 0x46, 0xab, 0x23, 0x8c,0xf3, 0xb2, 0xc6}
/*************AMS UUID************/
/*********************************************************************
* Profile Attributes - Table
* ÿһÏî¶¼ÊÇÒ»¸öcharacteristic attribute¶ÔÓ¦µÄUUIDµÄ¶¨Òå¡£
* µÚÒ»¸öÊÇUUIDµÄ³¤¶È£¬
* ÿ¶þ¸öÊÇUUIDµÄÖµ¡£
*/
const gatt_uuid_t ANCS_AMS_att_tb[] =
{
[ANCS_ATT_IDX_CTL_POINT] = { UUID_SIZE_16, CTL_POINT_UUID},
[ANCS_ATT_IDX_NTF_SRC] = { UUID_SIZE_16, NTF_SRC_UUID},
[ANCS_ATT_IDX_DATA_SRC] = { UUID_SIZE_16, DATA_SRC_UUID},
[AMS_ATT_IDX_REMOTE_CMDx] = { UUID_SIZE_16, REMOTE_CMD_UUIDx},
[AMS_ATT_IDX_ENT_UPDATEx] = { UUID_SIZE_16, ENT_UPDATE_UUIDx},
[AMS_ATT_IDX_ENT_ATTx] = { UUID_SIZE_16, ENT_ATT_UUIDx},
};
static uint16_t ANCS_hdl_cache[6] = {0};
static uint16_t android_buf[6]={0,0,0,0,0,0};
uint32_t call_notification_uid ;
uint32_t social_notification_uid ;
#define EVENT_ID_NOTIFICATION_ADD (0) /**< The arrival of a new iOS notification on the NP */
#define EVENT_ID_NOTIFICATION_MODIFIED (1) /**< The modification of an iOS notification on the NP */
#define EVENT_ID_NOTIFICATION_REMOVED (2) /**< The removal of an iOS notification on the NP */
#define EVENT_ID_NOTIFICATION_RESERVED (0xff)
#define EVT_FLAG_SILENT BIT(0)
#define EVT_FLAG_IMPORTANT BIT(1)
#define EVT_FLAG_PRE_EXSITING BIT(2)
#define EVT_FLAG_POSITIVE BIT(3)
#define EVT_FLAG_NEGATIVE BIT(4)
#define CATGRY_ID_OTHER (0)
#define CATGRY_ID_INCOMING_CALL (1)
#define CATGRY_ID_MISS_CALL (2)
#define CATGRY_ID_VOICE_MAIL (3)
#define CATGRY_ID_SOCIAL (4)
#define CATGRY_ID_SCHEDULE (5)
#define CATGRY_ID_EMAIL (6)
#define CATGRY_ID_NEWS (7)
#define CATGRY_ID_HEALTH (8)
#define CATGRY_ID_BUSINESS (9)
#define CATGRY_ID_LOCATION (10)
#define CATGRY_ID_ENTERTAINMENT (11)
struct ancs_ntf_src
{
uint8_t event_id;
uint8_t event_flags;
uint8_t category_id;
uint8_t category_cnt;
uint32_t ntf_uid;
};
#define NTF_ATT_ID_APPLE 0
#define NTF_ATT_ID_TITLE 1
#define NTF_ATT_ID_SUBTITLE 2
#define NTF_ATT_ID_MSG 3
#define NTF_ATT_ID_MSG_SIZE 4
#define NTF_ATT_ID_DATE 5
#define NTF_ATT_ID_POSITIVE_ACT 6
#define NTF_ATT_ID_NEGATIVE_ACT 7
extern uint16_t AMS_gatt_msg_handler(struct gatt_msg *p_msg);
extern uint16_t app_ble_get_mtu(uint8_t conidx);
static void show_utf8_hex(uint8_t *data,uint32_t len,uint8_t dbg_on)
{
uint32_t i=0;
if(len == 0 || (dbg_on==0)) return;
for(; i<len; i++)
{
ANCS_LOG("0x%02X ",data[i]);
}
printf("\r\n");
}
void ANCS_recv_ntf_src(uint8_t conidx,uint8_t *p_data, uint16_t len)
{
if(len != 8)
goto _exit;
struct ancs_ntf_src *ntf_src = (struct ancs_ntf_src *)p_data;
ANCS_LOG("event_id:%d,event_flags:%x,category_id:%d,category_cnt:%d,ntf_uid:%x\r\n",ntf_src->event_id
,ntf_src->event_flags,ntf_src->category_id,ntf_src->category_cnt,ntf_src->ntf_uid);
if( (ntf_src->category_id == CATGRY_ID_SOCIAL
|| ntf_src->category_id == CATGRY_ID_OTHER
|| ntf_src->category_id == CATGRY_ID_INCOMING_CALL
|| ntf_src->category_id == CATGRY_ID_EMAIL) &&
((ntf_src->event_flags & EVT_FLAG_PRE_EXSITING) != 0x04))
{
if(ntf_src->category_id == CATGRY_ID_INCOMING_CALL)
call_notification_uid = ntf_src->ntf_uid;
if(ntf_src->category_id == CATGRY_ID_SOCIAL)
social_notification_uid = ntf_src->ntf_uid;
if(ntf_src->category_id == CATGRY_ID_MISS_CALL)
printf("Miss call !\r\n");
if(ntf_src->event_id != EVENT_ID_NOTIFICATION_REMOVED)
{
printf("Send RSP\r\n");
uint16_t max_att_len = app_ble_get_mtu(conidx)-3;
uint8_t rsp[19];
uint8_t i = 0;
rsp[i++] = ANCS_CMD_ID_GET_NOTIFICATION_ATTR; //cmd id
*(uint32_t *)(rsp + i) = ntf_src->ntf_uid; //ntf_uid
i+=4;
rsp[i++] = NTF_ATT_ID_APPLE;
rsp[i++] = NTF_ATT_ID_TITLE;
rsp[i++] = (max_att_len & 0xff);
rsp[i++] = (max_att_len & 0xff00)>>8;
rsp[i++] = NTF_ATT_ID_SUBTITLE;
rsp[i++] = (max_att_len & 0xff);
rsp[i++] = (max_att_len & 0xff00)>>8;
rsp[i++] = NTF_ATT_ID_MSG;
rsp[i++] = (max_att_len & 0xff);
rsp[i++] = (max_att_len & 0xff00)>>8;
rsp[i++] = NTF_ATT_ID_MSG_SIZE;
rsp[i++] = NTF_ATT_ID_DATE;
rsp[i++] = NTF_ATT_ID_POSITIVE_ACT;
rsp[i++] = NTF_ATT_ID_NEGATIVE_ACT;
ANCS_gatt_write_req(conidx,ANCS_ATT_IDX_CTL_POINT,rsp,sizeof(rsp));
}
}
_exit:
;
}
enum ntf_msg_type_t
{
WEIXIN,
MOBILE_SMS,
MOBILE_PHONE,
QQ,
};
void ANCS_recv_data_src(uint8_t conidx,uint8_t *p_data, uint16_t len)
{
uint8_t *str = NULL;
uint16_t str_len = 0;
enum ntf_msg_type_t msg_type = 0;
uint16_t i = 0;
uint16_t data_len = 0;
uint8_t event_id = p_data[i++];
uint32_t uid = *(uint32_t *)(p_data + i);
i+=4;
ANCS_LOG("evt_id:%d,uid:%x,len:%d\r\n",event_id,uid,len);
while(i < len)
{
switch(p_data[i++])
{
case NTF_ATT_ID_APPLE:
data_len = *(uint16_t *)(p_data + i);
i+=2;
//show_reg(p_data + i,data_len,1);
if( memcmp(p_data+i,"com.tencent.xin",strlen("com.tencent.xin"))==0 )
msg_type = WEIXIN;
else if( memcmp(p_data+i,"com.apple.MobileSMS",strlen("com.apple.MobileSMS"))==0 )
msg_type = MOBILE_SMS;
else if( memcmp(p_data+i,"com.apple.mobilephone",strlen("com.apple.mobilephone"))==0 )
msg_type = MOBILE_PHONE;
else if( memcmp(p_data+i,"com.tencent.mqq",strlen("com.tencent.mqq"))==0 )
msg_type = QQ;
else if( memcmp(p_data+i,"com.tencent.qq",strlen("com.tencent.qq"))==0 )
msg_type = QQ;
ANCS_LOG("NTF_ATT_ID_APPLE,msg_type:%d,len:%d\r\n",msg_type,data_len);
i+=data_len;
break;
case NTF_ATT_ID_TITLE: //UTF-8
data_len = *(uint16_t *)(p_data + i);
ANCS_LOG("NTF_ATT_ID_TITLE,len:%d\r\n",data_len);
i+=2;
show_utf8_hex(p_data + i,data_len,1);
//str = (uint8_t *)(p_data + i);
//str_len += data_len;
i+=data_len;
break;
case NTF_ATT_ID_SUBTITLE: //UTF-8
data_len = *(uint16_t *)(p_data + i);
ANCS_LOG("NTF_ATT_ID_SUBTITLE,len:%d\r\n",data_len);
i+=2;
show_utf8_hex(p_data + i,data_len,1);
i+=data_len;
break;
case NTF_ATT_ID_MSG: //UTF-8
data_len = *(uint16_t *)(p_data + i);
ANCS_LOG("NTF_ATT_ID_MSG,len:%d\r\n",data_len);
i+=2;
show_utf8_hex(p_data + i,data_len,1);
//str = (uint8_t *)(p_data + i);
//str_len += data_len;
i+=data_len;
break;
case NTF_ATT_ID_MSG_SIZE: //ASCII
data_len = *(uint16_t *)(p_data + i);
ANCS_LOG("NTF_ATT_ID_MSG_SIZE,len:%d\r\n",data_len);
i+=2;
show_utf8_hex(p_data + i,data_len,1);
i+=data_len;
break;
case NTF_ATT_ID_DATE: //ASCII
data_len = *(uint16_t *)(p_data + i);
ANCS_LOG("NTF_ATT_ID_DATE,len:%d\r\n",data_len);
i+=2;
show_utf8_hex(p_data + i,data_len,1);
i+=data_len;
break;
case NTF_ATT_ID_POSITIVE_ACT: //UTF-8
data_len = *(uint16_t *)(p_data + i);
ANCS_LOG("NTF_ATT_ID_POSITIVE_ACT,len:%d\r\n",data_len);
i+=2;
show_utf8_hex(p_data + i,data_len,1);
i+=data_len;
break;
case NTF_ATT_ID_NEGATIVE_ACT: //UTF-8
data_len = *(uint16_t *)(p_data + i);
ANCS_LOG("NTF_ATT_ID_NEGATIVE_ACT,len:%d\r\n",data_len);
i+=2;
show_utf8_hex(p_data + i,data_len,1);
i+=data_len;
break;
default:
ANCS_LOG("ERRR\r\n");
break;
}
}
// *(str + str_len) = 0;
if(msg_type == 0)
{
//ui_show_phone_call(3000,str);
}
else
{
//ui_show_chinese_str(msg_type,3000,str);
}
}
bool phone_type = 0; //0:android 1:ios
void set_phone_type(bool type)
{
phone_type = type;
}
bool get_phone_type(void)
{
return phone_type;
}
/*********************************************************************
* @fn dis_gatt_msg_handler
*
* @brief Device information gatt message handler.
*
*
* @param p_msg - messages from GATT layer.
*
* @return none.
*/
uint16_t ANCS_AMS_gatt_msg_handler(struct gatt_msg *p_msg)
{
ANCS_LOG("ANCS_msg,evt:%d,att_idx[%d]\r\n",p_msg->msg_evt,p_msg->att_idx);
switch(p_msg->msg_evt)
{
case GATTC_MSG_NTF_REQ:
{
if(p_msg->att_idx == ANCS_ATT_IDX_CTL_POINT)
{
;
}
else if(p_msg->att_idx == ANCS_ATT_IDX_NTF_SRC)
{
ANCS_recv_ntf_src(p_msg->conn_idx,p_msg->param.gatt_data.p_msg_data,p_msg->param.gatt_data.msg_len);
}
else if(p_msg->att_idx == ANCS_ATT_IDX_DATA_SRC)
{
// ANCS_recv_data_src(p_msg->conn_idx,p_msg->param.gatt_data.p_msg_data,p_msg->param.gatt_data.msg_len);
// extern void user_ANCS_recv_data_src(uint8_t conidx,uint8_t *p_data, uint16_t len);
// user_ANCS_recv_data_src(p_msg->conn_idx,p_msg->param.gatt_data.p_msg_data,p_msg->param.gatt_data.msg_len);
}
}
break;
case GATTC_MSG_READ_IND:
{
;
}
break;
case GATTC_MSG_CMP_EVT:
{
ANCS_LOG("op:%d done\r\n",p_msg->param.gatt_op_cmp.operation);
if(p_msg->param.gatt_op_cmp.operation == GATT_OP_PEER_SVC_REGISTERED)
{
ANCS_LOG("ANCS all svc reg\r\n");
memcpy(ANCS_hdl_cache,p_msg->param.gatt_op_cmp.arg,12);
show_utf8_hex((uint8_t *)ANCS_hdl_cache,12,1);
if(memcmp((uint8_t *)(android_buf),(uint8_t *)(ANCS_hdl_cache),12)==0)
{
//android
ANCS_LOG("phone type android\r\n");
set_phone_type(0);
}else {
//ios
//if(ANCS_hdl_cache[3] == 0)//找到ams后不再发起配对请求
{
ANCS_LOG("phone type ios %d\r\n",gap_get_encrypted_status(p_msg->conn_idx));
set_phone_type(1);
//gap_security_req(p_msg->conn_idx);
#if 1
if(gap_get_encrypted_status(p_msg->conn_idx) == 0) //已配对的情况不再重新发起
gap_security_req(p_msg->conn_idx);
else
{
ANCS_LOG("already encryption \r\n");
ancs_enable_src_notify(p_msg->conn_idx);
}
#endif
}
#if 0
if(ANCS_hdl_cache[0] != 0)
{
gatt_client_enable_event_t ntf_enable;
ntf_enable.conidx = p_msg->conn_idx;
ntf_enable.client_id = ANCS_AMS_client_id;
ntf_enable.att_idx = ANCS_ATT_IDX_NTF_SRC;
gatt_client_enable_ntf_ind(&ntf_enable, ENABLE_TYPE_NTF);
ntf_enable.att_idx = ANCS_ATT_IDX_DATA_SRC;
gatt_client_enable_ntf_ind(&ntf_enable, ENABLE_TYPE_NTF);
}
#endif
}
}
}
break;
default:
break;
}
AMS_gatt_msg_handler(p_msg);
return 0;
}
void ancs_enable_src_notify(uint8_t condix)
{
if(ANCS_hdl_cache[0] != 0)
{
ANCS_LOG("%s \r\n", __func__);
gatt_client_enable_event_t ntf_enable;
ntf_enable.conidx = condix;//p_msg->conn_idx;
ntf_enable.client_id = ANCS_AMS_client_id;
ntf_enable.att_idx = ANCS_ATT_IDX_NTF_SRC;
gatt_client_enable_ntf_ind(&ntf_enable, ENABLE_TYPE_NTF);
ntf_enable.att_idx = ANCS_ATT_IDX_DATA_SRC;
gatt_client_enable_ntf_ind(&ntf_enable, ENABLE_TYPE_NTF);
}
}
/*********************************************************************
* @fn batt_gatt_notify
*
* @brief Send batt level notification to peer.
*
*
* @param conidx - link idx.
* batt_level - battery energy percentage.
*
* @return none.
*/
void ANCS_gatt_write_cmd(uint8_t conidx,enum ancs_ams_att_idx att_idx,uint8_t *p_data, uint16_t len)
{
struct gatt_client_write_param write;
write.conidx = conidx;
write.client_id = ANCS_AMS_client_id;
write.att_idx = att_idx;
write.p_data = p_data;
write.data_len = len;
gatt_client_write_cmd(&write);
}
void ANCS_gatt_write_req(uint8_t conidx,enum ancs_ams_att_idx att_idx,uint8_t *p_data, uint16_t len)
{
struct gatt_client_write_param write;
write.conidx = conidx;
write.client_id = ANCS_AMS_client_id;
write.att_idx = att_idx;
write.p_data = p_data;
write.data_len = len;
gatt_client_write_req(&write);
}
void ANCS_gatt_read(uint8_t conidx,enum ancs_ams_att_idx att_idx)
{
struct gatt_client_read_param read;
read.conidx = conidx;
read.client_id = ANCS_AMS_client_id;
read.att_idx = att_idx;
gatt_client_read(&read);
}
void ANCS_perform_ntf_act(uint8_t conidx, uint32_t notification_uid, enum ancs_act_id action_id)
{
ANCS_LOG("enter\r\n");
if(ANCS_hdl_cache[ANCS_ATT_IDX_CTL_POINT])
{
ANCS_LOG("ntf act\r\n");
uint8_t rsp[12];
uint8_t i = 0;
rsp[i++] = ANCS_CMD_ID_PERFORM_NOTIFICATION_ACTION; //cmd id
*(uint32_t *)(rsp + i) = notification_uid; //ntf_uid
i+=4;
rsp[i++] = action_id;
ANCS_gatt_write_req(conidx,ANCS_ATT_IDX_CTL_POINT,rsp,i);
}
}
/*********************************************************************
* @fn batt_gatt_add_service
*
* @brief Simple Profile add GATT service function.
* Ìí¼ÓGATT serviceµ½ATTµÄÊý¾Ý¿âÀïÃæ¡£
*
* @param None.
*
*
* @return None.
*/
void ANCS_AMS_gatt_add_client(void)
{
gatt_client_t client;
client.p_att_tb = ANCS_AMS_att_tb;
client.att_nb = ANCS_AMS_ATT_IDX_MAX;
client.gatt_msg_handler = ANCS_AMS_gatt_msg_handler;
ANCS_AMS_client_id = gatt_add_client(&client);
AMS_client_id = ANCS_AMS_client_id;
}

View File

@ -0,0 +1,133 @@
/**
* Copyright (c) 2019, Freqchip
*
* All rights reserved.
*
*
*/
#ifndef ANCS_AMS_CLIENT_H
#define ANCS_AMS_CLIENT_H
/*
* INCLUDES (<28><><EFBFBD><EFBFBD>ͷ<EFBFBD>ļ<EFBFBD>)
*/
#include <stdio.h>
#include <string.h>
#include "gap_api.h"
#include "gatt_api.h"
#include "gatt_sig_uuid.h"
/*
* MACROS (<28><EFBFBD><EAB6A8>)
*/
#define ANCS_SVC_UUID "\xd0\x00\x2d\x12\x1e\x4b\x0f\xa4\x99\x4e\xce\xb5\x31\xf4\x05\x79"
/*
* CONSTANTS (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
*/
/*
* TYPEDEFS (<28><><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>)
*/
enum ancs_ams_att_idx
{
ANCS_ATT_IDX_CTL_POINT, //18
ANCS_ATT_IDX_NTF_SRC, //27
ANCS_ATT_IDX_DATA_SRC, //33
AMS_ATT_IDX_REMOTE_CMDx, //47
AMS_ATT_IDX_ENT_UPDATEx, //51
AMS_ATT_IDX_ENT_ATTx, //55
ANCS_AMS_ATT_IDX_MAX,
};
/** @brief ANCS client control command id*/
enum ancs_cmd_id
{
ANCS_CMD_ID_GET_NOTIFICATION_ATTR = 0,
ANCS_CMD_ID_GET_APP_ATTR = 1,
ANCS_CMD_ID_PERFORM_NOTIFICATION_ACTION = 2,
ANCS_CMD_ID_RESERVED = 255
};
/** @brief ANCS action id state */
enum ancs_act_id
{
ANCS_ACT_ID_POSITIVE = 0,
ANCS_ACT_ID_NEGATIVE = 1,
ANCS_ACT_ID_RESERVED = 255
};
/*
* GLOBAL VARIABLES (ȫ<>ֱ<EFBFBD><D6B1><EFBFBD>)
*/
//current call msg uid
extern uint32_t call_notification_uid ;
//current call social msg uid
extern uint32_t social_notification_uid ;
/*
* LOCAL VARIABLES (<28><><EFBFBD>ر<EFBFBD><D8B1><EFBFBD>)
*/
/*
* PUBLIC FUNCTIONS (ȫ<>ֺ<EFBFBD><D6BA><EFBFBD>)
*/
extern uint8_t ANCS_AMS_client_id;
/*********************************************************************
* @fn ANCS_gatt_add_client
*
* @brief Create battery server.
*
* @param None.
*
* @return None.
*/
void ANCS_AMS_gatt_add_client(void);
/*********************************************************************
* @fn ANCS_perform_ntf_act
*
* @brief execute positive or negative action for current ancs msg, ex: call or social msg.
*
*
* @param conidx - link idx.
* notification_uid - current ancs msg uid. call_notification_uid, or social_notification_uid.
* action_id - postive or negative.
*
* @return none.
*/
void ANCS_perform_ntf_act(uint8_t conidx, uint32_t notification_uid, enum ancs_act_id action_id);
/*********************************************************************
* @fn ANCS_gatt_write_cmd
*
* @brief Send batt level notification to peer, and update batt level
*
*
* @param conidx - link idx.
* att_idx - index in client profile uuid table .
* p_data - pointer to the buff which will be sent.
* len - buff len.
*
* @return none.
*/
void ANCS_gatt_write_cmd(uint8_t conidx,enum ancs_ams_att_idx att_idx,uint8_t *p_data, uint16_t len);
void ANCS_gatt_write_req(uint8_t conidx,enum ancs_ams_att_idx att_idx,uint8_t *p_data, uint16_t len);
void ANCS_gatt_read(uint8_t conidx,enum ancs_ams_att_idx att_idx);
extern void ancs_enable_src_notify(uint8_t condix);
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

View File

@ -0,0 +1,52 @@
ʹ<EFBFBD>ò<EFBFBD><EFBFBD>
1 <20>ڹ<EFBFBD><DAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>AMS_client.c<><63>ANCS_AMS_client.c<><63> <20><><EFBFBD><EFBFBD><EFBFBD>ں<EFBFBD><DABA><EFBFBD>void user_entry_after_ble_init(void) <20>ڵ<EFBFBD><DAB5><EFBFBD> ANCS_AMS_gatt_add_client();
2 case GAP_EVT_SLAVE_CONNECT: slave<76><65>ɫ<EFBFBD><C9AB><EFBFBD>ӳɹ<D3B3><C9B9><EFBFBD><EFBFBD>¼<EFBFBD><C2BC>ص<EFBFBD><D8B5>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD>
gap_security_req(event->param.slave_connect.conidx); <20><><EFBFBD>м<EFBFBD><D0BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
3 <20><>case GAP_SEC_EVT_SLAVE_ENCRYPT: slave<76><65>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɵ<EFBFBD><C9B5>¼<EFBFBD><C2BC>ص<EFBFBD><D8B5>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>´<EFBFBD><C2B4>룬ɨ<EBA3AC><C9A8>ANCS_AMS<4D>ķ<EFBFBD><C4B7><EFBFBD><EFBFBD><EFBFBD>
gatt_discovery_all_peer_svc(ANCS_AMS_client_id,event->param.slave_connect.conidx);
AMS<EFBFBD><EFBFBD>ANCS<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ˵<EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>£<EFBFBD>
/****ANCS********/
4 ANCS_Client.c <20>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD>ĵط<C4B5><D8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void ANCS_recv_ntf_src(uint8_t conidx,uint8_t *p_data, uint16_t len);
void ANCS_recv_data_src(uint8_t conidx,uint8_t *p_data, uint16_t len);
<EFBFBD><EFBFBD>1<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾiosҪ<EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD><EFBFBD><EFBFBD>Ϣuid<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD>ĸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>id<EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>2<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾios<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>id<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣϸ<EFBFBD>ڡ<EFBFBD>Ĭ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>8<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>id<EFBFBD><EFBFBD>
5 ANCS_recv_data_src<72><63><EFBFBD><EFBFBD><EFBFBD>ڣ<EFBFBD><DAA3><EFBFBD>ʾ<EFBFBD><CABE>Ϣϸ<CFA2>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD>utf-8 <20><>ascii<69><69><EFBFBD>μ<EFBFBD>ע<EFBFBD>͡<EFBFBD>
6 ÿ<>ε<EFBFBD><CEB5><EFBFBD>Ϣ<EFBFBD>ᴫNTF_ATT_ID_POSITIVE_ACT <20><> NTF_ATT_ID_NEGATIVE_ACT<43><54><EFBFBD><EFBFBD>ʾִ<CABE><D6B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD>Ľ<EFBFBD><C4BD><EFBFBD><EFBFBD><EFBFBD>
ִ<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ANCS_perform_ntf_act<63>Ե<EFBFBD>ǰ<EFBFBD><C7B0>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ANCS_perform_ntf_act(0,call_notification_uid,ANCS_ACT_ID_POSITIVE); <20><><EFBFBD>Խ<EFBFBD><D4BD><EFBFBD><EFBFBD><EFBFBD><E7BBB0>
ANCS_perform_ntf_act(0,call_notification_uid,ANCS_ACT_ID_NEGATIVE); <20><><EFBFBD>ԹҶϵ绰<CFB5><E7BBB0>
/****AMS********/
4 AMS_Client.c <20>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD>ĵط<C4B5><D8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void AMS_recv_entity_info(uint8_t conidx,uint8_t *p_data, uint16_t len)
5 AMS_recv_entity_info<66><6F><EFBFBD><EFBFBD><EFBFBD>ڣ<EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD>˶<EFBFBD><CBB6>ĵ<EFBFBD>ENTI_ID_TRACK <20><><EFBFBD>ĸ<EFBFBD><C4B8><EFBFBD><EFBFBD>ԵĴ<D4B5><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߡ<EFBFBD>ר<EFBFBD><D7A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD>ͣ<EFBFBD><CDA3>û<EFBFBD><C3BB><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> asm_subscribe_entity_update() <20><><EFBFBD>Ķ<EFBFBD>Ӧ<EFBFBD><D3A6>entity֮<79><D6AE><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1>
ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD>ڱ仯<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Բ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͡<EFBFBD>
6 Ҫ<><D2AA><EFBFBD>Ƹ<EFBFBD><C6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ţ<EFBFBD>ʹ<EFBFBD>ú<EFBFBD><C3BA><EFBFBD>ams_crtl_cmd()<29><><EFBFBD>С<EFBFBD>
7 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD>ݹ<EFBFBD><DDB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݱ<EFBFBD><DDB1>ضϣ<D8B6><CFA3><EFBFBD><EFBFBD>Ե<EFBFBD><D4B5><EFBFBD>ams_subscribe_entity_att(...)<29><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡijһ<C4B3><D2BB><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2>
8 <20><><EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD>ams<6D><73><EFBFBD>Կ<EFBFBD><D4BF>Ʒ<EFBFBD>ios<6F>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֲ<EFBFBD><D6B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E7A3BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
a) <20><><EFBFBD>ӽ<EFBFBD><D3BD><EFBFBD><EFBFBD>󣬰<EFBFBD><F3A3ACB0>°<EFBFBD><C2B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڰ<EFBFBD><DAB0><EFBFBD><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>´<EFBFBD><C2B4><EFBFBD>ĸ<EFBFBD><C4B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߡ<EFBFBD>ר<EFBFBD><D7A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>
ams_subscribe_entity_update(ENTI_ID_TRACK ,BIT(TRACK_ATT_ID_ARTIST)|BIT(TRACK_ATT_ID_ALBUM)|BIT(TRACK_ATT_ID_TITLE)|BIT(TRACK_ATT_ID_DURATION)); AMS_recv_entity_info(...) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD>˶<EFBFBD><CBB6>ĵĸ<C4B5><C4B8><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2>ÿ<EFBFBD>е<EFBFBD><D0B5><EFBFBD>һ<EFBFBD>׸<EFBFBD>ʱ<EFBFBD><CAB1>ios<6F><73><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Щ<EFBFBD><D0A9><EFBFBD>ݡ<EFBFBD>
b) <20><><EFBFBD>ӽ<EFBFBD><D3BD><EFBFBD><EFBFBD>󣬰<EFBFBD><F3A3ACB0>°<EFBFBD><C2B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڰ<EFBFBD><DAB0><EFBFBD><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>´<EFBFBD><C2B4><EFBFBD><EBB2A5><EFBFBD><EFBFBD>һ<EFBFBD>׸衣
ams_crtl_cmd(CMD_ID_NEXT_TRACK);
c) AMS_recv_entity_info(...) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD>˶<EFBFBD><CBB6>ĵĸ<C4B5><C4B8><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD>п<EFBFBD><D0BF><EFBFBD><EFBFBD><EFBFBD>Ϣ̫<CFA2><CCAB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݱ<EFBFBD><DDB1>ضϵ<D8B6><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E6B4A6>
else if(p_data[1] ==TRACK_ATT_ID_TITLE)
{
//show_utf8_string(&rsp[3],len -3);
if(p_data[2] & ENTI_UPDATE_FLAG_TRUNCATED)
ams_subscribe_entity_att(ENTI_ID_TRACK,BIT(TRACK_ATT_ID_TITLE));
}

View File

@ -0,0 +1,124 @@
#ifndef __AUTONAVI_CONFIG_H__
#define __AUTONAVI_CONFIG_H__
#include "autonavi_profile.h"
#define AUTONAVI_LOG printf
typedef struct
{
uint8_t msgid:4;
uint8_t cmd:4;
uint8_t totalframe;
uint8_t frame_seq;
uint16_t frame_len;
uint8_t *buff;
// uint16_t data_len;
}autonavi_protocol_data_t;
typedef struct
{
uint8_t state;//导航状态
int8_t icon;//图标
uint8_t text[128];//文本信息
uint16_t next_dist;//下个路口距离 米
uint16_t remaining_time;//导航剩余时间,单位秒
uint16_t remaining_mileage;//剩余里程
uint16_t arrival_time;//到达时间
uint8_t next_name[128];//下个路口名称
int8_t event;//导航事件
uint8_t fault_code;//故障码
//uint8_t fault_info;//异常信息说明
}autonavi_payload_t;
//命令类型
enum
{
CMD_TYPE_UNKNOWN = 0,
CMD_TYPE_BIND_DEVICE = 0x01,
CMD_TYPE_AUC=0x02,
CMD_TYPE_NAVI=0x03,
CMD_TYPE_LOOCK = 0x04,//not
};
//导航参数id
enum{
NAVI_PARAM_ID_UNKNOWN = 0,
NAVI_PARAM_ID_STATE=0x01,//导航状态
NAVI_PARAM_ID_ICON=0x02,//icon指引箭头
NAVI_PARAM_ID_TEXT=0x03,//文字导航信息
NAVI_PARAM_ID_DIST=0x04,//距离下个路口的距离 单位米
NAVI_PARAM_ID_LEFT_TIME=0x05,//剩余时间
NAVI_PARAM_ID_REMAIN_KM=0x06,//剩余里程
NAVI_PARAM_ID_ARRIVAL_TIME=0x07,//到达时间
NAVI_PARAM_ID_NEXT_NAME=0x08,//下一个路口名称
NAVI_PARAM_ID_EVENT_TYPE=0x09,//导航事件类型
NAVI_PARAM_ID_FAULT_CODE=0xf0,//故障代码
NAVI_PARAM_ID_FAULT_INFO=0xf1,//故障信息
NAVI_PARAM_ID_DEBUG_INFO=0xff,//导航调试信息
};
enum{
NAVI_ICON_ID_NULL = 0,
NAVI_ICON_ID_CAR=0x01,//自车图标
NAVI_ICON_ID_TURN_LEFT=0x02,//左转图标
NAVI_ICON_ID_TURN_RIGHT=0x03,//右转图标
NAVI_ICON_ID_SLIGHT_LEFT=0x04,//左前方
NAVI_ICON_ID_SLIGHT_RIGHT=0x05,//右前方
NAVI_ICON_ID_TURN_HARDLEFT=0x06,//左后方
NAVI_ICON_ID_TURN_HARDRIGHT=0x07,//右后方
NAVI_ICON_ID_UTURN=0x08,//左转掉头
NAVI_ICON_ID_CONTINUE=0x09,//直行图标
NAVI_ICON_ID_WAY=0x0a,//到达途径点
NAVI_ICON_ID_ENTRY_RING=0x0b,//进⼊环岛图标,右侧通⾏地区的逆时针环岛
NAVI_ICON_ID_LEAVE_RING=0x0c,//驶出环岛图标,右侧通⾏地区的逆时针环岛
NAVI_ICON_ID_SAPA=0x0d,//到达服务区图标 not yet implemented
//...
NAVI_ICON_ID_UTURN_RIGHT=0x13,//右转掉头图标,左侧通⾏地区的掉头
//...
NAVI_ICON_ID_CROSS_WALK=0x1d,//通过人行横道
NAVI_ICON_ID_OVER_PASS=0x1e,//通过过街天桥
NAVI_ICON_ID_UNDER_GROUND=0x1f,//通过地下通道图标
NAVI_ICON_ID_SQUARE=0x20,//通过广场
NAVI_ICON_ID_PARK=0x21,//通过公园
NAVI_ICON_ID_STAIRCASE=0x22,//通过扶梯
NAVI_ICON_ID_LIGFT=0x23,//通过直梯
NAVI_ICON_ID_CABLEWAY=0x24,//通过索道
NAVI_ICON_ID_SKY_CHANNEL=0x25,//通过空中通道
NAVI_ICON_ID_CHANNEL=0x26,//通过通道
NAVI_ICON_ID_WALKR_ROAD=0x27,//通过行人道路
NAVI_ICON_ID_BOAT_LINE=0x28,//通过游船路线
NAVI_ICON_ID_SIGHTSEEING_LINE=0x29,//通过观光车路线
NAVI_ICON_ID_SKIDWAY=0x2a,//通过滑道
NAVI_ICON_ID_LADDER=0x2b,//通过阶梯
NAVI_ICON_ID_SLOPE=0x2c,//通过斜坡
NAVI_ICON_ID_BRIDGE=0x2d,//通过桥
NAVI_ICON_ID_FERRY=0x2e,//通过轮渡
NAVI_ICON_ID_SUBEAY=0x2f,//通过地铁通道
NAVI_ICON_ID_ENTER_BUILDING=0x30,//通过建筑物
NAVI_ICON_ID_LEAVE_BUILDING=0x31,//离开建筑物
NAVI_ICON_ID_BY_ELEVATOR=0x32,//电梯换层
NAVI_ICON_ID_BY_STAIR=0x33,//楼梯换层
NAVI_ICON_ID_BY_ESCALATOR=0x34,//扶梯换层
NAVI_ICON_ID_LOW_TRAFFICCROSS=0x35,//非导航段通过红绿灯路口
NAVI_ICON_ID_LOW_CROSS=0x36,//非导航段通过普通路口
NAVI_ICON_ID_HOSING_ESTATELNNER=0X37,//小区内部路偏航抑制态
NAVI_ICON_ID_LEAVE_OVERPASS=0x38,//下天桥
NAVI_ICON_ID_LEAVE_UNDERGROUND=0x39,//出地下通道
NAVI_ICON_ID_LEAVE_LADDER=0x3a,//出阶梯
NAVI_ICON_ID_CROSS_ROAD_DIAGONAL=0x3b,//到马路斜对面
NAVI_ICON_ID_RIDE_TAB_START=-7,//骑行导航页顶部栏起点
NAVI_ICON_ID_FOOT_TAB_END=-6,//步行导航页顶部栏终点
NAVI_ICON_ID_FOOT_START=-5,//步行导航顶部栏起点
NAVI_ICON_ID_PREVIEW_TAB_END=-4,//预览页面导航页tab终点
NAVI_ICON_ID_TAB_SUBWAY = -11,//步行中地铁标识
//NAVI_ICON_ID_DEFAULT,
};
#endif

View File

@ -0,0 +1,235 @@
#include "autonavi_handler.h"
#include "autonavi_config.h"
#include "FreeRTOS.h"
#include "task.h"
#include "app_lvgl.h"
static bool bond_flag=false;
void autonavi_data_decode(autonavi_protocol_data_t *msg);
#define PVER_STR "1"
#define NVER_STR "1"
#define MANUFACTURE_STR "freqchip"
#define DEVICE_STR "G0"
#define DID_STR "FR309x"
#define SVER_STR "1"
#if 0
#define KEY_STR "3084f2321ceb3845087220046466a87c"
#define SIG_STR "40f62e001f0da15d9d8bec5ba8e8569b"
#else
#define KEY_STR "3084f2321ceb3845087220046466a87c"
#define SIG_STR "32e7c7d5a4164d260402d29d4e6538bd"
#endif
#define SEED_STR "a1b2c3d4"
//did=FR309x&key=3084f2321ceb3845087220046466a87c&seed=a1b2c3d4
static autonavi_protocol_data_t protocol_msg={0};
static autonavi_payload_t autonavi_payload={0};
uint16_t read_basic_attribute_service(uint8_t *param,uint16_t max_len)
{
uint16_t dst_len = 0;
#if 1
if(bond_flag==false)
{
dst_len = snprintf((char*)param,max_len,"pver=%s&nver=%s&manu=%s&device=%s&did=%s&sver=%s&key=%s&sig=%s&seed=%s",\
PVER_STR,NVER_STR,MANUFACTURE_STR,DEVICE_STR,DID_STR,SVER_STR,KEY_STR,SIG_STR,SEED_STR);
AUTONAVI_LOG("len:%d src:%s\r\n",dst_len,param);
}else{
dst_len = snprintf((char*)param,max_len,"pver=%s&nver=%s&manu=%s&device=%s&did=%s&sver=%s&key=%s&sig=%s&seed=%s&status=authed",\
PVER_STR,NVER_STR,MANUFACTURE_STR,DEVICE_STR,DID_STR,SVER_STR,KEY_STR,SIG_STR,SEED_STR);
AUTONAVI_LOG("len:%d src:%s\r\n",dst_len,param);
}
#else
uint16_t dst_len = snprintf((char*)param,max_len,"pver=%s&nver=%s&manu=%s&device=%s&did=%s&sver=%s&=seed=%s",\
PVER_STR,NVER_STR,MANUFACTURE_STR,DEVICE_STR,DID_STR,SVER_STR,SEED_STR);
AUTONAVI_LOG("len:%d src:%s\r\n",dst_len,param);
#endif
return dst_len;
}
/*
msgid|cmd totalframe frame_seq frame_length frame_length
1字节 1字节 1字节 1字节 1字节
*/
void autonavi_data_recv(uint8_t *data,uint16_t len)
{
static bool first_flag=false;
static uint16_t frame_cnt=0;
static uint16_t frame_sum=0;
static uint8_t last_id=0;
protocol_msg.msgid = data[0]&0xf0;
protocol_msg.cmd = data[0]&0x0f;
uint16_t src_len = ((data[4]<<8)|data[3]);
switch(protocol_msg.cmd)
{
case CMD_TYPE_BIND_DEVICE://绑定
{
AUTONAVI_LOG("CMD_TYPE_BIND_DEVICE :%x\r\n",protocol_msg.cmd);
char *param = pvPortMalloc(300);
if(param==NULL)return;
uint16_t dst_len = snprintf((char*)param,300,"pver=%s&nver=%s&manu=%s&device=%s&did=%s&sver=%s&key=%s&sig=%s&seed=%s&status=authed",\
PVER_STR,NVER_STR,MANUFACTURE_STR,DEVICE_STR,DID_STR,SVER_STR,KEY_STR,SIG_STR,SEED_STR);
AUTONAVI_LOG("send len:%d data:%s\r\n",dst_len,param);
autonavi_send_notify((uint8_t*)param,dst_len);
vPortFree(param);
bond_flag = true; //绑定成功后需要保存这个状态 下次直接链接
}
break;
case CMD_TYPE_AUC:// 鉴权
{
}
break;
case CMD_TYPE_NAVI:
{
if(data[1]==0x01) //单包数据
{
frame_sum = 0;
frame_cnt = 0;
first_flag = false;
if(len>5)
{
protocol_msg.buff = pvPortMalloc(src_len);
if(protocol_msg.buff==NULL)return;
protocol_msg.frame_len = (len-5);
memcpy(protocol_msg.buff,&data[5],(len-5));
}else{
protocol_msg.frame_len = 0;
protocol_msg.buff = NULL;
}
autonavi_data_decode(&protocol_msg);
vPortFree(protocol_msg.buff);
}else if(data[1]>0x01){//拼包数据
if((first_flag==false) && (data[2]==0x01))
{
first_flag = true;
frame_cnt = 0;
frame_sum = (data[1]*src_len);
protocol_msg.buff = pvPortMalloc(frame_sum);
if(protocol_msg.buff==NULL)return;
memset(protocol_msg.buff,0,frame_sum);
}
memcpy(&protocol_msg.buff[frame_cnt],&data[5],src_len);
frame_cnt+=src_len;
AUTONAVI_LOG("cnt:%d sum:%d\r\n",frame_cnt,frame_sum);
if((data[2] == data[1]) && (frame_cnt <= frame_sum)) //接收最后一帧拼包
{
protocol_msg.frame_len=frame_cnt;
autonavi_data_decode(&protocol_msg);
//aicare_app_data_decode(data[1],data[2],data[3],src_len,frame_recving_buffer);
vPortFree(protocol_msg.buff);
protocol_msg.buff=NULL;
frame_sum = 0;
frame_cnt = 0;
first_flag = false;
}
}
}
break;
}
}
void autonavi_data_handler(uint8_t *data)
{
uint8_t len = data[1];
printf("len:%d\r\n",len);
switch(data[0])
{
case NAVI_PARAM_ID_STATE://导航状态
autonavi_payload.state = data[2];
AUTONAVI_LOG("autonavi_payload.state:0x%x\r\n",autonavi_payload.state);
break;
case NAVI_PARAM_ID_ICON://icon指引箭头
autonavi_payload.icon = data[2];
AUTONAVI_LOG("autonavi_payload.icon:0x%x %d\r\n",autonavi_payload.icon,(int)autonavi_payload.icon);
break;
case NAVI_PARAM_ID_TEXT://文字导航信息
if(len>0)
{
memset(autonavi_payload.text,0,sizeof(autonavi_payload.text));
memcpy(autonavi_payload.text,&data[2],len);
AUTONAVI_LOG("autonavi_payload.text:%s\r\n",autonavi_payload.text);
}
break;
case NAVI_PARAM_ID_DIST://距离下个路口的距离 单位米
memcpy((void*)&autonavi_payload.next_dist,&data[2],len);
AUTONAVI_LOG("autonavi_payload.next_dist:%d\r\n",autonavi_payload.next_dist);
break;
case NAVI_PARAM_ID_LEFT_TIME://剩余时间
memcpy((void*)&autonavi_payload.remaining_time,&data[2],len);
AUTONAVI_LOG("autonavi_payload.remaining_time:%d\r\n",autonavi_payload.remaining_time);
break;
case NAVI_PARAM_ID_REMAIN_KM://剩余里程
//= (data[2]<<8|data[3]);
memcpy((void*)&autonavi_payload.remaining_mileage,&data[2],len);
AUTONAVI_LOG("autonavi_payload.remaining_mileage:%d\r\n",autonavi_payload.remaining_mileage);
break;
case NAVI_PARAM_ID_ARRIVAL_TIME://到达时间
// autonavi_payload.arrival_time = (data[2]<<8|data[3]);
memcpy((void*)&autonavi_payload.arrival_time,&data[2],len);
AUTONAVI_LOG("autonavi_payload.arrival_time:%d\r\n",autonavi_payload.arrival_time);
break;
case NAVI_PARAM_ID_NEXT_NAME://下一个路口名称
if(len>0)
{
memset(autonavi_payload.next_name,0,sizeof(autonavi_payload.next_name));
memcpy(autonavi_payload.next_name,&data[2],len);
AUTONAVI_LOG("autonavi_payload.next_name:%s\r\n",autonavi_payload.next_name);
}
break;
case NAVI_PARAM_ID_EVENT_TYPE://导航事件类型
autonavi_payload.event = data[2];
AUTONAVI_LOG("autonavi_payload.event:0x%x\r\n",autonavi_payload.event);
break;
case NAVI_PARAM_ID_FAULT_CODE://故障代码
autonavi_payload.fault_code = data[2];
AUTONAVI_LOG("autonavi_payload.fault_code:0x%x\r\n",autonavi_payload.fault_code);
break;
case NAVI_PARAM_ID_FAULT_INFO://故障信息
AUTONAVI_LOG("fault_info:%s\r\n",&data[2]);
break;
case NAVI_PARAM_ID_DEBUG_INFO://导航调试信息
AUTONAVI_LOG("autonavi_debug:%s\r\n",&data[2]);
break;
}
}
void autonavi_data_decode(autonavi_protocol_data_t *msg)
{
uint8_t sver = msg->buff[0];
printf("sver:%d\r\n",sver);
for(uint16_t i = 1;i<msg->frame_len;)
{
autonavi_data_handler(&msg->buff[i]);
i+=msg->buff[i+1]+2;
}
// gui_task_msg_send(AUTONAVI_MSG_IN_EVT,NULL,0,NULL,0,NULL);
}
void autonavi_msg_clear(void)
{
memset((void*)&autonavi_payload,0,sizeof(autonavi_payload_t));
}
autonavi_payload_t *get_autonavi_msg(void)
{
return &autonavi_payload;
}

View File

@ -0,0 +1,17 @@
#ifndef __AUTONAVI_HANDLER_H__
#define __AUTONAVI_HANDLER_H__
#include "autonavi_profile.h"
#include "autonavi_config.h"
uint16_t read_basic_attribute_service(uint8_t *param,uint16_t max_len);
void autonavi_data_recv(uint8_t *data,uint16_t len);
void autonavi_msg_clear(void);
autonavi_payload_t *get_autonavi_msg(void);
#endif

View File

@ -0,0 +1,433 @@
#include "autonavi_profile.h"
#include "autonavi_config.h"
#include "autonavi_handler.h"
static const uint8_t sp_autonavi_uuid[] = SP_AUTONAVI_UUID;
static uint8_t conn_svc_idx = 0;
/******************************* Characteristic 1 defination *******************************/
#define AUTONAVI_CHAR1_VALUE_LEN 512
static uint8_t autonavi_char1_value[AUTONAVI_CHAR1_VALUE_LEN] = {0};
//#define SP_CHAR1_USER_DESC_LEN 17
static uint8_t desc_data[2] = {0};
/******************************* Characteristic 2 defination *******************************/
#define AUTONAVI_CHAR2_VALUE_LEN 512
static uint8_t autonavi_char2_value[AUTONAVI_CHAR2_VALUE_LEN] = {0x11, 0x22, 0x33, 0x44, 0x55};
//#define SP_CHAR2_USER_DESC_LEN 17
static uint16_t ble_mtu = 0;
static const gatt_attribute_t simple_profile_att_table[] =
{
// Simple gatt Service Declaration
[AUTONAVI_IDX_SERVICE] = { // autonvio read
{ UUID_SIZE_2, UUID16_ARR(GATT_PRIMARY_SERVICE_UUID) }, /* UUID */
GATT_PROP_READ, /* Permissions */
UUID_SIZE_16, /* Max size of the value */ /* Service UUID size in service declaration */
(uint8_t*)sp_autonavi_uuid, /* Value of the attribute */ /* Service UUID value in service declaration */
},
/******************************* Characteristic 1 defination *******************************/
// Characteristic 1 Declaration
[AUTONAVI_IDX_CHAR1_DECLARATION] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID) }, /* UUID */
GATT_PROP_READ, /* Permissions */
0, /* Max size of the value */
NULL, /* Value of the attribute */
},
// Characteristic 1 Value
[AUTONAVI_IDX_CHAR1_VALUE] = {
{ UUID_SIZE_16, SP_AUTONAVI_CHAR1_UUID }, /* UUID */
GATT_PROP_READ | GATT_PROP_NOTI , /* Permissions */
AUTONAVI_CHAR1_VALUE_LEN, /* Max size of the value */
NULL, /* Value of the attribute */ /* Can assign a buffer here, or can be assigned in the application by user */
/* When the buffer is null, if a read request is received,
* the lower layer will report a read event to the gatt callback.
* The user must assign a value to the data pointer in the callback event
* to reply to the read request
*/
},
// Characteristic 1 client characteristic configuration
[AUTONAVI_IDX_CHAR1_CFG] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_CLIENT_CHAR_CFG_UUID) }, /* UUID */
GATT_PROP_WRITE_REQ, /* Permissions */
2, /* Max size of the value */
desc_data, /* Value of the attribute */ /* Can assign a buffer here, or can be assigned in the application by user */
},
// // Characteristic 1 User Description
// [SP_IDX_CHAR1_USER_DESCRIPTION] = {
// { UUID_SIZE_2, UUID16_ARR(GATT_CHAR_USER_DESC_UUID) }, /* UUID */
// GATT_PROP_READ, /* Permissions */
// SP_CHAR1_USER_DESC_LEN, /* Max size of the value */
// (uint8_t *)sp_char1_user_desc_data, /* Value of the attribute */
// },
/******************************* Characteristic 2 defination *******************************/
// Characteristic 2 Declaration
[AUTONAVI_IDX_CHAR2_DECLARATION] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID) }, /* UUID */
GATT_PROP_WRITE_CMD, /* Permissions */
0, /* Max size of the value */
NULL, /* Value of the attribute */
},
// Characteristic 2 Value
[AUTONAVI_IDX_CHAR2_VALUE] = {
{ UUID_SIZE_16, SP_AUTONAVI_CHAR2_UUID }, /* UUID */
GATT_PROP_WRITE_CMD , /* Permissions */
AUTONAVI_CHAR2_VALUE_LEN, /* Max size of the value */
autonavi_char2_value, /* Value of the attribute */ /* Can assign a buffer here, or can be assigned in the application by user */
/* When the buffer is null, if a read request is received,
* the lower layer will report a read event to the gatt callback.
* The user must assign a value to the data pointer in the callback event
* to reply to the read request
*/
},
// Characteristic 2 User Description
// [SP_IDX_CHAR2_USER_DESCRIPTION] = {
// { UUID_SIZE_2, UUID16_ARR(GATT_CHAR_USER_DESC_UUID) }, /* UUID */
// GATT_PROP_READ, /* Permissions */
// SP_CHAR2_USER_DESC_LEN, /* Max size of the value */
// (uint8_t *)sp_char2_user_desc_data, /* Value of the attribute */
// },
};
static void app_ble_start_advertising(void);
static char local_device_name[] = "AutoNavi";
static adv_handle adv;
static uint8_t service_id;
/*
* Advertising data, max size is 28 bytes
*/
//61 75 12 76-fd d6-11 ed-be 56-02 42 ac 12 00 02
static uint8_t adv_data[] = {
/* gatt service information */
#if 1
0x11, //length of this AD
GAP_ADVTYPE_128BIT_MORE, //128bit service uuid AD type
0x02,0x00,0x12, 0xac,0x42,0x02,0x56,0xbe,0xed,0x11,0xd6,0xfd,0x76,0x12,0x75,0x61,//value.service uuid:0xFFF0
#else
0x03,
GAP_ADVTYPE_16BIT_COMPLETE,
0xf1,0xfe,
#endif
/* local device name information */
0x09, //length of this AD
GAP_ADVTYPE_LOCAL_NAME_COMPLETE, //complete name AD type
'A','u','t','o','N','a','v','i', //value.local device name
};
/*
* Advertising scan response data, max size is 31 bytes
*/
static uint8_t adv_scan_rsp_data[] = {
/* local device name information */
0x09, //length of this AD
GAP_ADVTYPE_LOCAL_NAME_COMPLETE, //complete name AD type
'A','u','t','o','N','a','v','i', //value.local device name
};
static uint16_t gap_callback(struct gap_event *event)
{
// AUTONAVI_LOG("gap_callback: type = %d\r\n", event->type);
switch(event->type) {
case GATT_EVT_PROFILE_ADDED:
{
AUTONAVI_LOG("gap_callback: GATT_EVT_PROFILE_ADDED: 0x%02X\r\n", event->param.profile_added_status);
/* service profile has been added successfully, then the advertising can be started */
app_ble_start_advertising();
}
break;
case GAP_EVT_ADV_SET_PARAM:
AUTONAVI_LOG("adv param set: 0x%02X\r\n", event->param.adv_set_param.status);
break;
case GAP_EVT_ADV_SET_ADV_DATA:
AUTONAVI_LOG("adv data set: 0x%02X\r\n", event->param.adv_set_adv_data.status);
break;
case GAP_EVT_ADV_SET_SCAN_RSP:
AUTONAVI_LOG("adv scan rsp data set: 0x%02X\r\n", event->param.adv_set_scan_rsp.status);
break;
case GAP_EVT_ADV_START:
AUTONAVI_LOG("adv start :0x%02X\r\n", event->param.adv_start.status);
break;
case GAP_EVT_ADV_END:
AUTONAVI_LOG("adv end: 0x%02X\r\n", event->param.adv_end.status);
break;
case GAP_EVT_SLAVE_CONNECT:
{
//gap_get_link_version(event->param.connect.conidx);
//gap_get_link_rssi(event->param.connect.conidx);
//gap_get_link_features(event->param.connect.conidx);
AUTONAVI_LOG("slave connect[%d], connect num: %d\r\n", event->param.connect.conidx, gap_get_connect_num());
//gatt_mtu_exchange_req(service_id, event->param.connect.conidx, 23);
gatt_mtu_exchange_req(service_id, event->param.connect.conidx, 247);
autonavi_msg_clear();
}
break;
case GAP_EVT_DISCONNECT:
{
AUTONAVI_LOG("gap_callback: GAP_EVT_DISCONNECT, conidx:%d, reason:0x%02X\r\n", event->param.disconnect.conidx,
event->param.disconnect.reason);
gap_adv_start(adv, 0, 0);
}
break;
case GATT_EVT_MTU:
AUTONAVI_LOG("gap_callback: conidx: %d, GATT_EVT_MTU: %d\r\n", event->param.mtu_ind.conidx, event->param.mtu_ind.mtu);
break;
case GAP_EVT_NAME_REQ:
{
gap_name_req_rsp(event->param.name_req.conidx,
event->param.name_req.token,
sizeof(local_device_name),
(uint8_t *)local_device_name);
}
break;
case GAP_EVT_APPEARANCE_REQ:
{
gap_appearance_req_rsp(event->param.appearance_req.conidx,
event->param.appearance_req.token,
GAP_APPEARE_UNKNOWN);
}
break;
case GAP_EVT_LINK_PARAM_REQ:
{
struct gap_link_param_update_rsp rsp;
rsp.accept = true;
rsp.conidx = event->param.link_param_update_req.conidx;
rsp.ce_len_max = 2;
rsp.ce_len_min = 2;
gap_param_update_rsp(&rsp);
}
break;
case GAP_EVT_LINK_PARAM_UPDATE:
{
AUTONAVI_LOG("conn param update,conidx:%d, con_int:%d, latency:%d, timeout%d\r\n", event->param.link_param_update.conidx,
event->param.link_param_update.con_interval,
event->param.link_param_update.con_latency,
event->param.link_param_update.sup_to);
}
break;
case GAP_EVT_LINK_RSSI:
AUTONAVI_LOG("gap_callback: conidx: %d, GAP_EVT_LINK_RSSI: %d\r\n", event->param.gap_link_rssi.conidx, event->param.gap_link_rssi.link_rssi);
break;
case GAP_EVT_PHY_IND:
AUTONAVI_LOG("gap_callback: conidx: %d, GAP_EVT_PHY_IND: %d\r\n", event->param.gap_phy_ind.conidx, event->param.gap_phy_ind.tx_phy);
break;
case GAP_EVT_PHY_REJECT:
AUTONAVI_LOG("gap_callback: conidx: %d, GAP_EVT_PHY_REJECT, status: %d\r\n", event->param.gap_phy_update_reject.conidx, event->param.gap_phy_update_reject.status);
break;
case GAP_EVT_LINK_VER:
AUTONAVI_LOG("gap_callback: conidx: %d, GAP_EVT_LINK_VER\r\n", event->param.gap_link_ver.conidx);
break;
case GAP_EVT_LINK_FEATURE:
AUTONAVI_LOG("gap_callback: conidx: %d, GAP_EVT_LINK_FEATURE:%d\r\n", event->param.gap_link_feature.conidx, event->param.gap_link_feature.features[0]);
break;
default:
break;
}
return 0;
}
static uint16_t gatt_callback(struct gatt_msg *p_msg)
{
uint8_t uuid_temp[16];
conn_svc_idx = p_msg->conn_idx;
switch(p_msg->msg_evt) {
case GATTC_MSG_CMP_EVT:
{
switch(p_msg->param.gatt_op_cmp.operation) {
case GATT_OP_NOTIFY:
/*opearation of notification is complete */
AUTONAVI_LOG("notify cmp, conidx:%d, status:0x%02X\r\n", p_msg->conn_idx, p_msg->param.gatt_op_cmp.status);
break;
default:
AUTONAVI_LOG("notify cmp, default\r\n");
break;
}
}
break;
/* Received a read request from the peer device */
case GATTS_MSG_READ_REQ:
{
AUTONAVI_LOG("GATTS_MSG_READ_REQ, conidx:%d, att idx:%d\r\n", p_msg->conn_idx, p_msg->att_idx);
if(p_msg->att_idx == AUTONAVI_IDX_CHAR1_VALUE)
{
/*
* Because the buffer pointer of SP_IDX_CHAR1_VALUE is NULL,
* read requests will be report to the application layer for user response
*/
//uint8_t read_rsp_data[] = {0x00, 0x01, 0x02, 0x03, 0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15};
//memcpy(p_msg->param.gatt_data.p_msg_data, read_rsp_data, sizeof(read_rsp_data));
/* Return the length of response data */
return read_basic_attribute_service(p_msg->param.gatt_data.p_msg_data,AUTONAVI_CHAR1_VALUE_LEN);
}
}
break;
/* Received a write request from the peer device */
case GATTS_MSG_WRITE_REQ:
{
AUTONAVI_LOG("GATTS_MSG_WRITE_REQ, conidx:%d, att idx:%d\r\n", p_msg->conn_idx, p_msg->att_idx);
if(p_msg->att_idx == AUTONAVI_IDX_CHAR1_VALUE)
{
AUTONAVI_LOG("recv data: 0x");
for(uint8_t i=0; i<p_msg->param.gatt_data.msg_len; i++)
AUTONAVI_LOG("%02X", p_msg->param.gatt_data.p_msg_data[i]);
AUTONAVI_LOG("\r\n");
}
else if(p_msg->att_idx == AUTONAVI_IDX_CHAR2_VALUE) //write data cmd
{
AUTONAVI_LOG("recv data: ");
for(uint8_t i=0; i<p_msg->param.gatt_data.msg_len; i++)
AUTONAVI_LOG("%02X ", p_msg->param.gatt_data.p_msg_data[i]);
AUTONAVI_LOG(" \r\n");
autonavi_data_recv(p_msg->param.gatt_data.p_msg_data,p_msg->param.gatt_data.msg_len);
}
else if(p_msg->att_idx == AUTONAVI_IDX_CHAR1_CFG) //config notify
{
uint8_t data[2];
memcpy(data, p_msg->param.gatt_data.p_msg_data, 2);
if(data[0] & 0x01)
{
/* peer device enable notify */
AUTONAVI_LOG("ntf enable, att_idx:%d\r\n", p_msg->att_idx);
// uint8_t send_data[5] = {0x01, 0x02, 0x03, 0x04, 0x05};
// struct gatt_send_event ntf;
// ntf.conidx = p_msg->conn_idx;
// ntf.att_idx = AUTONAVI_IDX_CHAR1_VALUE;
// ntf.p_data = send_data;
// ntf.data_len = sizeof(send_data);
// ntf.svc_id = service_id;
// /* Send a notification to the peer device */
// gatt_notification(&ntf);
}
}
}
break;
case GATTC_MSG_LINK_CREATE:
AUTONAVI_LOG("gatt linkk create, conidx:%d\r\n", p_msg->conn_idx);
break;
case GATTC_MSG_LINK_LOST:
AUTONAVI_LOG("gatt linkk lost, conidx:%d\r\n", p_msg->conn_idx);
break;
default:
break;
}
return 0;
}
void autonavi_send_notify(uint8_t *p_data,uint16_t len)
{
// if(user_ntf_enable_flag)
{
struct gatt_send_event ntf;
ntf.conidx = conn_svc_idx;
ntf.att_idx = AUTONAVI_IDX_CHAR1_VALUE;
ntf.p_data = p_data;
ntf.data_len = len;
ntf.svc_id = service_id;
/* Send a notification to the peer device */
gatt_notification(&ntf);
}
}
static void autonavi_ble_add_service(void)
{
struct gatt_service service;
service.att_nb = AUTONAVI_IDX_NB;
service.p_att_tb = simple_profile_att_table;
service.gatt_msg_handler = gatt_callback; //set GATT event callback
service_id = gatt_add_service(&service);
}
static void app_ble_start_advertising(void)
{
/* creat a handle of advertising*/
adv = gap_adv_create();
gap_adv_param_t adv_param = {
.own_addr_type = GAP_ADDR_TYPE_STATIC, //own address type
.adv_mode = GAP_ADV_MODE_UNDIRECT,
.disc_mode = GAP_ADV_DISC_MODE_GEN_DISC,
.adv_chnl_map = GAP_ADV_CHAN_ALL,
.filt_policy = GAP_ADV_FILTER_SCAN_ANY_CON_ANY, //Policy for filtering scanning or connection requests from peer devices
.phy_mode = GAP_PHY_TYPE_LE_1M,
.adv_intv_min = 160, //advertising min interval, in unit of 0.625ms
.adv_intv_max = 160, //advertising max interval, in unit of 0.625ms
};
/* set advertising param */
gap_adv_set_param(adv, &adv_param);
/* set advertising data */
gap_adv_set_adv_data(adv, adv_data, sizeof(adv_data));
/* set advertising scan response data */
gap_adv_set_scan_rsp(adv, adv_scan_rsp_data, sizeof(adv_scan_rsp_data));
/* start sadvertising */
gap_adv_start(adv, 0, 0);
}
void autonavi_ble_init(void)
{
AUTONAVI_LOG("app_ble_init\r\n");
/* set GAP event callback*/
gap_set_cb_func(gap_callback);
/* set security param */
struct gap_security_param smp_param;
smp_param.mitm = true;
smp_param.secure_connection = false;
smp_param.bond = true;
smp_param.rsp_mode = ENABLE_AUTO_RSP;
smp_param.oob_used = GAP_OOB_AUTH_DATA_NOT_PRESENT;
smp_param.io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT;
gap_security_param_init(&smp_param);
/* add service profile, The GAP callback event is GATT_EVT_PROFILE_ADDED*/
autonavi_ble_add_service();
}

View File

@ -0,0 +1,40 @@
#ifndef __AUTONAVI_PROFILE_H__
#define __AUTONAVI_PROFILE_H__
/*
* INCLUDES (包含头文件)
*/
#include <stdio.h>
#include <string.h>
#include "gap_api.h"
#include "gatt_api.h"
#include "gatt_sig_uuid.h"
#define SP_AUTONAVI_UUID {0x02,0x00,0x12, 0xac,0x42,0x02,0x56,0xbe,0xed,0x11,0xd6,0xfd,0x76,0x12,0x75,0x61}
#define SP_AUTONAVI_CHAR2_UUID {0x02,0x00,0x12, 0xac,0x42,0x02,0x56,0xbe,0xed,0x11,0xda,0xfd,0xe2,0x30,0xea,0x99}
#define SP_AUTONAVI_CHAR1_UUID {0x02,0x00,0x12, 0xac,0x42,0x02,0x56,0xbe,0xed,0x11,0xc4,0xfb,0xea,0x84,0xe4,0x7e}
enum
{
AUTONAVI_IDX_SERVICE,
AUTONAVI_IDX_CHAR1_DECLARATION,
AUTONAVI_IDX_CHAR1_VALUE,
AUTONAVI_IDX_CHAR1_CFG,
// SP_IDX_CHAR1_USER_DESCRIPTION,
AUTONAVI_IDX_CHAR2_DECLARATION,
AUTONAVI_IDX_CHAR2_VALUE,
AUTONAVI_IDX_NB,
};
/*
* MACROS (宏定义)
*/
void autonavi_ble_init(void);
void autonavi_send_notify(uint8_t *p_data,uint16_t len);
#endif

View File

@ -0,0 +1,223 @@
/**
* Copyright (c) 2019, Freqchip
*
* All rights reserved.
*
*
*/
/*
* INCLUDES (<28><><EFBFBD><EFBFBD>ͷ<EFBFBD>ļ<EFBFBD>)
*/
#include <stdio.h>
#include <string.h>
#include "gap_api.h"
#include "gatt_api.h"
#include "gatt_sig_uuid.h"
#include "batt_service.h"
/*
* MACROS (<28><EFBFBD><EAB6A8>)
*/
#define CFG_CON 20
/*
* CONSTANTS (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
*/
// Device Information Service UUID: 0x180A
static const uint8_t batt_svc_uuid[UUID_SIZE_2] = UUID16_ARR(BATT_SERV_UUID);
/******************************* Battery level defination *******************************/
// Battery level data
static uint8_t battery_level;
/*
* TYPEDEFS (<28><><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>)
*/
/*
* GLOBAL VARIABLES (ȫ<>ֱ<EFBFBD><D6B1><EFBFBD>)
*/
/*
* LOCAL VARIABLES (<28><><EFBFBD>ر<EFBFBD><D8B1><EFBFBD>)
*/
static uint8_t batt_svc_id;
static uint8_t batt_link_ntf_enable[CFG_CON] = {0};
/*********************************************************************
* Profile Attributes - Table
* ÿһ<C3BF><EFBFBD><EEB6BC>һ<EFBFBD><D2BB>attribute<74>Ķ<EFBFBD><C4B6>
* <20><>һ<EFBFBD><D2BB>attributeΪService <20>ĵĶ<C4B5><C4B6>
* ÿһ<C3BF><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ(characteristic)<29>Ķ<EFBFBD><C4B6><EFBFBD><E5A3AC><EFBFBD><EFBFBD><EFBFBD>ٰ<EFBFBD><D9B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>attribute<74>Ķ<EFBFBD><C4B6>
* 1. <20><><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD>(Characteristic Declaration)
* 2. <20><><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5>ֵ(Characteristic value)
* 3. <20><><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(Characteristic description)
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>notification <20><><EFBFBD><EFBFBD>indication <20>Ĺ<EFBFBD><C4B9>ܣ<EFBFBD><DCA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD>attribute<74>Ķ<EFBFBD><C4B6><EFBFBD><E5A3AC><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><E6B6A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(client characteristic configuration)<29><>
*
*/
static const gatt_attribute_t batt_att_table[] =
{
[IDX_BATT_SERVICE] = { { UUID_SIZE_2, UUID16_ARR(GATT_PRIMARY_SERVICE_UUID)},
GATT_PROP_READ, UUID_SIZE_2, (uint8_t *)batt_svc_uuid,
},
[IDX_BATT_LEVEL_CHAR_DECLARATION] = { { UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID)},
GATT_PROP_READ,0, NULL,
},
[IDX_BATT_LEVEL_CHAR_VALUE] = { { UUID_SIZE_2, UUID16_ARR(BATT_LEVEL_UUID)},
GATT_PROP_READ | GATT_PROP_NOTI, sizeof(uint8_t),NULL,
},
[IDX_BATT_LEVEL_CCCD] = { {UUID_SIZE_2, UUID16_ARR(GATT_CLIENT_CHAR_CFG_UUID)},
GATT_PROP_READ | GATT_PROP_WRITE_CMD | GATT_PROP_WRITE_REQ,sizeof(uint16_t),NULL,
},
};
static void show_reg(uint8_t *data,uint32_t len,uint8_t dbg_on)
{
uint32_t i=0;
if(len == 0 || (dbg_on==0)) return;
for(; i<len; i++)
{
printf("0x%02X,",data[i]);
}
printf("\r\n");
}
/*********************************************************************
* @fn batt_gatt_op_cmp_handler
*
* @brief Gatt operation complete handler.
*
*
* @param p_operation - operation that has compeleted
*
* @return none.
*/
void batt_gatt_op_cmp_handler(void *p_operation)
{
// if (p_operation->status == 0)
// {}
}
/*********************************************************************
* @fn dis_gatt_msg_handler
*
* @brief Device information gatt message handler.
*
*
* @param p_msg - messages from GATT layer.
*
* @return none.
*/
static uint16_t batt_gatt_msg_handler(struct gatt_msg *p_msg)
{
switch(p_msg->msg_evt)
{
case GATTS_MSG_READ_REQ:
if(p_msg->att_idx == IDX_BATT_LEVEL_CHAR_VALUE)
{
printf("batt_levle request\r\n");
memcpy(p_msg->param.gatt_data.p_msg_data, &battery_level, sizeof(battery_level));
return sizeof(battery_level);
}
else if(p_msg->att_idx == IDX_BATT_LEVEL_CCCD)
{
*(uint16_t *)(p_msg->param.gatt_data.p_msg_data) = batt_link_ntf_enable[p_msg->conn_idx];
return sizeof(uint16_t);
}
break;
case GATTS_MSG_WRITE_REQ:
printf("batt_write:%d\r\n",p_msg->att_idx);
show_reg(p_msg->param.gatt_data.p_msg_data,p_msg->param.gatt_data.msg_len,1);
if(p_msg->att_idx == IDX_BATT_LEVEL_CCCD)
{
batt_link_ntf_enable[p_msg->conn_idx] = *(uint16_t *)(p_msg->param.gatt_data.p_msg_data);
}
break;
case GATTC_MSG_CMP_EVT:
batt_gatt_op_cmp_handler((struct gatt_op_cmp*)&(p_msg->param.gatt_op_cmp));
break;
case GATTC_MSG_LINK_CREATE:
//co_printf("batt svc link[%d] create\r\n",p_msg->conn_idx);
break;
case GATTC_MSG_LINK_LOST:
//co_printf("batt svc link[%d] lost\r\n",p_msg->conn_idx);
batt_link_ntf_enable[p_msg->conn_idx] = 0x0;
break;
default:
break;
}
return 0;
}
/*********************************************************************
* @fn batt_gatt_notify
*
* @brief Send batt level notification to peer.
*
*
* @param conidx - link idx.
* batt_level - battery energy percentage.
*
* @return none.
*/
void batt_gatt_notify(uint8_t conidx,uint8_t batt_level)
{
battery_level = batt_level;
if(batt_link_ntf_enable[conidx])
{
struct gatt_send_event ntf;
ntf.conidx = conidx;
ntf.svc_id = batt_svc_id;
ntf.att_idx = IDX_BATT_LEVEL_CHAR_VALUE;
ntf.data_len = 1;
ntf.p_data = &battery_level;
gatt_notification(&ntf);
}
}
/*********************************************************************
* @fn batt_gatt_add_service
*
* @brief Simple Profile add GATT service function.
* <20><><EFBFBD><EFBFBD>GATT service<63><65>ATT<54><54><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><DDBF><EFBFBD><EFBFBD>
*
* @param None.
*
*
* @return None.
*/
void batt_gatt_add_service(void)
{
gatt_service_t batt_profie_svc;
batt_profie_svc.p_att_tb = batt_att_table;
batt_profie_svc.att_nb = IDX_BATT_NB;
batt_profie_svc.gatt_msg_handler = batt_gatt_msg_handler;
battery_level = 100;
batt_svc_id = gatt_add_service(&batt_profie_svc);
}

View File

@ -0,0 +1,90 @@
/**
* Copyright (c) 2019, Freqchip
*
* All rights reserved.
*
*
*/
#ifndef BATT_SERVICE_H
#define BATT_SERVICE_H
/*
* INCLUDES (<28><><EFBFBD><EFBFBD>ͷ<EFBFBD>ļ<EFBFBD>)
*/
#include <stdio.h>
#include <string.h>
#include "gap_api.h"
#include "gatt_api.h"
#include "gatt_sig_uuid.h"
/*
* MACROS (<28><EFBFBD><EAB6A8>)
*/
/*
* CONSTANTS (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
*/
// Battery Server Profile attributes index.
enum
{
IDX_BATT_SERVICE,
IDX_BATT_LEVEL_CHAR_DECLARATION,
IDX_BATT_LEVEL_CHAR_VALUE,
IDX_BATT_LEVEL_CCCD,
IDX_BATT_NB,
};
/*
* TYPEDEFS (<28><><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>)
*/
/*
* GLOBAL VARIABLES (ȫ<>ֱ<EFBFBD><D6B1><EFBFBD>)
*/
/*
* LOCAL VARIABLES (<28><><EFBFBD>ر<EFBFBD><D8B1><EFBFBD>)
*/
/*
* PUBLIC FUNCTIONS (ȫ<>ֺ<EFBFBD><D6BA><EFBFBD>)
*/
/*********************************************************************
* @fn batt_gatt_add_service
*
* @brief Create battery server.
*
* @param None.
*
* @return None.
*/
void batt_gatt_add_service(void);
/*********************************************************************
* @fn batt_gatt_notify
*
* @brief Send batt level notification to peer, and update batt level
*
*
* @param conidx - link idx.
* batt_level - battery energy percentage.
*
* @return none.
*/
void batt_gatt_notify(uint8_t conidx,uint8_t batt_level);
#endif

View File

@ -0,0 +1,302 @@
/**
* Copyright (c) 2019, Freqchip
*
* All rights reserved.
*
*
*/
/*
* INCLUDES (<28><><EFBFBD><EFBFBD>ͷ<EFBFBD>ļ<EFBFBD>)
*/
#include <stdio.h>
#include <string.h>
#include "gap_api.h"
#include "gatt_api.h"
#include "gatt_sig_uuid.h"
#include "dev_info_service.h"
/*
* MACROS (<28><EFBFBD><EAB6A8>)
*/
/// Maximal length for Characteristic values - 128 bytes
#define DIS_VAL_MAX_LEN (128)
/*
* CONSTANTS (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
*/
// Device Information Service UUID: 0x180A
static const uint8_t dis_svc_uuid[UUID_SIZE_2] = UUID16_ARR(DEVINFO_SERV_UUID);
/*
* TYPEDEFS (<28><><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>)
*/
/*
* GLOBAL VARIABLES (ȫ<>ֱ<EFBFBD><D6B1><EFBFBD>)
*/
uint8_t dis_svc_id = 0;
/*
* LOCAL VARIABLES (<28><><EFBFBD>ر<EFBFBD><D8B1><EFBFBD>)
*/
/*********************************************************************
* Profile Attributes - Table
* ÿһ<C3BF><EFBFBD><EEB6BC>һ<EFBFBD><D2BB>attribute<74>Ķ<EFBFBD><C4B6>
* <20><>һ<EFBFBD><D2BB>attributeΪService <20>ĵĶ<C4B5><C4B6>
* ÿһ<C3BF><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ(characteristic)<29>Ķ<EFBFBD><C4B6><EFBFBD><E5A3AC><EFBFBD><EFBFBD><EFBFBD>ٰ<EFBFBD><D9B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>attribute<74>Ķ<EFBFBD><C4B6>
* 1. <20><><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD>(Characteristic Declaration)
* 2. <20><><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5>ֵ(Characteristic value)
* 3. <20><><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(Characteristic description)
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>notification <20><><EFBFBD><EFBFBD>indication <20>Ĺ<EFBFBD><C4B9>ܣ<EFBFBD><DCA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD>attribute<74>Ķ<EFBFBD><C4B6><EFBFBD><E5A3AC><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><E6B6A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(client characteristic configuration)<29><>
*
*/
static const gatt_attribute_t dis_att_table[] =
{
// Device information Service Declaration
[DIS_IDX_SERVICE] = { { UUID_SIZE_2, UUID16_ARR(GATT_PRIMARY_SERVICE_UUID)},
GATT_PROP_READ,UUID_SIZE_2,(uint8_t *)dis_svc_uuid,
},
#if ((DIS_FEATURES & DIS_MANUFACTURER_NAME_CHAR_SUP) == DIS_MANUFACTURER_NAME_CHAR_SUP)
// Manufacturer name Declaration
[DIS_IDX_MANUFACTURER_NAME_CHAR_DECLARATION] = { { UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID)},
GATT_PROP_READ,0,NULL,
},
[DIS_IDX_MANUFACTURER_NAME_VALUE] = { { UUID_SIZE_2, UUID16_ARR(MANUFACTURER_NAME_UUID)},
GATT_PROP_READ,DIS_VAL_MAX_LEN,NULL,
},
#endif
#if ((DIS_FEATURES & DIS_MODEL_NB_STR_CHAR_SUP) == DIS_MODEL_NB_STR_CHAR_SUP)
// Model Number String Declaration
[DIS_IDX_MODEL_NUMBER_CHAR_DECLARATION] = { { UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID)},
GATT_PROP_READ, 0,NULL,
},
[DIS_IDX_MODEL_NUMBER_VALUE] = { { UUID_SIZE_2, UUID16_ARR(MODEL_NUMBER_UUID)},
GATT_PROP_READ,DIS_VAL_MAX_LEN,NULL,
},
#endif
#if ((DIS_FEATURES & DIS_SERIAL_NB_STR_CHAR_SUP) == DIS_SERIAL_NB_STR_CHAR_SUP)
// Serial Number String Declaration
[DIS_IDX_SERIAL_NUMBER_CHAR_DECLARATION] = { { UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID)},
GATT_PROP_READ,0,NULL,
},
[DIS_IDX_SERIAL_NUMBER_VALUE] = { { UUID_SIZE_2, UUID16_ARR(SERIAL_NUMBER_UUID)},
GATT_PROP_READ,DIS_VAL_MAX_LEN,NULL,
},
#endif
#if ((DIS_FEATURES & DIS_HARD_REV_STR_CHAR_SUP) == DIS_HARD_REV_STR_CHAR_SUP)
// Hardware Revision String Declaration
[DIS_IDX_HARDWARE_REVISION_CHAR_DECLARATION] = { { UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID)},
GATT_PROP_READ,0,NULL,
},
[DIS_IDX_HARDWARE_REVISION_VALUE]= { { UUID_SIZE_2, UUID16_ARR(HARDWARE_REV_UUID)},
GATT_PROP_READ,DIS_VAL_MAX_LEN,NULL,
},
#endif
#if ((DIS_FEATURES & DIS_FIRM_REV_STR_CHAR_SUP) == DIS_FIRM_REV_STR_CHAR_SUP)
// Firmware Revision String Declaration
[DIS_IDX_FIRMWARE_REVISION_CHAR_DECLARATION] = { { UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID)},
GATT_PROP_READ,0,NULL,
},
[DIS_IDX_FIRMWARE_REVISION_VALUE] = { { UUID_SIZE_2, UUID16_ARR(FIRMWARE_REV_UUID)},
GATT_PROP_READ,DIS_VAL_MAX_LEN,NULL,
},
#endif
#if ((DIS_FEATURES & DIS_SW_REV_STR_CHAR_SUP) == DIS_SW_REV_STR_CHAR_SUP)
// Software Revision String Declaration
[DIS_IDX_SOFTWARE_REVISION_CHAR_DECLARATION] = { { UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID)},
GATT_PROP_READ,0,NULL,
},
[DIS_IDX_SOFTWARE_REVISION_VALUE] = { { UUID_SIZE_2, UUID16_ARR(SOFTWARE_REV_UUID)},
GATT_PROP_READ,DIS_VAL_MAX_LEN,NULL,
},
#endif
#if ((DIS_FEATURES & DIS_SYSTEM_ID_CHAR_SUP) == DIS_SYSTEM_ID_CHAR_SUP)
// System ID Declaration
[DIS_IDX_SYSTEM_ID_CHAR_DECLARATION] = { { UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID)},
GATT_PROP_READ,0,NULL,
},
// System ID Value
[DIS_IDX_SYSTEM_ID_VALUE] = {{ UUID_SIZE_2, UUID16_ARR(SYSTEM_ID_UUID) },
GATT_PROP_READ,DIS_VAL_MAX_LEN,NULL,
},
#endif
#if ((DIS_FEATURES & DIS_IEEE_CHAR_SUP) == DIS_IEEE_CHAR_SUP)
// IEEE 11073-20601 Regulatory Certification Data List Characteristic Declaration
[DIS_IDX_IEEE_11073_CHAR_DECLARATION] = { { UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID)},
GATT_PROP_READ,0,NULL,
},
[DIS_IDX_IEEE_11073_VALUE] = { { UUID_SIZE_2, UUID16_ARR(IEEE_11073_CERT_DATA_UUID)},
GATT_PROP_READ,DIS_VAL_MAX_LEN,NULL,
},
#endif
#if ((DIS_FEATURES & DIS_PNP_ID_CHAR_SUP) == DIS_PNP_ID_CHAR_SUP)
// PNP ID Declaration
[DIS_IDX_PNP_ID_CHAR_DECLARATION] = { { UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID)},
GATT_PROP_READ,0,NULL,
},
// PNP ID Value
[DIS_IDX_PNP_ID_VALUE] = {{ UUID_SIZE_2, UUID16_ARR(PNP_ID_UUID) },
GATT_PROP_READ,DIS_VAL_MAX_LEN,NULL,
},
#endif
};
/*********************************************************************
* @fn hid_gatt_op_cmp_handler
*
* @brief Gatt operation complete handler.
*
*
* @param p_operation - operation that has compeleted
*
* @return none.
*/
void dis_gatt_op_cmp_handler(void *p_operation)
{
// if (p_operation->status == 0)
// {}
}
/*********************************************************************
* @fn dis_gatt_msg_handler
*
* @brief Device information gatt message handler.
*
*
* @param p_msg - messages from GATT layer.
*
* @return none.
*/
static uint16_t dis_gatt_msg_handler(struct gatt_msg *p_msg)
{
switch(p_msg->msg_evt)
{
case GATTS_MSG_READ_REQ:
printf("dis read:%d\r\n",p_msg->att_idx);
#if ((DIS_FEATURES & DIS_MANUFACTURER_NAME_CHAR_SUP) == DIS_MANUFACTURER_NAME_CHAR_SUP)
if(p_msg->att_idx == DIS_IDX_MANUFACTURER_NAME_VALUE)
{
memcpy(p_msg->param.gatt_data.p_msg_data, DIS_MANUFACTURER_NAME, DIS_MANUFACTURER_NAME_LEN);
return DIS_MANUFACTURER_NAME_LEN;
}
#endif
#if ((DIS_FEATURES & DIS_MODEL_NB_STR_CHAR_SUP) == DIS_MODEL_NB_STR_CHAR_SUP)
else if(p_msg->att_idx == DIS_IDX_MODEL_NUMBER_VALUE)
{
memcpy(p_msg->param.gatt_data.p_msg_data, DIS_MODEL_NB_STR, DIS_MODEL_NB_STR_LEN);
return DIS_MODEL_NB_STR_LEN;
}
#endif
#if ((DIS_FEATURES & DIS_SERIAL_NB_STR_CHAR_SUP) == DIS_SERIAL_NB_STR_CHAR_SUP)
else if(p_msg->att_idx == DIS_IDX_SERIAL_NUMBER_VALUE)
{
memcpy(p_msg->param.gatt_data.p_msg_data, DIS_SERIAL_NB_STR, DIS_SERIAL_NB_STR_LEN);
return DIS_SERIAL_NB_STR_LEN;
}
#endif
#if ((DIS_FEATURES & DIS_HARD_REV_STR_CHAR_SUP) == DIS_HARD_REV_STR_CHAR_SUP)
else if(p_msg->att_idx == DIS_IDX_HARDWARE_REVISION_VALUE)
{
memcpy(p_msg->param.gatt_data.p_msg_data, DIS_HARD_REV_STR, DIS_HARD_REV_STR_LEN);
return DIS_HARD_REV_STR_LEN;
}
#endif
#if ((DIS_FEATURES & DIS_FIRM_REV_STR_CHAR_SUP) == DIS_FIRM_REV_STR_CHAR_SUP)
else if(p_msg->att_idx == DIS_IDX_FIRMWARE_REVISION_VALUE)
{
memcpy(p_msg->param.gatt_data.p_msg_data, DIS_FIRM_REV_STR, DIS_FIRM_REV_STR_LEN);
return DIS_FIRM_REV_STR_LEN;
}
#endif
#if ((DIS_FEATURES & DIS_SW_REV_STR_CHAR_SUP) == DIS_SW_REV_STR_CHAR_SUP)
else if(p_msg->att_idx == DIS_IDX_SOFTWARE_REVISION_VALUE)
{
memcpy(p_msg->param.gatt_data.p_msg_data, DIS_SW_REV_STR, DIS_SW_REV_STR_LEN);
return DIS_SW_REV_STR_LEN;
}
#endif
#if ((DIS_FEATURES & DIS_SYSTEM_ID_CHAR_SUP) == DIS_SYSTEM_ID_CHAR_SUP)
else if(p_msg->att_idx == DIS_IDX_SYSTEM_ID_VALUE)
{
memcpy(p_msg->param.gatt_data.p_msg_data, DIS_SYSTEM_ID, DIS_SYSTEM_ID_LEN);
return DIS_SYSTEM_ID_LEN;
}
#endif
#if ((DIS_FEATURES & DIS_IEEE_CHAR_SUP) == DIS_IEEE_CHAR_SUP)
else if(p_msg->att_idx == DIS_IDX_IEEE_11073_VALUE)
{
memcpy(p_msg->param.msg.p_msg_data, DIS_IEEE, DIS_IEEE_LEN);
return DIS_IEEE_LEN;
}
#endif
#if ((DIS_FEATURES & DIS_PNP_ID_CHAR_SUP) == DIS_PNP_ID_CHAR_SUP)
else if(p_msg->att_idx == DIS_IDX_PNP_ID_VALUE)
{
memcpy(p_msg->param.gatt_data.p_msg_data, DIS_PNP_ID, DIS_PNP_ID_LEN);
return DIS_PNP_ID_LEN;
}
#endif
break;
case GATTS_MSG_WRITE_REQ:
break;
case GATTC_MSG_CMP_EVT:
dis_gatt_op_cmp_handler((struct gatt_op_cmp*)&(p_msg->param.gatt_op_cmp));
break;
default:
break;
}
return 0;
}
/*********************************************************************
* @fn dis_gatt_add_service
*
* @brief Simple Profile add GATT service function.
* <20><><EFBFBD><EFBFBD>GATT service<63><65>ATT<54><54><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><DDBF><EFBFBD><EFBFBD>
*
* @param None.
*
*
* @return None.
*/
void dis_gatt_add_service(void)
{
gatt_service_t dis_profie_svc;
dis_profie_svc.p_att_tb = dis_att_table;
dis_profie_svc.att_nb = DIS_IDX_NB;
dis_profie_svc.gatt_msg_handler = dis_gatt_msg_handler;
dis_svc_id = gatt_add_service(&dis_profie_svc);
}

View File

@ -0,0 +1,190 @@
/**
* Copyright (c) 2019, Freqchip
*
* All rights reserved.
*
*
*/
#ifndef DEV_INFO_SERVICE_H
#define DEV_INFO_SERVICE_H
/*
* INCLUDES (<28><><EFBFBD><EFBFBD>ͷ<EFBFBD>ļ<EFBFBD>)
*/
#include <stdint.h>
/*
* MACROS (<28><EFBFBD><EAB6A8>)
*/
/// Manufacturer Name Value
#define DIS_MANUFACTURER_NAME ("Freqchip")
#define DIS_MANUFACTURER_NAME_LEN (8)
/// Model Number String Value
#define DIS_MODEL_NB_STR ("Fr-BLE-1.0")
#define DIS_MODEL_NB_STR_LEN (10)
/// Firmware Revision
#define DIS_FIRM_REV_STR ("6.1.2")
#define DIS_FIRM_REV_STR_LEN (5)
/// System ID Value - LSB -> MSB
#define DIS_SYSTEM_ID ("\x12\x34\x56\xFF\xFE\x9A\xBC\xDE")
#define DIS_SYSTEM_ID_LEN (8)
/// Software Revision String
#define DIS_SW_REV_STR ("6.3.0")
#define DIS_SW_REV_STR_LEN (5)
/**
* PNP ID Value - LSB -> MSB
* Vendor ID Source : 0x02 (USB Implementers Forum assigned Vendor ID value)
* Vendor ID : 0x045E (Microsoft Corp)
* Product ID : 0x0040
* Product Version : 0x0300
*/
#define DIS_PNP_ID ("\x01\x17\x27\xb0\x32\x10\x24")
#define DIS_PNP_ID_LEN (7)
/// Serial Number
#define DIS_SERIAL_NB_STR ("1.0.0.0-LE")
#define DIS_SERIAL_NB_STR_LEN (10)
/// Hardware Revision String
#define DIS_HARD_REV_STR ("1.0.0")
#define DIS_HARD_REV_STR_LEN (5)
/// IEEE
#define DIS_IEEE ("\xFF\xEE\xDD\xCC\xBB\xAA")
#define DIS_IEEE_LEN (6)
///Indicate if Manufacturer Name String Char. is supported
#define DIS_MANUFACTURER_NAME_CHAR_SUP 0x0001
///Indicate if Model Number String Char. is supported
#define DIS_MODEL_NB_STR_CHAR_SUP 0x0002
///Indicate if Serial Number String Char. is supported
#define DIS_SERIAL_NB_STR_CHAR_SUP 0x0004
///Indicate if Hardware Revision String Char. supports indications
#define DIS_HARD_REV_STR_CHAR_SUP 0x0008
///Indicate if Firmware Revision String Char. is writable
#define DIS_FIRM_REV_STR_CHAR_SUP 0x0010
///Indicate if Software Revision String Char. is writable
#define DIS_SW_REV_STR_CHAR_SUP 0x0020
///Indicate if System ID Char. is writable
#define DIS_SYSTEM_ID_CHAR_SUP 0x0040
///Indicate if IEEE Char. is writable
#define DIS_IEEE_CHAR_SUP 0x0080
///Indicate if PnP ID Char. is writable
#define DIS_PNP_ID_CHAR_SUP 0x0100
///All features are supported
#define DIS_ALL_FEAT_SUP 0x01FF
#define DIS_FEATURES (DIS_MANUFACTURER_NAME_CHAR_SUP | \
DIS_HARD_REV_STR_CHAR_SUP | \
DIS_MODEL_NB_STR_CHAR_SUP | \
DIS_SERIAL_NB_STR_CHAR_SUP | \
DIS_SYSTEM_ID_CHAR_SUP | \
DIS_FIRM_REV_STR_CHAR_SUP | \
DIS_SW_REV_STR_CHAR_SUP | \
DIS_PNP_ID_CHAR_SUP)
/*
* CONSTANTS (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
*/
// Simple Profile attributes index.
enum
{
DIS_IDX_SERVICE,
#if ((DIS_FEATURES & DIS_MANUFACTURER_NAME_CHAR_SUP) == DIS_MANUFACTURER_NAME_CHAR_SUP)
DIS_IDX_MANUFACTURER_NAME_CHAR_DECLARATION,
DIS_IDX_MANUFACTURER_NAME_VALUE,
#endif
#if ((DIS_FEATURES & DIS_MODEL_NB_STR_CHAR_SUP) == DIS_MODEL_NB_STR_CHAR_SUP)
DIS_IDX_MODEL_NUMBER_CHAR_DECLARATION,
DIS_IDX_MODEL_NUMBER_VALUE,
#endif
#if ((DIS_FEATURES & DIS_SERIAL_NB_STR_CHAR_SUP) == DIS_SERIAL_NB_STR_CHAR_SUP)
DIS_IDX_SERIAL_NUMBER_CHAR_DECLARATION,
DIS_IDX_SERIAL_NUMBER_VALUE,
#endif
#if ((DIS_FEATURES & DIS_HARD_REV_STR_CHAR_SUP) == DIS_HARD_REV_STR_CHAR_SUP)
DIS_IDX_HARDWARE_REVISION_CHAR_DECLARATION,
DIS_IDX_HARDWARE_REVISION_VALUE,
#endif
#if ((DIS_FEATURES & DIS_FIRM_REV_STR_CHAR_SUP) == DIS_FIRM_REV_STR_CHAR_SUP)
DIS_IDX_FIRMWARE_REVISION_CHAR_DECLARATION,
DIS_IDX_FIRMWARE_REVISION_VALUE,
#endif
#if ((DIS_FEATURES & DIS_SW_REV_STR_CHAR_SUP) == DIS_SW_REV_STR_CHAR_SUP)
DIS_IDX_SOFTWARE_REVISION_CHAR_DECLARATION,
DIS_IDX_SOFTWARE_REVISION_VALUE,
#endif
#if ((DIS_FEATURES & DIS_SYSTEM_ID_CHAR_SUP) == DIS_SYSTEM_ID_CHAR_SUP)
DIS_IDX_SYSTEM_ID_CHAR_DECLARATION,
DIS_IDX_SYSTEM_ID_VALUE,
#endif
#if ((DIS_FEATURES & DIS_IEEE_CHAR_SUP) == DIS_IEEE_CHAR_SUP)
DIS_IDX_IEEE_11073_CHAR_DECLARATION,
DIS_IDX_IEEE_11073_VALUE,
#endif
#if ((DIS_FEATURES & DIS_PNP_ID_CHAR_SUP) == DIS_PNP_ID_CHAR_SUP)
DIS_IDX_PNP_ID_CHAR_DECLARATION,
DIS_IDX_PNP_ID_VALUE,
#endif
DIS_IDX_NB,
};
/*
* TYPEDEFS (<28><><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>)
*/
/*
* GLOBAL VARIABLES (ȫ<>ֱ<EFBFBD><D6B1><EFBFBD>)
*/
extern uint8_t dis_svc_id;
/*
* LOCAL VARIABLES (<28><><EFBFBD>ر<EFBFBD><D8B1><EFBFBD>)
*/
/*
* PUBLIC FUNCTIONS (ȫ<>ֺ<EFBFBD><D6BA><EFBFBD>)
*/
/*********************************************************************
* @fn dis_gatt_add_service
*
* @brief Create device information server.
*
* @param None.
*
* @return None.
*/
void dis_gatt_add_service(void);
#endif

View File

@ -0,0 +1,680 @@
/**
* Copyright (c) 2019, Freqchip
*
* All rights reserved.
*
*
*/
/*
* INCLUDES (<28><><EFBFBD><EFBFBD>ͷ<EFBFBD>ļ<EFBFBD>)
*/
#include <stdio.h>
#include <string.h>
#include "gap_api.h"
#include "gatt_api.h"
#include "gatt_sig_uuid.h"
#include "hid_service.h"
/*
* MACROS (<28><EFBFBD><EAB6A8>)
*/
#define CFG_CON 20
/*
* CONSTANTS (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
*/
const uint8_t hid_svc_uuid[] = UUID16_ARR(HID_SERV_UUID);
// HID Information data
const uint8_t hid_info_value[] =
{
LO_UINT16(0x0111), HI_UINT16(0x0111), // bcdHID (USB HID version)
0x00, // bCountryCode
HID_FLAGS_REMOTE_WAKE | HID_FLAGS_NORMALLY_CONNECTABLE // Flags
};
/******************************* HID Report Map characteristic defination */
static const uint8_t hid_report_map[] =
{
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x02, // Usage (Mouse)
0xA1, 0x01, // Collection (Application)
0x85, 0x01, // Report Id (1)
0x09, 0x01, // Usage (Pointer)
0xA1, 0x00, // Collection (Physical)
//rpt id == 1
0x05, 0x09, // Usage Page (Mouse)
0x19, 0x01, // Usage Minimum (01) - Button 1
0x29, 0x03, // Usage Maximum (03) - Button 3
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x03, // Report Count (3)
0x81, 0x02, // Input (Data, Variable, Absolute) - Button states
0x75, 0x05, // Report Size (5)
0x95, 0x01, // Report Count (1)
0x81, 0x01, // Input (Constant) - Padding or Reserved bits
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x09, 0x38, // Usage (Wheel)
0x15, 0x81, // Logical Minimum (-127)
0x25, 0x7F, // Logical Maximum (127)
0x75, 0x08, // Report Size (8)
0x95, 0x03, // Report Count (3)
0x81, 0x06, // Input (Data, Variable, Relative) - X & Y wheal 3bytes
0xC0, // End Collection
0xC0, // End Collection
//rpt id == 2
0x05,0x0c, // Usage Page (Consumer Devices)
0x09,0x01, // Usage index(Consumer Control)
0xa1,0x01, // Collection (Application)
0x85,0x02, // Report ID (2)
#if 0
0x15,0x00, // Logical Minimum (0)
0x25,0x01, // Logical Maximum (1)
0x75,0x01, // Report Size (1)
0x95,0x01, // Report Count (1)
0x09,0xcd, // Usage index(Play/Pause)
0x81,0x06, //input(Data,Value,Relative,Bit,Filed)
0x0a, 0x21, 0x02, // Usage (OPEN_SEARCHA) 5
0x81,0x06, //input(Data,Value,Relative,Bit,Filed)
0x09,0xb5, // Usage (Scan Next Track)
0x81,0x06, //input(Data,Value,Relative,Bit,Filed)
0x09,0xb6, // Usage (Scan Previous Track)
0x81,0x06, //input(Data,Value,Relative,Bit,Filed)
0x09,0xea, // Usage (Volume -)
0x81,0x06, //input(Data,Value,Relative,Bit,Filed)
0x09,0xe9, // Usage (Volume +)
0x81,0x06, //input(Data,Value,Relative,Bit,Filed)
0x0a,0x25,0x02, //Usage(AC Forward)
0x81,0x06, //input(Data,Value,Relative,Bit,Filed)
0x0a,0x24,0x02, //Usage(AC Back)
0x81,0x06, //input(Data,Value,Relative,Bit,Filed)
#else
0x75,0x10, // Report Size (16)
0x95,0x01, // Report Count (1)
0x15, 0x01, /* LOGICAL_MINIMUM */
0x26, 0xff, 0x03, /* LOGICAL_MAXIMUM */
0x19, 0x01, /* USAGE MINIMUM (Consumer control) */
0x2a, 0xff, 0x03, /* USAGE MAXIMUM (Reserved) */
0x81, 0x60, /* INPUT (No preferred state, null state) */
#endif
0xc0, // End Collection
//rpt id == 3
0x05, 0x01, // Usage Pg (Generic Desktop)
0x09, 0x06, // Usage (Keyboard)
0xA1, 0x01, // Collection: (Application)
0x85, 0x03, // Report Id (3 for keyboard)
//
0x05, 0x07, // Usage Pg (Key Codes)
0x19, 0xE0, // Usage Min (224)
0x29, 0xE7, // Usage Max (231)
0x15, 0x00, // Log Min (0)
0x25, 0x01, // Log Max (1)
//
// Modifier byte
0x75, 0x01, // Report Size (1) 1 bit * 8
0x95, 0x08, // Report Count (8)
0x81, 0x02, // Input: (Data, Variable, Absolute)
// Reserved byte
0x95, 0x01, // Report Count (1)
0x75, 0x08, // Report Size (8)
0x81, 0x01, // Input: (Constant)
//LED repor
0x95, 0x05, //Report Count (5)
0x75, 0x01, //Report Size (1)
0x05, 0x08, //Usage Pg (LEDs )
0x19, 0x01, //Usage Min
0x29, 0x05, //Usage Max
0x91, 0x02, //Output (Data, Variable, Absolute)
//3 bit reserved
0x95, 0x01, //Report Count (1)
0x75, 0x03, //Report Size (3)
0x91, 0x01, //Output (Constant)
// Key arrays (6 bytes)
// this is key array,support simultaneously pressing 6keys report,
// from report_buf[3]~report_buf[3]
0x95, 0x06, // Report Count (6)
0x75, 0x08, // Report Size (8)
0x15, 0x00, // Log Min (0)
0x25, 0xE7, // Log Max (237)
0x05, 0x07, // Usage Pg (Key Codes) , here is the key page,look usb hid key define
0x19, 0x00, // Usage Min (0)
0x29, 0xE7, // Usage Max (237)
0x81, 0x00, // Input: (Data, Array)
0xC0, // End Collection
};
/******************************* External Report Reference defination */
// External Report Reference Descriptor UUID
const uint8_t ext_report_ref_uuid[] = UUID16_ARR(0x00);
uint8_t hid_svc_id = 0;
// HID report information table
static hid_report_ref_t hid_rpt_info[HID_NUM_REPORTS];
static bool hid_link_ntf_enable[CFG_CON] = {0};
static bool hid_link_enable[CFG_CON] = {0};
/*
* TYPEDEFS (<28><><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>)
*/
/*
* EXTERNAL VARIABLES (<28>ⲿ<EFBFBD><E2B2BF><EFBFBD><EFBFBD>)
*/
/*
* GLOBAL VARIABLES (ȫ<>ֱ<EFBFBD><D6B1><EFBFBD>)
*/
/*
* LOCAL VARIABLES (<28><><EFBFBD>ر<EFBFBD><D8B1><EFBFBD>)
*/
/*********************************************************************
* Profile Attributes - Table
* ÿһ<C3BF><EFBFBD><EEB6BC>һ<EFBFBD><D2BB>attribute<74>Ķ<EFBFBD><C4B6>
* <20><>һ<EFBFBD><D2BB>attributeΪService <20>ĵĶ<C4B5><C4B6>
* ÿһ<C3BF><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ(characteristic)<29>Ķ<EFBFBD><C4B6><EFBFBD><E5A3AC><EFBFBD><EFBFBD><EFBFBD>ٰ<EFBFBD><D9B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>attribute<74>Ķ<EFBFBD><C4B6>
* 1. <20><><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD>(Characteristic Declaration)
* 2. <20><><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5>ֵ(Characteristic value)
* 3. <20><><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(Characteristic description)
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>notification <20><><EFBFBD><EFBFBD>indication <20>Ĺ<EFBFBD><C4B9>ܣ<EFBFBD><DCA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD>attribute<74>Ķ<EFBFBD><C4B6><EFBFBD><E5A3AC><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><E6B6A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(client characteristic configuration)<29><>
*
*/
const gatt_attribute_t hid_profile_att_table[] =
{
[HID_SERVICE_IDX] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_PRIMARY_SERVICE_UUID) },
GATT_PROP_READ,
UUID_SIZE_2,
(uint8_t *)hid_svc_uuid,
},
#if ((HID_DEV & HID_DEV_MAP_EXT_REF) == HID_DEV_MAP_EXT_REF)
//[HID_INCLUDED_SERVICE_IDX] = {
// { UUID_SIZE_2, UUID16_ARR(GATT_INCLUDE_UUID) },
// GATT_PROP_READ,
// 0,
// NULL,
// },
#endif //((HID_DEV & HID_DEV_MAP_EXT_REF) == HID_DEV_MAP_EXT_REF)
[HID_INFO_DECL_IDX] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID) },
GATT_PROP_READ,
0,
NULL,
},
[HID_INFO_IDX] = {
{ UUID_SIZE_2, UUID16_ARR(HID_INFORMATION_UUID) },
GATT_PROP_READ | GATT_PROP_READ_UNAUTH | GATT_PROP_WRITE_UNAUTH | GATT_PROP_NI_UNAUTH, //GATT_PROP_AUTHEN
sizeof(hid_info_value),
NULL,
},
// HID Control Point characteristic declaration
[HID_CONTROL_POINT_DECL_IDX] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID) },
GATT_PROP_READ,
0,
NULL,
},
// HID Control Point characteristic value
[HID_CONTROL_POINT_IDX] = {
{ UUID_SIZE_2, UUID16_ARR(HID_CTRL_PT_UUID) },
GATT_PROP_WRITE_REQ | GATT_PROP_WRITE_CMD,
sizeof(uint8_t),
NULL,
},
// HID Report Map characteristic declaration
[HID_REPORT_MAP_DECL_IDX] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID) },
GATT_PROP_READ,
0,
NULL,
},
// HID Report Map characteristic
[HID_REPORT_MAP_IDX] = {
{ UUID_SIZE_2, UUID16_ARR(REPORT_MAP_UUID) },
GATT_PROP_READ,
512,
NULL,
},
#if ((HID_DEV & HID_DEV_MAP_EXT_REF) == HID_DEV_MAP_EXT_REF)
// Report Map Characteristic - External Report Reference Descriptor
[HID_REPORT_MAP_EXT_REP_REF] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_EXT_REPORT_REF_UUID) },
GATT_PROP_WRITE,
sizeof(ext_report_ref_uuid),
(uint8_t *)ext_report_ref_uuid,
},
#endif //((HID_DEV & HID_DEV_MAP_EXT_REF) == HID_DEV_MAP_EXT_REF)
#if ((HID_DEV & HID_DEV_PROTO_MODE) == HID_DEV_PROTO_MODE)
// HID Protocol Mode characteristic declaration
[HID_PROTOCOL_MODE_DECL_IDX] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID) },
GATT_PROP_READ,
0,
NULL,
},
// HID Protocol Mode characteristic
[HID_PROTOCOL_MODE_IDX] = {
{ UUID_SIZE_2, UUID16_ARR(PROTOCOL_MODE_UUID) },
GATT_PROP_READ | GATT_PROP_WRITE,
sizeof(uint8_t),
NULL,
},
#endif //((HID_DEV & HID_DEV_PROTO_MODE) == HID_DEV_PROTO_MODE)
#if ((HID_DEV & HID_DEV_KEYBOARD) == HID_DEV_KEYBOARD)
// HID Boot Keyboard Input Report declaration
[HID_BOOT_KEY_IN_DECL_IDX] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID) },
GATT_PROP_READ,
0,
NULL,
},
// HID Boot Keyboard Input Report
[HID_BOOT_KEY_IN_IDX] = {
{ UUID_SIZE_2, UUID16_ARR(BOOT_KEY_INPUT_UUID) },
GATT_PROP_READ | GATT_PROP_NOTI,
8,
NULL,
},
// HID Report characteristic, key input client characteristic configuration
[HID_BOOT_KEY_IN_CCCD_IDX] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_CLIENT_CHAR_CFG_UUID) },
GATT_PROP_READ | GATT_PROP_WRITE_CMD | GATT_PROP_WRITE_REQ,
0,
NULL,
},
// HID Boot Keyboard Output Report declaration
[HID_BOOT_KEY_OUT_DECL_IDX] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID) },
GATT_PROP_READ,
0,
NULL,
},
// HID Boot Keyboard Output Report
[HID_BOOT_KEY_OUT_IDX] = {
{ UUID_SIZE_2, UUID16_ARR(BOOT_KEY_OUTPUT_UUID) },
GATT_PROP_READ | GATT_PROP_WRITE_CMD | GATT_PROP_WRITE_REQ,
8,
NULL,
},
#endif //((HID_DEV & HID_DEV_KEYBOARD) == HID_DEV_KEYBOARD)
#if ((HID_DEV & HID_DEV_MOUSE) == HID_DEV_MOUSE)
// HID Boot Mouse Input Report declaration
[HID_BOOT_MOUSE_IN_DECL_IDX] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID) },
GATT_PROP_READ,
0,
NULL,
},
// HID Boot Mouse Input Report
[HID_BOOT_MOUSE_IN_IDX] = {
{ UUID_SIZE_2, UUID16_ARR(BOOT_MOUSE_INPUT_UUID) },
GATT_PROP_READ | GATT_PROP_WRITE | GATT_PROP_NOTI,
8,
NULL,
},
// HID Report characteristic, key input client characteristic configuration
[HID_BOOT_MOUSE_IN_CCCD_IDX] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_CLIENT_CHAR_CFG_UUID) },
GATT_PROP_READ | GATT_PROP_WRITE,
0,
NULL,
},
#endif // ((HID_DEV & HID_DEV_MOUSE) == HID_DEV_MOUSE)
// HID Feature Report No 0
[HID_FEATURE_DECL_IDX] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID) },
GATT_PROP_READ,
0,
NULL,
},
[HID_FEATURE_IDX] = {
{ UUID_SIZE_2, UUID16_ARR(REPORT_UUID) },
GATT_PROP_READ | GATT_PROP_NOTI,
60,
NULL,
},
[HID_REPORT_REF_FEATURE_IDX] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_REPORT_REF_UUID) },
GATT_PROP_READ,
sizeof(hid_report_ref_t),
NULL,
},
[HID_FEATURE_CCCD_IDX] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_CLIENT_CHAR_CFG_UUID) },
GATT_PROP_READ | GATT_PROP_WRITE_CMD | GATT_PROP_WRITE_REQ,
0,
NULL,
},
// HID Feature Report No 1
[HID_FEATURE_DECL_IDX + 4 * 1] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID) },
GATT_PROP_READ,
0,
NULL,
},
[HID_FEATURE_IDX + 4 * 1] = {
{ UUID_SIZE_2, UUID16_ARR(REPORT_UUID) },
GATT_PROP_READ | GATT_PROP_NOTI,
60,
NULL,
},
[HID_REPORT_REF_FEATURE_IDX + 4 * 1] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_REPORT_REF_UUID) },
GATT_PROP_READ,
sizeof(hid_report_ref_t),
NULL,
},
[HID_FEATURE_CCCD_IDX + 4 * 1] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_CLIENT_CHAR_CFG_UUID) },
GATT_PROP_READ | GATT_PROP_WRITE_CMD | GATT_PROP_WRITE_REQ,
0,
NULL,
},
// HID Feature Report No 2
[HID_FEATURE_DECL_IDX + 4 * 2] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID) },
GATT_PROP_READ,
0,
NULL,
},
[HID_FEATURE_IDX + 4 * 2] = {
{ UUID_SIZE_2, UUID16_ARR(REPORT_UUID) },
GATT_PROP_READ | GATT_PROP_NOTI,
60,
NULL,
},
[HID_REPORT_REF_FEATURE_IDX + 4 * 2] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_REPORT_REF_UUID) },
GATT_PROP_READ,
sizeof(hid_report_ref_t),
NULL,
},
[HID_FEATURE_CCCD_IDX + 4 * 2] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_CLIENT_CHAR_CFG_UUID) },
GATT_PROP_READ | GATT_PROP_WRITE_CMD | GATT_PROP_WRITE_REQ,
0,
NULL,
},
// HID Feature Report No 3
[HID_FEATURE_DECL_IDX + 4 * 3] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID) },
GATT_PROP_READ,
0,
NULL,
},
[HID_FEATURE_IDX + 4 * 3] = {
{ UUID_SIZE_2, UUID16_ARR(REPORT_UUID) },
GATT_PROP_READ | GATT_PROP_WRITE_CMD | GATT_PROP_WRITE_REQ,
60,
NULL,
},
[HID_REPORT_REF_FEATURE_IDX + 4 * 3] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_REPORT_REF_UUID) },
GATT_PROP_READ,
sizeof(hid_report_ref_t),
NULL,
},
[HID_FEATURE_CCCD_IDX + 4 * 3] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_CLIENT_CHAR_CFG_UUID) },
GATT_PROP_READ | GATT_PROP_WRITE_CMD | GATT_PROP_WRITE_REQ,
0,
NULL,
},
};
static void show_reg(uint8_t *data,uint32_t len,uint8_t dbg_on)
{
uint32_t i=0;
if(len == 0 || (dbg_on==0)) return;
for(; i<len; i++)
{
printf("0x%02X,",data[i]);
}
printf("\r\n");
}
/*********************************************************************
* @fn hid_gatt_op_cmp_handler
*
* @brief Gatt operation complete handler.
*
*
* @param p_operation - operation that has compeleted
*
* @return none.
*/
void hid_gatt_op_cmp_handler(void *p_operation)
{
}
/*********************************************************************
* @fn hid_gatt_msg_handler
*
* @brief HID gatt message handler.
*
*
* @param p_msg - messages from GATT layer.
*
* @return none.
*/
static uint16_t hid_gatt_msg_handler(struct gatt_msg *p_msg)
{
printf("hid mag handler,evt is %d\r\n", p_msg->msg_evt);
switch(p_msg->msg_evt)
{
case GATTS_MSG_READ_REQ:
//if(hid_link_enable[p_msg->conn_idx] == false)
// return 0xffff; //save this msg
if(p_msg->att_idx == HID_REPORT_MAP_IDX)
{
printf("report_map request:%d\r\n",sizeof(hid_report_map));
memcpy(p_msg->param.gatt_data.p_msg_data, hid_report_map, sizeof(hid_report_map));
return sizeof(hid_report_map);
}
else if (p_msg->att_idx == HID_INFO_IDX)
{
printf("hid info request\r\n");
memcpy(p_msg->param.gatt_data.p_msg_data, hid_info_value, sizeof(hid_info_value));
return sizeof(hid_info_value);
}
else
{
for(uint8_t idx=0; idx<HID_NUM_REPORTS; idx++)
{
if(p_msg->att_idx == HID_REPORT_REF_FEATURE_IDX + 4 * idx)
{
printf("report_ref[%d] request\r\n",idx);
memcpy(p_msg->param.gatt_data.p_msg_data, (uint8_t *)&hid_rpt_info[idx], sizeof(hid_report_ref_t));
return sizeof(hid_report_ref_t);
}
}
}
break;
case GATTS_MSG_WRITE_REQ:
//if(hid_link_enable[p_msg->conn_idx] == false)
//return 0xffff; //save this msg
if(p_msg->att_idx == HID_BOOT_KEY_IN_CCCD_IDX)
{
printf("boot_key_ntf_enable:");
show_reg(p_msg->param.gatt_data.p_msg_data,p_msg->param.gatt_data.msg_len,1);
}
else if(p_msg->att_idx == HID_FEATURE_IDX + 4 * 3)
{
printf("write report_id 3:");
show_reg(p_msg->param.gatt_data.p_msg_data,p_msg->param.gatt_data.msg_len,1);
uint8_t *data = p_msg->param.gatt_data.p_msg_data;
if(data[0] & (1<<0))
printf("num_lock on\r\n");
else
printf("num_lock off\r\n");
if (data[0] & (1<<1))
printf("caps_lock on\r\n");
else
printf("caps_lock off\r\n");
hid_link_ntf_enable[p_msg->conn_idx] = true;
}
else
{
for(uint8_t idx=0; idx<HID_NUM_REPORTS; idx++)
{
if(p_msg->att_idx == HID_FEATURE_CCCD_IDX + 4 * idx)
{
printf("ntf_enable[%d]:",idx);
show_reg(p_msg->param.gatt_data.p_msg_data,p_msg->param.gatt_data.msg_len,1);
}
if(idx == 2)
hid_link_ntf_enable[p_msg->conn_idx] = true;
}
}
break;
case GATTC_MSG_CMP_EVT:
hid_gatt_op_cmp_handler((struct gatt_op_cmp*)&(p_msg->param.gatt_op_cmp));
break;
case GATTC_MSG_LINK_CREATE:
printf("hid link[%d] create\r\n",p_msg->conn_idx);
hid_link_ntf_enable[p_msg->conn_idx] = true;
//gatt_mtu_exchange_req(hid_svc_id, p_msg->conn_idx, 247);
break;
case GATTC_MSG_LINK_LOST:
//printf("link[%d] lost\r\n",p_msg->conn_idx);
hid_link_ntf_enable[p_msg->conn_idx] = false;
hid_link_enable[p_msg->conn_idx] = false;
break;
default:
break;
}
return 0;
}
void hid_service_enable(uint8_t conidx)
{
//hid_link_enable[conidx] = true;
//os_task_process_saved_msg(gatt_get_task_no_from_prf_id(hid_svc_id));
}
/*********************************************************************
* @fn hid_gatt_report_notify
*
* @brief Send HID notification, keys, mouse values, etc.
*
*
* @param rpt_info_id - report idx of the hid_rpt_info array.
* len - length of the HID information data.
* p_data - data of the HID information to be sent.
*
* @return none.
*/
void hid_gatt_report_notify(uint8_t conidx, uint8_t rpt_info_id, uint8_t *p_data, uint16_t len)
{
if (rpt_info_id < HID_NUM_REPORTS && hid_link_ntf_enable[conidx])
{
printf("hid ntf\r\n");
struct gatt_send_event ntf;
ntf.conidx = conidx;
ntf.svc_id = hid_svc_id;
ntf.att_idx = HID_FEATURE_IDX + 4*(rpt_info_id) ;
ntf.data_len = len;
ntf.p_data = p_data;
gatt_notification(&ntf);
}
}
/*********************************************************************
* @fn hid_gatt_add_service
*
* @brief Simple Profile add GATT service function.
* <20><><EFBFBD><EFBFBD>GATT service<63><65>ATT<54><54><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><DDBF><EFBFBD><EFBFBD>
*
* @param None.
*
*
* @return None.
*/
void hid_gatt_add_service(void)
{
gatt_service_t hid_profie_svc;
hid_profie_svc.p_att_tb = hid_profile_att_table;
hid_profie_svc.att_nb = HID_ATT_NB;
hid_profie_svc.gatt_msg_handler = hid_gatt_msg_handler;
hid_rpt_info[0].report_id = 1; //refer to report map, this is Mouse
hid_rpt_info[0].report_type = HID_REPORT_TYPE_INPUT;
hid_rpt_info[1].report_id = 2; //refer to report map, this is Cosumer Controller
hid_rpt_info[1].report_type = HID_REPORT_TYPE_INPUT;
hid_rpt_info[2].report_id = 3; //refer to report map, this is Keyboard input.
hid_rpt_info[2].report_type = HID_REPORT_TYPE_INPUT; //att_table, perm must be GATT_PROP_READ | GATT_PROP_NOTI
hid_rpt_info[3].report_id = 3; //refer to report map, this is Keyboard output.
hid_rpt_info[3].report_type = HID_REPORT_TYPE_OUTPUT; //att_table, perm must be GATT_PROP_READ | GATT_PROP_WRITE
hid_svc_id = gatt_add_service(&hid_profie_svc);
}

View File

@ -0,0 +1,181 @@
/**
* Copyright (c) 2019, Freqchip
*
* All rights reserved.
*
*
*/
#ifndef HID_SERVICE_H
#define HID_SERVICE_H
/*
* INCLUDES (<28><><EFBFBD><EFBFBD>ͷ<EFBFBD>ļ<EFBFBD>)
*/
#include <stdio.h>
#include <string.h>
#include "gap_api.h"
#include "gatt_api.h"
#include "gatt_sig_uuid.h"
/*
* MACROS (<28><EFBFBD><EAB6A8>)
*/
/// Keyboard Device
#define HID_DEV_KEYBOARD 0x01
/// Mouse Device
#define HID_DEV_MOUSE 0x02
/// Protocol Mode present
#define HID_DEV_PROTO_MODE 0x04
/// Extended Reference Present
#define HID_DEV_MAP_EXT_REF 0x08
/*
*NOTICE: User shold define hid device and report information array number.
* Current only support keyboard device.
*/
#define HID_DEV (HID_DEV_KEYBOARD)
// Number of HID reports defined in the service
#define HID_NUM_REPORTS 4
/*
* CONSTANTS (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
*/
/* HID information flags */
#define HID_FLAGS_REMOTE_WAKE 0x01 // RemoteWake
#define HID_FLAGS_NORMALLY_CONNECTABLE 0x02 // NormallyConnectable
/* HID protocol mode values */
#define HID_PROTOCOL_MODE_BOOT 0x00 // Boot Protocol Mode
#define HID_PROTOCOL_MODE_REPORT 0x01 // Report Protocol Mode
/** @defgroup HID_REPORT_TYPE_GROUP */
#define HID_REPORT_TYPE_INPUT 0x01
#define HID_REPORT_TYPE_OUTPUT 0x02
#define HID_REPORT_TYPE_FEATURE 0x03
#define HID_REPORT_TYPE_WR 0x10 /// Input report with Write capabilities
// HID service attributes index.
// Attribute index enumeration-- these indexes match array elements above
enum
{
HID_SERVICE_IDX, // HID Service
#if ((HID_DEV & HID_DEV_MAP_EXT_REF) == HID_DEV_MAP_EXT_REF)
//HID_INCLUDED_SERVICE_IDX, // Included Service
#endif
HID_INFO_DECL_IDX, // HID Information characteristic declaration
HID_INFO_IDX, // HID Information characteristic
HID_CONTROL_POINT_DECL_IDX, // HID Control Point characteristic declaration
HID_CONTROL_POINT_IDX, // HID Control Point characteristic
HID_REPORT_MAP_DECL_IDX, // HID Report Map characteristic declaration
HID_REPORT_MAP_IDX, // HID Report Map characteristic
#if ((HID_DEV & HID_DEV_MAP_EXT_REF) == HID_DEV_MAP_EXT_REF)
HID_REPORT_MAP_EXT_REP_REF,
#endif
#if ((HID_DEV & HID_DEV_PROTO_MODE) == HID_DEV_PROTO_MODE)
HID_PROTOCOL_MODE_DECL_IDX, // HID Protocol Mode characteristic declaration
HID_PROTOCOL_MODE_IDX, // HID Protocol Mode characteristic
#endif
#if ((HID_DEV & HID_DEV_KEYBOARD) == HID_DEV_KEYBOARD)
HID_BOOT_KEY_IN_DECL_IDX, // HID Boot Keyboard Input Report declaration
HID_BOOT_KEY_IN_IDX, // HID Boot Keyboard Input Report
HID_BOOT_KEY_IN_CCCD_IDX, // HID Boot Keyboard Input Report characteristic client characteristic configuration
HID_BOOT_KEY_OUT_DECL_IDX, // HID Boot Keyboard Output Report declaration
HID_BOOT_KEY_OUT_IDX, // HID Boot Keyboard Output Report
#endif
#if ((HID_DEV & HID_DEV_MOUSE) == HID_DEV_MOUSE)
HID_BOOT_MOUSE_IN_DECL_IDX, // HID Boot Mouse Input Report declaration
HID_BOOT_MOUSE_IN_IDX, // HID Boot Mouse Input Report
HID_BOOT_MOUSE_IN_CCCD_IDX, // HID Boot Mouse Input Report characteristic client characteristic configuration
#endif
HID_IDX_ATT_UNIQ_NB,
HID_FEATURE_DECL_IDX = HID_IDX_ATT_UNIQ_NB, // Feature Report declaration
HID_FEATURE_IDX, // Feature Report
HID_REPORT_REF_FEATURE_IDX, // HID Report Reference characteristic descriptor, feature
HID_FEATURE_CCCD_IDX,
HID_ATT_NB = HID_IDX_ATT_UNIQ_NB + (4* (HID_NUM_REPORTS)),
};
/*
* TYPEDEFS (<28><><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>)
*/
// HID report mapping table
typedef struct
{
///Report ID, refer to report map.
uint8_t report_id;
///Report Type, define report id type, see HID Report type
uint8_t report_type;
} hid_report_ref_t;
/*
* GLOBAL VARIABLES (ȫ<>ֱ<EFBFBD><D6B1><EFBFBD>)
*/
extern uint8_t hid_svc_id;
/*
* LOCAL VARIABLES (<28><><EFBFBD>ر<EFBFBD><D8B1><EFBFBD>)
*/
/*
* PUBLIC FUNCTIONS (ȫ<>ֺ<EFBFBD><D6BA><EFBFBD>)
*/
/*********************************************************************
* @fn hid_gatt_add_service
*
* @brief Create hid server.
*
* @param None.
*
* @return None.
*/
void hid_gatt_add_service(void);
/*********************************************************************
* @fn hid_gatt_report_notify
*
* @brief Send HID notification, keys, mouse values, etc.
*
*
* @param rpt_info_id - report idx, see hid_report_ref_t hid_rpt_info[HID_NUM_REPORTS].
* len - length of the HID information data.
* p_data - data of the HID information to be sent.
*
* @return none.
*/
void hid_gatt_report_notify(uint8_t conidx, uint8_t rpt_info_id, uint8_t *p_data, uint16_t len);
/*********************************************************************
* @fn hid_service_enable
*
* @brief hid service is valid only after link is encrypted, so need to call this function
* after link is encrypted.
*
* @param conidx - link index.
*
* @return none.
*/
void hid_service_enable(uint8_t conidx);
#endif

View File

@ -0,0 +1,431 @@
/**
* Copyright (c) 2019, Freqchip
*
* All rights reserved.
*
*
*/
/*
* INCLUDES (<28><><EFBFBD><EFBFBD>ͷ<EFBFBD>ļ<EFBFBD>)
*/
#include <stdio.h>
#include <string.h>
#include "gap_api.h"
#include "gatt_api.h"
#include "gatt_sig_uuid.h"
#include "simple_gatt_service.h"
#include "co_log.h"
/*
* MACROS (<28><EFBFBD><EAB6A8>)
*/
/*
* CONSTANTS (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
*/
/*
user application
*/
const uint8_t wrx_service_uuid[16] = {0xa1, 0x11, 0xb9, 0x58, 0x84, 0x17, 0x27, 0x94, 0x57, 0x46, 0xe6, 0xdf, 0xe0, 0x8a, 0x72, 0x75};
#define WRX_NOTIFY_CHAR_UUID 0xa1, 0x11, 0xb9, 0x58, 0x84, 0x17, 0x27, 0x94, 0x57, 0x46, 0xe6, 0xdf, 0xe1, 0x8a, 0x72, 0x75
#define LOG_NOTIFY_CHAR_UUID 0xb7, 0xe4, 0x44, 0x2e, 0x8e, 0x6a, 0x7f, 0x97, 0xc3, 0x44, 0x4d, 0x8e, 0x10, 0x12, 0x0c, 0x3e
#define WRX_BLE_OTA_CHAR_UUID 0x35, 0x45, 0x28, 0x45, 0xb4, 0xf5, 0x38, 0x88, 0x2e, 0x48, 0xa9, 0xc8, 0xe3, 0xec, 0x31, 0x43
#define WRX_NOTIFY_CHAR_LEN 500
#define WRX_CHAR3_VALUE_LEN 500
// Simple GATT Profile Service UUID: 0xFFF0
const uint8_t sp_svc_uuid[] = UUID16_ARR(SP_SVC_UUID);
/******************************* Characteristic 1 defination *******************************/
// Characteristic 1 UUID: 0xFFF1
// Characteristic 1 data
#define SP_CHAR1_VALUE_LEN 10
uint8_t sp_char1_value[SP_CHAR1_VALUE_LEN] = {0};
#define SP_CHAR1_CCC_LEN 2
uint8_t sp_char1_ccc[SP_CHAR1_CCC_LEN] = {0};
// Characteristic 1 User Description
#define SP_CHAR1_DESC_LEN 17
const uint8_t sp_char1_desc[SP_CHAR1_DESC_LEN] = "Characteristic 1";
/******************************* Characteristic 2 defination *******************************/
// Characteristic 2 UUID: 0xFFF2
// Characteristic 2 data
#define SP_CHAR2_VALUE_LEN 20
uint8_t sp_char2_value[SP_CHAR2_VALUE_LEN] = {0};
#define SP_CHAR2_CCC_LEN 2
uint8_t sp_char2_ccc[SP_CHAR2_CCC_LEN] = {0};
// Characteristic 2 User Description
#define SP_CHAR2_DESC_LEN 17
const uint8_t sp_char2_desc[SP_CHAR2_DESC_LEN] = "Characteristic 2";
/******************************* Characteristic 3 defination *******************************/
// Characteristic 3 UUID: 0xFFF3
// Characteristic 3 data
#define SP_CHAR3_VALUE_LEN 30
uint8_t sp_char3_value[SP_CHAR3_VALUE_LEN] = {0};
// Characteristic 3 client characteristic configuration
#define SP_CHAR3_CCC_LEN 2
uint8_t sp_char3_ccc[SP_CHAR3_CCC_LEN] = {0};
// Characteristic 3 User Description
#define SP_CHAR3_DESC_LEN 17
const uint8_t sp_char3_desc[SP_CHAR3_DESC_LEN] = "Characteristic 3";
/******************************* Characteristic 4 defination *******************************/
// Characteristic 4 UUID: 0xFFF4
// Characteristic 4 data
#define SP_CHAR4_VALUE_LEN 40
uint8_t sp_char4_value[SP_CHAR4_VALUE_LEN] = {0};
#define SP_CHAR4_CCC_LEN 2
uint8_t sp_char4_ccc[SP_CHAR4_CCC_LEN] = {0};
// Characteristic 4 User Description
#define SP_CHAR4_DESC_LEN 17
const uint8_t sp_char4_desc[SP_CHAR4_DESC_LEN] = "Characteristic 4";
/******************************* Characteristic 5 defination *******************************/
// Characteristic 5 UUID: 0xFFF5
uint8_t sp_char5_uuid[UUID_SIZE_2] =
{
LO_UINT16(SP_CHAR5_UUID), HI_UINT16(SP_CHAR5_UUID)
};
// Characteristic 5 data
#define SP_CHAR5_VALUE_LEN 50
uint8_t sp_char5_value[SP_CHAR5_VALUE_LEN] = {0};
// Characteristic 5 User Description
#define SP_CHAR5_DESC_LEN 17
const uint8_t sp_char5_desc[SP_CHAR5_DESC_LEN] = "Characteristic 5";
/*
* TYPEDEFS (<28><><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>)
*/
/*
* GLOBAL VARIABLES (ȫ<>ֱ<EFBFBD><D6B1><EFBFBD>)
*/
uint8_t sp_svc_id = 0;
uint8_t sp_conidx = 0;
/*
* LOCAL VARIABLES (<28><><EFBFBD>ر<EFBFBD><D8B1><EFBFBD>)
*/
static gatt_service_t simple_profile_svc;
/*********************************************************************
* Profile Attributes - Table
* ÿһ<C3BF><EFBFBD><EEB6BC>һ<EFBFBD><D2BB>attribute<74>Ķ<EFBFBD><C4B6>
* <20><>һ<EFBFBD><D2BB>attributeΪService <20>ĵĶ<C4B5><C4B6>
* ÿһ<C3BF><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ(characteristic)<29>Ķ<EFBFBD><C4B6><EFBFBD><E5A3AC><EFBFBD><EFBFBD><EFBFBD>ٰ<EFBFBD><D9B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>attribute<74>Ķ<EFBFBD><C4B6>
* 1. <20><><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD>(Characteristic Declaration)
* 2. <20><><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5>ֵ(Characteristic value)
* 3. <20><><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(Characteristic description)
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>notification <20><><EFBFBD><EFBFBD>indication <20>Ĺ<EFBFBD><C4B9>ܣ<EFBFBD><DCA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD>attribute<74>Ķ<EFBFBD><C4B6><EFBFBD><E5A3AC><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><E6B6A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(client characteristic configuration)<29><>
*
*/
const gatt_attribute_t simple_profile_att_table[SP_IDX_NB] =
{
// Simple gatt Service Declaration
[SP_IDX_SERVICE] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_PRIMARY_SERVICE_UUID) }, /* UUID */
GATT_PROP_READ, /* Permissions */
UUID_SIZE_16, /* Max size of the value */ /* Service UUID size in service declaration */
(uint8_t*)wrx_service_uuid, /* Value of the attribute */ /* Service UUID value in service declaration */
},
// Characteristic 1 Declaration
[SP_IDX_CHAR1_DECLARATION] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID) }, /* UUID */
GATT_PROP_READ, /* Permissions */
0, /* Max size of the value */
NULL, /* Value of the attribute */
},
// Characteristic 1 Value
[SP_IDX_CHAR1_VALUE] = {
{ UUID_SIZE_16, WRX_NOTIFY_CHAR_UUID }, /* UUID */
GATT_PROP_NOTI | GATT_PROP_WRITE_CMD, /* Permissions */
WRX_NOTIFY_CHAR_LEN, /* Max size of the value */
NULL, /* Value of the attribute */ /* Can assign a buffer here, or can be assigned in the application by user */
},
// Characteristic 1 User Description
[SP_IDX_CHAR1_USER_DESCRIPTION] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_CLIENT_CHAR_CFG_UUID) }, /* UUID */
GATT_PROP_READ|GATT_PROP_WRITE_CMD, /* Permissions */
0, /* Max size of the value */
NULL, /* Value of the attribute */
},
// Characteristic 3 Declaration
[SP_IDX_CHAR3_DECLARATION] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID) }, /* UUID */
GATT_PROP_READ, /* Permissions */
0, /* Max size of the value */
NULL, /* Value of the attribute */
},
// Characteristic 3 Value
[SP_IDX_CHAR3_VALUE] = {
{ UUID_SIZE_16, LOG_NOTIFY_CHAR_UUID }, /* UUID */
GATT_PROP_NOTI, /* Permissions */
WRX_CHAR3_VALUE_LEN, /* Max size of the value */
NULL, /* Value of the attribute */ /* Can assign a buffer here, or can be assigned in the application by user */
},
// Characteristic 3 User Description
[SP_IDX_CHAR3_USER_DESCRIPTION] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_CLIENT_CHAR_CFG_UUID) }, /* UUID */
GATT_PROP_READ | GATT_PROP_WRITE_CMD, /* Permissions */
0, /* Max size of the value */
NULL, /* Value of the attribute */
},
// Characteristic 4 Declaration
[SP_IDX_CHAR4_DECLARATION] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID) }, /* UUID */
GATT_PROP_NOTI, /* Permissions */
0, /* Max size of the value */
NULL, /* Value of the attribute */
},
// Characteristic 4 Value
[SP_IDX_CHAR4_VALUE] = {
{ UUID_SIZE_16, WRX_BLE_OTA_CHAR_UUID }, /* UUID */
GATT_PROP_NOTI | GATT_PROP_WRITE_REQ | GATT_PROP_WRITE_CMD, /* Permissions */
WRX_CHAR3_VALUE_LEN, /* Max size of the value */
NULL, /* Value of the attribute */ /* Can assign a buffer here, or can be assigned in the application by user */
},
// Characteristic 4 User Description
[SP_IDX_CHAR4_USER_DESCRIPTION] = {
{ UUID_SIZE_2, UUID16_ARR(GATT_CLIENT_CHAR_CFG_UUID) }, /* UUID */
GATT_PROP_READ | GATT_PROP_WRITE_CMD, /* Permissions */
0, /* Max size of the value */
NULL, /* Value of the attribute */
},
};
//norify api
void Send_Data2App_notificate(uint8_t att_idx,uint8_t *p_data, uint16_t len)
{
uint8_t enable = 0;
if(att_idx == SP_IDX_CHAR1_VALUE)
{
if(sp_char1_ccc[0])
{
enable = 1;
}
}
//else if(att_idx == SP_IDX_CHAR2_VALUE)
//{
// if(sp_char2_ccc[0])
// {
// enable = 1;
// }
//}
else if(att_idx == SP_IDX_CHAR3_VALUE)
{
if(sp_char3_ccc[0])
{
enable = 1;
}
}
//else if(att_idx == SP_IDX_CHAR4_VALUE)
//{
// if(sp_char4_ccc[0])
// {
// enable = 1;
// }
//}
if(enable)
{
struct gatt_send_event ntf;
ntf.conidx = sp_conidx;
ntf.svc_id = sp_svc_id;
ntf.att_idx = att_idx ;
ntf.data_len = len;
ntf.p_data = p_data;
gatt_notification(&ntf);
#if 1 //printf send notify data
printf("att_idx%d:",att_idx);
for(uint8_t i = 0; i < len; i++)
{
printf("0x%02x,",p_data[i]);
}
printf("\r\n");
#endif
}
else{
printf("character disable!\r\n");
}
}
/*********************************************************************
* @fn sp_gatt_read_cb
*
* @brief Simple Profile user application handles read request in this callback.
* Ӧ<>ò<EFBFBD><C3B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E6B4A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* @param p_read - the pointer to read buffer. NOTE: It's just a pointer from lower layer, please create the buffer in application layer.
* ָ<><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><20><>ע<EFBFBD><D7A2><EFBFBD><EFBFBD>ֻ<EFBFBD><D6BB>һ<EFBFBD><D2BB>ָ<EFBFBD><EFBFBD><EBA3AC><EFBFBD><EFBFBD>Ӧ<EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD>з<EFBFBD><D0B7><EFBFBD><E4BBBA><EFBFBD><EFBFBD>. Ϊ<><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD>Ϊָ<CEAA><D6B8><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>.
* len - the pointer to the length of read buffer. Application to assign it.
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD><C4B3>ȣ<EFBFBD><C8A3>û<EFBFBD>Ӧ<EFBFBD>ó<EFBFBD><C3B3><EFBFBD>ȥ<EFBFBD><C8A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ.
* att_idx - index of the attribute value in it's attribute table.
* Attribute<74><65>ƫ<EFBFBD><C6AB><EFBFBD><EFBFBD>.
*
* @return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD><C4B3><EFBFBD>.
*/
static void sp_gatt_read_cb(uint8_t *p_read, uint16_t *len, uint16_t att_idx)
{
switch (att_idx)
{
case SP_IDX_CHAR1_VALUE:
for (int i = 0; i < SP_CHAR1_VALUE_LEN; i++)
sp_char1_value[i] = sp_char1_value[0] + i + 1;
memcpy(p_read, sp_char1_value, SP_CHAR1_VALUE_LEN);
*len = SP_CHAR1_VALUE_LEN;
break;
#if 0
case SP_IDX_CHAR2_VALUE:
for (int i = 0; i < SP_CHAR2_VALUE_LEN; i++)
sp_char2_value[i] = sp_char2_value[0] + i + 1;
memcpy(p_read, sp_char2_value, SP_CHAR2_VALUE_LEN);
*len = SP_CHAR2_VALUE_LEN;
break;
#endif
#if 0
case SP_IDX_CHAR3_CFG:
*len = 2;
memcpy(p_read, sp_char3_ccc, 2);
break;
#endif /* if 0. 2020-12-24 15:43:27 joe */
#if 0
case SP_IDX_CHAR5_VALUE:
for (int i = 0; i < SP_CHAR5_VALUE_LEN; i++)
sp_char5_value[i] = sp_char3_value[0] + i + 1;
memcpy(p_read, sp_char5_value, SP_CHAR5_VALUE_LEN);
*len = SP_CHAR5_VALUE_LEN;
break;
#endif
default:
break;
}
LOG_INFO("Read request: len: %d value: 0x%x 0x%x \r\n", *len, (p_read)[0], (p_read)[*len-1]);
}
/*********************************************************************
* @fn sp_gatt_write_cb
*
* @brief Simple Profile user application handles write request in this callback.
* Ӧ<>ò<EFBFBD><C3B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E6B4A6>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* @param write_buf - the buffer for write
* д<><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
*
* len - the length of write buffer.
* д<><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD><C4B3><EFBFBD>.
* att_idx - index of the attribute value in it's attribute table.
* Attribute<74><65>ƫ<EFBFBD><C6AB><EFBFBD><EFBFBD>.
*
* @return д<><D0B4><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD><C4B3><EFBFBD>.
*/
static void sp_gatt_write_cb(uint8_t *write_buf, uint16_t len, uint16_t att_idx)
{
printf("Write request: att index is %d, len is %d\r\n",att_idx, len);
printf("recv data is:");
for(uint32_t i=0;i<len;i++)
{
printf("0x%02x ", write_buf[i]);
}
printf("\r\n");
if(att_idx == SP_IDX_CHAR1_VALUE)
{
/*
add user gatt write_cb
*/
printf("char1 value recevice \r\n");
}
uint16_t uuid = BUILD_UINT16( simple_profile_att_table[att_idx].uuid.p_uuid[0], simple_profile_att_table[att_idx].uuid.p_uuid[1] );
printf("uuid %x \r\n",uuid);
if (uuid == GATT_CLIENT_CHAR_CFG_UUID)
{
printf("Notification status changed\r\n");
#if 1
if (att_idx == SP_IDX_CHAR1_USER_DESCRIPTION)
{
sp_char1_ccc[0] = write_buf[0];
sp_char1_ccc[1] = write_buf[1];
printf("Char1 ccc: 0x%x 0x%x \r\n", sp_char1_ccc[0], sp_char1_ccc[1]);
}
#endif
}
//Send_Data2App_notificate(SP_IDX_CHAR1_VALUE,(uint8_t *)"222",3); //if notify enable, send test data to app
}
/*********************************************************************
* @fn sp_gatt_msg_handler
*
* @brief Simple Profile callback funtion for GATT messages. GATT read/write
* operations are handeled here.
*
* @param p_msg - GATT messages from GATT layer.
*
* @return uint16_t - Length of handled message.
*/
static uint16_t sp_gatt_msg_handler(struct gatt_msg *p_msg)
{
switch(p_msg->msg_evt)
{
case GATTS_MSG_READ_REQ:
printf("read request: att idx is %d\r\n", p_msg->att_idx);
sp_gatt_read_cb((uint8_t *)(p_msg->param.gatt_data.p_msg_data), &(p_msg->param.gatt_data.msg_len), p_msg->att_idx);
break;
case GATTS_MSG_WRITE_REQ:
sp_gatt_write_cb((uint8_t*)(p_msg->param.gatt_data.p_msg_data), (p_msg->param.gatt_data.msg_len), p_msg->att_idx);
break;
default:
break;
}
sp_conidx = p_msg->conn_idx;
return p_msg->param.gatt_data.msg_len;
}
/*********************************************************************
* @fn sp_gatt_add_service
*
* @brief Simple Profile add GATT service function.
* <09><><EFBFBD><EFBFBD>GATT service<63><65>ATT<54><54><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><DDBF><EFBFBD><EFBFBD>
*
* @param None.
*
*
* @return None.
*/
void sp_gatt_add_service(void)
{
simple_profile_svc.p_att_tb = simple_profile_att_table;
simple_profile_svc.att_nb = SP_IDX_NB;
simple_profile_svc.gatt_msg_handler = sp_gatt_msg_handler;
sp_svc_id = gatt_add_service(&simple_profile_svc);
}

View File

@ -0,0 +1,130 @@
/**
* Copyright (c) 2019, Freqchip
*
* All rights reserved.
*
*
*/
#ifndef SP_GATT_PROFILE_H
#define SP_GATT_PROFILE_H
/*
* INCLUDES (<28><><EFBFBD><EFBFBD>ͷ<EFBFBD>ļ<EFBFBD>)
*/
#include <stdio.h>
#include <string.h>
#include "gap_api.h"
#include "gatt_api.h"
#include "gatt_sig_uuid.h"
/*
* MACROS (<28><EFBFBD><EAB6A8>)
*/
/*
* CONSTANTS (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
*/
// Simple Profile attributes index.
#if 1
enum
{
SP_IDX_SERVICE,
SP_IDX_CHAR1_DECLARATION,
SP_IDX_CHAR1_VALUE,
SP_IDX_CHAR1_USER_DESCRIPTION,
SP_IDX_CHAR3_DECLARATION,
SP_IDX_CHAR3_VALUE,
SP_IDX_CHAR3_USER_DESCRIPTION,
SP_IDX_CHAR4_DECLARATION,
SP_IDX_CHAR4_VALUE,
SP_IDX_CHAR4_USER_DESCRIPTION,
SP_IDX_NB,
};
#else
enum
{
SP_IDX_SERVICE,
SP_IDX_CHAR1_DECLARATION,
SP_IDX_CHAR1_VALUE,
SP_IDX_CHAR1_CFG,
SP_IDX_CHAR1_USER_DESCRIPTION,
SP_IDX_CHAR2_DECLARATION,
SP_IDX_CHAR2_VALUE,
//SP_IDX_CHAR2_CFG,
SP_IDX_CHAR2_USER_DESCRIPTION,
SP_IDX_CHAR3_DECLARATION,
SP_IDX_CHAR3_VALUE,
SP_IDX_CHAR3_CFG,
SP_IDX_CHAR3_USER_DESCRIPTION,
SP_IDX_CHAR4_DECLARATION,
SP_IDX_CHAR4_VALUE,
//SP_IDX_CHAR4_CFG,
SP_IDX_CHAR4_USER_DESCRIPTION,
SP_IDX_CHAR5_DECLARATION,
SP_IDX_CHAR5_VALUE,
SP_IDX_CHAR5_USER_DESCRIPTION,
SP_IDX_NB,
};
#endif
// Simple GATT Profile Service UUID
#define SP_SVC_UUID 0xFFF0
#define SP_CHAR1_UUID 0xFFF1
#define SP_CHAR2_UUID 0xFFF2
#define SP_CHAR3_UUID 0xFFF3
#define SP_CHAR4_UUID 0xFFF4
#define SP_CHAR5_UUID 0xFFF5
/*
* TYPEDEFS (<28><><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>)
*/
/*
* GLOBAL VARIABLES (ȫ<>ֱ<EFBFBD><D6B1><EFBFBD>)
*/
extern const gatt_attribute_t simple_profile_att_table[];
/*
* LOCAL VARIABLES (<28><><EFBFBD>ر<EFBFBD><D8B1><EFBFBD>)
*/
/*
* PUBLIC FUNCTIONS (ȫ<>ֺ<EFBFBD><D6BA><EFBFBD>)
*/
/*********************************************************************
* @fn sp_gatt_add_service
*
* @brief Simple Profile add GATT service function.
* <09><><EFBFBD><EFBFBD>GATT service<63><65>ATT<54><54><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><DDBF><EFBFBD><EFBFBD>
*
* @param None.
*
*
* @return None.
*/
void sp_gatt_add_service(void);
void Send_Data2App_notificate(uint8_t att_idx,uint8_t *p_data, uint16_t len);
#endif