[FL-2623] Add BLE disconnect request #1686
Co-authored-by: LionZXY <nikita@kulikof.ru> Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
parent
9ff29d12b2
commit
ead9f134f4
@ -165,6 +165,11 @@ static uint16_t bt_serial_event_callback(SerialServiceEvent event, void* context
|
|||||||
ret = rpc_session_get_available_size(bt->rpc_session);
|
ret = rpc_session_get_available_size(bt->rpc_session);
|
||||||
} else if(event.event == SerialServiceEventTypeDataSent) {
|
} else if(event.event == SerialServiceEventTypeDataSent) {
|
||||||
furi_event_flag_set(bt->rpc_event, BT_RPC_EVENT_BUFF_SENT);
|
furi_event_flag_set(bt->rpc_event, BT_RPC_EVENT_BUFF_SENT);
|
||||||
|
} else if(event.event == SerialServiceEventTypesBleResetRequest) {
|
||||||
|
FURI_LOG_I(TAG, "BLE restart request received");
|
||||||
|
BtMessage message = {.type = BtMessageTypeSetProfile, .data.profile = BtProfileSerial};
|
||||||
|
furi_check(
|
||||||
|
furi_message_queue_put(bt->message_queue, &message, FuriWaitForever) == FuriStatusOk);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -226,6 +231,7 @@ static bool bt_on_gap_event_callback(GapEvent event, void* context) {
|
|||||||
rpc_session_set_context(bt->rpc_session, bt);
|
rpc_session_set_context(bt->rpc_session, bt);
|
||||||
furi_hal_bt_serial_set_event_callback(
|
furi_hal_bt_serial_set_event_callback(
|
||||||
RPC_BUFFER_SIZE, bt_serial_event_callback, bt);
|
RPC_BUFFER_SIZE, bt_serial_event_callback, bt);
|
||||||
|
furi_hal_bt_serial_set_rpc_status(FuriHalBtSerialRpcStatusActive);
|
||||||
} else {
|
} else {
|
||||||
FURI_LOG_W(TAG, "RPC is busy, failed to open new session");
|
FURI_LOG_W(TAG, "RPC is busy, failed to open new session");
|
||||||
}
|
}
|
||||||
@ -241,6 +247,7 @@ static bool bt_on_gap_event_callback(GapEvent event, void* context) {
|
|||||||
} else if(event.type == GapEventTypeDisconnected) {
|
} else if(event.type == GapEventTypeDisconnected) {
|
||||||
if(bt->profile == BtProfileSerial && bt->rpc_session) {
|
if(bt->profile == BtProfileSerial && bt->rpc_session) {
|
||||||
FURI_LOG_I(TAG, "Close RPC connection");
|
FURI_LOG_I(TAG, "Close RPC connection");
|
||||||
|
furi_hal_bt_serial_set_rpc_status(FuriHalBtSerialRpcStatusNotActive);
|
||||||
furi_event_flag_set(bt->rpc_event, BT_RPC_EVENT_DISCONNECTED);
|
furi_event_flag_set(bt->rpc_event, BT_RPC_EVENT_DISCONNECTED);
|
||||||
rpc_session_close(bt->rpc_session);
|
rpc_session_close(bt->rpc_session);
|
||||||
furi_hal_bt_serial_set_event_callback(0, NULL, NULL);
|
furi_hal_bt_serial_set_event_callback(0, NULL, NULL);
|
||||||
@ -330,14 +337,20 @@ static void bt_change_profile(Bt* bt, BtMessage* message) {
|
|||||||
}
|
}
|
||||||
furi_hal_bt_set_key_storage_change_callback(bt_on_key_storage_change_callback, bt);
|
furi_hal_bt_set_key_storage_change_callback(bt_on_key_storage_change_callback, bt);
|
||||||
bt->profile = message->data.profile;
|
bt->profile = message->data.profile;
|
||||||
*message->result = true;
|
if(message->result) {
|
||||||
|
*message->result = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
FURI_LOG_E(TAG, "Failed to start Bt App");
|
FURI_LOG_E(TAG, "Failed to start Bt App");
|
||||||
*message->result = false;
|
if(message->result) {
|
||||||
|
*message->result = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bt_show_warning(bt, "Radio stack doesn't support this app");
|
bt_show_warning(bt, "Radio stack doesn't support this app");
|
||||||
*message->result = false;
|
if(message->result) {
|
||||||
|
*message->result = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
furi_event_flag_set(bt->api_event, BT_API_UNLOCK_EVENT);
|
furi_event_flag_set(bt->api_event, BT_API_UNLOCK_EVENT);
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ typedef struct {
|
|||||||
uint16_t rx_char_handle;
|
uint16_t rx_char_handle;
|
||||||
uint16_t tx_char_handle;
|
uint16_t tx_char_handle;
|
||||||
uint16_t flow_ctrl_char_handle;
|
uint16_t flow_ctrl_char_handle;
|
||||||
|
uint16_t rpc_status_char_handle;
|
||||||
FuriMutex* buff_size_mtx;
|
FuriMutex* buff_size_mtx;
|
||||||
uint32_t buff_size;
|
uint32_t buff_size;
|
||||||
uint16_t bytes_ready_to_receive;
|
uint16_t bytes_ready_to_receive;
|
||||||
@ -28,6 +29,8 @@ static const uint8_t char_rx_uuid[] =
|
|||||||
{0x00, 0x00, 0xfe, 0x62, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19};
|
{0x00, 0x00, 0xfe, 0x62, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19};
|
||||||
static const uint8_t flow_ctrl_uuid[] =
|
static const uint8_t flow_ctrl_uuid[] =
|
||||||
{0x00, 0x00, 0xfe, 0x63, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19};
|
{0x00, 0x00, 0xfe, 0x63, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19};
|
||||||
|
static const uint8_t rpc_status_uuid[] =
|
||||||
|
{0x00, 0x00, 0xfe, 0x64, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19};
|
||||||
|
|
||||||
static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void* event) {
|
static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void* event) {
|
||||||
SVCCTL_EvtAckStatus_t ret = SVCCTL_EvtNotAck;
|
SVCCTL_EvtAckStatus_t ret = SVCCTL_EvtNotAck;
|
||||||
@ -67,6 +70,17 @@ static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void* event) {
|
|||||||
furi_check(furi_mutex_release(serial_svc->buff_size_mtx) == FuriStatusOk);
|
furi_check(furi_mutex_release(serial_svc->buff_size_mtx) == FuriStatusOk);
|
||||||
}
|
}
|
||||||
ret = SVCCTL_EvtAckFlowEnable;
|
ret = SVCCTL_EvtAckFlowEnable;
|
||||||
|
} else if(attribute_modified->Attr_Handle == serial_svc->rpc_status_char_handle + 1) {
|
||||||
|
SerialServiceRpcStatus* rpc_status =
|
||||||
|
(SerialServiceRpcStatus*)attribute_modified->Attr_Data;
|
||||||
|
if(*rpc_status == SerialServiceRpcStatusNotActive) {
|
||||||
|
if(serial_svc->callback) {
|
||||||
|
SerialServiceEvent event = {
|
||||||
|
.event = SerialServiceEventTypesBleResetRequest,
|
||||||
|
};
|
||||||
|
serial_svc->callback(event, serial_svc->context);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if(blecore_evt->ecode == ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE) {
|
} else if(blecore_evt->ecode == ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE) {
|
||||||
FURI_LOG_T(TAG, "Ack received");
|
FURI_LOG_T(TAG, "Ack received");
|
||||||
@ -82,6 +96,18 @@ static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void* event) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void serial_svc_update_rpc_char(SerialServiceRpcStatus status) {
|
||||||
|
tBleStatus ble_status = aci_gatt_update_char_value(
|
||||||
|
serial_svc->svc_handle,
|
||||||
|
serial_svc->rpc_status_char_handle,
|
||||||
|
0,
|
||||||
|
sizeof(SerialServiceRpcStatus),
|
||||||
|
(uint8_t*)&status);
|
||||||
|
if(ble_status) {
|
||||||
|
FURI_LOG_E(TAG, "Failed to update RPC status char: %d", ble_status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void serial_svc_start() {
|
void serial_svc_start() {
|
||||||
tBleStatus status;
|
tBleStatus status;
|
||||||
serial_svc = malloc(sizeof(SerialSvc));
|
serial_svc = malloc(sizeof(SerialSvc));
|
||||||
@ -90,7 +116,7 @@ void serial_svc_start() {
|
|||||||
|
|
||||||
// Add service
|
// Add service
|
||||||
status = aci_gatt_add_service(
|
status = aci_gatt_add_service(
|
||||||
UUID_TYPE_128, (Service_UUID_t*)service_uuid, PRIMARY_SERVICE, 10, &serial_svc->svc_handle);
|
UUID_TYPE_128, (Service_UUID_t*)service_uuid, PRIMARY_SERVICE, 12, &serial_svc->svc_handle);
|
||||||
if(status) {
|
if(status) {
|
||||||
FURI_LOG_E(TAG, "Failed to add Serial service: %d", status);
|
FURI_LOG_E(TAG, "Failed to add Serial service: %d", status);
|
||||||
}
|
}
|
||||||
@ -141,6 +167,22 @@ void serial_svc_start() {
|
|||||||
if(status) {
|
if(status) {
|
||||||
FURI_LOG_E(TAG, "Failed to add Flow Control characteristic: %d", status);
|
FURI_LOG_E(TAG, "Failed to add Flow Control characteristic: %d", status);
|
||||||
}
|
}
|
||||||
|
// Add RPC status characteristic
|
||||||
|
status = aci_gatt_add_char(
|
||||||
|
serial_svc->svc_handle,
|
||||||
|
UUID_TYPE_128,
|
||||||
|
(const Char_UUID_t*)rpc_status_uuid,
|
||||||
|
sizeof(SerialServiceRpcStatus),
|
||||||
|
CHAR_PROP_READ | CHAR_PROP_WRITE | CHAR_PROP_NOTIFY,
|
||||||
|
ATTR_PERMISSION_AUTHEN_READ | ATTR_PERMISSION_AUTHEN_WRITE,
|
||||||
|
GATT_NOTIFY_ATTRIBUTE_WRITE,
|
||||||
|
10,
|
||||||
|
CHAR_VALUE_LEN_CONSTANT,
|
||||||
|
&serial_svc->rpc_status_char_handle);
|
||||||
|
if(status) {
|
||||||
|
FURI_LOG_E(TAG, "Failed to add RPC status characteristic: %d", status);
|
||||||
|
}
|
||||||
|
serial_svc_update_rpc_char(SerialServiceRpcStatusNotActive);
|
||||||
// Allocate buffer size mutex
|
// Allocate buffer size mutex
|
||||||
serial_svc->buff_size_mtx = furi_mutex_alloc(FuriMutexTypeNormal);
|
serial_svc->buff_size_mtx = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||||
}
|
}
|
||||||
@ -198,6 +240,10 @@ void serial_svc_stop() {
|
|||||||
if(status) {
|
if(status) {
|
||||||
FURI_LOG_E(TAG, "Failed to delete Flow Control characteristic: %d", status);
|
FURI_LOG_E(TAG, "Failed to delete Flow Control characteristic: %d", status);
|
||||||
}
|
}
|
||||||
|
status = aci_gatt_del_char(serial_svc->svc_handle, serial_svc->rpc_status_char_handle);
|
||||||
|
if(status) {
|
||||||
|
FURI_LOG_E(TAG, "Failed to delete RPC Status characteristic: %d", status);
|
||||||
|
}
|
||||||
// Delete service
|
// Delete service
|
||||||
status = aci_gatt_del_service(serial_svc->svc_handle);
|
status = aci_gatt_del_service(serial_svc->svc_handle);
|
||||||
if(status) {
|
if(status) {
|
||||||
@ -242,3 +288,8 @@ bool serial_svc_update_tx(uint8_t* data, uint16_t data_len) {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void serial_svc_set_rpc_status(SerialServiceRpcStatus status) {
|
||||||
|
furi_assert(serial_svc);
|
||||||
|
serial_svc_update_rpc_char(status);
|
||||||
|
}
|
||||||
|
@ -10,9 +10,15 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SerialServiceRpcStatusNotActive = 0UL,
|
||||||
|
SerialServiceRpcStatusActive = 1UL,
|
||||||
|
} SerialServiceRpcStatus;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SerialServiceEventTypeDataReceived,
|
SerialServiceEventTypeDataReceived,
|
||||||
SerialServiceEventTypeDataSent,
|
SerialServiceEventTypeDataSent,
|
||||||
|
SerialServiceEventTypesBleResetRequest,
|
||||||
} SerialServiceEventType;
|
} SerialServiceEventType;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -34,6 +40,8 @@ void serial_svc_set_callbacks(
|
|||||||
SerialServiceEventCallback callback,
|
SerialServiceEventCallback callback,
|
||||||
void* context);
|
void* context);
|
||||||
|
|
||||||
|
void serial_svc_set_rpc_status(SerialServiceRpcStatus status);
|
||||||
|
|
||||||
void serial_svc_notify_buffer_is_empty();
|
void serial_svc_notify_buffer_is_empty();
|
||||||
|
|
||||||
void serial_svc_stop();
|
void serial_svc_stop();
|
||||||
|
@ -31,6 +31,16 @@ void furi_hal_bt_serial_notify_buffer_is_empty() {
|
|||||||
serial_svc_notify_buffer_is_empty();
|
serial_svc_notify_buffer_is_empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void furi_hal_bt_serial_set_rpc_status(FuriHalBtSerialRpcStatus status) {
|
||||||
|
SerialServiceRpcStatus st;
|
||||||
|
if(status == FuriHalBtSerialRpcStatusActive) {
|
||||||
|
st = SerialServiceRpcStatusActive;
|
||||||
|
} else {
|
||||||
|
st = SerialServiceRpcStatusNotActive;
|
||||||
|
}
|
||||||
|
serial_svc_set_rpc_status(st);
|
||||||
|
}
|
||||||
|
|
||||||
bool furi_hal_bt_serial_tx(uint8_t* data, uint16_t size) {
|
bool furi_hal_bt_serial_tx(uint8_t* data, uint16_t size) {
|
||||||
if(size > FURI_HAL_BT_SERIAL_PACKET_SIZE_MAX) {
|
if(size > FURI_HAL_BT_SERIAL_PACKET_SIZE_MAX) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -8,6 +8,11 @@ extern "C" {
|
|||||||
|
|
||||||
#define FURI_HAL_BT_SERIAL_PACKET_SIZE_MAX SERIAL_SVC_DATA_LEN_MAX
|
#define FURI_HAL_BT_SERIAL_PACKET_SIZE_MAX SERIAL_SVC_DATA_LEN_MAX
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FuriHalBtSerialRpcStatusNotActive,
|
||||||
|
FuriHalBtSerialRpcStatusActive,
|
||||||
|
} FuriHalBtSerialRpcStatus;
|
||||||
|
|
||||||
/** Serial service callback type */
|
/** Serial service callback type */
|
||||||
typedef SerialServiceEventCallback FuriHalBtSerialCallback;
|
typedef SerialServiceEventCallback FuriHalBtSerialCallback;
|
||||||
|
|
||||||
@ -30,6 +35,12 @@ void furi_hal_bt_serial_set_event_callback(
|
|||||||
FuriHalBtSerialCallback callback,
|
FuriHalBtSerialCallback callback,
|
||||||
void* context);
|
void* context);
|
||||||
|
|
||||||
|
/** Set BLE RPC status
|
||||||
|
*
|
||||||
|
* @param status FuriHalBtSerialRpcStatus instance
|
||||||
|
*/
|
||||||
|
void furi_hal_bt_serial_set_rpc_status(FuriHalBtSerialRpcStatus status);
|
||||||
|
|
||||||
/** Notify that application buffer is empty
|
/** Notify that application buffer is empty
|
||||||
*/
|
*/
|
||||||
void furi_hal_bt_serial_notify_buffer_is_empty();
|
void furi_hal_bt_serial_notify_buffer_is_empty();
|
||||||
|
Loading…
Reference in New Issue
Block a user