mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-03-12 14:16:06 +00:00
feat(core): add BLE to bootloader
[no changelog]
This commit is contained in:
parent
e997dcea32
commit
5a68da1d23
@ -11,7 +11,7 @@ PRODUCTION = 0 if BOOTLOADER_QA else ARGUMENTS.get('PRODUCTION', '0') == '1'
|
|||||||
HW_REVISION = ARGUMENTS.get('HW_REVISION', None)
|
HW_REVISION = ARGUMENTS.get('HW_REVISION', None)
|
||||||
UI_DEBUG_OVERLAY = ARGUMENTS.get('UI_DEBUG_OVERLAY', '0') == '1'
|
UI_DEBUG_OVERLAY = ARGUMENTS.get('UI_DEBUG_OVERLAY', '0') == '1'
|
||||||
|
|
||||||
FEATURES_WANTED = ["input", "rgb_led", "consumption_mask", "usb", "optiga", "dma2d"]
|
FEATURES_WANTED = ["input", "rgb_led", "consumption_mask", "usb", "optiga", "dma2d", "ble"]
|
||||||
|
|
||||||
CCFLAGS_MOD = ''
|
CCFLAGS_MOD = ''
|
||||||
CPPPATH_MOD = []
|
CPPPATH_MOD = []
|
||||||
@ -116,8 +116,10 @@ SOURCE_BOOTLOADER = [
|
|||||||
'embed/projects/bootloader/workflow/wf_empty_device.c',
|
'embed/projects/bootloader/workflow/wf_empty_device.c',
|
||||||
'embed/projects/bootloader/workflow/wf_auto_update.c',
|
'embed/projects/bootloader/workflow/wf_auto_update.c',
|
||||||
'embed/projects/bootloader/workflow/wf_host_control.c',
|
'embed/projects/bootloader/workflow/wf_host_control.c',
|
||||||
|
'embed/projects/bootloader/workflow/wf_ble_pairing_request.c',
|
||||||
'embed/projects/bootloader/wire/codec_v1.c',
|
'embed/projects/bootloader/wire/codec_v1.c',
|
||||||
'embed/projects/bootloader/wire/wire_iface_usb.c',
|
'embed/projects/bootloader/wire/wire_iface_usb.c',
|
||||||
|
'embed/projects/bootloader/wire/wire_iface_ble.c',
|
||||||
'embed/projects/bootloader/protob/protob.c',
|
'embed/projects/bootloader/protob/protob.c',
|
||||||
'embed/projects/bootloader/protob/pb/messages.pb.c',
|
'embed/projects/bootloader/protob/pb/messages.pb.c',
|
||||||
'embed/projects/bootloader/version_check.c',
|
'embed/projects/bootloader/version_check.c',
|
||||||
|
@ -59,6 +59,9 @@
|
|||||||
#ifdef USE_TAMPER
|
#ifdef USE_TAMPER
|
||||||
#include <sys/tamper.h>
|
#include <sys/tamper.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef USE_BLE
|
||||||
|
#include <io/ble.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "antiglitch.h"
|
#include "antiglitch.h"
|
||||||
#include "bootui.h"
|
#include "bootui.h"
|
||||||
@ -122,6 +125,9 @@ static void drivers_init(secbool *touch_initialized) {
|
|||||||
#ifdef USE_RGB_LED
|
#ifdef USE_RGB_LED
|
||||||
rgb_led_init();
|
rgb_led_init();
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef USE_BLE
|
||||||
|
ble_init();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drivers_deinit(void) {
|
static void drivers_deinit(void) {
|
||||||
|
@ -18,17 +18,30 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <trezor_bsp.h>
|
#include <trezor_bsp.h>
|
||||||
|
#include <trezor_rtl.h>
|
||||||
|
|
||||||
#include "poll.h"
|
#include "poll.h"
|
||||||
|
|
||||||
#include <io/usb.h>
|
#include <io/usb.h>
|
||||||
#include <sys/systick.h>
|
#include <sys/systick.h>
|
||||||
|
|
||||||
|
#ifdef USE_BLE
|
||||||
|
#include <io/ble.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_BUTTON
|
||||||
|
#include <io/button.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_TOUCH
|
||||||
|
#include <io/touch.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef TREZOR_EMULATOR
|
#ifdef TREZOR_EMULATOR
|
||||||
#include "SDL.h"
|
#include "SDL.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint8_t poll_events(const uint16_t* ifaces, size_t ifaces_num,
|
int16_t poll_events(const uint16_t* ifaces, size_t ifaces_num,
|
||||||
poll_event_t* event, uint32_t timeout_ms) {
|
poll_event_t* event, uint32_t timeout_ms) {
|
||||||
uint32_t deadline = ticks_timeout(timeout_ms);
|
uint32_t deadline = ticks_timeout(timeout_ms);
|
||||||
|
|
||||||
@ -45,11 +58,41 @@ uint8_t poll_events(const uint16_t* ifaces, size_t ifaces_num,
|
|||||||
if ((ifaces[i] & MODE_READ) == MODE_READ) {
|
if ((ifaces[i] & MODE_READ) == MODE_READ) {
|
||||||
// check if USB can read
|
// check if USB can read
|
||||||
if (sectrue == usb_webusb_can_read(iface_num)) {
|
if (sectrue == usb_webusb_can_read(iface_num)) {
|
||||||
event->type = EVENT_USB_CAN_READ;
|
event->event.usb_data_event = EVENT_USB_CAN_READ;
|
||||||
return iface_num;
|
return iface_num;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef USE_BLE
|
||||||
|
if (iface_num == IFACE_BLE) {
|
||||||
|
if ((ifaces[i] & MODE_READ) == MODE_READ) {
|
||||||
|
// check if BLE can read
|
||||||
|
if (ble_can_read()) {
|
||||||
|
event->event.ble_data_event = EVENT_BLE_CAN_READ;
|
||||||
|
return iface_num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (iface_num == IFACE_BLE_EVENT) {
|
||||||
|
ble_event_t ble_event = {0};
|
||||||
|
if (ble_get_event(&ble_event)) {
|
||||||
|
memcpy(&event->event.ble_event, &ble_event, sizeof(ble_event_t));
|
||||||
|
return iface_num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef USE_BUTTON
|
||||||
|
if (iface_num == IFACE_BUTTON) {
|
||||||
|
uint32_t btn_event = button_get_event();
|
||||||
|
uint32_t etype = (btn_event >> 24) & 0x3U; // button down/up
|
||||||
|
uint32_t btn_number = btn_event & 0xFFFF;
|
||||||
|
if (etype != 0) {
|
||||||
|
event->event.button_event.type = etype;
|
||||||
|
event->event.button_event.button = btn_number;
|
||||||
|
return iface_num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef TREZOR_EMULATOR
|
#ifndef TREZOR_EMULATOR
|
||||||
@ -57,6 +100,5 @@ uint8_t poll_events(const uint16_t* ifaces, size_t ifaces_num,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
event->type = EVENT_NONE;
|
return -1;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
@ -21,19 +21,55 @@
|
|||||||
|
|
||||||
#include <trezor_types.h>
|
#include <trezor_types.h>
|
||||||
|
|
||||||
|
#include <io/usb.h>
|
||||||
|
|
||||||
|
#ifdef USE_BLE
|
||||||
|
#include <io/ble.h>
|
||||||
|
#endif
|
||||||
|
#ifdef USE_BUTTON
|
||||||
|
#include <io/button.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define IFACE_USB_MAX (15) // 0-15 reserved for USB
|
#define IFACE_USB_MAX (15) // 0-15 reserved for USB
|
||||||
|
#define IFACE_BLE (16)
|
||||||
|
#define IFACE_BLE_EVENT (252)
|
||||||
|
#define IFACE_BUTTON (254)
|
||||||
|
#define IFACE_TOUCH (255)
|
||||||
|
|
||||||
#define MODE_READ 0x0000
|
#define MODE_READ 0x0000
|
||||||
#define MODE_WRITE 0x0100
|
#define MODE_WRITE 0x0100
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
EVENT_NONE = 0,
|
EVENT_USB_CAN_READ,
|
||||||
EVENT_USB_CAN_READ = 0x01,
|
} usb_data_event_type_t;
|
||||||
} poll_event_type_t;
|
|
||||||
|
#ifdef USE_BLE
|
||||||
|
typedef enum {
|
||||||
|
EVENT_BLE_CAN_READ,
|
||||||
|
} ble_data_event_type_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_BUTTON
|
||||||
|
typedef struct {
|
||||||
|
uint32_t type;
|
||||||
|
button_t button;
|
||||||
|
} button_event_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
poll_event_type_t type;
|
union {
|
||||||
|
usb_data_event_type_t usb_data_event;
|
||||||
|
usb_event_t usb_event;
|
||||||
|
#ifdef USE_BLE
|
||||||
|
ble_data_event_type_t ble_data_event;
|
||||||
|
ble_event_t ble_event;
|
||||||
|
#endif
|
||||||
|
#ifdef USE_BUTTON
|
||||||
|
button_event_t button_event;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} event;
|
||||||
} poll_event_t;
|
} poll_event_t;
|
||||||
|
|
||||||
uint8_t poll_events(const uint16_t* ifaces, size_t ifaces_num,
|
int16_t poll_events(const uint16_t* ifaces, size_t ifaces_num,
|
||||||
poll_event_t* event, uint32_t timeout_ms);
|
poll_event_t* event, uint32_t timeout_ms);
|
||||||
|
116
core/embed/projects/bootloader/wire/wire_iface_ble.c
Normal file
116
core/embed/projects/bootloader/wire/wire_iface_ble.c
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Trezor project, https://trezor.io/
|
||||||
|
*
|
||||||
|
* Copyright (c) SatoshiLabs
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <trezor_model.h>
|
||||||
|
#include <trezor_rtl.h>
|
||||||
|
|
||||||
|
#include "wire_iface_ble.h"
|
||||||
|
|
||||||
|
#include <io/ble.h>
|
||||||
|
#include <sys/systick.h>
|
||||||
|
|
||||||
|
static bool ble_write_(uint8_t* data, size_t size) {
|
||||||
|
if (size != BLE_TX_PACKET_SIZE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t deadline = ticks_timeout(500);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (ticks_expired(deadline)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (ble_can_write()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ble_write(data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ble_read_(uint8_t* buffer, size_t buffer_size) {
|
||||||
|
if (buffer_size != BLE_RX_PACKET_SIZE) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t deadline = ticks_timeout(500);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (ticks_expired(deadline)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (ble_can_read()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int r = ble_read(buffer, buffer_size);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ble_error(void) {
|
||||||
|
error_shutdown_ex("BLE ERROR",
|
||||||
|
"Error reading from BLE. Try different BLE cable.", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ble_iface_init(wire_iface_t* iface) {
|
||||||
|
ble_start();
|
||||||
|
|
||||||
|
memset(iface, 0, sizeof(wire_iface_t));
|
||||||
|
|
||||||
|
iface->poll_iface_id = 16;
|
||||||
|
iface->tx_packet_size = BLE_TX_PACKET_SIZE;
|
||||||
|
iface->rx_packet_size = BLE_RX_PACKET_SIZE;
|
||||||
|
iface->write = &ble_write_;
|
||||||
|
iface->read = &ble_read_;
|
||||||
|
iface->error = &ble_error;
|
||||||
|
|
||||||
|
ble_start();
|
||||||
|
|
||||||
|
ble_state_t state = {0};
|
||||||
|
|
||||||
|
ble_get_state(&state);
|
||||||
|
|
||||||
|
if (!state.connectable && !state.pairing) {
|
||||||
|
if (state.peer_count > 0) {
|
||||||
|
ble_command_t cmd = {
|
||||||
|
.cmd_type = BLE_SWITCH_ON,
|
||||||
|
};
|
||||||
|
ble_issue_command(&cmd);
|
||||||
|
} else {
|
||||||
|
ble_iface_start_pairing();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ble_iface_deinit(wire_iface_t* iface) { ble_stop(); }
|
||||||
|
|
||||||
|
void ble_iface_start_pairing(void) {
|
||||||
|
ble_command_t cmd = {
|
||||||
|
.cmd_type = BLE_PAIRING_MODE,
|
||||||
|
.data = {.adv_start =
|
||||||
|
{
|
||||||
|
.name = "Trezor Bootloader",
|
||||||
|
.static_mac = false,
|
||||||
|
}},
|
||||||
|
.data_len = 0,
|
||||||
|
};
|
||||||
|
ble_issue_command(&cmd);
|
||||||
|
}
|
28
core/embed/projects/bootloader/wire/wire_iface_ble.h
Normal file
28
core/embed/projects/bootloader/wire/wire_iface_ble.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Trezor project, https://trezor.io/
|
||||||
|
*
|
||||||
|
* Copyright (c) SatoshiLabs
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "codec_v1.h"
|
||||||
|
|
||||||
|
void ble_iface_init(wire_iface_t* iface);
|
||||||
|
|
||||||
|
void ble_iface_deinit(wire_iface_t* iface);
|
||||||
|
|
||||||
|
void ble_iface_start_pairing(void);
|
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Trezor project, https://trezor.io/
|
||||||
|
*
|
||||||
|
* Copyright (c) SatoshiLabs
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#ifdef USE_BLE
|
||||||
|
|
||||||
|
#include <trezor_model.h>
|
||||||
|
#include <trezor_rtl.h>
|
||||||
|
|
||||||
|
#include <io/ble.h>
|
||||||
|
|
||||||
|
#include "bootui.h"
|
||||||
|
#include "rust_ui_bootloader.h"
|
||||||
|
#include "workflow.h"
|
||||||
|
|
||||||
|
workflow_result_t workflow_ble_pairing_request(const uint8_t *data) {
|
||||||
|
ui_result_t result = screen_confirm_pairing(data);
|
||||||
|
|
||||||
|
if (result == UI_RESULT_CONFIRM) {
|
||||||
|
ble_command_t cmd = {
|
||||||
|
.cmd_type = BLE_ALLOW_PAIRING,
|
||||||
|
};
|
||||||
|
ble_issue_command(&cmd);
|
||||||
|
} else {
|
||||||
|
ble_command_t cmd = {
|
||||||
|
.cmd_type = BLE_REJECT_PAIRING,
|
||||||
|
};
|
||||||
|
ble_issue_command(&cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
screen_connect(false);
|
||||||
|
return WF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -521,9 +521,9 @@ workflow_result_t workflow_firmware_update(protob_io_t *iface) {
|
|||||||
while (true) {
|
while (true) {
|
||||||
uint16_t ifaces[1] = {protob_get_iface_flag(iface) | MODE_READ};
|
uint16_t ifaces[1] = {protob_get_iface_flag(iface) | MODE_READ};
|
||||||
poll_event_t e = {0};
|
poll_event_t e = {0};
|
||||||
uint8_t i = poll_events(ifaces, 1, &e, 100);
|
uint16_t i = poll_events(ifaces, 1, &e, 100);
|
||||||
|
|
||||||
if (e.type == EVENT_NONE || i != protob_get_iface_flag(iface)) {
|
if (i < 0 || i != protob_get_iface_flag(iface)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,11 +30,21 @@
|
|||||||
#include "wire/wire_iface_usb.h"
|
#include "wire/wire_iface_usb.h"
|
||||||
#include "workflow.h"
|
#include "workflow.h"
|
||||||
|
|
||||||
|
#ifdef USE_BLE
|
||||||
|
#include <wire/wire_iface_ble.h>
|
||||||
|
|
||||||
|
#ifdef USE_BUTTON
|
||||||
|
#include <io/button.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
workflow_result_t workflow_host_control(const vendor_header *const vhdr,
|
workflow_result_t workflow_host_control(const vendor_header *const vhdr,
|
||||||
const image_header *const hdr,
|
const image_header *const hdr,
|
||||||
void (*redraw_wait_screen)(void)) {
|
void (*redraw_wait_screen)(void)) {
|
||||||
wire_iface_t usb_iface = {0};
|
wire_iface_t usb_iface = {0};
|
||||||
|
wire_iface_t ble_iface = {0};
|
||||||
protob_io_t protob_usb_iface = {0};
|
protob_io_t protob_usb_iface = {0};
|
||||||
|
protob_io_t protob_ble_iface = {0};
|
||||||
|
|
||||||
redraw_wait_screen();
|
redraw_wait_screen();
|
||||||
|
|
||||||
@ -43,31 +53,89 @@ workflow_result_t workflow_host_control(const vendor_header *const vhdr,
|
|||||||
usb_iface_init(&usb_iface,
|
usb_iface_init(&usb_iface,
|
||||||
(vhdr == NULL && hdr == NULL) ? sectrue : secfalse);
|
(vhdr == NULL && hdr == NULL) ? sectrue : secfalse);
|
||||||
|
|
||||||
|
ble_iface_init(&ble_iface);
|
||||||
|
|
||||||
protob_init(&protob_usb_iface, &usb_iface);
|
protob_init(&protob_usb_iface, &usb_iface);
|
||||||
|
protob_init(&protob_ble_iface, &ble_iface);
|
||||||
|
|
||||||
workflow_result_t result = WF_ERROR_FATAL;
|
workflow_result_t result = WF_ERROR_FATAL;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
uint16_t ifaces[1] = {protob_get_iface_flag(&protob_usb_iface) | MODE_READ};
|
uint16_t ifaces[] = {
|
||||||
|
protob_get_iface_flag(&protob_usb_iface) | MODE_READ,
|
||||||
|
#ifdef USE_BLE
|
||||||
|
protob_get_iface_flag(&protob_ble_iface) | MODE_READ,
|
||||||
|
IFACE_BLE_EVENT,
|
||||||
|
#ifdef USE_BUTTON
|
||||||
|
IFACE_BUTTON,
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
poll_event_t e = {0};
|
poll_event_t e = {0};
|
||||||
|
|
||||||
uint8_t i = poll_events(ifaces, 1, &e, 100);
|
int16_t i = poll_events(ifaces, ARRAY_LENGTH(ifaces), &e, 100);
|
||||||
|
|
||||||
|
if (i < 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t msg_id = 0;
|
uint16_t msg_id = 0;
|
||||||
protob_io_t *active_iface = NULL;
|
protob_io_t *active_iface = NULL;
|
||||||
|
|
||||||
switch (e.type) {
|
if (i < IFACE_USB_MAX) {
|
||||||
case EVENT_USB_CAN_READ:
|
switch (e.event.usb_data_event) {
|
||||||
if (i == protob_get_iface_flag(&protob_usb_iface) &&
|
case EVENT_USB_CAN_READ:
|
||||||
sectrue == protob_get_msg_header(&protob_usb_iface, &msg_id)) {
|
if (i == protob_get_iface_flag(&protob_usb_iface) &&
|
||||||
active_iface = &protob_usb_iface;
|
sectrue == protob_get_msg_header(&protob_usb_iface, &msg_id)) {
|
||||||
} else {
|
active_iface = &protob_usb_iface;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case EVENT_NONE:
|
#ifdef USE_BLE
|
||||||
default:
|
if (i == IFACE_BLE) {
|
||||||
continue;
|
switch (e.event.ble_data_event) {
|
||||||
|
case EVENT_BLE_CAN_READ:
|
||||||
|
if (i == protob_get_iface_flag(&protob_ble_iface) &&
|
||||||
|
sectrue == protob_get_msg_header(&protob_ble_iface, &msg_id)) {
|
||||||
|
active_iface = &protob_ble_iface;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == IFACE_BLE_EVENT) {
|
||||||
|
switch (e.event.ble_event.type) {
|
||||||
|
case BLE_PAIRING_REQUEST:
|
||||||
|
workflow_ble_pairing_request(e.event.ble_event.data);
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef USE_BUTTON
|
||||||
|
if (i == IFACE_BUTTON) {
|
||||||
|
switch (e.event.button_event.type) {
|
||||||
|
case (BTN_EVT_DOWN >> 24):
|
||||||
|
ble_iface_start_pairing();
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (active_iface == NULL) {
|
||||||
|
continue;
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (msg_id) {
|
switch (msg_id) {
|
||||||
|
@ -66,3 +66,7 @@ workflow_result_t workflow_host_control(const vendor_header *const vhdr,
|
|||||||
|
|
||||||
workflow_result_t workflow_auto_update(const vendor_header *const vhdr,
|
workflow_result_t workflow_auto_update(const vendor_header *const vhdr,
|
||||||
const image_header *const hdr);
|
const image_header *const hdr);
|
||||||
|
|
||||||
|
#ifdef USE_BLE
|
||||||
|
workflow_result_t workflow_ble_pairing_request(const uint8_t *data);
|
||||||
|
#endif
|
||||||
|
@ -27,3 +27,5 @@ void bld_continue_label(uint16_t bg_color);
|
|||||||
void screen_boot(bool warning, const char* vendor_str, size_t vendor_str_len,
|
void screen_boot(bool warning, const char* vendor_str, size_t vendor_str_len,
|
||||||
uint32_t version, const void* vendor_img,
|
uint32_t version, const void* vendor_img,
|
||||||
size_t vendor_img_len, int wait);
|
size_t vendor_img_len, int wait);
|
||||||
|
|
||||||
|
uint32_t screen_confirm_pairing(const uint8_t* code);
|
||||||
|
@ -144,3 +144,10 @@ extern "C" fn screen_wipe_success() {
|
|||||||
extern "C" fn screen_wipe_fail() {
|
extern "C" fn screen_wipe_fail() {
|
||||||
ModelUI::screen_wipe_fail()
|
ModelUI::screen_wipe_fail()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn screen_confirm_pairing(code: *const cty::c_char) -> u32 {
|
||||||
|
let code = unwrap!(unsafe { from_c_array(code, 6) });
|
||||||
|
|
||||||
|
ModelUI::screen_confirm_pairing(code)
|
||||||
|
}
|
||||||
|
@ -439,4 +439,18 @@ impl BootloaderUI for UIBolt {
|
|||||||
|
|
||||||
display::refresh();
|
display::refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ble")]
|
||||||
|
fn screen_confirm_pairing(code: &str) -> u32 {
|
||||||
|
let title = Label::centered("Pair device".into(), TEXT_NORMAL);
|
||||||
|
|
||||||
|
let msg = Label::centered(code.into(), TEXT_NORMAL);
|
||||||
|
|
||||||
|
let right = Button::with_text("CONFIRM".into()).styled(button_confirm());
|
||||||
|
let left = Button::with_text("REJECT".into()).styled(button_bld());
|
||||||
|
|
||||||
|
let mut frame = Confirm::new(BLD_BG, left, right, ConfirmTitle::Text(title), msg);
|
||||||
|
|
||||||
|
run(&mut frame)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,4 +48,7 @@ pub trait BootloaderUI {
|
|||||||
vendor_img: &'static [u8],
|
vendor_img: &'static [u8],
|
||||||
wait: i32,
|
wait: i32,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#[cfg(feature = "ble")]
|
||||||
|
fn screen_confirm_pairing(code: &str) -> u32;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user