BLE multi-connection: broadcast responses to all clients, support 2 simultaneous connections
This commit is contained in:
parent
9ec77e071f
commit
595e25466c
94
main/ble.c
94
main/ble.c
|
|
@ -30,13 +30,20 @@ static const ble_uuid128_t midi_chr_uuid = BLE_UUID128_INIT(
|
||||||
0xf3, 0x6b, 0x10, 0x9d, 0x66, 0xf2, 0xa9, 0xa1,
|
0xf3, 0x6b, 0x10, 0x9d, 0x66, 0xf2, 0xa9, 0xa1,
|
||||||
0x12, 0x41, 0x68, 0x38, 0xdb, 0xe5, 0x72, 0x77);
|
0x12, 0x41, 0x68, 0x38, 0xdb, 0xe5, 0x72, 0x77);
|
||||||
|
|
||||||
|
#define MAX_CONNECTIONS 2
|
||||||
|
|
||||||
static EventGroupHandle_t ble_events;
|
static EventGroupHandle_t ble_events;
|
||||||
static QueueHandle_t cmd_queue;
|
static QueueHandle_t cmd_queue;
|
||||||
static uint16_t conn_hdl = BLE_HS_CONN_HANDLE_NONE;
|
|
||||||
static uint16_t midi_val_hdl;
|
static uint16_t midi_val_hdl;
|
||||||
static uint16_t hid_input_val_hdl;
|
static uint16_t hid_input_val_hdl;
|
||||||
static bool midi_notify_en;
|
|
||||||
static bool hid_notify_en;
|
static struct {
|
||||||
|
uint16_t hdl;
|
||||||
|
bool midi_notify;
|
||||||
|
bool hid_notify;
|
||||||
|
} conns[MAX_CONNECTIONS];
|
||||||
|
|
||||||
|
static int conn_count;
|
||||||
|
|
||||||
/* ---- HID keyboard report map ---- */
|
/* ---- HID keyboard report map ---- */
|
||||||
|
|
||||||
|
|
@ -436,14 +443,19 @@ static const struct ble_gatt_svc_def gatt_svcs[] = {
|
||||||
|
|
||||||
/* ---- send empty keyboard report ---- */
|
/* ---- send empty keyboard report ---- */
|
||||||
|
|
||||||
static void send_empty_hid_report(void)
|
static int conn_find(uint16_t hdl)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < conn_count; i++)
|
||||||
|
if (conns[i].hdl == hdl) return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void send_empty_hid_report(uint16_t hdl)
|
||||||
{
|
{
|
||||||
if (conn_hdl == BLE_HS_CONN_HANDLE_NONE || !hid_notify_en)
|
|
||||||
return;
|
|
||||||
static const uint8_t empty[8] = {0};
|
static const uint8_t empty[8] = {0};
|
||||||
struct os_mbuf *om = ble_hs_mbuf_from_flat(empty, sizeof(empty));
|
struct os_mbuf *om = ble_hs_mbuf_from_flat(empty, sizeof(empty));
|
||||||
if (om)
|
if (om)
|
||||||
ble_gatts_notify_custom(conn_hdl, hid_input_val_hdl, om);
|
ble_gatts_notify_custom(hdl, hid_input_val_hdl, om);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---- GAP / advertising ---- */
|
/* ---- GAP / advertising ---- */
|
||||||
|
|
@ -456,33 +468,49 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg)
|
||||||
switch (event->type) {
|
switch (event->type) {
|
||||||
case BLE_GAP_EVENT_CONNECT:
|
case BLE_GAP_EVENT_CONNECT:
|
||||||
if (event->connect.status == 0) {
|
if (event->connect.status == 0) {
|
||||||
conn_hdl = event->connect.conn_handle;
|
uint16_t hdl = event->connect.conn_handle;
|
||||||
|
if (conn_count < MAX_CONNECTIONS) {
|
||||||
|
conns[conn_count].hdl = hdl;
|
||||||
|
conns[conn_count].midi_notify = false;
|
||||||
|
conns[conn_count].hid_notify = false;
|
||||||
|
conn_count++;
|
||||||
|
}
|
||||||
xEventGroupSetBits(ble_events, CONNECTED_BIT);
|
xEventGroupSetBits(ble_events, CONNECTED_BIT);
|
||||||
ble_att_set_preferred_mtu(128);
|
ble_att_set_preferred_mtu(128);
|
||||||
ble_gattc_exchange_mtu(conn_hdl, NULL, NULL);
|
ble_gattc_exchange_mtu(hdl, NULL, NULL);
|
||||||
ble_gap_security_initiate(conn_hdl);
|
ble_gap_security_initiate(hdl);
|
||||||
printf("BLE: connected\n");
|
printf("BLE: connected (%d/%d)\n", conn_count, MAX_CONNECTIONS);
|
||||||
|
if (conn_count < MAX_CONNECTIONS)
|
||||||
|
start_adv();
|
||||||
} else {
|
} else {
|
||||||
start_adv();
|
start_adv();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BLE_GAP_EVENT_DISCONNECT:
|
case BLE_GAP_EVENT_DISCONNECT: {
|
||||||
conn_hdl = BLE_HS_CONN_HANDLE_NONE;
|
uint16_t hdl = event->disconnect.conn.conn_handle;
|
||||||
midi_notify_en = false;
|
int idx = conn_find(hdl);
|
||||||
hid_notify_en = false;
|
if (idx >= 0) {
|
||||||
xEventGroupClearBits(ble_events, CONNECTED_BIT);
|
conns[idx] = conns[--conn_count];
|
||||||
printf("BLE: disconnected\n");
|
}
|
||||||
|
if (conn_count == 0)
|
||||||
|
xEventGroupClearBits(ble_events, CONNECTED_BIT);
|
||||||
|
printf("BLE: disconnected (%d/%d)\n", conn_count, MAX_CONNECTIONS);
|
||||||
start_adv();
|
start_adv();
|
||||||
break;
|
break;
|
||||||
case BLE_GAP_EVENT_SUBSCRIBE:
|
}
|
||||||
if (event->subscribe.attr_handle == midi_val_hdl)
|
case BLE_GAP_EVENT_SUBSCRIBE: {
|
||||||
midi_notify_en = event->subscribe.cur_notify;
|
int idx = conn_find(event->subscribe.conn_handle);
|
||||||
if (event->subscribe.attr_handle == hid_input_val_hdl) {
|
if (idx >= 0) {
|
||||||
hid_notify_en = event->subscribe.cur_notify;
|
if (event->subscribe.attr_handle == midi_val_hdl)
|
||||||
if (hid_notify_en)
|
conns[idx].midi_notify = event->subscribe.cur_notify;
|
||||||
send_empty_hid_report();
|
if (event->subscribe.attr_handle == hid_input_val_hdl) {
|
||||||
|
conns[idx].hid_notify = event->subscribe.cur_notify;
|
||||||
|
if (conns[idx].hid_notify)
|
||||||
|
send_empty_hid_report(event->subscribe.conn_handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case BLE_GAP_EVENT_REPEAT_PAIRING: {
|
case BLE_GAP_EVENT_REPEAT_PAIRING: {
|
||||||
struct ble_gap_conn_desc desc;
|
struct ble_gap_conn_desc desc;
|
||||||
ble_gap_conn_find(event->repeat_pairing.conn_handle, &desc);
|
ble_gap_conn_find(event->repeat_pairing.conn_handle, &desc);
|
||||||
|
|
@ -547,10 +575,9 @@ static void host_task(void *param)
|
||||||
|
|
||||||
static int send_sysex(const uint8_t *sysex, uint16_t len)
|
static int send_sysex(const uint8_t *sysex, uint16_t len)
|
||||||
{
|
{
|
||||||
if (conn_hdl == BLE_HS_CONN_HANDLE_NONE || !midi_notify_en)
|
if (conn_count == 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* BLE MIDI SysEx: [header, ts, F0, payload..., ts, F7] */
|
|
||||||
uint16_t pkt_len = len + 3;
|
uint16_t pkt_len = len + 3;
|
||||||
uint8_t pkt[80];
|
uint8_t pkt[80];
|
||||||
if (pkt_len > sizeof(pkt))
|
if (pkt_len > sizeof(pkt))
|
||||||
|
|
@ -562,10 +589,15 @@ static int send_sysex(const uint8_t *sysex, uint16_t len)
|
||||||
pkt[len + 1] = 0x80;
|
pkt[len + 1] = 0x80;
|
||||||
pkt[len + 2] = 0xF7;
|
pkt[len + 2] = 0xF7;
|
||||||
|
|
||||||
struct os_mbuf *om = ble_hs_mbuf_from_flat(pkt, pkt_len);
|
int sent = 0;
|
||||||
if (!om) return -1;
|
for (int i = 0; i < conn_count; i++) {
|
||||||
|
if (!conns[i].midi_notify) continue;
|
||||||
return ble_gatts_notify_custom(conn_hdl, midi_val_hdl, om);
|
struct os_mbuf *om = ble_hs_mbuf_from_flat(pkt, pkt_len);
|
||||||
|
if (!om) continue;
|
||||||
|
if (ble_gatts_notify_custom(conns[i].hdl, midi_val_hdl, om) == 0)
|
||||||
|
sent++;
|
||||||
|
}
|
||||||
|
return sent > 0 ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---- public API ---- */
|
/* ---- public API ---- */
|
||||||
|
|
@ -604,7 +636,7 @@ int ble_init(void)
|
||||||
|
|
||||||
int ble_is_connected(void)
|
int ble_is_connected(void)
|
||||||
{
|
{
|
||||||
return conn_hdl != BLE_HS_CONN_HANDLE_NONE;
|
return conn_count > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ble_wait_for_connection(void)
|
void ble_wait_for_connection(void)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
|
CONFIG_IDF_TARGET="esp32s3"
|
||||||
CONFIG_BT_ENABLED=y
|
CONFIG_BT_ENABLED=y
|
||||||
CONFIG_BT_NIMBLE_ENABLED=y
|
CONFIG_BT_NIMBLE_ENABLED=y
|
||||||
CONFIG_BT_NIMBLE_MAX_CONNECTIONS=1
|
CONFIG_BT_NIMBLE_MAX_CONNECTIONS=2
|
||||||
CONFIG_BT_NIMBLE_ROLE_PERIPHERAL=y
|
CONFIG_BT_NIMBLE_ROLE_PERIPHERAL=y
|
||||||
CONFIG_BT_NIMBLE_ROLE_CENTRAL=y
|
CONFIG_BT_NIMBLE_ROLE_CENTRAL=y
|
||||||
CONFIG_BT_NIMBLE_ROLE_OBSERVER=n
|
CONFIG_BT_NIMBLE_ROLE_OBSERVER=n
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue