ble: add bonding support
This commit is contained in:
135
src/ble.c
135
src/ble.c
@@ -5,10 +5,70 @@
|
|||||||
#include "CH58x_sys.h"
|
#include "CH58x_sys.h"
|
||||||
#include "CH58xBLE_LIB.h"
|
#include "CH58xBLE_LIB.h"
|
||||||
#include "led.h"
|
#include "led.h"
|
||||||
|
#include "screen.h"
|
||||||
#include "wang.h"
|
#include "wang.h"
|
||||||
|
|
||||||
|
|
||||||
|
// Digits are from Spleen, under BSD-3-Clause.
|
||||||
|
const uint8_t digit_font[10 * 4] = {
|
||||||
|
0x1e,0x29,0x25,0x1e,
|
||||||
|
0x00,0x22,0x3f,0x20,
|
||||||
|
0x32,0x29,0x29,0x26,
|
||||||
|
0x12,0x21,0x25,0x1a,
|
||||||
|
0x0f,0x08,0x3e,0x08,
|
||||||
|
0x27,0x25,0x25,0x19,
|
||||||
|
0x1e,0x25,0x25,0x18,
|
||||||
|
0x03,0x31,0x09,0x07,
|
||||||
|
0x1a,0x25,0x25,0x1a,
|
||||||
|
0x06,0x29,0x29,0x1e
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint16_t magic = 0x201;
|
||||||
|
static const uint16_t magic2 = 0x1FE;
|
||||||
|
|
||||||
|
static uint32_t ble_pin = 0;
|
||||||
|
|
||||||
|
static void ble_popup_render(struct row_buf *buf) {
|
||||||
|
uint16_t fb[44] = {0};
|
||||||
|
int num = ble_pin;
|
||||||
|
|
||||||
|
fb[6] = magic2;
|
||||||
|
fb[7] = magic;
|
||||||
|
fb[37] = magic;
|
||||||
|
fb[38] = magic2;
|
||||||
|
|
||||||
|
for (int i = 5; i >= 0; i--) {
|
||||||
|
int x = 8 + (i * 5);
|
||||||
|
int digit = (num % 10);
|
||||||
|
|
||||||
|
for (int j = 0; j < 4; j++) {
|
||||||
|
fb[x + j] = magic | (((uint16_t) digit_font[digit * 4 + j]) << 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
fb[x + 4] = magic;
|
||||||
|
|
||||||
|
num = num / 10;
|
||||||
|
}
|
||||||
|
display_make_buf_all(fb, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ble_popup_event(struct screen_event event) {
|
||||||
|
if (event.type == SE_BUTTON_PRESS) {
|
||||||
|
screen_pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct screen ble_screen = {
|
||||||
|
ble_popup_render,
|
||||||
|
ble_popup_event,
|
||||||
|
};
|
||||||
|
|
||||||
int ble_on = 0;
|
int ble_on = 0;
|
||||||
int ble_connected = 0;
|
int ble_connected = 0;
|
||||||
|
|
||||||
|
// Whether the device is bonded or was previously bonded and recovered the keys successfully.
|
||||||
|
int ble_paired = 0;
|
||||||
|
|
||||||
void ble_toggle(void) {
|
void ble_toggle(void) {
|
||||||
uint8_t ble_mode = ble_on ? FALSE : TRUE;
|
uint8_t ble_mode = ble_on ? FALSE : TRUE;
|
||||||
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(ble_mode), &ble_mode);
|
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(ble_mode), &ble_mode);
|
||||||
@@ -23,6 +83,27 @@ static void ble_calib_cb(void) {
|
|||||||
Calibration_LSI(Level_128);
|
Calibration_LSI(Level_128);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void passcode_callback(uint8_t *device_addr, uint16_t handle, uint8_t uiInputs, uint8_t uiOutputs) {
|
||||||
|
ble_pin = tmos_rand() % 1000000;
|
||||||
|
screen_dirty = 1;
|
||||||
|
|
||||||
|
GAPBondMgr_PasscodeRsp(handle, SUCCESS, ble_pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pair_state_callback(uint16_t handle, uint8_t state, uint8_t status) {
|
||||||
|
if (state == GAPBOND_PAIRING_STATE_STARTED) {
|
||||||
|
screen_push(&ble_screen);
|
||||||
|
} else {
|
||||||
|
if (current_screen == &ble_screen) screen_pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != SUCCESS) return;
|
||||||
|
if (state != GAPBOND_PAIRING_STATE_BONDED && state != GAPBOND_PAIRING_STATE_COMPLETE) return;
|
||||||
|
|
||||||
|
ble_paired = 1;
|
||||||
|
}
|
||||||
|
|
||||||
static uint8_t periph_task = INVALID_TASK_ID;
|
static uint8_t periph_task = INVALID_TASK_ID;
|
||||||
|
|
||||||
static uint16_t peripheral_task(uint8_t task_id, uint16_t events) {
|
static uint16_t peripheral_task(uint8_t task_id, uint16_t events) {
|
||||||
@@ -41,7 +122,24 @@ static uint16_t peripheral_task(uint8_t task_id, uint16_t events) {
|
|||||||
|
|
||||||
static void gap_onParamUpdate(uint16_t a, uint16_t b, uint16_t c, uint16_t d) {
|
static void gap_onParamUpdate(uint16_t a, uint16_t b, uint16_t c, uint16_t d) {
|
||||||
}
|
}
|
||||||
static void gap_onStateChange(gapRole_States_t a, gapRoleEvent_t *b) {
|
static gapRole_States_t previous_state = GAPROLE_INIT;
|
||||||
|
|
||||||
|
static void gap_onStateChange(gapRole_States_t new_state, gapRoleEvent_t *event) {
|
||||||
|
if (previous_state == GAPROLE_CONNECTED && (new_state & GAPROLE_STATE_ADV_MASK) != GAPROLE_CONNECTED) {
|
||||||
|
ble_paired = 0;
|
||||||
|
ble_connected = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((new_state & GAPROLE_STATE_ADV_MASK) == GAPROLE_ADVERTISING && event->gap.opcode == GAP_LINK_TERMINATED_EVENT) {
|
||||||
|
uint8_t ble_mode = TRUE;
|
||||||
|
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(ble_mode), &ble_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_state == GAPROLE_CONNECTED) {
|
||||||
|
ble_connected = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
previous_state = new_state & GAPROLE_STATE_ADV_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t advertData[] = {
|
uint8_t advertData[] = {
|
||||||
@@ -85,8 +183,8 @@ static gapRolesCBs_t gap_handlers = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static gapBondCBs_t bond_managers = {
|
static gapBondCBs_t bond_managers = {
|
||||||
0,
|
passcode_callback,
|
||||||
0,
|
pair_state_callback,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint8_t service_uuid[2] = {LO_UINT16(0xFEE0), HI_UINT16(0xFEE0)};
|
static const uint8_t service_uuid[2] = {LO_UINT16(0xFEE0), HI_UINT16(0xFEE0)};
|
||||||
@@ -102,10 +200,11 @@ static gattAttribute_t attr_table[] = {
|
|||||||
{{2, rx_char_uuid}, GATT_PERMIT_WRITE, 0, (uint8_t *)&rx_char_val},
|
{{2, rx_char_uuid}, GATT_PERMIT_WRITE, 0, (uint8_t *)&rx_char_val},
|
||||||
};
|
};
|
||||||
|
|
||||||
uint16_t blefb[44] = {0};
|
|
||||||
|
|
||||||
static bStatus_t write_handler(uint16_t conn_handle, gattAttribute_t *pAttr, uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method) {
|
static bStatus_t write_handler(uint16_t conn_handle, gattAttribute_t *pAttr, uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method) {
|
||||||
if (gattPermitAuthorWrite(pAttr->permissions)) return ATT_ERR_INSUFFICIENT_AUTHOR;
|
uint8_t bonded_count = 0;
|
||||||
|
GAPBondMgr_GetParameter(GAPBOND_BOND_COUNT, &bonded_count);
|
||||||
|
|
||||||
|
if (gattPermitAuthorWrite(pAttr->permissions) || (bonded_count && !ble_paired)) return ATT_ERR_INSUFFICIENT_AUTHOR;
|
||||||
|
|
||||||
uint16_t uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
|
uint16_t uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
|
||||||
if (uuid != 0xFEE1) return ATT_ERR_ATTR_NOT_FOUND;
|
if (uuid != 0xFEE1) return ATT_ERR_ATTR_NOT_FOUND;
|
||||||
@@ -121,6 +220,17 @@ static gattServiceCBs_t service_handlers = {
|
|||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
uint32_t ble_read_flash(uint32_t addr, uint32_t num, uint32_t *buf) {
|
||||||
|
EEPROM_READ(addr, buf, num * 4);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ble_write_flash(uint32_t addr, uint32_t num, uint32_t *buf) {
|
||||||
|
EEPROM_ERASE(addr, num * 4);
|
||||||
|
EEPROM_WRITE(addr, buf, num * 4);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void ble_init(void) {
|
void ble_init(void) {
|
||||||
bleConfig_t cfg = {0};
|
bleConfig_t cfg = {0};
|
||||||
|
|
||||||
@@ -128,8 +238,11 @@ void ble_init(void) {
|
|||||||
cfg.MEMAddr = (uint32_t) BLE_BUF;
|
cfg.MEMAddr = (uint32_t) BLE_BUF;
|
||||||
cfg.MEMLen = (uint32_t) sizeof(BLE_BUF);
|
cfg.MEMLen = (uint32_t) sizeof(BLE_BUF);
|
||||||
|
|
||||||
// not using the bonding information, as we do not support _bonding_.
|
cfg.SNVAddr = (uint32_t) EEPROM_MAX_SIZE - 0x200;
|
||||||
// This should be changed. but. you know.
|
cfg.SNVBlock = 256;
|
||||||
|
cfg.SNVNum = 1;
|
||||||
|
cfg.readFlashCB = ble_read_flash;
|
||||||
|
cfg.writeFlashCB = ble_write_flash;
|
||||||
|
|
||||||
// TODO: magic numbers
|
// TODO: magic numbers
|
||||||
// amount of buffered packets
|
// amount of buffered packets
|
||||||
@@ -177,10 +290,10 @@ void ble_init(void) {
|
|||||||
GAP_SetParamValue(TGAP_DISC_ADV_INT_MAX, 200);
|
GAP_SetParamValue(TGAP_DISC_ADV_INT_MAX, 200);
|
||||||
|
|
||||||
SET_PARAM(GAPBondMgr_SetParameter, GAPBOND_PERI_DEFAULT_PASSCODE, uint32_t, 0);
|
SET_PARAM(GAPBondMgr_SetParameter, GAPBOND_PERI_DEFAULT_PASSCODE, uint32_t, 0);
|
||||||
SET_PARAM(GAPBondMgr_SetParameter, GAPBOND_PERI_PAIRING_MODE, uint8_t, GAPBOND_PAIRING_MODE_NO_PAIRING);
|
SET_PARAM(GAPBondMgr_SetParameter, GAPBOND_PERI_PAIRING_MODE, uint8_t, GAPBOND_PAIRING_MODE_WAIT_FOR_REQ);
|
||||||
SET_PARAM(GAPBondMgr_SetParameter, GAPBOND_PERI_MITM_PROTECTION, uint8_t, FALSE);
|
SET_PARAM(GAPBondMgr_SetParameter, GAPBOND_PERI_MITM_PROTECTION, uint8_t, TRUE);
|
||||||
SET_PARAM(GAPBondMgr_SetParameter, GAPBOND_PERI_IO_CAPABILITIES, uint8_t, GAPBOND_IO_CAP_DISPLAY_ONLY);
|
SET_PARAM(GAPBondMgr_SetParameter, GAPBOND_PERI_IO_CAPABILITIES, uint8_t, GAPBOND_IO_CAP_DISPLAY_ONLY);
|
||||||
SET_PARAM(GAPBondMgr_SetParameter, GAPBOND_PERI_BONDING_ENABLED, uint8_t, FALSE);
|
SET_PARAM(GAPBondMgr_SetParameter, GAPBOND_PERI_BONDING_ENABLED, uint8_t, TRUE);
|
||||||
|
|
||||||
GAPRole_BroadcasterSetCB(&broadcast_handlers);
|
GAPRole_BroadcasterSetCB(&broadcast_handlers);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user