Add next gen profile and configurations (#67)

* 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
This commit is contained in:
Dien-Nhung Nguyen
2025-02-17 16:05:23 +07:00
committed by GitHub
parent 512134607b
commit 4e556ab11f
29 changed files with 912 additions and 243 deletions

View File

@@ -1,5 +1,6 @@
#include "CH58xBLE_LIB.h"
#include "setup.h"
#include "../config.h"
#define ADV_UUID (0xFEE0)
@@ -24,29 +25,6 @@ typedef struct
#define CONN_TIMEOUT 100 // Supervision timeout (units of 10ms)
// GAP - SCAN RSP data (max size = 31 bytes)
static uint8 scanRspData[] = {
// complete name
16, // length of this section
GAP_ADTYPE_LOCAL_NAME_COMPLETE,
'L', 'E','D', ' ',
'B', 'a','d', 'g', 'e', ' ',
'M', 'a','g', 'i', 'c',
// 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
};
// GAP - Advertisement data (max size = 31 bytes)
// keep short, save energy, save the planet
static uint8 advertData[] = {
@@ -61,9 +39,6 @@ static uint8 advertData[] = {
HI_UINT16(ADV_UUID)
};
// GAP GATT Attributes
static uint8 devName[GAP_DEVICE_NAME_LEN] = "LED Badge Magic";
// Connection item list
static peripheralConnItem_t conn_list;
@@ -210,21 +185,58 @@ void ble_disable_advertise()
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();
static uint16 desired_min_interval = 6;
static uint16 desired_max_interval = 500;
uint16_t min_interval = 6;
uint16_t max_interval = 500;
// Set the GAP Role Parameters
GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, sizeof(scanRspData), scanRspData);
setup_scan_rsp(badge_cfg.ble_devname, 20);
GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData);
GAPRole_SetParameter(GAPROLE_MIN_CONN_INTERVAL, sizeof(uint16), &desired_min_interval);
GAPRole_SetParameter(GAPROLE_MAX_CONN_INTERVAL, sizeof(uint16), &desired_max_interval);
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, GAP_DEVICE_NAME_LEN, devName);
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);

View File

@@ -4,5 +4,8 @@
int legacy_registerService();
int devInfo_registerService();
int batt_registerService();
int ng_registerService();
bStatus_t ng_notify(uint8_t *pValue, uint8_t len);
#endif /* __BLE_UART_SERVICE_H__ */

View File

@@ -1,8 +1,6 @@
#include "utils.h"
#include "../../data.h"
#include "../../power.h"
#include "../../leddrv.h"
#include "../../legacyctrl.h"
static const uint16_t ServiceUUID = 0xFEE0;
static const gattAttrType_t service = {2, (uint8_t *)&ServiceUUID};
@@ -18,39 +16,6 @@ static gattAttribute_t attr_table[] = {
CHAR_VAL_DECLAR(&RxCharUUID, 2, GATT_PERMIT_WRITE, RxCharVal),
};
static bStatus_t receive(uint8_t *val, uint16_t len)
{
static uint16_t c, data_len, n;
static uint8_t *data;
if (len != LEGACY_TRANSFER_WIDTH) {
return ATT_ERR_INVALID_VALUE_SIZE;
}
if (c == 0) {
if (memcmp(val, "wang\0\0", 6)) {
return ATT_ERR_INVALID_VALUE;
} else {
data = malloc(sizeof(data_legacy_t));
}
}
memcpy(data + c * len, val, len);
if (c == 1) {
data_legacy_t *d = (data_legacy_t *)data;
n = bigendian16_sum(d->sizes, 8);
data_len = LEGACY_HEADER_SIZE + LED_ROWS * n;
data = realloc(data, data_len);
}
if (c > 2 && ((c+1) * LEGACY_TRANSFER_WIDTH) >= data_len) {
data_flatSave(data, data_len);
reset_jump();
}
c++;
return SUCCESS;
}
static bStatus_t write_handler(uint16 connHandle, gattAttribute_t *pAttr,
uint8 *pValue, uint16 len, uint16 offset, uint8 method)
{
@@ -60,7 +25,10 @@ static bStatus_t write_handler(uint16 connHandle, gattAttribute_t *pAttr,
uint16_t uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
if(uuid == RxCharUUID) {
return receive(pValue, len);
if (legacy_ble_rx(pValue, len)) {
return ATT_ERR_UNLIKELY;
}
return SUCCESS;
}
return ATT_ERR_ATTR_NOT_FOUND;
}

160
src/ble/profile/ng.c Normal file
View File

@@ -0,0 +1,160 @@
#include "utils.h"
#include "CH583SFR.h"
#include "../../power.h"
#include "../../ngctrl.h"
#include "../../debug.h"
static const uint16_t ServiceUUID = 0xF055;
static const gattAttrType_t service = {2, (uint8_t *)&ServiceUUID};
static const uint16_t TxCharUUID = 0xF056;
static uint8_t TxCharProps = GATT_PROP_READ | GATT_PROP_NOTIFY;
static uint8_t TxCharVal[256];
static uint16_t TxLen;
static const uint16_t RxCharUUID = 0xF057;
static uint8_t RxCharProps = GATT_PROP_WRITE;
#define RxCharVal TxCharVal
static gattCharCfg_t TxCCCD[1];
static gattAttribute_t attr_table[] = {
ATTR_DECLAR(primaryServiceUUID, 2, GATT_PERMIT_READ, &service),
CHAR_DECLAR(&RxCharProps),
CHAR_VAL_DECLAR(&RxCharUUID, 2, GATT_PERMIT_WRITE, RxCharVal),
CHAR_DECLAR(&TxCharProps),
CHAR_VAL_DECLAR(&TxCharUUID, 2, GATT_PERMIT_READ, TxCharVal),
ATTR_DECLAR(clientCharCfgUUID, 2, GATT_PERMIT_READ | GATT_PERMIT_WRITE, TxCCCD),
};
#define notiAttr attr_table[4]
static bStatus_t write_handler(uint16 connHandle, gattAttribute_t *pAttr,
uint8 *pValue, uint16 len, uint16 offset, uint8 method)
{
PRINT("ble: write_handler(): connHandle: %04X\n", connHandle);
if (!gattPermitWrite(pAttr->permissions)) {
return ATT_ERR_WRITE_NOT_PERMITTED;
}
uint16_t uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
if(uuid == GATT_CLIENT_CHAR_CFG_UUID) {
bStatus_t ret = GATTServApp_ProcessCCCWriteReq(connHandle, pAttr, pValue, len,
offset, GATT_CLIENT_CFG_NOTIFY);
PRINT("ble: CCCD changed: %02X\n", TxCCCD->value);
return ret;
}
if (uuid == RxCharUUID) {
return ng_parse(pValue, len);
}
return ATT_ERR_ATTR_NOT_FOUND;
}
static bStatus_t read_handler(uint16_t connHandle, gattAttribute_t *pAttr,
uint8_t *pValue, uint16_t *pLen, uint16_t offset,
uint16_t maxLen, uint8_t method)
{
if (!gattPermitRead(pAttr->permissions)) {
return ATT_ERR_READ_NOT_PERMITTED;
}
uint16_t uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
if(uuid == GATT_CLIENT_CHAR_CFG_UUID) {
*pLen = 2;
tmos_memcpy(pValue, pAttr->pValue, *pLen);
return SUCCESS;
}
if (uuid == TxCharUUID) {
*pLen = MIN(TxLen-offset, maxLen);
tmos_memcpy(pValue, &pAttr->pValue[offset], *pLen);
return SUCCESS;
}
return ATT_ERR_ATTR_NOT_FOUND;
}
static gattServiceCBs_t service_handlers = {
read_handler,
write_handler,
NULL
};
static void connStatus_handler(uint16 connHandle, uint8 changeType)
{
if(connHandle == LOOPBACK_CONNHANDLE)
return;
// Reset ClientCharConfig if connection has dropped
if((changeType == LINKDB_STATUS_UPDATE_REMOVED)
|| ((changeType == LINKDB_STATUS_UPDATE_STATEFLAGS)
&& (!linkDB_Up(connHandle)))) {
GATTServApp_InitCharCfg(connHandle, TxCCCD);
}
}
int ng_registerService()
{
uint8 status = SUCCESS;
GATTServApp_InitCharCfg(INVALID_CONNHANDLE, TxCCCD);
linkDB_Register(connStatus_handler);
status = GATTServApp_RegisterService(attr_table,
GATT_NUM_ATTRS(attr_table),
GATT_MAX_ENCRYPT_KEY_SIZE,
&service_handlers);
return (status);
}
static uint8 isNotifyEnabled(uint16 connHandle)
{
uint16_t val = GATTServApp_ReadCharCfg(connHandle, TxCCCD);
return val & GATT_CLIENT_CFG_NOTIFY;
}
/**
* @brief Send notify to client. Currently support one client connection
* only.
*
* @param val Value to be sent
* @param len length of val. This should not be larger than MTU.
* @return bStatus_t
*/
bStatus_t ng_notify(uint8_t *val, uint8_t len)
{
if(!isNotifyEnabled(TxCCCD->connHandle)) {
PRINT("ble: ng_notify() notify is not enabled\n");
return bleIncorrectMode;
}
if(len > ATT_GetMTU(TxCCCD->connHandle)) {
return bleInvalidRange;
}
attHandleValueNoti_t noti = {
.handle = notiAttr.handle,
.len = len
};
noti.pValue = GATT_bm_alloc(TxCCCD->connHandle, ATT_HANDLE_VALUE_NOTI,
len, NULL, 0);
if (noti.pValue == NULL) {
return bleMemAllocError;
}
tmos_memcpy(noti.pValue, val, len);
bStatus_t ret = GATT_Notification(TxCCCD->connHandle, &noti, FALSE);
GATT_bm_free((gattMsg_t *)&noti, ATT_HANDLE_VALUE_NOTI);
if (ret != SUCCESS) {
PRINT("ble: noti sending failed\n");
return ret;
}
PRINT("ble: noti sent\n");
return SUCCESS;
}

View File

@@ -6,28 +6,39 @@
#include "CH58x_common.h"
#ifndef BLE_BUFF_LEN
#define BLE_BUFF_LEN 27
#endif
#ifndef BLE_BUFF_NUM
#define BLE_BUFF_NUM 5
// MTU = 64 but clients should request new MTU, otherwise default will be 23
#define BLE_BUFF_LEN (64 + 4)
#endif
#ifndef BLE_TX_NUM_EVENT
#define BLE_TX_NUM_EVENT 1
#endif
#ifndef BLE_TX_POWER
#define BLE_TX_POWER LL_TX_POWEER_6_DBM
// #define BLE_TX_POWER LL_TX_POWEER_MINUS_16_DBM
#endif
#ifndef BLE_MEMHEAP_SIZE
#define BLE_MEMHEAP_SIZE (1024*6)
#define BLE_MEMHEAP_SIZE (1024 * 6)
#endif
#ifndef CENTRAL_MAX_CONNECTION
#define CENTRAL_MAX_CONNECTION 3
#define CENTRAL_MAX_CONNECTION 1
#endif
#ifndef BLE_BUFF_NUM
// The BLE lib automatically stack up Write Long messages in Write handler.
// A connection will be disconnected if this number is some how not enough.
#define BLE_BUFF_NUM (512 / 23)
#endif
#ifndef PERIPHERAL_MAX_CONNECTION
#define PERIPHERAL_MAX_CONNECTION 1
#endif
static __attribute__((aligned(4))) uint32_t MEM_BUF[BLE_MEMHEAP_SIZE / 4];
static __attribute__((aligned(4), section(".noinit")))
uint32_t MEM_BUF[BLE_MEMHEAP_SIZE / 4];
static void lsi_calib(void)
{