* fix: crash in picture animation * ble: add next gen profile * force read header from flash anyway * fix: bmlist: mem leak * feat: add reset option after legacy transfers
269 lines
7.1 KiB
C
269 lines
7.1 KiB
C
#include "CH58xBLE_LIB.h"
|
|
#include "setup.h"
|
|
#include "../config.h"
|
|
|
|
#define ADV_UUID (0xFEE0)
|
|
|
|
static uint8 taskid = INVALID_TASK_ID;
|
|
|
|
typedef struct
|
|
{
|
|
uint16 connHandle; // Connection handle of current connection
|
|
uint16 connInterval;
|
|
uint16 connSlaveLatency;
|
|
uint16 connTimeout;
|
|
} peripheralConnItem_t;
|
|
|
|
#define SBP_PARAM_UPDATE_DELAY 1600 // Parameter update delay (unit of 0.625ms)
|
|
#define SLAVE_LATENCY 0
|
|
|
|
#define MIN_ADV_INTERVAL 100 // Advertising interval (units of 0.625ms)
|
|
#define MAX_ADV_INTERVAL 200 // Advertising interval (units of 0.625ms)
|
|
|
|
#define MIN_CONN_INTERVAL 20 // Connection interval (units of 1.25ms)
|
|
#define MAX_CONN_INTERVAL 100 // Connection interval (units of 1.25ms)
|
|
|
|
#define CONN_TIMEOUT 100 // Supervision timeout (units of 10ms)
|
|
|
|
// GAP - Advertisement data (max size = 31 bytes)
|
|
// keep short, save energy, save the planet
|
|
static uint8 advertData[] = {
|
|
0x02, // section length
|
|
GAP_ADTYPE_FLAGS,
|
|
GAP_ADTYPE_FLAGS_GENERAL | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,
|
|
|
|
// advertise UUID
|
|
0x03, // section length
|
|
GAP_ADTYPE_16BIT_MORE,
|
|
LO_UINT16(ADV_UUID),
|
|
HI_UINT16(ADV_UUID)
|
|
};
|
|
|
|
// Connection item list
|
|
static peripheralConnItem_t conn_list;
|
|
|
|
static void initConn(peripheralConnItem_t *conn)
|
|
{
|
|
conn->connHandle = GAP_CONNHANDLE_INIT;
|
|
conn->connInterval = 0;
|
|
conn->connSlaveLatency = 0;
|
|
conn->connTimeout = 0;
|
|
}
|
|
|
|
static void processTMOSMsg(tmos_event_hdr_t *pMsg)
|
|
{
|
|
switch(pMsg->event) {
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void enable_advertising(uint8_t enable)
|
|
{
|
|
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8), &enable);
|
|
}
|
|
|
|
static void link_onEstablished(gapRoleEvent_t *pe)
|
|
{
|
|
gapEstLinkReqEvent_t *e = (gapEstLinkReqEvent_t *)pe;
|
|
|
|
// If already connected
|
|
if(conn_list.connHandle != GAP_CONNHANDLE_INIT) {
|
|
// Only allow 1 connection, so the new connection will be dropped:
|
|
GAPRole_TerminateLink(e->connectionHandle);
|
|
GAPRole_PeripheralConnParamUpdateReq(e->connectionHandle,
|
|
MIN_CONN_INTERVAL,
|
|
MAX_CONN_INTERVAL,
|
|
SLAVE_LATENCY,
|
|
CONN_TIMEOUT,
|
|
taskid);
|
|
return;
|
|
}
|
|
conn_list.connHandle = e->connectionHandle;
|
|
conn_list.connInterval = e->connInterval;
|
|
conn_list.connSlaveLatency = e->connLatency;
|
|
conn_list.connTimeout = e->connTimeout;
|
|
enable_advertising(FALSE);
|
|
}
|
|
|
|
static void link_onTerminated(gapRoleEvent_t *pe)
|
|
{
|
|
gapTerminateLinkEvent_t *event = (gapTerminateLinkEvent_t *)pe;
|
|
GAPRole_TerminateLink(pe->linkCmpl.connectionHandle);
|
|
enable_advertising(TRUE);
|
|
|
|
if(event->connectionHandle == conn_list.connHandle) {
|
|
conn_list.connHandle = GAP_CONNHANDLE_INIT;
|
|
conn_list.connInterval = 0;
|
|
conn_list.connSlaveLatency = 0;
|
|
conn_list.connTimeout = 0;
|
|
} else {
|
|
// Requested connection is not existed in connection list
|
|
}
|
|
}
|
|
|
|
static void gap_onParamUpdate(uint16 connHandle, uint16 connInterval,
|
|
uint16 connSlaveLatency, uint16 connTimeout)
|
|
{
|
|
conn_list.connHandle = connHandle;
|
|
conn_list.connInterval = connInterval;
|
|
conn_list.connSlaveLatency = connSlaveLatency;
|
|
conn_list.connTimeout = connTimeout;
|
|
}
|
|
|
|
static void gap_onStateChange(gapRole_States_t newState, gapRoleEvent_t *pEvent)
|
|
{
|
|
switch(newState & GAPROLE_STATE_ADV_MASK) {
|
|
case GAPROLE_ADVERTISING:
|
|
if(pEvent->gap.opcode == GAP_LINK_TERMINATED_EVENT) {
|
|
link_onTerminated(pEvent);
|
|
}
|
|
break;
|
|
|
|
case GAPROLE_CONNECTED:
|
|
if(pEvent->gap.opcode == GAP_LINK_ESTABLISHED_EVENT) {
|
|
link_onEstablished(pEvent);
|
|
}
|
|
break;
|
|
|
|
case GAPROLE_WAITING:
|
|
if(pEvent->gap.opcode == GAP_LINK_TERMINATED_EVENT) {
|
|
link_onTerminated(pEvent);
|
|
} else {
|
|
// refer to pEvent->gap.opcode
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// GAP Role Callbacks
|
|
static gapRolesCBs_t gap_handlers = {
|
|
gap_onStateChange,
|
|
NULL,
|
|
gap_onParamUpdate
|
|
};
|
|
|
|
// Broadcast Callbacks
|
|
static gapRolesBroadcasterCBs_t broadcast_handlers = {
|
|
NULL,
|
|
NULL
|
|
};
|
|
|
|
// GAP Bond Manager Callbacks
|
|
static gapBondCBs_t bond_managers = {
|
|
NULL,
|
|
NULL
|
|
};
|
|
|
|
|
|
static uint16 peripheral_task(uint8 task_id, uint16 events)
|
|
{
|
|
if(events & SYS_EVENT_MSG) { // Handle BLE stack message
|
|
uint8 *pMsg = tmos_msg_receive(taskid);
|
|
if(pMsg) {
|
|
processTMOSMsg((tmos_event_hdr_t *)pMsg);
|
|
tmos_msg_deallocate(pMsg);
|
|
}
|
|
return (events ^ SYS_EVENT_MSG);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void ble_enable_advertise()
|
|
{
|
|
uint8 e = TRUE;
|
|
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8), &e);
|
|
}
|
|
|
|
void ble_disable_advertise()
|
|
{
|
|
uint8 e = FALSE;
|
|
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8), &e);
|
|
}
|
|
|
|
// len should not exceed 20 chars excluding null-terminate char. Otherwise it
|
|
// will be trimmed off and return -1
|
|
static int setup_scan_rsp(char *name, uint8_t len)
|
|
{
|
|
int ret = 0;
|
|
// GAP - SCAN RSP data (max size = 31 bytes)
|
|
uint8_t scanRspData[31] = {
|
|
// connection interval range
|
|
0x05, // length of this section
|
|
GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE,
|
|
LO_UINT16(MIN_CONN_INTERVAL),
|
|
HI_UINT16(MIN_CONN_INTERVAL),
|
|
LO_UINT16(MAX_CONN_INTERVAL),
|
|
HI_UINT16(MAX_CONN_INTERVAL),
|
|
|
|
// Tx power level
|
|
0x02, // length of this data
|
|
GAP_ADTYPE_POWER_LEVEL,
|
|
9, // 9dBm
|
|
|
|
len + 1,
|
|
GAP_ADTYPE_LOCAL_NAME_COMPLETE,
|
|
};
|
|
|
|
if (len < (31 - 11)) {
|
|
tmos_memcpy(&scanRspData[11], name, len);
|
|
ret = -1;
|
|
} else {
|
|
tmos_memcpy(&scanRspData[11], name, 20);
|
|
}
|
|
int total_len = 11 + len;
|
|
tmos_memset(&scanRspData[total_len], 0, 31 - total_len);
|
|
GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, total_len, scanRspData);
|
|
return ret;
|
|
}
|
|
|
|
static void gap_init()
|
|
{
|
|
GAPRole_PeripheralInit();
|
|
|
|
uint16_t min_interval = 6;
|
|
uint16_t max_interval = 500;
|
|
|
|
// Set the GAP Role Parameters
|
|
setup_scan_rsp(badge_cfg.ble_devname, 20);
|
|
GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData);
|
|
GAPRole_SetParameter(GAPROLE_MIN_CONN_INTERVAL, sizeof(uint16), &min_interval);
|
|
GAPRole_SetParameter(GAPROLE_MAX_CONN_INTERVAL, sizeof(uint16), &max_interval);
|
|
|
|
// Set the GAP Characteristics
|
|
GGS_SetParameter(GGS_DEVICE_NAME_ATT, 20,
|
|
badge_cfg.ble_devname);
|
|
GAP_SetParamValue(TGAP_DISC_ADV_INT_MIN, MIN_ADV_INTERVAL);
|
|
GAP_SetParamValue(TGAP_DISC_ADV_INT_MAX, MAX_ADV_INTERVAL);
|
|
|
|
static uint32 passkey = 0; // passkey "000000"
|
|
static uint8 pairMode = GAPBOND_PAIRING_MODE_NO_PAIRING;
|
|
static uint8 mitm = FALSE;
|
|
static uint8 bonding = FALSE;
|
|
static uint8 ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY;
|
|
GAPBondMgr_SetParameter(GAPBOND_PERI_DEFAULT_PASSCODE, sizeof(uint32), &passkey);
|
|
GAPBondMgr_SetParameter(GAPBOND_PERI_PAIRING_MODE, sizeof(uint8), &pairMode);
|
|
GAPBondMgr_SetParameter(GAPBOND_PERI_MITM_PROTECTION, sizeof(uint8), &mitm);
|
|
GAPBondMgr_SetParameter(GAPBOND_PERI_IO_CAPABILITIES, sizeof(uint8), &ioCap);
|
|
GAPBondMgr_SetParameter(GAPBOND_PERI_BONDING_ENABLED, sizeof(uint8), &bonding);
|
|
|
|
GAPRole_BroadcasterSetCB(&broadcast_handlers);
|
|
|
|
GGS_AddService(GATT_ALL_SERVICES);
|
|
GATTServApp_AddService(GATT_ALL_SERVICES);
|
|
}
|
|
|
|
void peripheral_init()
|
|
{
|
|
taskid = TMOS_ProcessEventRegister(peripheral_task);
|
|
|
|
initConn(&conn_list);
|
|
gap_init();
|
|
|
|
GAPRole_PeripheralStartDevice(taskid, &bond_managers, &gap_handlers);
|
|
}
|