Merge branch 'dev' into release-candidate

This commit is contained in:
Aleksandr Kutuzov 2022-03-24 16:59:28 +03:00
commit c02d8beed9
No known key found for this signature in database
GPG Key ID: 0D0011717914BBCD
305 changed files with 5828 additions and 31785 deletions

View File

@ -6,7 +6,7 @@
- [ Describe how to verify changes ]
# Checklist (do not modify)
# Checklist (For Reviewer)
- [ ] PR has description of feature/bug or link to Confluence/Jira task
- [ ] Description contains actions to verify feature/bugfix

View File

@ -10,7 +10,7 @@ on:
pull_request:
env:
TARGETS: f6 f7
TARGETS: f7
DEFAULT_TARGET: f7
jobs:

View File

@ -10,7 +10,7 @@ on:
pull_request:
env:
TARGETS: f6 f7
TARGETS: f7
jobs:
lint_c_cpp:

View File

@ -1,7 +1,8 @@
cask "gcc-arm-embedded"
brew "protobuf"
brew "gdb"
brew "heatshrink"
brew "open-ocd"
brew "clang-format"
brew "dfu-util"
brew "imagemagick"
brew "imagemagick"

View File

@ -115,15 +115,10 @@ void bad_usb_app_free(BadUsbApp* app) {
}
int32_t bad_usb_app(void* p) {
FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config();
furi_hal_usb_set_config(&usb_hid);
BadUsbApp* bad_usb_app = bad_usb_app_alloc((char*)p);
view_dispatcher_run(bad_usb_app->view_dispatcher);
furi_hal_usb_set_config(usb_mode_prev);
bad_usb_app_free(bad_usb_app);
return 0;
}

View File

@ -24,6 +24,7 @@ typedef enum {
} WorkerEvtFlags;
struct BadUsbScript {
FuriHalUsbHidConfig hid_cfg;
BadUsbState st;
string_t file_path;
uint32_t defdelay;
@ -101,6 +102,7 @@ static const DuckyKey ducky_keys[] = {
};
static const char ducky_cmd_comment[] = {"REM"};
static const char ducky_cmd_id[] = {"ID"};
static const char ducky_cmd_delay[] = {"DELAY "};
static const char ducky_cmd_string[] = {"STRING "};
static const char ducky_cmd_defdelay_1[] = {"DEFAULT_DELAY "};
@ -240,12 +242,15 @@ static int32_t ducky_parse_line(BadUsbScript* bad_usb, string_t line) {
if(i == line_len - 1) return SCRIPT_STATE_NEXT_LINE; // Skip empty lines
}
FURI_LOG_I(WORKER_TAG, "line:%s", line_tmp);
FURI_LOG_D(WORKER_TAG, "line:%s", line_tmp);
// General commands
if(strncmp(line_tmp, ducky_cmd_comment, strlen(ducky_cmd_comment)) == 0) {
// REM - comment line
return (0);
} else if(strncmp(line_tmp, ducky_cmd_id, strlen(ducky_cmd_id)) == 0) {
// ID - executed in ducky_script_preload
return (0);
} else if(strncmp(line_tmp, ducky_cmd_delay, strlen(ducky_cmd_delay)) == 0) {
// DELAY
line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1];
@ -302,10 +307,37 @@ static int32_t ducky_parse_line(BadUsbScript* bad_usb, string_t line) {
return SCRIPT_STATE_ERROR;
}
static bool ducky_set_usb_id(BadUsbScript* bad_usb, const char* line) {
if(sscanf(line, "%lX:%lX", &bad_usb->hid_cfg.vid, &bad_usb->hid_cfg.pid) == 2) {
bad_usb->hid_cfg.manuf[0] = '\0';
bad_usb->hid_cfg.product[0] = '\0';
uint8_t id_len = ducky_get_command_len(line);
if(!ducky_is_line_end(line[id_len + 1])) {
sscanf(
&line[id_len + 1],
"%31[^\r\n:]:%31[^\r\n]",
bad_usb->hid_cfg.manuf,
bad_usb->hid_cfg.product);
}
FURI_LOG_D(
WORKER_TAG,
"set id: %04X:%04X mfr:%s product:%s",
bad_usb->hid_cfg.vid,
bad_usb->hid_cfg.pid,
bad_usb->hid_cfg.manuf,
bad_usb->hid_cfg.product);
return true;
}
return false;
}
static bool ducky_script_preload(BadUsbScript* bad_usb, File* script_file) {
uint8_t ret = 0;
uint32_t line_len = 0;
string_reset(bad_usb->line);
do {
ret = storage_file_read(script_file, bad_usb->file_buf, FILE_BUFFER_LEN);
for(uint16_t i = 0; i < ret; i++) {
@ -313,6 +345,9 @@ static bool ducky_script_preload(BadUsbScript* bad_usb, File* script_file) {
bad_usb->st.line_nb++;
line_len = 0;
} else {
if(bad_usb->st.line_nb == 0) { // Save first line
string_push_back(bad_usb->line, bad_usb->file_buf[i]);
}
line_len++;
}
}
@ -324,7 +359,20 @@ static bool ducky_script_preload(BadUsbScript* bad_usb, File* script_file) {
}
} while(ret > 0);
const char* line_tmp = string_get_cstr(bad_usb->line);
bool id_set = false; // Looking for ID command at first line
if(strncmp(line_tmp, ducky_cmd_id, strlen(ducky_cmd_id)) == 0) {
id_set = ducky_set_usb_id(bad_usb, &line_tmp[strlen(ducky_cmd_id) + 1]);
}
if(id_set) {
furi_hal_usb_set_config(&usb_hid, &bad_usb->hid_cfg);
} else {
furi_hal_usb_set_config(&usb_hid, NULL);
}
storage_file_seek(script_file, 0, true);
string_reset(bad_usb->line);
return true;
}
@ -403,6 +451,8 @@ static int32_t bad_usb_worker(void* context) {
BadUsbWorkerState worker_state = BadUsbStateInit;
int32_t delay_val = 0;
FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config();
FURI_LOG_I(WORKER_TAG, "Init");
File* script_file = storage_file_alloc(furi_record_open("storage"));
string_init(bad_usb->line);
@ -522,6 +572,8 @@ static int32_t bad_usb_worker(void* context) {
furi_hal_hid_set_state_callback(NULL, NULL);
furi_hal_usb_set_config(usb_mode_prev, NULL);
storage_file_close(script_file);
storage_file_free(script_file);
string_clear(bad_usb->line);

View File

@ -42,7 +42,7 @@ int32_t usb_mouse_app(void* p) {
ViewPort* view_port = view_port_alloc();
FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config();
furi_hal_usb_set_config(&usb_hid);
furi_hal_usb_set_config(&usb_hid, NULL);
view_port_draw_callback_set(view_port, usb_mouse_render_callback, NULL);
view_port_input_callback_set(view_port, usb_mouse_input_callback, event_queue);
@ -110,7 +110,7 @@ int32_t usb_mouse_app(void* p) {
view_port_update(view_port);
}
furi_hal_usb_set_config(usb_mode_prev);
furi_hal_usb_set_config(usb_mode_prev, NULL);
// remove & free all stuff created by app
gui_remove_view_port(gui, view_port);

View File

@ -10,6 +10,7 @@ typedef struct {
Gui* gui;
ViewDispatcher* view_dispatcher;
Submenu* submenu;
FuriHalUsbHidConfig hid_cfg;
} UsbTestApp;
typedef enum {
@ -19,12 +20,13 @@ typedef enum {
UsbTestSubmenuIndexVcpSingle,
UsbTestSubmenuIndexVcpDual,
UsbTestSubmenuIndexHid,
UsbTestSubmenuIndexHidWithParams,
UsbTestSubmenuIndexHidU2F,
} SubmenuIndex;
void usb_test_submenu_callback(void* context, uint32_t index) {
furi_assert(context);
//UsbTestApp* app = context;
UsbTestApp* app = context;
if(index == UsbTestSubmenuIndexEnable) {
furi_hal_usb_enable();
} else if(index == UsbTestSubmenuIndexDisable) {
@ -32,13 +34,19 @@ void usb_test_submenu_callback(void* context, uint32_t index) {
} else if(index == UsbTestSubmenuIndexRestart) {
furi_hal_usb_reinit();
} else if(index == UsbTestSubmenuIndexVcpSingle) {
furi_hal_usb_set_config(&usb_cdc_single);
furi_hal_usb_set_config(&usb_cdc_single, NULL);
} else if(index == UsbTestSubmenuIndexVcpDual) {
furi_hal_usb_set_config(&usb_cdc_dual);
furi_hal_usb_set_config(&usb_cdc_dual, NULL);
} else if(index == UsbTestSubmenuIndexHid) {
furi_hal_usb_set_config(&usb_hid);
furi_hal_usb_set_config(&usb_hid, NULL);
} else if(index == UsbTestSubmenuIndexHidWithParams) {
app->hid_cfg.vid = 0x1234;
app->hid_cfg.pid = 0xabcd;
strncpy(app->hid_cfg.manuf, "WEN", sizeof(app->hid_cfg.manuf));
strncpy(app->hid_cfg.product, "FLIP", sizeof(app->hid_cfg.product));
furi_hal_usb_set_config(&usb_hid, &app->hid_cfg);
} else if(index == UsbTestSubmenuIndexHidU2F) {
furi_hal_usb_set_config(&usb_hid_u2f);
furi_hal_usb_set_config(&usb_hid_u2f, NULL);
}
}
@ -71,6 +79,12 @@ UsbTestApp* usb_test_app_alloc() {
app->submenu, "Dual VCP", UsbTestSubmenuIndexVcpDual, usb_test_submenu_callback, app);
submenu_add_item(
app->submenu, "HID KB+Mouse", UsbTestSubmenuIndexHid, usb_test_submenu_callback, app);
submenu_add_item(
app->submenu,
"HID KB+Mouse custom ID",
UsbTestSubmenuIndexHidWithParams,
usb_test_submenu_callback,
app);
submenu_add_item(
app->submenu, "HID U2F", UsbTestSubmenuIndexHidU2F, usb_test_submenu_callback, app);
view_set_previous_callback(submenu_get_view(app->submenu), usb_test_exit);

View File

@ -48,6 +48,7 @@ static void desktop_scene_main_interact_animation_callback(void* context) {
desktop->view_dispatcher, DesktopAnimationEventInteractAnimation);
}
#ifdef APP_ARCHIVE
static void desktop_switch_to_app(Desktop* desktop, const FlipperApplication* flipper_app) {
furi_assert(desktop);
furi_assert(flipper_app);
@ -65,6 +66,7 @@ static void desktop_switch_to_app(Desktop* desktop, const FlipperApplication* fl
furi_thread_start(desktop->scene_thread);
}
#endif
void desktop_scene_main_callback(DesktopEvent event, void* context) {
Desktop* desktop = (Desktop*)context;

View File

@ -84,10 +84,10 @@ static void usb_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
static void usb_uart_vcp_init(UsbUartBridge* usb_uart, uint8_t vcp_ch) {
if(vcp_ch == 0) {
furi_hal_usb_set_config(&usb_cdc_single);
furi_hal_usb_set_config(&usb_cdc_single, NULL);
furi_hal_vcp_disable();
} else {
furi_hal_usb_set_config(&usb_cdc_dual);
furi_hal_usb_set_config(&usb_cdc_dual, NULL);
}
furi_hal_cdc_set_callbacks(vcp_ch, (CdcCallbacks*)&cdc_cb, usb_uart);
}
@ -247,7 +247,7 @@ static int32_t usb_uart_worker(void* context) {
usb_uart_vcp_deinit(usb_uart, usb_uart->cfg.vcp_ch);
usb_uart_serial_deinit(usb_uart, usb_uart->cfg.uart_ch);
furi_hal_usb_set_config(usb_mode_prev);
furi_hal_usb_set_config(usb_mode_prev, NULL);
if(usb_uart->cfg.flow_pins != 0) {
hal_gpio_init_simple(flow_pins[usb_uart->cfg.flow_pins - 1][0], GpioModeAnalog);
hal_gpio_init_simple(flow_pins[usb_uart->cfg.flow_pins - 1][1], GpioModeAnalog);

View File

@ -57,17 +57,18 @@ static void text_box_insert_endline(Canvas* canvas, TextBoxModel* model) {
const char* str = model->text;
size_t line_num = 0;
const size_t text_width = 140;
const size_t text_width = 120;
while(str[i] != '\0') {
char symb = str[i++];
if(symb != '\n') {
line_width += canvas_glyph_width(canvas, symb) + 1;
if(line_width > text_width) {
size_t glyph_width = canvas_glyph_width(canvas, symb);
if(line_width + glyph_width > text_width) {
line_num++;
line_width = 0;
string_push_back(model->text_formatted, '\n');
}
line_width += glyph_width;
} else {
line_num++;
line_width = 0;
@ -94,18 +95,19 @@ static void text_box_insert_endline(Canvas* canvas, TextBoxModel* model) {
static void text_box_view_draw_callback(Canvas* canvas, void* _model) {
TextBoxModel* model = _model;
if(!model->formatted) {
text_box_insert_endline(canvas, model);
model->formatted = true;
}
canvas_clear(canvas);
elements_slightly_rounded_frame(canvas, 0, 0, 124, 64);
if(model->font == TextBoxFontText) {
canvas_set_font(canvas, FontSecondary);
} else if(model->font == TextBoxFontHex) {
canvas_set_font(canvas, FontKeyboard);
}
if(!model->formatted) {
text_box_insert_endline(canvas, model);
model->formatted = true;
}
elements_slightly_rounded_frame(canvas, 0, 0, 124, 64);
elements_multiline_text(canvas, 3, 11, model->text_pos);
elements_scrollbar(canvas, model->scroll_pos, model->scroll_num);
}

233
applications/gui/modules/text_input.c Executable file → Normal file
View File

@ -131,7 +131,11 @@ static const bool char_is_lowercase(char letter) {
}
static const char char_to_uppercase(const char letter) {
return (letter - 0x20);
if(isalpha(letter)) {
return (letter - 0x20);
} else {
return letter;
}
}
static void text_input_backspace_cb(TextInputModel* model) {
@ -255,145 +259,158 @@ static void text_input_view_draw_callback(Canvas* canvas, void* _model) {
}
}
static void text_input_handle_up(TextInput* text_input) {
with_view_model(
text_input->view, (TextInputModel * model) {
if(model->selected_row > 0) {
model->selected_row--;
if(model->selected_column > get_row_size(model->selected_row) - 6) {
model->selected_column = model->selected_column + 1;
}
}
return true;
});
static void text_input_handle_up(TextInput* text_input, TextInputModel* model) {
if(model->selected_row > 0) {
model->selected_row--;
if(model->selected_column > get_row_size(model->selected_row) - 6) {
model->selected_column = model->selected_column + 1;
}
}
}
static void text_input_handle_down(TextInput* text_input) {
with_view_model(
text_input->view, (TextInputModel * model) {
if(model->selected_row < keyboard_row_count - 1) {
model->selected_row++;
if(model->selected_column > get_row_size(model->selected_row) - 4) {
model->selected_column = model->selected_column - 1;
}
}
return true;
});
static void text_input_handle_down(TextInput* text_input, TextInputModel* model) {
if(model->selected_row < keyboard_row_count - 1) {
model->selected_row++;
if(model->selected_column > get_row_size(model->selected_row) - 4) {
model->selected_column = model->selected_column - 1;
}
}
}
static void text_input_handle_left(TextInput* text_input) {
with_view_model(
text_input->view, (TextInputModel * model) {
if(model->selected_column > 0) {
model->selected_column--;
} else {
model->selected_column = get_row_size(model->selected_row) - 1;
}
return true;
});
static void text_input_handle_left(TextInput* text_input, TextInputModel* model) {
if(model->selected_column > 0) {
model->selected_column--;
} else {
model->selected_column = get_row_size(model->selected_row) - 1;
}
}
static void text_input_handle_right(TextInput* text_input) {
with_view_model(
text_input->view, (TextInputModel * model) {
if(model->selected_column < get_row_size(model->selected_row) - 1) {
model->selected_column++;
} else {
model->selected_column = 0;
}
return true;
});
static void text_input_handle_right(TextInput* text_input, TextInputModel* model) {
if(model->selected_column < get_row_size(model->selected_row) - 1) {
model->selected_column++;
} else {
model->selected_column = 0;
}
}
static void text_input_handle_ok(TextInput* text_input) {
with_view_model(
text_input->view, (TextInputModel * model) {
char selected = get_selected_char(model);
uint8_t text_length = strlen(model->text_buffer);
static void text_input_handle_ok(TextInput* text_input, TextInputModel* model, bool shift) {
char selected = get_selected_char(model);
uint8_t text_length = strlen(model->text_buffer);
if(selected == ENTER_KEY) {
if(model->validator_callback && (!model->validator_callback(
model->text_buffer,
model->validator_text,
model->validator_callback_context))) {
model->valadator_message_visible = true;
osTimerStart(text_input->timer, osKernelGetTickFreq() * 4);
} else if(model->callback != 0 && text_length > 0) {
model->callback(model->callback_context);
}
} else if(selected == BACKSPACE_KEY) {
text_input_backspace_cb(model);
} else if(text_length < (model->text_buffer_size - 1)) {
if(model->clear_default_text) {
text_length = 0;
}
if(text_length == 0 && char_is_lowercase(selected)) {
selected = char_to_uppercase(selected);
}
model->text_buffer[text_length] = selected;
model->text_buffer[text_length + 1] = 0;
}
model->clear_default_text = false;
return true;
});
if(shift) {
selected = char_to_uppercase(selected);
}
if(selected == ENTER_KEY) {
if(model->validator_callback &&
(!model->validator_callback(
model->text_buffer, model->validator_text, model->validator_callback_context))) {
model->valadator_message_visible = true;
osTimerStart(text_input->timer, osKernelGetTickFreq() * 4);
} else if(model->callback != 0 && text_length > 0) {
model->callback(model->callback_context);
}
} else if(selected == BACKSPACE_KEY) {
text_input_backspace_cb(model);
} else if(text_length < (model->text_buffer_size - 1)) {
if(model->clear_default_text) {
text_length = 0;
}
if(text_length == 0 && char_is_lowercase(selected)) {
selected = char_to_uppercase(selected);
}
model->text_buffer[text_length] = selected;
model->text_buffer[text_length + 1] = 0;
}
model->clear_default_text = false;
}
static bool text_input_view_input_callback(InputEvent* event, void* context) {
TextInput* text_input = context;
furi_assert(text_input);
bool consumed = false;
if(event->type == InputTypeShort || event->type == InputTypeRepeat) {
with_view_model(
text_input->view, (TextInputModel * model) {
if(model->valadator_message_visible) {
if(event->key == InputKeyBack) {
consumed = true;
}
}
model->valadator_message_visible = false;
return false;
});
// Acquire model
TextInputModel* model = view_get_model(text_input->view);
if((!(event->type == InputTypePress) && !(event->type == InputTypeRelease)) &&
model->valadator_message_visible) {
model->valadator_message_visible = false;
consumed = true;
} else if(event->type == InputTypeShort) {
consumed = true;
switch(event->key) {
case InputKeyUp:
text_input_handle_up(text_input);
consumed = true;
text_input_handle_up(text_input, model);
break;
case InputKeyDown:
text_input_handle_down(text_input);
consumed = true;
text_input_handle_down(text_input, model);
break;
case InputKeyLeft:
text_input_handle_left(text_input);
consumed = true;
text_input_handle_left(text_input, model);
break;
case InputKeyRight:
text_input_handle_right(text_input);
consumed = true;
text_input_handle_right(text_input, model);
break;
case InputKeyOk:
text_input_handle_ok(text_input);
consumed = true;
text_input_handle_ok(text_input, model, false);
break;
default:
consumed = false;
break;
}
} else if(event->type == InputTypeLong) {
consumed = true;
switch(event->key) {
case InputKeyUp:
text_input_handle_up(text_input, model);
break;
case InputKeyDown:
text_input_handle_down(text_input, model);
break;
case InputKeyLeft:
text_input_handle_left(text_input, model);
break;
case InputKeyRight:
text_input_handle_right(text_input, model);
break;
case InputKeyOk:
text_input_handle_ok(text_input, model, true);
break;
case InputKeyBack:
text_input_backspace_cb(model);
break;
default:
consumed = false;
break;
}
} else if(event->type == InputTypeRepeat) {
consumed = true;
switch(event->key) {
case InputKeyUp:
text_input_handle_up(text_input, model);
break;
case InputKeyDown:
text_input_handle_down(text_input, model);
break;
case InputKeyLeft:
text_input_handle_left(text_input, model);
break;
case InputKeyRight:
text_input_handle_right(text_input, model);
break;
case InputKeyBack:
text_input_backspace_cb(model);
break;
default:
consumed = false;
break;
}
}
if((event->type == InputTypeLong || event->type == InputTypeRepeat) &&
event->key == InputKeyBack) {
with_view_model(
text_input->view, (TextInputModel * model) {
if(model->valadator_message_visible) {
model->valadator_message_visible = false;
} else {
text_input_backspace_cb(model);
}
return true;
});
consumed = true;
}
// Commit model
view_commit_model(text_input->view, consumed);
return consumed;
}

View File

@ -3,8 +3,6 @@
#include <callback-connector.h>
#include <maxim_crc.h>
extern COMP_HandleTypeDef hcomp1;
KeyReader::Error KeyReader::read(iButtonKey* key) {
uint8_t tmp_key_data[8] = {0, 0, 0, 0, 0, 0, 0, 0};
iButtonKeyType key_type;
@ -116,9 +114,9 @@ void KeyReader::start_comaparator(void) {
comparator_callback_pointer =
cbc::obtain_connector(this, &KeyReader::comparator_trigger_callback);
api_interrupt_add(comparator_callback_pointer, InterruptTypeComparatorTrigger, this);
furi_hal_rfid_comp_set_callback(comparator_callback_pointer, this);
last_dwt_value = DWT->CYCCNT;
HAL_COMP_Start(&hcomp1);
furi_hal_rfid_comp_start();
}
void KeyReader::stop_comaparator(void) {
@ -127,23 +125,19 @@ void KeyReader::stop_comaparator(void) {
// rfid_pins_reset will disable ibutton pin
furi_hal_ibutton_start();
HAL_COMP_Stop(&hcomp1);
api_interrupt_remove(comparator_callback_pointer, InterruptTypeComparatorTrigger);
furi_hal_rfid_comp_stop();
furi_hal_rfid_comp_set_callback(NULL, NULL);
}
void KeyReader::comparator_trigger_callback(void* hcomp, void* comp_ctx) {
void KeyReader::comparator_trigger_callback(bool level, void* comp_ctx) {
KeyReader* _this = static_cast<KeyReader*>(comp_ctx);
if(hcomp == &hcomp1) {
uint32_t current_dwt_value = DWT->CYCCNT;
uint32_t current_dwt_value = DWT->CYCCNT;
_this->cyfral_decoder.process_front(
hal_gpio_get_rfid_in_level(), current_dwt_value - last_dwt_value);
_this->metakom_decoder.process_front(
hal_gpio_get_rfid_in_level(), current_dwt_value - last_dwt_value);
_this->cyfral_decoder.process_front(level, current_dwt_value - last_dwt_value);
_this->metakom_decoder.process_front(level, current_dwt_value - last_dwt_value);
last_dwt_value = current_dwt_value;
}
last_dwt_value = current_dwt_value;
}
void KeyReader::switch_to(ReadMode mode) {

View File

@ -28,8 +28,8 @@ private:
bool verify_key(iButtonKeyType key_type, const uint8_t* const data, uint8_t data_size);
// cyfral and metakom readers data
void comparator_trigger_callback(void* hcomp, void* comp_ctx);
void (*comparator_callback_pointer)(void* hcomp, void* comp_ctx);
void comparator_trigger_callback(bool level, void* comp_ctx);
void (*comparator_callback_pointer)(bool level, void* comp_ctx);
void start_comaparator(void);
void stop_comaparator(void);
@ -51,4 +51,4 @@ private:
void switch_to(ReadMode mode);
void switch_mode_if_needed();
};
};

View File

@ -2,8 +2,6 @@
#include <callback-connector.h>
#include <maxim_crc.h>
extern COMP_HandleTypeDef hcomp1;
KeyReader::Error KeyWorker::read(iButtonKey* key) {
KeyReader::Error result = key_reader.read(key);
@ -51,4 +49,4 @@ KeyWorker::KeyWorker(const GpioPin* one_wire_gpio)
}
KeyWorker::~KeyWorker() {
}
}

View File

@ -12,10 +12,11 @@ int32_t InfraredApp::run(void* args) {
bool exit = false;
if(args) {
std::string full_name = static_cast<const char*>(args);
std::string remote_name(full_name, full_name.find_last_of('/') + 1, full_name.size());
std::string path = static_cast<const char*>(args);
std::string remote_name(path, path.find_last_of('/') + 1, path.size());
remote_name.erase(remote_name.find_last_of('.'));
bool result = remote_manager.load(remote_name);
path.erase(path.find_last_of('/'));
bool result = remote_manager.load(path, remote_name);
if(result) {
current_scene = InfraredApp::Scene::Remote;
} else {

View File

@ -15,16 +15,18 @@
static const std::string default_remote_name = "remote";
std::string InfraredAppRemoteManager::make_full_name(const std::string& remote_name) const {
return std::string("") + InfraredApp::infrared_directory + "/" + remote_name +
InfraredApp::infrared_extension;
std::string InfraredAppRemoteManager::make_full_name(
const std::string& path,
const std::string& remote_name) const {
return std::string("") + path + "/" + remote_name + InfraredApp::infrared_extension;
}
std::string InfraredAppRemoteManager::find_vacant_remote_name(const std::string& name) {
bool exist = true;
FileWorkerCpp file_worker;
if(!file_worker.is_file_exist(make_full_name(name).c_str(), &exist)) {
if(!file_worker.is_file_exist(
make_full_name(InfraredApp::infrared_directory, name).c_str(), &exist)) {
return std::string();
} else if(!exist) {
return name;
@ -35,7 +37,7 @@ std::string InfraredAppRemoteManager::find_vacant_remote_name(const std::string&
bool file_worker_result = false;
std::string new_name;
do {
new_name = make_full_name(name + std::to_string(++i));
new_name = make_full_name(InfraredApp::infrared_directory, name + std::to_string(++i));
file_worker_result = file_worker.is_file_exist(new_name.c_str(), &exist);
} while(file_worker_result && exist);
@ -57,7 +59,7 @@ bool InfraredAppRemoteManager::add_remote_with_button(
return false;
}
remote = std::make_unique<InfraredAppRemote>(new_name);
remote = std::make_unique<InfraredAppRemote>(InfraredApp::infrared_directory, new_name);
return add_button(button_name, signal);
}
@ -84,7 +86,7 @@ const InfraredAppSignal& InfraredAppRemoteManager::get_button_data(size_t index)
bool InfraredAppRemoteManager::delete_remote() {
bool result;
FileWorkerCpp file_worker;
result = file_worker.remove(make_full_name(remote->name).c_str());
result = file_worker.remove(make_full_name(remote->path, remote->name).c_str());
reset_remote();
return result;
@ -128,8 +130,8 @@ bool InfraredAppRemoteManager::rename_remote(const char* str) {
}
FileWorkerCpp file_worker;
std::string old_filename = make_full_name(remote->name);
std::string new_filename = make_full_name(new_name);
std::string old_filename = make_full_name(remote->path, remote->name);
std::string new_filename = make_full_name(remote->path, new_name);
bool result = file_worker.rename(old_filename.c_str(), new_filename.c_str());
remote->name = new_name;
@ -160,8 +162,10 @@ bool InfraredAppRemoteManager::store(void) {
Storage* storage = static_cast<Storage*>(furi_record_open("storage"));
FlipperFormat* ff = flipper_format_file_alloc(storage);
FURI_LOG_I("RemoteManager", "store file: \'%s\'", make_full_name(remote->name).c_str());
result = flipper_format_file_open_always(ff, make_full_name(remote->name).c_str());
FURI_LOG_I(
"RemoteManager", "store file: \'%s\'", make_full_name(remote->path, remote->name).c_str());
result =
flipper_format_file_open_always(ff, make_full_name(remote->path, remote->name).c_str());
if(result) {
result = flipper_format_write_header_cstr(ff, "IR signals file", 1);
}
@ -179,13 +183,13 @@ bool InfraredAppRemoteManager::store(void) {
return result;
}
bool InfraredAppRemoteManager::load(const std::string& remote_name) {
bool InfraredAppRemoteManager::load(const std::string& path, const std::string& remote_name) {
bool result = false;
Storage* storage = static_cast<Storage*>(furi_record_open("storage"));
FlipperFormat* ff = flipper_format_file_alloc(storage);
FURI_LOG_I("RemoteManager", "load file: \'%s\'", make_full_name(remote_name).c_str());
result = flipper_format_file_open_existing(ff, make_full_name(remote_name).c_str());
FURI_LOG_I("RemoteManager", "load file: \'%s\'", make_full_name(path, remote_name).c_str());
result = flipper_format_file_open_existing(ff, make_full_name(path, remote_name).c_str());
if(result) {
string_t header;
string_init(header);
@ -197,7 +201,7 @@ bool InfraredAppRemoteManager::load(const std::string& remote_name) {
string_clear(header);
}
if(result) {
remote = std::make_unique<InfraredAppRemote>(remote_name);
remote = std::make_unique<InfraredAppRemote>(path, remote_name);
InfraredAppSignal signal;
std::string signal_name;
while(infrared_parser_read_signal(ff, signal, signal_name)) {

View File

@ -59,14 +59,18 @@ class InfraredAppRemote {
std::vector<InfraredAppRemoteButton> buttons;
/** Name of remote */
std::string name;
/** Path to remote file */
std::string path;
public:
/** Initialize new remote
*
*
* @param path - remote file path
* @param name - new remote name
*/
InfraredAppRemote(const std::string& name)
: name(name) {
InfraredAppRemote(const std::string& path, const std::string& name)
: name(name)
, path(path) {
}
};
@ -79,7 +83,7 @@ class InfraredAppRemoteManager {
* @param remote_name name of remote
* @retval full name of remote on disk
*/
std::string make_full_name(const std::string& remote_name) const;
std::string make_full_name(const std::string& path, const std::string& remote_name) const;
public:
/** Restriction to button name length. Buttons larger are ignored. */
@ -184,5 +188,5 @@ public:
* @param name - name of remote to load
* @retval true if success, false otherwise
*/
bool load(const std::string& name);
bool load(const std::string& path, const std::string& name);
};

View File

@ -29,7 +29,7 @@ void InfraredAppSceneRemoteList::on_enter(InfraredApp* app) {
last_selected_remote_name);
if(file_select_result) {
if(remote_manager->load(std::string(filename_ts->text))) {
if(remote_manager->load(InfraredApp::infrared_directory, std::string(filename_ts->text))) {
app->switch_to_next_scene(InfraredApp::Scene::Remote);
result = true;
}

View File

@ -4,8 +4,6 @@
#include <stm32wbxx_ll_cortex.h>
#include <tim.h>
extern COMP_HandleTypeDef hcomp1;
/**
* @brief private violation assistant for RfidReader
*/
@ -63,14 +61,10 @@ void RfidReader::switch_mode() {
switch_timer_reset();
}
static void comparator_trigger_callback(void* hcomp, void* comp_ctx) {
COMP_HandleTypeDef* _hcomp = static_cast<COMP_HandleTypeDef*>(hcomp);
static void comparator_trigger_callback(bool level, void* comp_ctx) {
RfidReader* _this = static_cast<RfidReader*>(comp_ctx);
if(hcomp == &hcomp1) {
RfidReaderAccessor::decode(
*_this, (HAL_COMP_GetOutputLevel(_hcomp) == COMP_OUTPUT_LEVEL_HIGH));
}
RfidReaderAccessor::decode(*_this, !level);
}
RfidReader::RfidReader() {
@ -163,25 +157,13 @@ bool RfidReader::any_read() {
}
void RfidReader::start_comparator(void) {
api_interrupt_add(comparator_trigger_callback, InterruptTypeComparatorTrigger, this);
furi_hal_rfid_comp_set_callback(comparator_trigger_callback, this);
last_dwt_value = DWT->CYCCNT;
hcomp1.Init.InputMinus = COMP_INPUT_MINUS_1_2VREFINT;
hcomp1.Init.InputPlus = COMP_INPUT_PLUS_IO1;
hcomp1.Init.OutputPol = COMP_OUTPUTPOL_NONINVERTED;
hcomp1.Init.Hysteresis = COMP_HYSTERESIS_HIGH;
hcomp1.Init.BlankingSrce = COMP_BLANKINGSRC_NONE;
hcomp1.Init.Mode = COMP_POWERMODE_MEDIUMSPEED;
hcomp1.Init.WindowMode = COMP_WINDOWMODE_DISABLE;
hcomp1.Init.TriggerMode = COMP_TRIGGERMODE_IT_RISING_FALLING;
if(HAL_COMP_Init(&hcomp1) != HAL_OK) {
Error_Handler();
}
HAL_COMP_Start(&hcomp1);
furi_hal_rfid_comp_start();
}
void RfidReader::stop_comparator(void) {
HAL_COMP_Stop(&hcomp1);
api_interrupt_remove(comparator_trigger_callback, InterruptTypeComparatorTrigger);
}
furi_hal_rfid_comp_stop();
furi_hal_rfid_comp_set_callback(NULL, NULL);
}

View File

@ -4,8 +4,6 @@
#include "protocols/protocol_hid_h10301.h"
#include "protocols/protocol_indala_40134.h"
extern COMP_HandleTypeDef hcomp1;
/**
* @brief all timings are specified in field clocks (field clock = 125 kHz, 8 us)
*

View File

@ -1,35 +1,16 @@
#include "lfrfid_debug_app_scene_tune.h"
#include <furi_hal.h>
extern COMP_HandleTypeDef hcomp1;
static void comparator_trigger_callback(void* hcomp, void* comp_ctx) {
COMP_HandleTypeDef* _hcomp = static_cast<COMP_HandleTypeDef*>(hcomp);
if(hcomp == &hcomp1) {
hal_gpio_write(&gpio_ext_pa7, HAL_COMP_GetOutputLevel(_hcomp) == COMP_OUTPUT_LEVEL_HIGH);
}
static void comparator_trigger_callback(bool level, void* comp_ctx) {
hal_gpio_write(&gpio_ext_pa7, !level);
}
void LfRfidDebugAppSceneTune::on_enter(LfRfidDebugApp* app, bool need_restore) {
app->view_controller.switch_to<LfRfidViewTuneVM>();
hal_gpio_init_simple(&gpio_ext_pa7, GpioModeOutputPushPull);
api_interrupt_add(comparator_trigger_callback, InterruptTypeComparatorTrigger, this);
hcomp1.Init.InputMinus = COMP_INPUT_MINUS_1_2VREFINT;
hcomp1.Init.InputPlus = COMP_INPUT_PLUS_IO1;
hcomp1.Init.OutputPol = COMP_OUTPUTPOL_NONINVERTED;
hcomp1.Init.Hysteresis = COMP_HYSTERESIS_HIGH;
hcomp1.Init.BlankingSrce = COMP_BLANKINGSRC_NONE;
hcomp1.Init.Mode = COMP_POWERMODE_MEDIUMSPEED;
hcomp1.Init.WindowMode = COMP_WINDOWMODE_DISABLE;
hcomp1.Init.TriggerMode = COMP_TRIGGERMODE_IT_RISING_FALLING;
if(HAL_COMP_Init(&hcomp1) != HAL_OK) {
Error_Handler();
}
HAL_COMP_Start(&hcomp1);
furi_hal_rfid_comp_set_callback(comparator_trigger_callback, this);
furi_hal_rfid_comp_start();
furi_hal_rfid_pins_read();
furi_hal_rfid_tim_read(125000, 0.5);
@ -50,11 +31,11 @@ bool LfRfidDebugAppSceneTune::on_event(LfRfidDebugApp* app, LfRfidDebugApp::Even
}
void LfRfidDebugAppSceneTune::on_exit(LfRfidDebugApp* app) {
HAL_COMP_Stop(&hcomp1);
api_interrupt_remove(comparator_trigger_callback, InterruptTypeComparatorTrigger);
furi_hal_rfid_comp_stop();
furi_hal_rfid_comp_set_callback(NULL, NULL);
hal_gpio_init_simple(&gpio_ext_pa7, GpioModeAnalog);
furi_hal_rfid_tim_read_stop();
furi_hal_rfid_tim_reset();
furi_hal_rfid_pins_reset();
}
}

View File

@ -102,7 +102,7 @@ typedef struct {
uint8_t volume_id_max;
} State;
const float volumes[] = {0, 0.02, 0.05, 0.1, 0.5};
const float volumes[] = {0, .25, .5, .75, 1};
bool is_white_note(const MelodyEventRecord* note_record, uint8_t id) {
if(note_record == NULL) return false;
@ -332,10 +332,10 @@ void process_note(
// play note
float note_delay = bar_length_ms / (float)note_record->length;
if(note_record->note != N) {
hal_pwm_set(volume, note_record->note, &SPEAKER_TIM, SPEAKER_CH);
furi_hal_speaker_start(note_record->note, volume);
}
delay(note_delay);
hal_pwm_stop(&SPEAKER_TIM, SPEAKER_CH);
furi_hal_speaker_stop();
}
void music_player_thread(void* p) {
@ -447,7 +447,7 @@ int32_t music_player_app(void* p) {
}
osThreadTerminate(player);
hal_pwm_stop(&SPEAKER_TIM, SPEAKER_CH);
furi_hal_speaker_stop();
view_port_enabled_set(view_port, false);
gui_remove_view_port(gui, view_port);
furi_record_close("gui");

View File

@ -8,4 +8,5 @@ enum NfcCustomEvent {
NfcCustomEventWorkerExit,
NfcCustomEventByteInputDone,
NfcCustomEventTextInputDone,
NfcCustomEventDictAttackDone,
};

View File

@ -0,0 +1,53 @@
#include "nfc_mf_classic_dict.h"
#include <flipper_format/flipper_format.h>
#include <lib/toolbox/args.h>
#define NFC_MF_CLASSIC_DICT_PATH "/ext/nfc/assets/mf_classic_dict.nfc"
#define NFC_MF_CLASSIC_KEY_LEN (13)
bool nfc_mf_classic_dict_check_presence(Storage* storage) {
furi_assert(storage);
return storage_common_stat(storage, NFC_MF_CLASSIC_DICT_PATH, NULL) == FSE_OK;
}
bool nfc_mf_classic_dict_open_file(Stream* stream) {
furi_assert(stream);
return file_stream_open(stream, NFC_MF_CLASSIC_DICT_PATH, FSAM_READ, FSOM_OPEN_EXISTING);
}
void nfc_mf_classic_dict_close_file(Stream* stream) {
furi_assert(stream);
file_stream_close(stream);
}
bool nfc_mf_classic_dict_get_next_key(Stream* stream, uint64_t* key) {
furi_assert(stream);
furi_assert(key);
uint8_t key_byte_tmp = 0;
string_t next_line;
string_init(next_line);
*key = 0;
bool next_key_read = false;
while(!next_key_read) {
if(stream_read_line(stream, next_line)) break;
if(string_get_char(next_line, 0) == '#') continue;
if(string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue;
for(uint8_t i = 0; i < 12; i += 2) {
args_char_to_hex(
string_get_char(next_line, i), string_get_char(next_line, i + 1), &key_byte_tmp);
*key |= (uint64_t)key_byte_tmp << 8 * (5 - i / 2);
}
next_key_read = true;
}
string_clear(next_line);
return next_key_read;
}
void nfc_mf_classic_dict_reset(Stream* stream) {
furi_assert(stream);
stream_rewind(stream);
}

View File

@ -0,0 +1,15 @@
#pragma once
#include <stdbool.h>
#include <storage/storage.h>
#include <lib/toolbox/stream/file_stream.h>
bool nfc_mf_classic_dict_check_presence(Storage* storage);
bool nfc_mf_classic_dict_open_file(Stream* stream);
void nfc_mf_classic_dict_close_file(Stream* stream);
bool nfc_mf_classic_dict_get_next_key(Stream* stream, uint64_t* key);
void nfc_mf_classic_dict_reset(Stream* stream);

View File

@ -79,6 +79,11 @@ Nfc* nfc_alloc() {
view_dispatcher_add_view(
nfc->view_dispatcher, NfcViewBankCard, bank_card_get_view(nfc->bank_card));
// Dict Attack
nfc->dict_attack = dict_attack_alloc();
view_dispatcher_add_view(
nfc->view_dispatcher, NfcViewDictAttack, dict_attack_get_view(nfc->dict_attack));
return nfc;
}
@ -121,6 +126,10 @@ void nfc_free(Nfc* nfc) {
view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewBankCard);
bank_card_free(nfc->bank_card);
// Dict Attack
view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewDictAttack);
dict_attack_free(nfc->dict_attack);
// Worker
nfc_worker_stop(nfc->worker);
nfc_worker_free(nfc->worker);

486
applications/nfc/nfc_device.c Executable file → Normal file
View File

@ -16,24 +16,29 @@ NfcDevice* nfc_device_alloc() {
void nfc_device_free(NfcDevice* nfc_dev) {
furi_assert(nfc_dev);
nfc_device_clear(nfc_dev);
furi_record_close("storage");
furi_record_close("dialogs");
free(nfc_dev);
}
void nfc_device_prepare_format_string(NfcDevice* dev, string_t format_string) {
static void nfc_device_prepare_format_string(NfcDevice* dev, string_t format_string) {
if(dev->format == NfcDeviceSaveFormatUid) {
string_set_str(format_string, "UID");
} else if(dev->format == NfcDeviceSaveFormatBankCard) {
string_set_str(format_string, "Bank card");
} else if(dev->format == NfcDeviceSaveFormatMifareUl) {
string_set_str(format_string, nfc_mf_ul_type(dev->dev_data.mf_ul_data.type, true));
} else if(dev->format == NfcDeviceSaveFormatMifareClassic) {
string_set_str(format_string, "Mifare Classic");
} else if(dev->format == NfcDeviceSaveFormatMifareDesfire) {
string_set_str(format_string, "Mifare DESFire");
} else {
string_set_str(format_string, "Unknown");
}
}
bool nfc_device_parse_format_string(NfcDevice* dev, string_t format_string) {
static bool nfc_device_parse_format_string(NfcDevice* dev, string_t format_string) {
if(string_start_with_str_p(format_string, "UID")) {
dev->format = NfcDeviceSaveFormatUid;
dev->dev_data.nfc_data.protocol = NfcDeviceProtocolUnknown;
@ -53,6 +58,16 @@ bool nfc_device_parse_format_string(NfcDevice* dev, string_t format_string) {
return true;
}
}
if(string_start_with_str_p(format_string, "Mifare Classic")) {
dev->format = NfcDeviceSaveFormatMifareClassic;
dev->dev_data.nfc_data.protocol = NfcDeviceProtocolMifareClassic;
return true;
}
if(string_start_with_str_p(format_string, "Mifare DESFire")) {
dev->format = NfcDeviceSaveFormatMifareDesfire;
dev->dev_data.nfc_data.protocol = NfcDeviceProtocolMifareDesfire;
return true;
}
return false;
}
@ -154,6 +169,383 @@ bool nfc_device_load_mifare_ul_data(FlipperFormat* file, NfcDevice* dev) {
return parsed;
}
static bool nfc_device_save_mifare_df_key_settings(
FlipperFormat* file,
MifareDesfireKeySettings* ks,
const char* prefix) {
bool saved = false;
string_t key;
string_init(key);
do {
string_printf(key, "%s Change Key ID", prefix);
if(!flipper_format_write_hex(file, string_get_cstr(key), &ks->change_key_id, 1)) break;
string_printf(key, "%s Config Changeable", prefix);
if(!flipper_format_write_bool(file, string_get_cstr(key), &ks->config_changeable, 1))
break;
string_printf(key, "%s Free Create Delete", prefix);
if(!flipper_format_write_bool(file, string_get_cstr(key), &ks->free_create_delete, 1))
break;
string_printf(key, "%s Free Directory List", prefix);
if(!flipper_format_write_bool(file, string_get_cstr(key), &ks->free_directory_list, 1))
break;
string_printf(key, "%s Key Changeable", prefix);
if(!flipper_format_write_bool(file, string_get_cstr(key), &ks->master_key_changeable, 1))
break;
string_printf(key, "%s Max Keys", prefix);
if(!flipper_format_write_hex(file, string_get_cstr(key), &ks->max_keys, 1)) break;
for(MifareDesfireKeyVersion* kv = ks->key_version_head; kv; kv = kv->next) {
string_printf(key, "%s Key %d Version", prefix, kv->id);
if(!flipper_format_write_hex(file, string_get_cstr(key), &kv->version, 1)) break;
}
saved = true;
} while(false);
string_clear(key);
return saved;
}
bool nfc_device_load_mifare_df_key_settings(
FlipperFormat* file,
MifareDesfireKeySettings* ks,
const char* prefix) {
bool parsed = false;
string_t key;
string_init(key);
do {
string_printf(key, "%s Change Key ID", prefix);
if(!flipper_format_read_hex(file, string_get_cstr(key), &ks->change_key_id, 1)) break;
string_printf(key, "%s Config Changeable", prefix);
if(!flipper_format_read_bool(file, string_get_cstr(key), &ks->config_changeable, 1)) break;
string_printf(key, "%s Free Create Delete", prefix);
if(!flipper_format_read_bool(file, string_get_cstr(key), &ks->free_create_delete, 1))
break;
string_printf(key, "%s Free Directory List", prefix);
if(!flipper_format_read_bool(file, string_get_cstr(key), &ks->free_directory_list, 1))
break;
string_printf(key, "%s Key Changeable", prefix);
if(!flipper_format_read_bool(file, string_get_cstr(key), &ks->master_key_changeable, 1))
break;
string_printf(key, "%s Max Keys", prefix);
if(!flipper_format_read_hex(file, string_get_cstr(key), &ks->max_keys, 1)) break;
MifareDesfireKeyVersion** kv_head = &ks->key_version_head;
for(int key_id = 0; key_id < ks->max_keys; key_id++) {
string_printf(key, "%s Key %d Version", prefix, key_id);
uint8_t version;
if(flipper_format_read_hex(file, string_get_cstr(key), &version, 1)) {
MifareDesfireKeyVersion* kv = malloc(sizeof(MifareDesfireKeyVersion));
memset(kv, 0, sizeof(MifareDesfireKeyVersion));
kv->id = key_id;
kv->version = version;
*kv_head = kv;
kv_head = &kv->next;
}
}
parsed = true;
} while(false);
string_clear(key);
return parsed;
}
static bool nfc_device_save_mifare_df_app(FlipperFormat* file, MifareDesfireApplication* app) {
bool saved = false;
string_t prefix, key;
string_init_printf(prefix, "Application %02x%02x%02x", app->id[0], app->id[1], app->id[2]);
string_init(key);
uint8_t* tmp = NULL;
do {
if(app->key_settings) {
if(!nfc_device_save_mifare_df_key_settings(
file, app->key_settings, string_get_cstr(prefix)))
break;
}
uint32_t n_files = 0;
for(MifareDesfireFile* f = app->file_head; f; f = f->next) {
n_files++;
}
tmp = malloc(n_files);
int i = 0;
for(MifareDesfireFile* f = app->file_head; f; f = f->next) {
tmp[i++] = f->id;
}
string_printf(key, "%s File IDs", string_get_cstr(prefix));
if(!flipper_format_write_hex(file, string_get_cstr(key), tmp, n_files)) break;
bool saved_files = true;
for(MifareDesfireFile* f = app->file_head; f; f = f->next) {
saved_files = false;
string_printf(key, "%s File %d Type", string_get_cstr(prefix), f->id);
if(!flipper_format_write_hex(file, string_get_cstr(key), &f->type, 1)) break;
string_printf(
key, "%s File %d Communication Settings", string_get_cstr(prefix), f->id);
if(!flipper_format_write_hex(file, string_get_cstr(key), &f->comm, 1)) break;
string_printf(key, "%s File %d Access Rights", string_get_cstr(prefix), f->id);
if(!flipper_format_write_hex(
file, string_get_cstr(key), (uint8_t*)&f->access_rights, 2))
break;
uint16_t size = 0;
if(f->type == MifareDesfireFileTypeStandard ||
f->type == MifareDesfireFileTypeBackup) {
size = f->settings.data.size;
string_printf(key, "%s File %d Size", string_get_cstr(prefix), f->id);
if(!flipper_format_write_uint32(
file, string_get_cstr(key), &f->settings.data.size, 1))
break;
} else if(f->type == MifareDesfireFileTypeValue) {
string_printf(key, "%s File %d Hi Limit", string_get_cstr(prefix), f->id);
if(!flipper_format_write_uint32(
file, string_get_cstr(key), &f->settings.value.hi_limit, 1))
break;
string_printf(key, "%s File %d Lo Limit", string_get_cstr(prefix), f->id);
if(!flipper_format_write_uint32(
file, string_get_cstr(key), &f->settings.value.lo_limit, 1))
break;
string_printf(
key, "%s File %d Limited Credit Value", string_get_cstr(prefix), f->id);
if(!flipper_format_write_uint32(
file, string_get_cstr(key), &f->settings.value.limited_credit_value, 1))
break;
string_printf(
key, "%s File %d Limited Credit Enabled", string_get_cstr(prefix), f->id);
if(!flipper_format_write_bool(
file, string_get_cstr(key), &f->settings.value.limited_credit_enabled, 1))
break;
size = 4;
} else if(
f->type == MifareDesfireFileTypeLinearRecord ||
f->type == MifareDesfireFileTypeCyclicRecord) {
string_printf(key, "%s File %d Size", string_get_cstr(prefix), f->id);
if(!flipper_format_write_uint32(
file, string_get_cstr(key), &f->settings.record.size, 1))
break;
string_printf(key, "%s File %d Max", string_get_cstr(prefix), f->id);
if(!flipper_format_write_uint32(
file, string_get_cstr(key), &f->settings.record.max, 1))
break;
string_printf(key, "%s File %d Cur", string_get_cstr(prefix), f->id);
if(!flipper_format_write_uint32(
file, string_get_cstr(key), &f->settings.record.cur, 1))
break;
size = f->settings.record.size * f->settings.record.cur;
}
if(f->contents) {
string_printf(key, "%s File %d", string_get_cstr(prefix), f->id);
if(!flipper_format_write_hex(file, string_get_cstr(key), f->contents, size)) break;
}
saved_files = true;
}
if(!saved_files) {
break;
}
saved = true;
} while(false);
free(tmp);
string_clear(prefix);
string_clear(key);
return saved;
}
bool nfc_device_load_mifare_df_app(FlipperFormat* file, MifareDesfireApplication* app) {
bool parsed = false;
string_t prefix, key;
string_init_printf(prefix, "Application %02x%02x%02x", app->id[0], app->id[1], app->id[2]);
string_init(key);
uint8_t* tmp = NULL;
MifareDesfireFile* f = NULL;
do {
app->key_settings = malloc(sizeof(MifareDesfireKeySettings));
memset(app->key_settings, 0, sizeof(MifareDesfireKeySettings));
if(!nfc_device_load_mifare_df_key_settings(
file, app->key_settings, string_get_cstr(prefix))) {
free(app->key_settings);
app->key_settings = NULL;
break;
}
string_printf(key, "%s File IDs", string_get_cstr(prefix));
uint32_t n_files;
if(!flipper_format_get_value_count(file, string_get_cstr(key), &n_files)) break;
tmp = malloc(n_files);
if(!flipper_format_read_hex(file, string_get_cstr(key), tmp, n_files)) break;
MifareDesfireFile** file_head = &app->file_head;
bool parsed_files = true;
for(int i = 0; i < n_files; i++) {
parsed_files = false;
f = malloc(sizeof(MifareDesfireFile));
memset(f, 0, sizeof(MifareDesfireFile));
f->id = tmp[i];
string_printf(key, "%s File %d Type", string_get_cstr(prefix), f->id);
if(!flipper_format_read_hex(file, string_get_cstr(key), &f->type, 1)) break;
string_printf(
key, "%s File %d Communication Settings", string_get_cstr(prefix), f->id);
if(!flipper_format_read_hex(file, string_get_cstr(key), &f->comm, 1)) break;
string_printf(key, "%s File %d Access Rights", string_get_cstr(prefix), f->id);
if(!flipper_format_read_hex(file, string_get_cstr(key), (uint8_t*)&f->access_rights, 2))
break;
if(f->type == MifareDesfireFileTypeStandard ||
f->type == MifareDesfireFileTypeBackup) {
string_printf(key, "%s File %d Size", string_get_cstr(prefix), f->id);
if(!flipper_format_read_uint32(
file, string_get_cstr(key), &f->settings.data.size, 1))
break;
} else if(f->type == MifareDesfireFileTypeValue) {
string_printf(key, "%s File %d Hi Limit", string_get_cstr(prefix), f->id);
if(!flipper_format_read_uint32(
file, string_get_cstr(key), &f->settings.value.hi_limit, 1))
break;
string_printf(key, "%s File %d Lo Limit", string_get_cstr(prefix), f->id);
if(!flipper_format_read_uint32(
file, string_get_cstr(key), &f->settings.value.lo_limit, 1))
break;
string_printf(
key, "%s File %d Limited Credit Value", string_get_cstr(prefix), f->id);
if(!flipper_format_read_uint32(
file, string_get_cstr(key), &f->settings.value.limited_credit_value, 1))
break;
string_printf(
key, "%s File %d Limited Credit Enabled", string_get_cstr(prefix), f->id);
if(!flipper_format_read_bool(
file, string_get_cstr(key), &f->settings.value.limited_credit_enabled, 1))
break;
} else if(
f->type == MifareDesfireFileTypeLinearRecord ||
f->type == MifareDesfireFileTypeCyclicRecord) {
string_printf(key, "%s File %d Size", string_get_cstr(prefix), f->id);
if(!flipper_format_read_uint32(
file, string_get_cstr(key), &f->settings.record.size, 1))
break;
string_printf(key, "%s File %d Max", string_get_cstr(prefix), f->id);
if(!flipper_format_read_uint32(
file, string_get_cstr(key), &f->settings.record.max, 1))
break;
string_printf(key, "%s File %d Cur", string_get_cstr(prefix), f->id);
if(!flipper_format_read_uint32(
file, string_get_cstr(key), &f->settings.record.cur, 1))
break;
}
string_printf(key, "%s File %d", string_get_cstr(prefix), f->id);
if(flipper_format_key_exist(file, string_get_cstr(key))) {
uint32_t size;
if(!flipper_format_get_value_count(file, string_get_cstr(key), &size)) break;
f->contents = malloc(size);
if(!flipper_format_read_hex(file, string_get_cstr(key), f->contents, size)) break;
}
*file_head = f;
file_head = &f->next;
f = NULL;
parsed_files = true;
}
if(!parsed_files) {
break;
}
parsed = true;
} while(false);
if(f) {
free(f->contents);
free(f);
}
free(tmp);
string_clear(prefix);
string_clear(key);
return parsed;
}
static bool nfc_device_save_mifare_df_data(FlipperFormat* file, NfcDevice* dev) {
bool saved = false;
MifareDesfireData* data = &dev->dev_data.mf_df_data;
uint8_t* tmp = NULL;
do {
if(!flipper_format_write_comment_cstr(file, "Mifare DESFire specific data")) break;
if(!flipper_format_write_hex(
file, "PICC Version", (uint8_t*)&data->version, sizeof(data->version)))
break;
if(data->free_memory) {
if(!flipper_format_write_uint32(file, "PICC Free Memory", &data->free_memory->bytes, 1))
break;
}
if(data->master_key_settings) {
if(!nfc_device_save_mifare_df_key_settings(file, data->master_key_settings, "PICC"))
break;
}
uint32_t n_apps = 0;
for(MifareDesfireApplication* app = data->app_head; app; app = app->next) {
n_apps++;
}
if(!flipper_format_write_uint32(file, "Application Count", &n_apps, 1)) break;
tmp = malloc(n_apps * 3);
int i = 0;
for(MifareDesfireApplication* app = data->app_head; app; app = app->next) {
memcpy(tmp + i, app->id, 3);
i += 3;
}
if(!flipper_format_write_hex(file, "Application IDs", tmp, n_apps * 3)) break;
for(MifareDesfireApplication* app = data->app_head; app; app = app->next) {
if(!nfc_device_save_mifare_df_app(file, app)) break;
}
saved = true;
} while(false);
free(tmp);
return saved;
}
bool nfc_device_load_mifare_df_data(FlipperFormat* file, NfcDevice* dev) {
bool parsed = false;
MifareDesfireData* data = &dev->dev_data.mf_df_data;
memset(data, 0, sizeof(MifareDesfireData));
uint8_t* tmp = NULL;
do {
if(!flipper_format_read_hex(
file, "PICC Version", (uint8_t*)&data->version, sizeof(data->version)))
break;
if(flipper_format_key_exist(file, "PICC Free Memory")) {
data->free_memory = malloc(sizeof(MifareDesfireFreeMemory));
memset(data->free_memory, 0, sizeof(MifareDesfireFreeMemory));
if(!flipper_format_read_uint32(
file, "PICC Free Memory", &data->free_memory->bytes, 1)) {
free(data->free_memory);
break;
}
}
data->master_key_settings = malloc(sizeof(MifareDesfireKeySettings));
memset(data->master_key_settings, 0, sizeof(MifareDesfireKeySettings));
if(!nfc_device_load_mifare_df_key_settings(file, data->master_key_settings, "PICC")) {
free(data->master_key_settings);
data->master_key_settings = NULL;
break;
}
uint32_t n_apps;
if(!flipper_format_read_uint32(file, "Application Count", &n_apps, 1)) break;
tmp = malloc(n_apps * 3);
if(!flipper_format_read_hex(file, "Application IDs", tmp, n_apps * 3)) break;
bool parsed_apps = true;
MifareDesfireApplication** app_head = &data->app_head;
for(int i = 0; i < n_apps; i++) {
MifareDesfireApplication* app = malloc(sizeof(MifareDesfireApplication));
memset(app, 0, sizeof(MifareDesfireApplication));
memcpy(app->id, &tmp[i * 3], 3);
if(!nfc_device_load_mifare_df_app(file, app)) {
free(app);
parsed_apps = false;
break;
}
*app_head = app;
app_head = &app->next;
}
if(!parsed_apps) break;
parsed = true;
} while(false);
free(tmp);
return parsed;
}
static bool nfc_device_save_bank_card_data(FlipperFormat* file, NfcDevice* dev) {
bool saved = false;
NfcEmvData* data = &dev->dev_data.emv_data;
@ -220,6 +612,79 @@ bool nfc_device_load_bank_card_data(FlipperFormat* file, NfcDevice* dev) {
return parsed;
}
static bool nfc_device_save_mifare_classic_data(FlipperFormat* file, NfcDevice* dev) {
bool saved = false;
MfClassicData* data = &dev->dev_data.mf_classic_data;
string_t temp_str;
string_init(temp_str);
uint16_t blocks = 0;
// Save Mifare Classic specific data
do {
if(!flipper_format_write_comment_cstr(file, "Mifare Classic specific data")) break;
if(data->type == MfClassicType1k) {
if(!flipper_format_write_string_cstr(file, "Mifare Classic type", "1K")) break;
blocks = 64;
} else if(data->type == MfClassicType4k) {
if(!flipper_format_write_string_cstr(file, "Mifare Classic type", "4K")) break;
blocks = 256;
}
if(!flipper_format_write_comment_cstr(file, "Mifare Classic blocks")) break;
bool block_saved = true;
for(size_t i = 0; i < blocks; i++) {
string_printf(temp_str, "Block %d", i);
if(!flipper_format_write_hex(
file, string_get_cstr(temp_str), data->block[i].value, 16)) {
block_saved = false;
break;
}
}
if(!block_saved) break;
saved = true;
} while(false);
string_clear(temp_str);
return saved;
}
static bool nfc_device_load_mifare_classic_data(FlipperFormat* file, NfcDevice* dev) {
bool parsed = false;
MfClassicData* data = &dev->dev_data.mf_classic_data;
string_t temp_str;
string_init(temp_str);
uint16_t data_blocks = 0;
do {
// Read Mifare Classic type
if(!flipper_format_read_string(file, "Mifare Classic type", temp_str)) break;
if(!string_cmp_str(temp_str, "1K")) {
data->type = MfClassicType1k;
data_blocks = 64;
} else if(!string_cmp_str(temp_str, "4K")) {
data->type = MfClassicType4k;
data_blocks = 256;
} else {
break;
}
// Read Mifare Classic blocks
bool block_read = true;
for(size_t i = 0; i < data_blocks; i++) {
string_printf(temp_str, "Block %d", i);
if(!flipper_format_read_hex(
file, string_get_cstr(temp_str), data->block[i].value, 16)) {
block_read = false;
break;
}
}
if(!block_read) break;
parsed = true;
} while(false);
string_clear(temp_str);
return parsed;
}
void nfc_device_set_name(NfcDevice* dev, const char* name) {
furi_assert(dev);
@ -250,7 +715,7 @@ static bool nfc_device_save_file(
if(!flipper_format_write_header_cstr(file, nfc_file_header, nfc_file_version)) break;
// Write nfc device type
if(!flipper_format_write_comment_cstr(
file, "Nfc device type can be UID, Mifare Ultralight, Bank card"))
file, "Nfc device type can be UID, Mifare Ultralight, Mifare Classic, Bank card"))
break;
nfc_device_prepare_format_string(dev, temp_str);
if(!flipper_format_write_string(file, "Device type", temp_str)) break;
@ -263,8 +728,12 @@ static bool nfc_device_save_file(
// Save more data if necessary
if(dev->format == NfcDeviceSaveFormatMifareUl) {
if(!nfc_device_save_mifare_ul_data(file, dev)) break;
} else if(dev->format == NfcDeviceSaveFormatMifareDesfire) {
if(!nfc_device_save_mifare_df_data(file, dev)) break;
} else if(dev->format == NfcDeviceSaveFormatBankCard) {
if(!nfc_device_save_bank_card_data(file, dev)) break;
} else if(dev->format == NfcDeviceSaveFormatMifareClassic) {
if(!nfc_device_save_mifare_classic_data(file, dev)) break;
}
saved = true;
} while(0);
@ -327,6 +796,10 @@ static bool nfc_device_load_data(NfcDevice* dev, string_t path) {
// Parse other data
if(dev->format == NfcDeviceSaveFormatMifareUl) {
if(!nfc_device_load_mifare_ul_data(file, dev)) break;
} else if(dev->format == NfcDeviceSaveFormatMifareClassic) {
if(!nfc_device_load_mifare_classic_data(file, dev)) break;
} else if(dev->format == NfcDeviceSaveFormatMifareDesfire) {
if(!nfc_device_load_mifare_df_data(file, dev)) break;
} else if(dev->format == NfcDeviceSaveFormatBankCard) {
if(!nfc_device_load_bank_card_data(file, dev)) break;
}
@ -389,9 +862,16 @@ bool nfc_file_select(NfcDevice* dev) {
return res;
}
void nfc_device_data_clear(NfcDeviceData* dev_data) {
if(dev_data->nfc_data.protocol == NfcDeviceProtocolMifareDesfire) {
mf_df_clear(&dev_data->mf_df_data);
}
}
void nfc_device_clear(NfcDevice* dev) {
furi_assert(dev);
nfc_device_data_clear(&dev->dev_data);
memset(&dev->dev_data, 0, sizeof(dev->dev_data));
dev->format = NfcDeviceSaveFormatUid;
}

View File

@ -5,7 +5,9 @@
#include <storage/storage.h>
#include <dialogs/dialogs.h>
#include "mifare_ultralight.h"
#include <lib/nfc_protocols/mifare_ultralight.h>
#include <lib/nfc_protocols/mifare_classic.h>
#include <lib/nfc_protocols/mifare_desfire.h>
#define NFC_DEV_NAME_MAX_LEN 22
#define NFC_FILE_NAME_MAX_LEN 120
@ -26,12 +28,16 @@ typedef enum {
NfcDeviceProtocolUnknown,
NfcDeviceProtocolEMV,
NfcDeviceProtocolMifareUl,
NfcDeviceProtocolMifareClassic,
NfcDeviceProtocolMifareDesfire,
} NfcProtocol;
typedef enum {
NfcDeviceSaveFormatUid,
NfcDeviceSaveFormatBankCard,
NfcDeviceSaveFormatMifareUl,
NfcDeviceSaveFormatMifareClassic,
NfcDeviceSaveFormatMifareDesfire,
} NfcDeviceSaveFormat;
typedef struct {
@ -62,10 +68,12 @@ typedef struct {
typedef struct {
NfcDeviceCommonData nfc_data;
NfcReaderRequestData reader_data;
union {
NfcEmvData emv_data;
MifareUlData mf_ul_data;
NfcReaderRequestData reader_data;
MfClassicData mf_classic_data;
MifareDesfireData mf_df_data;
};
} NfcDeviceData;
@ -93,6 +101,8 @@ bool nfc_device_load(NfcDevice* dev, const char* file_path);
bool nfc_file_select(NfcDevice* dev);
void nfc_device_data_clear(NfcDeviceData* dev);
void nfc_device_clear(NfcDevice* dev);
bool nfc_device_delete(NfcDevice* dev);

View File

@ -24,6 +24,7 @@
#include <gui/modules/widget.h>
#include "views/bank_card.h"
#include "views/dict_attack.h"
#include <nfc/scenes/nfc_scene.h>
#include <nfc/helpers/nfc_custom_event.h>
@ -53,6 +54,7 @@ struct Nfc {
TextBox* text_box;
Widget* widget;
BankCard* bank_card;
DictAttack* dict_attack;
};
typedef enum {
@ -64,6 +66,7 @@ typedef enum {
NfcViewTextBox,
NfcViewWidget,
NfcViewBankCard,
NfcViewDictAttack,
} NfcView;
Nfc* nfc_alloc();

View File

@ -53,6 +53,10 @@ const char* nfc_guess_protocol(NfcProtocol protocol) {
return "EMV bank card";
} else if(protocol == NfcDeviceProtocolMifareUl) {
return "Mifare Ultral/NTAG";
} else if(protocol == NfcDeviceProtocolMifareClassic) {
return "Mifare Classic";
} else if(protocol == NfcDeviceProtocolMifareDesfire) {
return "Mifare DESFire";
} else {
return "Unrecognized";
}
@ -73,3 +77,13 @@ const char* nfc_mf_ul_type(MfUltralightType type, bool full_name) {
return "Mifare Ultralight";
}
}
const char* nfc_mf_classic_type(MfClassicType type) {
if(type == MfClassicType1k) {
return "Mifare Classic 1K";
} else if(type == MfClassicType4k) {
return "Mifare Classic 4K";
} else {
return "Mifare Classic";
}
}

View File

@ -15,3 +15,5 @@ const char* nfc_get_nfca_type(rfalNfcaListenDeviceType type);
const char* nfc_guess_protocol(NfcProtocol protocol);
const char* nfc_mf_ul_type(MfUltralightType type, bool full_name);
const char* nfc_mf_classic_type(MfClassicType type);

433
applications/nfc/nfc_worker.c Executable file → Normal file
View File

@ -1,7 +1,13 @@
#include "nfc_worker_i.h"
#include <furi_hal.h>
#include "nfc_protocols/emv_decoder.h"
#include "nfc_protocols/mifare_ultralight.h"
#include <lib/nfc_protocols/nfc_util.h>
#include <lib/nfc_protocols/emv_decoder.h>
#include <lib/nfc_protocols/mifare_ultralight.h>
#include <lib/nfc_protocols/mifare_classic.h>
#include <lib/nfc_protocols/mifare_desfire.h>
#include "helpers/nfc_mf_classic_dict.h"
#define TAG "NfcWorker"
@ -19,6 +25,7 @@ NfcWorker* nfc_worker_alloc() {
nfc_worker->callback = NULL;
nfc_worker->context = NULL;
nfc_worker->storage = furi_record_open("storage");
// Initialize rfal
while(furi_hal_nfc_is_busy()) {
@ -32,6 +39,7 @@ NfcWorker* nfc_worker_alloc() {
void nfc_worker_free(NfcWorker* nfc_worker) {
furi_assert(nfc_worker);
furi_thread_free(nfc_worker->thread);
furi_record_close("storage");
free(nfc_worker);
}
@ -94,6 +102,10 @@ int32_t nfc_worker_task(void* context) {
nfc_worker_read_mifare_ul(nfc_worker);
} else if(nfc_worker->state == NfcWorkerStateEmulateMifareUl) {
nfc_worker_emulate_mifare_ul(nfc_worker);
} else if(nfc_worker->state == NfcWorkerStateReadMifareClassic) {
nfc_worker_mifare_classic_dict_attack(nfc_worker);
} else if(nfc_worker->state == NfcWorkerStateReadMifareDesfire) {
nfc_worker_read_mifare_desfire(nfc_worker);
} else if(nfc_worker->state == NfcWorkerStateField) {
nfc_worker_field(nfc_worker);
}
@ -108,6 +120,7 @@ void nfc_worker_detect(NfcWorker* nfc_worker) {
rfalNfcDevice* dev_list;
rfalNfcDevice* dev;
uint8_t dev_cnt;
nfc_device_data_clear(nfc_worker->dev_data);
NfcDeviceCommonData* result = &nfc_worker->dev_data->nfc_data;
while(nfc_worker->state == NfcWorkerStateDetect) {
@ -126,6 +139,16 @@ void nfc_worker_detect(NfcWorker* nfc_worker) {
dev->dev.nfca.sensRes.platformInfo,
dev->dev.nfca.selRes.sak)) {
result->protocol = NfcDeviceProtocolMifareUl;
} else if(mf_classic_check_card_type(
dev->dev.nfca.sensRes.anticollisionInfo,
dev->dev.nfca.sensRes.platformInfo,
dev->dev.nfca.selRes.sak)) {
result->protocol = NfcDeviceProtocolMifareClassic;
} else if(mf_df_check_card_type(
dev->dev.nfca.sensRes.anticollisionInfo,
dev->dev.nfca.sensRes.platformInfo,
dev->dev.nfca.selRes.sak)) {
result->protocol = NfcDeviceProtocolMifareDesfire;
} else if(dev->rfInterface == RFAL_NFC_INTERFACE_ISODEP) {
result->protocol = NfcDeviceProtocolEMV;
} else {
@ -140,7 +163,7 @@ void nfc_worker_detect(NfcWorker* nfc_worker) {
}
// Notify caller and exit
if(nfc_worker->callback) {
nfc_worker->callback(nfc_worker->context);
nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context);
}
break;
}
@ -162,7 +185,7 @@ bool nfc_worker_emulate_uid_callback(
if(reader_data->size > 0) {
memcpy(reader_data->data, buff_rx, reader_data->size);
if(nfc_worker->callback) {
nfc_worker->callback(nfc_worker->context);
nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context);
}
}
return true;
@ -192,6 +215,7 @@ void nfc_worker_read_emv_app(NfcWorker* nfc_worker) {
uint8_t* rx_buff;
uint16_t* rx_len;
NfcDeviceData* result = nfc_worker->dev_data;
nfc_device_data_clear(result);
while(nfc_worker->state == NfcWorkerStateReadEMVApp) {
memset(&emv_app, 0, sizeof(emv_app));
@ -221,7 +245,7 @@ void nfc_worker_read_emv_app(NfcWorker* nfc_worker) {
result->emv_data.aid_len = emv_app.aid_len;
memcpy(result->emv_data.aid, emv_app.aid, emv_app.aid_len);
if(nfc_worker->callback) {
nfc_worker->callback(nfc_worker->context);
nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context);
}
break;
} else {
@ -253,6 +277,7 @@ void nfc_worker_read_emv(NfcWorker* nfc_worker) {
uint8_t* rx_buff;
uint16_t* rx_len;
NfcDeviceData* result = nfc_worker->dev_data;
nfc_device_data_clear(result);
while(nfc_worker->state == NfcWorkerStateReadEMV) {
memset(&emv_app, 0, sizeof(emv_app));
@ -318,7 +343,7 @@ void nfc_worker_read_emv(NfcWorker* nfc_worker) {
memcpy(result->emv_data.number, emv_app.card_number, emv_app.card_number_len);
// Notify caller and exit
if(nfc_worker->callback) {
nfc_worker->callback(nfc_worker->context);
nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context);
}
break;
} else {
@ -367,7 +392,7 @@ void nfc_worker_read_emv(NfcWorker* nfc_worker) {
}
// Notify caller and exit
if(nfc_worker->callback) {
nfc_worker->callback(nfc_worker->context);
nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context);
}
break;
} else {
@ -516,6 +541,7 @@ void nfc_worker_read_mifare_ul(NfcWorker* nfc_worker) {
uint16_t* rx_len;
MifareUlDevice mf_ul_read;
NfcDeviceData* result = nfc_worker->dev_data;
nfc_device_data_clear(result);
while(nfc_worker->state == NfcWorkerStateReadMifareUl) {
furi_hal_nfc_deactivate();
@ -621,7 +647,7 @@ void nfc_worker_read_mifare_ul(NfcWorker* nfc_worker) {
// Notify caller and exit
if(nfc_worker->callback) {
nfc_worker->callback(nfc_worker->context);
nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context);
}
break;
} else {
@ -651,13 +677,402 @@ void nfc_worker_emulate_mifare_ul(NfcWorker* nfc_worker) {
if(mf_ul_emulate.data_changed) {
nfc_worker->dev_data->mf_ul_data = mf_ul_emulate.data;
if(nfc_worker->callback) {
nfc_worker->callback(nfc_worker->context);
nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context);
}
mf_ul_emulate.data_changed = false;
}
}
}
void nfc_worker_mifare_classic_dict_attack(NfcWorker* nfc_worker) {
furi_assert(nfc_worker->callback);
rfalNfcDevice* dev_list;
rfalNfcDevice* dev;
NfcDeviceCommonData* nfc_common;
uint8_t dev_cnt = 0;
FuriHalNfcTxRxContext tx_rx_ctx = {};
MfClassicAuthContext auth_ctx = {};
MfClassicReader reader = {};
uint64_t curr_key = 0;
uint16_t curr_sector = 0;
uint8_t total_sectors = 0;
NfcWorkerEvent event;
// Open dictionary
nfc_worker->dict_stream = file_stream_alloc(nfc_worker->storage);
if(!nfc_mf_classic_dict_open_file(nfc_worker->dict_stream)) {
event = NfcWorkerEventNoDictFound;
nfc_worker->callback(event, nfc_worker->context);
nfc_mf_classic_dict_close_file(nfc_worker->dict_stream);
stream_free(nfc_worker->dict_stream);
return;
}
// Detect Mifare Classic card
while(nfc_worker->state == NfcWorkerStateReadMifareClassic) {
if(furi_hal_nfc_detect(&dev_list, &dev_cnt, 300, false)) {
dev = &dev_list[0];
if(mf_classic_get_type(
dev->nfcid,
dev->nfcidLen,
dev->dev.nfca.sensRes.anticollisionInfo,
dev->dev.nfca.sensRes.platformInfo,
dev->dev.nfca.selRes.sak,
&reader)) {
total_sectors = mf_classic_get_total_sectors_num(&reader);
if(reader.type == MfClassicType1k) {
event = NfcWorkerEventDetectedClassic1k;
} else {
event = NfcWorkerEventDetectedClassic4k;
}
nfc_worker->callback(event, nfc_worker->context);
break;
}
} else {
event = NfcWorkerEventNoCardDetected;
nfc_worker->callback(event, nfc_worker->context);
}
}
if(nfc_worker->state == NfcWorkerStateReadMifareClassic) {
bool card_removed_notified = false;
bool card_found_notified = false;
// Seek for mifare classic keys
for(curr_sector = 0; curr_sector < total_sectors; curr_sector++) {
FURI_LOG_I(TAG, "Sector: %d ...", curr_sector);
event = NfcWorkerEventNewSector;
nfc_worker->callback(event, nfc_worker->context);
mf_classic_auth_init_context(&auth_ctx, reader.cuid, curr_sector);
bool sector_key_found = false;
while(nfc_mf_classic_dict_get_next_key(nfc_worker->dict_stream, &curr_key)) {
furi_hal_nfc_deactivate();
if(furi_hal_nfc_activate_nfca(300, &reader.cuid)) {
if(!card_found_notified) {
if(reader.type == MfClassicType1k) {
event = NfcWorkerEventDetectedClassic1k;
} else {
event = NfcWorkerEventDetectedClassic4k;
}
nfc_worker->callback(event, nfc_worker->context);
card_found_notified = true;
card_removed_notified = false;
}
FURI_LOG_D(
TAG,
"Try to auth to sector %d with key %04lx%08lx",
curr_sector,
(uint32_t)(curr_key >> 32),
(uint32_t)curr_key);
if(mf_classic_auth_attempt(&tx_rx_ctx, &auth_ctx, curr_key)) {
sector_key_found = true;
if((auth_ctx.key_a != MF_CLASSIC_NO_KEY) &&
(auth_ctx.key_b != MF_CLASSIC_NO_KEY))
break;
}
} else {
// Notify that no tag is availalble
FURI_LOG_D(TAG, "Can't find tags");
if(!card_removed_notified) {
event = NfcWorkerEventNoCardDetected;
nfc_worker->callback(event, nfc_worker->context);
card_removed_notified = true;
card_found_notified = false;
}
}
if(nfc_worker->state != NfcWorkerStateReadMifareClassic) break;
}
if(nfc_worker->state != NfcWorkerStateReadMifareClassic) break;
if(sector_key_found) {
// Notify that keys were found
if(auth_ctx.key_a != MF_CLASSIC_NO_KEY) {
FURI_LOG_I(
TAG,
"Sector %d key A: %04lx%08lx",
curr_sector,
(uint32_t)(auth_ctx.key_a >> 32),
(uint32_t)auth_ctx.key_a);
event = NfcWorkerEventFoundKeyA;
nfc_worker->callback(event, nfc_worker->context);
}
if(auth_ctx.key_b != MF_CLASSIC_NO_KEY) {
FURI_LOG_I(
TAG,
"Sector %d key B: %04lx%08lx",
curr_sector,
(uint32_t)(auth_ctx.key_b >> 32),
(uint32_t)auth_ctx.key_b);
event = NfcWorkerEventFoundKeyB;
nfc_worker->callback(event, nfc_worker->context);
}
// Add sectors to read sequence
mf_classic_reader_add_sector(&reader, curr_sector, auth_ctx.key_a, auth_ctx.key_b);
}
nfc_mf_classic_dict_reset(nfc_worker->dict_stream);
}
}
if(nfc_worker->state == NfcWorkerStateReadMifareClassic) {
FURI_LOG_I(TAG, "Found keys to %d sectors. Start reading sectors", reader.sectors_to_read);
uint8_t sectors_read =
mf_classic_read_card(&tx_rx_ctx, &reader, &nfc_worker->dev_data->mf_classic_data);
if(sectors_read) {
dev = &dev_list[0];
nfc_common = &nfc_worker->dev_data->nfc_data;
nfc_common->uid_len = dev->dev.nfca.nfcId1Len;
nfc_common->atqa[0] = dev->dev.nfca.sensRes.anticollisionInfo;
nfc_common->atqa[1] = dev->dev.nfca.sensRes.platformInfo;
nfc_common->sak = dev->dev.nfca.selRes.sak;
nfc_common->protocol = NfcDeviceProtocolMifareClassic;
memcpy(nfc_common->uid, dev->dev.nfca.nfcId1, nfc_common->uid_len);
event = NfcWorkerEventSuccess;
FURI_LOG_I(TAG, "Successfully read %d sectors", sectors_read);
} else {
event = NfcWorkerEventFail;
FURI_LOG_W(TAG, "Failed to read any sector");
}
nfc_worker->callback(event, nfc_worker->context);
}
nfc_mf_classic_dict_close_file(nfc_worker->dict_stream);
stream_free(nfc_worker->dict_stream);
}
ReturnCode nfc_exchange_full(
uint8_t* tx_buff,
uint16_t tx_len,
uint8_t* rx_buff,
uint16_t rx_cap,
uint16_t* rx_len) {
ReturnCode err;
uint8_t* part_buff;
uint16_t* part_len;
err = furi_hal_nfc_data_exchange(tx_buff, tx_len, &part_buff, &part_len, false);
if(*part_len > rx_cap) {
return ERR_OVERRUN;
}
memcpy(rx_buff, part_buff, *part_len);
*rx_len = *part_len;
while(err == ERR_NONE && rx_buff[0] == 0xAF) {
err = furi_hal_nfc_data_exchange(rx_buff, 1, &part_buff, &part_len, false);
if(*part_len > rx_cap - *rx_len) {
return ERR_OVERRUN;
}
if(*part_len == 0) {
return ERR_PROTO;
}
memcpy(rx_buff + *rx_len, part_buff + 1, *part_len - 1);
*rx_buff = *part_buff;
*rx_len += *part_len - 1;
}
return err;
}
void nfc_worker_read_mifare_desfire(NfcWorker* nfc_worker) {
ReturnCode err;
rfalNfcDevice* dev_list;
uint8_t dev_cnt = 0;
uint8_t tx_buff[64] = {};
uint16_t tx_len = 0;
uint8_t rx_buff[512] = {};
uint16_t rx_len;
NfcDeviceData* result = nfc_worker->dev_data;
nfc_device_data_clear(result);
MifareDesfireData* data = &result->mf_df_data;
while(nfc_worker->state == NfcWorkerStateReadMifareDesfire) {
furi_hal_nfc_deactivate();
if(!furi_hal_nfc_detect(&dev_list, &dev_cnt, 300, false)) {
osDelay(100);
continue;
}
memset(data, 0, sizeof(MifareDesfireData));
if(dev_list[0].type != RFAL_NFC_LISTEN_TYPE_NFCA ||
!mf_df_check_card_type(
dev_list[0].dev.nfca.sensRes.anticollisionInfo,
dev_list[0].dev.nfca.sensRes.platformInfo,
dev_list[0].dev.nfca.selRes.sak)) {
FURI_LOG_D(TAG, "Tag is not DESFire");
osDelay(100);
continue;
}
FURI_LOG_D(TAG, "Found DESFire tag");
// Fill non-DESFire result data
result->nfc_data.uid_len = dev_list[0].dev.nfca.nfcId1Len;
result->nfc_data.atqa[0] = dev_list[0].dev.nfca.sensRes.anticollisionInfo;
result->nfc_data.atqa[1] = dev_list[0].dev.nfca.sensRes.platformInfo;
result->nfc_data.sak = dev_list[0].dev.nfca.selRes.sak;
result->nfc_data.device = NfcDeviceNfca;
result->nfc_data.protocol = NfcDeviceProtocolMifareDesfire;
memcpy(result->nfc_data.uid, dev_list[0].dev.nfca.nfcId1, result->nfc_data.uid_len);
// Get DESFire version
tx_len = mf_df_prepare_get_version(tx_buff);
err = nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len);
if(err != ERR_NONE) {
FURI_LOG_W(TAG, "Bad exchange getting version, err: %d", err);
continue;
}
if(!mf_df_parse_get_version_response(rx_buff, rx_len, &data->version)) {
FURI_LOG_W(TAG, "Bad DESFire GET_VERSION response");
continue;
}
tx_len = mf_df_prepare_get_free_memory(tx_buff);
err = nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len);
if(err == ERR_NONE) {
data->free_memory = malloc(sizeof(MifareDesfireFreeMemory));
memset(data->free_memory, 0, sizeof(MifareDesfireFreeMemory));
if(!mf_df_parse_get_free_memory_response(rx_buff, rx_len, data->free_memory)) {
FURI_LOG_D(TAG, "Bad DESFire GET_FREE_MEMORY response (normal for pre-EV1 cards)");
free(data->free_memory);
data->free_memory = NULL;
}
}
tx_len = mf_df_prepare_get_key_settings(tx_buff);
err = nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len);
if(err != ERR_NONE) {
FURI_LOG_D(TAG, "Bad exchange getting key settings, err: %d", err);
} else {
data->master_key_settings = malloc(sizeof(MifareDesfireKeySettings));
memset(data->master_key_settings, 0, sizeof(MifareDesfireKeySettings));
if(!mf_df_parse_get_key_settings_response(rx_buff, rx_len, data->master_key_settings)) {
FURI_LOG_W(TAG, "Bad DESFire GET_KEY_SETTINGS response");
free(data->master_key_settings);
data->master_key_settings = NULL;
}
MifareDesfireKeyVersion** key_version_head =
&data->master_key_settings->key_version_head;
for(uint8_t key_id = 0; key_id < data->master_key_settings->max_keys; key_id++) {
tx_len = mf_df_prepare_get_key_version(tx_buff, key_id);
err = nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len);
if(err != ERR_NONE) {
FURI_LOG_W(TAG, "Bad exchange getting key version, err: %d", err);
continue;
}
MifareDesfireKeyVersion* key_version = malloc(sizeof(MifareDesfireKeyVersion));
memset(key_version, 0, sizeof(MifareDesfireKeyVersion));
key_version->id = key_id;
if(!mf_df_parse_get_key_version_response(rx_buff, rx_len, key_version)) {
FURI_LOG_W(TAG, "Bad DESFire GET_KEY_VERSION response");
free(key_version);
continue;
}
*key_version_head = key_version;
key_version_head = &key_version->next;
}
}
tx_len = mf_df_prepare_get_application_ids(tx_buff);
err = nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len);
if(err != ERR_NONE) {
FURI_LOG_W(TAG, "Bad exchange getting application IDs, err: %d", err);
} else {
if(!mf_df_parse_get_application_ids_response(rx_buff, rx_len, &data->app_head)) {
FURI_LOG_W(TAG, "Bad DESFire GET_APPLICATION_IDS response");
}
}
for(MifareDesfireApplication* app = data->app_head; app; app = app->next) {
tx_len = mf_df_prepare_select_application(tx_buff, app->id);
err = nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len);
if(!mf_df_parse_select_application_response(rx_buff, rx_len)) {
FURI_LOG_W(TAG, "Bad exchange selecting application, err: %d", err);
continue;
}
tx_len = mf_df_prepare_get_key_settings(tx_buff);
err = nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len);
if(err != ERR_NONE) {
FURI_LOG_W(TAG, "Bad exchange getting key settings, err: %d", err);
} else {
app->key_settings = malloc(sizeof(MifareDesfireKeySettings));
memset(app->key_settings, 0, sizeof(MifareDesfireKeySettings));
if(!mf_df_parse_get_key_settings_response(rx_buff, rx_len, app->key_settings)) {
FURI_LOG_W(TAG, "Bad DESFire GET_KEY_SETTINGS response");
free(app->key_settings);
app->key_settings = NULL;
}
MifareDesfireKeyVersion** key_version_head = &app->key_settings->key_version_head;
for(uint8_t key_id = 0; key_id < app->key_settings->max_keys; key_id++) {
tx_len = mf_df_prepare_get_key_version(tx_buff, key_id);
err = nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len);
if(err != ERR_NONE) {
FURI_LOG_W(TAG, "Bad exchange getting key version, err: %d", err);
continue;
}
MifareDesfireKeyVersion* key_version = malloc(sizeof(MifareDesfireKeyVersion));
memset(key_version, 0, sizeof(MifareDesfireKeyVersion));
key_version->id = key_id;
if(!mf_df_parse_get_key_version_response(rx_buff, rx_len, key_version)) {
FURI_LOG_W(TAG, "Bad DESFire GET_KEY_VERSION response");
free(key_version);
continue;
}
*key_version_head = key_version;
key_version_head = &key_version->next;
}
}
tx_len = mf_df_prepare_get_file_ids(tx_buff);
err = nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len);
if(err != ERR_NONE) {
FURI_LOG_W(TAG, "Bad exchange getting file IDs, err: %d", err);
} else {
if(!mf_df_parse_get_file_ids_response(rx_buff, rx_len, &app->file_head)) {
FURI_LOG_W(TAG, "Bad DESFire GET_FILE_IDS response");
}
}
for(MifareDesfireFile* file = app->file_head; file; file = file->next) {
tx_len = mf_df_prepare_get_file_settings(tx_buff, file->id);
err = nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len);
if(err != ERR_NONE) {
FURI_LOG_W(TAG, "Bad exchange getting file settings, err: %d", err);
continue;
}
if(!mf_df_parse_get_file_settings_response(rx_buff, rx_len, file)) {
FURI_LOG_W(TAG, "Bad DESFire GET_FILE_SETTINGS response");
continue;
}
switch(file->type) {
case MifareDesfireFileTypeStandard:
case MifareDesfireFileTypeBackup:
tx_len = mf_df_prepare_read_data(tx_buff, file->id, 0, 0);
break;
case MifareDesfireFileTypeValue:
tx_len = mf_df_prepare_get_value(tx_buff, file->id);
break;
case MifareDesfireFileTypeLinearRecord:
case MifareDesfireFileTypeCyclicRecord:
tx_len = mf_df_prepare_read_records(tx_buff, file->id, 0, 0);
break;
}
err = nfc_exchange_full(tx_buff, tx_len, rx_buff, sizeof(rx_buff), &rx_len);
if(err != ERR_NONE) {
FURI_LOG_W(TAG, "Bad exchange reading file %d, err: %d", file->id, err);
continue;
}
if(!mf_df_parse_read_data_response(rx_buff, rx_len, file)) {
FURI_LOG_W(TAG, "Bad response reading file %d", file->id);
continue;
}
}
}
// Notify caller and exit
if(nfc_worker->callback) {
nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context);
}
break;
}
}
void nfc_worker_field(NfcWorker* nfc_worker) {
furi_hal_nfc_field_on();
while(nfc_worker->state == NfcWorkerStateField) {

View File

@ -18,11 +18,27 @@ typedef enum {
NfcWorkerStateField,
NfcWorkerStateReadMifareUl,
NfcWorkerStateEmulateMifareUl,
NfcWorkerStateReadMifareClassic,
NfcWorkerStateReadMifareDesfire,
// Transition
NfcWorkerStateStop,
} NfcWorkerState;
typedef void (*NfcWorkerCallback)(void* context);
typedef enum {
NfcWorkerEventSuccess,
NfcWorkerEventFail,
NfcWorkerEventNoCardDetected,
// Mifare Classic events
NfcWorkerEventNoDictFound,
NfcWorkerEventDetectedClassic1k,
NfcWorkerEventDetectedClassic4k,
NfcWorkerEventNewSector,
NfcWorkerEventFoundKeyA,
NfcWorkerEventFoundKeyB,
NfcWorkerEventStartReading,
} NfcWorkerEvent;
typedef void (*NfcWorkerCallback)(NfcWorkerEvent event, void* context);
NfcWorker* nfc_worker_alloc();

View File

@ -5,6 +5,7 @@
#include <furi.h>
#include <stdbool.h>
#include <lib/toolbox/stream/file_stream.h>
#include <rfal_analogConfig.h>
#include <rfal_rf.h>
@ -18,6 +19,8 @@
struct NfcWorker {
FuriThread* thread;
Storage* storage;
Stream* dict_stream;
NfcDeviceData* dev_data;
@ -45,4 +48,10 @@ void nfc_worker_field(NfcWorker* nfc_worker);
void nfc_worker_read_mifare_ul(NfcWorker* nfc_worker);
void nfc_worker_mifare_classic_dict_attack(NfcWorker* nfc_worker);
void nfc_worker_read_mifare_desfire(NfcWorker* nfc_worker);
void nfc_worker_emulate_mifare_ul(NfcWorker* nfc_worker);
void nfc_worker_emulate_mifare_classic(NfcWorker* nfc_worker);

View File

@ -8,13 +8,13 @@ enum SubmenuIndex {
};
void nfc_scene_card_menu_submenu_callback(void* context, uint32_t index) {
Nfc* nfc = (Nfc*)context;
Nfc* nfc = context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
}
void nfc_scene_card_menu_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
Nfc* nfc = context;
Submenu* submenu = nfc->submenu;
if(nfc->dev->dev_data.nfc_data.protocol > NfcDeviceProtocolUnknown) {
@ -42,7 +42,8 @@ void nfc_scene_card_menu_on_enter(void* context) {
}
bool nfc_scene_card_menu_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = (Nfc*)context;
Nfc* nfc = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubmenuIndexRunApp) {
@ -50,36 +51,40 @@ bool nfc_scene_card_menu_on_event(void* context, SceneManagerEvent event) {
nfc->scene_manager, NfcSceneCardMenu, SubmenuIndexRunApp);
if(nfc->dev->dev_data.nfc_data.protocol == NfcDeviceProtocolMifareUl) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadMifareUl);
} else if(nfc->dev->dev_data.nfc_data.protocol == NfcDeviceProtocolMifareDesfire) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadMifareDesfire);
} else if(nfc->dev->dev_data.nfc_data.protocol == NfcDeviceProtocolEMV) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadEmvApp);
} else if(nfc->dev->dev_data.nfc_data.protocol == NfcDeviceProtocolMifareClassic) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadMifareClassic);
}
return true;
consumed = true;
} else if(event.event == SubmenuIndexChooseScript) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneCardMenu, SubmenuIndexChooseScript);
scene_manager_next_scene(nfc->scene_manager, NfcSceneScriptsMenu);
return true;
consumed = true;
} else if(event.event == SubmenuIndexEmulate) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneCardMenu, SubmenuIndexEmulate);
scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid);
return true;
consumed = true;
} else if(event.event == SubmenuIndexSave) {
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneCardMenu, SubmenuIndexSave);
nfc->dev->format = NfcDeviceSaveFormatUid;
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
return true;
consumed = true;
}
} else if(event.type == SceneManagerEventTypeBack) {
return scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneStart);
consumed =
scene_manager_search_and_switch_to_previous_scene(nfc->scene_manager, NfcSceneStart);
}
return false;
return consumed;
}
void nfc_scene_card_menu_on_exit(void* context) {
Nfc* nfc = (Nfc*)context;
Nfc* nfc = context;
submenu_reset(nfc->submenu);
}

View File

@ -19,6 +19,11 @@ ADD_SCENE(nfc, mifare_ul_menu, MifareUlMenu)
ADD_SCENE(nfc, emulate_mifare_ul, EmulateMifareUl)
ADD_SCENE(nfc, read_emv_app, ReadEmvApp)
ADD_SCENE(nfc, read_emv_app_success, ReadEmvAppSuccess)
ADD_SCENE(nfc, read_mifare_desfire, ReadMifareDesfire)
ADD_SCENE(nfc, read_mifare_desfire_success, ReadMifareDesfireSuccess)
ADD_SCENE(nfc, mifare_desfire_menu, MifareDesfireMenu)
ADD_SCENE(nfc, mifare_desfire_data, MifareDesfireData)
ADD_SCENE(nfc, mifare_desfire_app, MifareDesfireApp)
ADD_SCENE(nfc, device_info, DeviceInfo)
ADD_SCENE(nfc, delete, Delete)
ADD_SCENE(nfc, delete_success, DeleteSuccess)
@ -29,3 +34,5 @@ ADD_SCENE(nfc, emulate_apdu_sequence, EmulateApduSequence)
ADD_SCENE(nfc, restore_original, RestoreOriginal)
ADD_SCENE(nfc, debug, Debug)
ADD_SCENE(nfc, field, Field)
ADD_SCENE(nfc, read_mifare_classic, ReadMifareClassic)
ADD_SCENE(nfc, dict_not_found, DictNotFound)

39
applications/nfc/scenes/nfc_scene_device_info.c Executable file → Normal file
View File

@ -30,13 +30,19 @@ void nfc_scene_device_info_bank_card_callback(GuiButtonType result, InputType ty
void nfc_scene_device_info_on_enter(void* context) {
Nfc* nfc = context;
bool data_display_supported = (nfc->dev->format == NfcDeviceSaveFormatUid) ||
(nfc->dev->format == NfcDeviceSaveFormatMifareUl) ||
(nfc->dev->format == NfcDeviceSaveFormatMifareDesfire) ||
(nfc->dev->format == NfcDeviceSaveFormatBankCard);
// Setup Custom Widget view
widget_add_text_box_element(
nfc->widget, 0, 0, 128, 22, AlignCenter, AlignCenter, nfc->dev->dev_name);
nfc->widget, 0, 0, 128, 22, AlignCenter, AlignTop, nfc->dev->dev_name);
widget_add_button_element(
nfc->widget, GuiButtonTypeLeft, "Back", nfc_scene_device_info_widget_callback, nfc);
widget_add_button_element(
nfc->widget, GuiButtonTypeRight, "Data", nfc_scene_device_info_widget_callback, nfc);
if(data_display_supported) {
widget_add_button_element(
nfc->widget, GuiButtonTypeRight, "Data", nfc_scene_device_info_widget_callback, nfc);
}
char uid_str[32];
NfcDeviceCommonData* data = &nfc->dev->dev_data.nfc_data;
if(data->uid_len == 4) {
@ -64,10 +70,13 @@ void nfc_scene_device_info_on_enter(void* context) {
widget_add_string_element(nfc->widget, 64, 21, AlignCenter, AlignTop, FontSecondary, uid_str);
const char* protocol_name = NULL;
if(data->protocol == NfcDeviceProtocolEMV) {
if(data->protocol == NfcDeviceProtocolEMV ||
data->protocol == NfcDeviceProtocolMifareDesfire) {
protocol_name = nfc_guess_protocol(data->protocol);
} else if(data->protocol == NfcDeviceProtocolMifareUl) {
protocol_name = nfc_mf_ul_type(nfc->dev->dev_data.mf_ul_data.type, false);
} else if(data->protocol == NfcDeviceProtocolMifareClassic) {
protocol_name = nfc_mf_classic_type(nfc->dev->dev_data.mf_classic_data.type);
}
if(protocol_name) {
widget_add_string_element(
@ -101,6 +110,25 @@ void nfc_scene_device_info_on_enter(void* context) {
nfc->text_box_store, "%02X%02X ", mf_ul_data->data[i], mf_ul_data->data[i + 1]);
}
text_box_set_text(text_box, string_get_cstr(nfc->text_box_store));
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareDesfire) {
MifareDesfireData* mf_df_data = &nfc->dev->dev_data.mf_df_data;
uint16_t n_apps = 0;
uint16_t n_files = 0;
for(MifareDesfireApplication* app = mf_df_data->app_head; app; app = app->next) {
n_apps++;
for(MifareDesfireFile* file = app->file_head; file; file = file->next) {
n_files++;
}
}
nfc_text_store_set(
nfc,
"%d application%s, %d file%s",
n_apps,
n_apps == 1 ? "" : "s",
n_files,
n_files == 1 ? "" : "s");
widget_add_string_element(
nfc->widget, 64, 17, AlignCenter, AlignBottom, FontSecondary, nfc->text_store);
} else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) {
NfcEmvData* emv_data = &nfc->dev->dev_data.emv_data;
BankCard* bank_card = nfc->bank_card;
@ -162,6 +190,9 @@ bool nfc_scene_device_info_on_event(void* context, SceneManagerEvent event) {
nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoData);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewBankCard);
consumed = true;
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareDesfire) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMifareDesfireData);
consumed = true;
}
} else if(state == NfcSceneDeviceInfoData && event.event == NfcCustomEventViewExit) {
scene_manager_set_scene_state(

View File

@ -0,0 +1,52 @@
#include "../nfc_i.h"
void nfc_scene_dict_not_found_popup_callback(void* context) {
Nfc* nfc = context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit);
}
void nfc_scene_dict_not_found_on_enter(void* context) {
Nfc* nfc = context;
// Setup view
Popup* popup = nfc->popup;
popup_set_text(
popup,
"Function requires\nan SD card with\nfresh databases.",
82,
24,
AlignCenter,
AlignCenter);
popup_set_icon(popup, 6, 10, &I_SDQuestion_35x43);
popup_set_timeout(popup, 2500);
popup_set_context(popup, nfc);
popup_set_callback(popup, nfc_scene_dict_not_found_popup_callback);
popup_enable_timeout(popup);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
}
bool nfc_scene_dict_not_found_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventViewExit) {
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneScriptsMenu)) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneScriptsMenu);
} else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneCardMenu)) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneCardMenu);
} else {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneStart);
}
}
}
return consumed;
}
void nfc_scene_dict_not_found_on_exit(void* context) {
Nfc* nfc = context;
popup_reset(nfc->popup);
}

View File

@ -4,7 +4,7 @@
#define NFC_MF_UL_DATA_NOT_CHANGED (0UL)
#define NFC_MF_UL_DATA_CHANGED (1UL)
void nfc_emulate_mifare_ul_worker_callback(void* context) {
void nfc_emulate_mifare_ul_worker_callback(NfcWorkerEvent event, void* context) {
Nfc* nfc = (Nfc*)context;
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneEmulateMifareUl, NFC_MF_UL_DATA_CHANGED);

View File

@ -6,7 +6,7 @@ enum {
NfcSceneEmulateUidStateTextBox,
};
void nfc_emulate_uid_worker_callback(void* context) {
void nfc_emulate_uid_worker_callback(NfcWorkerEvent event, void* context) {
furi_assert(context);
Nfc* nfc = context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit);

View File

@ -0,0 +1,119 @@
#include "../nfc_i.h"
#define TAG "NfcSceneMifareDesfireApp"
enum SubmenuIndex {
SubmenuIndexAppInfo,
SubmenuIndexDynamic, // dynamic indexes start here
};
MifareDesfireApplication* nfc_scene_mifare_desfire_app_get_app(Nfc* nfc) {
uint32_t app_idx =
scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMifareDesfireApp) >> 1;
MifareDesfireApplication* app = nfc->dev->dev_data.mf_df_data.app_head;
for(int i = 0; i < app_idx && app; i++) {
app = app->next;
}
return app;
}
void nfc_scene_mifare_desfire_app_submenu_callback(void* context, uint32_t index) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
}
void nfc_scene_mifare_desfire_app_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
Submenu* submenu = nfc->submenu;
MifareDesfireApplication* app = nfc_scene_mifare_desfire_app_get_app(nfc);
if(!app) {
popup_set_icon(nfc->popup, 5, 5, &I_WarningDolphin_45x42);
popup_set_header(nfc->popup, "Internal Error!", 55, 12, AlignLeft, AlignBottom);
popup_set_text(
nfc->popup,
"No app selected.\nThis should\nnever happen,\nplease file a bug.",
55,
15,
AlignLeft,
AlignTop);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
FURI_LOG_E(TAG, "Bad state. No app selected?");
return;
}
text_box_set_font(nfc->text_box, TextBoxFontHex);
submenu_add_item(
submenu,
"App info",
SubmenuIndexAppInfo,
nfc_scene_mifare_desfire_app_submenu_callback,
nfc);
uint16_t cap = NFC_TEXT_STORE_SIZE;
char* buf = nfc->text_store;
int idx = SubmenuIndexDynamic;
for(MifareDesfireFile* file = app->file_head; file; file = file->next) {
int size = snprintf(buf, cap, "File %d", file->id);
if(size < 0 || size >= cap) {
FURI_LOG_W(
TAG,
"Exceeded NFC_TEXT_STORE_SIZE when preparing file id strings; menu truncated");
break;
}
char* label = buf;
cap -= size + 1;
buf += size + 1;
submenu_add_item(
submenu, label, idx++, nfc_scene_mifare_desfire_app_submenu_callback, nfc);
}
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
}
bool nfc_scene_mifare_desfire_app_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = (Nfc*)context;
uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMifareDesfireApp);
if(event.type == SceneManagerEventTypeCustom) {
MifareDesfireApplication* app = nfc_scene_mifare_desfire_app_get_app(nfc);
TextBox* text_box = nfc->text_box;
string_reset(nfc->text_box_store);
if(event.event == SubmenuIndexAppInfo) {
mf_df_cat_application_info(app, nfc->text_box_store);
} else {
uint16_t index = event.event - SubmenuIndexDynamic;
MifareDesfireFile* file = app->file_head;
for(int i = 0; file && i < index; i++) {
file = file->next;
}
if(!file) {
return false;
}
mf_df_cat_file(file, nfc->text_box_store);
}
text_box_set_text(text_box, string_get_cstr(nfc->text_box_store));
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMifareDesfireApp, state | 1);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox);
return true;
} else if(event.type == SceneManagerEventTypeBack) {
if(state & 1) {
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneMifareDesfireApp, state & ~1);
return true;
}
}
return false;
}
void nfc_scene_mifare_desfire_app_on_exit(void* context) {
Nfc* nfc = (Nfc*)context;
text_box_reset(nfc->text_box);
string_reset(nfc->text_box_store);
submenu_reset(nfc->submenu);
}

View File

@ -0,0 +1,108 @@
#include "../nfc_i.h"
#define TAG "NfcSceneMifareDesfireData"
enum {
MifareDesfireDataStateMenu,
MifareDesfireDataStateItem, // MUST be last, states >= this correspond with submenu index
};
enum SubmenuIndex {
SubmenuIndexCardInfo,
SubmenuIndexDynamic, // dynamic indexes start here
};
void nfc_scene_mifare_desfire_data_submenu_callback(void* context, uint32_t index) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
}
void nfc_scene_mifare_desfire_data_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
Submenu* submenu = nfc->submenu;
uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMifareDesfireData);
MifareDesfireData* data = &nfc->dev->dev_data.mf_df_data;
text_box_set_font(nfc->text_box, TextBoxFontHex);
submenu_add_item(
submenu,
"Card info",
SubmenuIndexCardInfo,
nfc_scene_mifare_desfire_data_submenu_callback,
nfc);
uint16_t cap = NFC_TEXT_STORE_SIZE;
char* buf = nfc->text_store;
int idx = SubmenuIndexDynamic;
for(MifareDesfireApplication* app = data->app_head; app; app = app->next) {
int size = snprintf(buf, cap, "App %02x%02x%02x", app->id[0], app->id[1], app->id[2]);
if(size < 0 || size >= cap) {
FURI_LOG_W(
TAG, "Exceeded NFC_TEXT_STORE_SIZE when preparing app id strings; menu truncated");
break;
}
char* label = buf;
cap -= size + 1;
buf += size + 1;
submenu_add_item(
submenu, label, idx++, nfc_scene_mifare_desfire_data_submenu_callback, nfc);
}
if(state >= MifareDesfireDataStateItem) {
submenu_set_selected_item(
nfc->submenu, state - MifareDesfireDataStateItem + SubmenuIndexDynamic);
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneMifareDesfireData, MifareDesfireDataStateMenu);
}
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
}
bool nfc_scene_mifare_desfire_data_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = (Nfc*)context;
uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMifareDesfireData);
MifareDesfireData* data = &nfc->dev->dev_data.mf_df_data;
if(event.type == SceneManagerEventTypeCustom) {
TextBox* text_box = nfc->text_box;
string_reset(nfc->text_box_store);
if(event.event == SubmenuIndexCardInfo) {
mf_df_cat_card_info(data, nfc->text_box_store);
text_box_set_text(text_box, string_get_cstr(nfc->text_box_store));
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox);
scene_manager_set_scene_state(
nfc->scene_manager,
NfcSceneMifareDesfireData,
MifareDesfireDataStateItem + SubmenuIndexCardInfo);
return true;
} else {
uint16_t index = event.event - SubmenuIndexDynamic;
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneMifareDesfireData, MifareDesfireDataStateItem + index);
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneMifareDesfireApp, index << 1);
scene_manager_next_scene(nfc->scene_manager, NfcSceneMifareDesfireApp);
return true;
}
} else if(event.type == SceneManagerEventTypeBack) {
if(state >= MifareDesfireDataStateItem) {
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneMifareDesfireData, MifareDesfireDataStateMenu);
return true;
}
}
return false;
}
void nfc_scene_mifare_desfire_data_on_exit(void* context) {
Nfc* nfc = (Nfc*)context;
text_box_reset(nfc->text_box);
string_reset(nfc->text_box_store);
submenu_reset(nfc->submenu);
}

View File

@ -0,0 +1,52 @@
#include "../nfc_i.h"
enum SubmenuIndex {
SubmenuIndexSave,
};
void nfc_scene_mifare_desfire_menu_submenu_callback(void* context, uint32_t index) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
}
void nfc_scene_mifare_desfire_menu_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
Submenu* submenu = nfc->submenu;
submenu_add_item(
submenu,
"Name and save",
SubmenuIndexSave,
nfc_scene_mifare_desfire_menu_submenu_callback,
nfc);
submenu_set_selected_item(
nfc->submenu,
scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMifareDesfireMenu));
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
}
bool nfc_scene_mifare_desfire_menu_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = (Nfc*)context;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubmenuIndexSave) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneMifareDesfireMenu, SubmenuIndexSave);
nfc->dev->format = NfcDeviceSaveFormatMifareDesfire;
// Clear device name
nfc_device_set_name(nfc->dev, "");
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
return true;
}
}
return false;
}
void nfc_scene_mifare_desfire_menu_on_exit(void* context) {
Nfc* nfc = (Nfc*)context;
submenu_reset(nfc->submenu);
}

View File

@ -1,7 +1,7 @@
#include "../nfc_i.h"
#include <dolphin/dolphin.h>
void nfc_read_card_worker_callback(void* context) {
void nfc_read_card_worker_callback(NfcWorkerEvent event, void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit);
}

View File

@ -1,7 +1,7 @@
#include "../nfc_i.h"
#include <dolphin/dolphin.h>
void nfc_read_emv_app_worker_callback(void* context) {
void nfc_read_emv_app_worker_callback(NfcWorkerEvent event, void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit);
}

View File

@ -1,7 +1,7 @@
#include "../nfc_i.h"
#include <dolphin/dolphin.h>
void nfc_read_emv_data_worker_callback(void* context) {
void nfc_read_emv_data_worker_callback(NfcWorkerEvent event, void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit);
}

View File

@ -0,0 +1,95 @@
#include "../nfc_i.h"
enum {
NfcSceneReadMifareClassicStateInProgress,
NfcSceneReadMifareClassicStateDone,
};
void nfc_read_mifare_classic_worker_callback(NfcWorkerEvent event, void* context) {
furi_assert(context);
Nfc* nfc = context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, event);
}
void nfc_read_mifare_classic_dict_attack_result_callback(void* context) {
furi_assert(context);
Nfc* nfc = context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventDictAttackDone);
}
void nfc_scene_read_mifare_classic_on_enter(void* context) {
Nfc* nfc = context;
// Setup and start worker
memset(&nfc->dev->dev_data.mf_classic_data, 0, sizeof(MfClassicData));
dict_attack_set_result_callback(
nfc->dict_attack, nfc_read_mifare_classic_dict_attack_result_callback, nfc);
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneReadMifareClassic, NfcSceneReadMifareClassicStateInProgress);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDictAttack);
nfc_worker_start(
nfc->worker,
NfcWorkerStateReadMifareClassic,
&nfc->dev->dev_data,
nfc_read_mifare_classic_worker_callback,
nfc);
}
bool nfc_scene_read_mifare_classic_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = context;
bool consumed = false;
uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadMifareClassic);
if(event.type == SceneManagerEventTypeTick) {
if(state == NfcSceneReadMifareClassicStateInProgress) {
notification_message(nfc->notifications, &sequence_blink_blue_10);
}
consumed = true;
} else if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventDictAttackDone) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
consumed = true;
} else if(event.event == NfcWorkerEventDetectedClassic1k) {
dict_attack_card_detected(nfc->dict_attack, MfClassicType1k);
consumed = true;
} else if(event.event == NfcWorkerEventDetectedClassic4k) {
dict_attack_card_detected(nfc->dict_attack, MfClassicType4k);
consumed = true;
} else if(event.event == NfcWorkerEventNewSector) {
dict_attack_inc_curr_sector(nfc->dict_attack);
consumed = true;
} else if(event.event == NfcWorkerEventFoundKeyA) {
dict_attack_inc_found_key(nfc->dict_attack, MfClassicKeyA);
consumed = true;
} else if(event.event == NfcWorkerEventFoundKeyB) {
dict_attack_inc_found_key(nfc->dict_attack, MfClassicKeyB);
consumed = true;
} else if(event.event == NfcWorkerEventNoCardDetected) {
dict_attack_card_removed(nfc->dict_attack);
consumed = true;
} else if(event.event == NfcWorkerEventSuccess) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneReadMifareClassic, NfcSceneReadMifareClassicStateDone);
notification_message(nfc->notifications, &sequence_success);
nfc->dev->format = NfcDeviceSaveFormatMifareClassic;
dict_attack_set_result(nfc->dict_attack, true);
consumed = true;
} else if(event.event == NfcWorkerEventFail) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneReadMifareClassic, NfcSceneReadMifareClassicStateDone);
dict_attack_set_result(nfc->dict_attack, false);
consumed = true;
} else if(event.event == NfcWorkerEventNoDictFound) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneDictNotFound);
consumed = true;
}
}
return consumed;
}
void nfc_scene_read_mifare_classic_on_exit(void* context) {
Nfc* nfc = context;
// Stop worker
nfc_worker_stop(nfc->worker);
dict_attack_reset(nfc->dict_attack);
}

View File

@ -0,0 +1,56 @@
#include "../nfc_i.h"
#include <dolphin/dolphin.h>
void nfc_read_mifare_desfire_worker_callback(NfcWorkerEvent event, void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit);
}
void nfc_scene_read_mifare_desfire_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
DOLPHIN_DEED(DolphinDeedNfcRead);
// Setup view
Popup* popup = nfc->popup;
popup_set_header(popup, "Reading\nDESFire", 70, 34, AlignLeft, AlignTop);
popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
// Start worker
nfc_worker_start(
nfc->worker,
NfcWorkerStateReadMifareDesfire,
&nfc->dev->dev_data,
nfc_read_mifare_desfire_worker_callback,
nfc);
}
bool nfc_scene_read_mifare_desfire_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = (Nfc*)context;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventWorkerExit) {
notification_message(nfc->notifications, &sequence_success);
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadMifareDesfireSuccess);
return true;
}
} else if(event.type == SceneManagerEventTypeTick) {
notification_message(nfc->notifications, &sequence_blink_blue_10);
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
return true;
}
return false;
}
void nfc_scene_read_mifare_desfire_on_exit(void* context) {
Nfc* nfc = (Nfc*)context;
// Stop worker
nfc_worker_stop(nfc->worker);
// Clear view
Popup* popup = nfc->popup;
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
popup_set_icon(popup, 0, 0, NULL);
}

View File

@ -0,0 +1,106 @@
#include "../nfc_i.h"
#include <dolphin/dolphin.h>
#define NFC_SCENE_READ_SUCCESS_SHIFT " "
enum {
ReadMifareDesfireSuccessStateShowUID,
ReadMifareDesfireSuccessStateShowData,
};
void nfc_scene_read_mifare_desfire_success_dialog_callback(DialogExResult result, void* context) {
Nfc* nfc = (Nfc*)context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
}
void nfc_scene_read_mifare_desfire_success_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
MifareDesfireData* data = &nfc->dev->dev_data.mf_df_data;
DialogEx* dialog_ex = nfc->dialog_ex;
dialog_ex_set_left_button_text(dialog_ex, "Back");
dialog_ex_set_center_button_text(dialog_ex, "Data");
dialog_ex_set_right_button_text(dialog_ex, "More");
dialog_ex_set_icon(dialog_ex, 8, 16, &I_Medium_chip_22x21);
uint16_t n_apps = 0;
uint16_t n_files = 0;
for(MifareDesfireApplication* app = data->app_head; app; app = app->next) {
n_apps++;
for(MifareDesfireFile* file = app->file_head; file; file = file->next) {
n_files++;
}
}
nfc_text_store_set(
nfc,
"UID: %02X %02X %02X %02X %02X %02X %02X\n" NFC_SCENE_READ_SUCCESS_SHIFT
"%d%s bytes\n" NFC_SCENE_READ_SUCCESS_SHIFT "%d bytes free\n"
"%d application%s, %d file%s",
data->version.uid[0],
data->version.uid[1],
data->version.uid[2],
data->version.uid[3],
data->version.uid[4],
data->version.uid[5],
data->version.uid[6],
1 << (data->version.sw_storage >> 1),
(data->version.sw_storage & 1) ? "+" : "",
data->free_memory ? data->free_memory->bytes : 0,
n_apps,
n_apps == 1 ? "" : "s",
n_files,
n_files == 1 ? "" : "s");
dialog_ex_set_text(dialog_ex, nfc->text_store, 8, 6, AlignLeft, AlignTop);
dialog_ex_set_context(dialog_ex, nfc);
dialog_ex_set_result_callback(
dialog_ex, nfc_scene_read_mifare_desfire_success_dialog_callback);
scene_manager_set_scene_state(
nfc->scene_manager,
NfcSceneReadMifareDesfireSuccess,
ReadMifareDesfireSuccessStateShowUID);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx);
}
bool nfc_scene_read_mifare_desfire_success_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = context;
uint32_t state =
scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadMifareDesfireSuccess);
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(state == ReadMifareDesfireSuccessStateShowUID && event.event == DialogExResultLeft) {
scene_manager_previous_scene(nfc->scene_manager);
consumed = true;
} else if(
state == ReadMifareDesfireSuccessStateShowUID && event.event == DialogExResultCenter) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMifareDesfireData);
consumed = true;
} else if(state == ReadMifareDesfireSuccessStateShowUID && event.event == DialogExResultRight) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMifareDesfireMenu);
consumed = true;
}
} else if(event.type == SceneManagerEventTypeBack) {
if(state == ReadMifareDesfireSuccessStateShowData) {
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx);
scene_manager_set_scene_state(
nfc->scene_manager,
NfcSceneReadMifareDesfireSuccess,
ReadMifareDesfireSuccessStateShowUID);
consumed = true;
}
}
return consumed;
}
void nfc_scene_read_mifare_desfire_success_on_exit(void* context) {
Nfc* nfc = (Nfc*)context;
// Clean dialog
DialogEx* dialog_ex = nfc->dialog_ex;
dialog_ex_reset(dialog_ex);
}

View File

@ -1,13 +1,13 @@
#include "../nfc_i.h"
#include <dolphin/dolphin.h>
void nfc_read_mifare_ul_worker_callback(void* context) {
Nfc* nfc = (Nfc*)context;
void nfc_read_mifare_ul_worker_callback(NfcWorkerEvent event, void* context) {
Nfc* nfc = context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit);
}
void nfc_scene_read_mifare_ul_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
Nfc* nfc = context;
DOLPHIN_DEED(DolphinDeedNfcRead);
// Setup view
@ -26,29 +26,25 @@ void nfc_scene_read_mifare_ul_on_enter(void* context) {
}
bool nfc_scene_read_mifare_ul_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = (Nfc*)context;
Nfc* nfc = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventWorkerExit) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadMifareUlSuccess);
return true;
consumed = true;
}
} else if(event.type == SceneManagerEventTypeTick) {
notification_message(nfc->notifications, &sequence_blink_blue_10);
return true;
consumed = true;
}
return false;
return consumed;
}
void nfc_scene_read_mifare_ul_on_exit(void* context) {
Nfc* nfc = (Nfc*)context;
Nfc* nfc = context;
// Stop worker
nfc_worker_stop(nfc->worker);
// Clear view
Popup* popup = nfc->popup;
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
popup_set_icon(popup, 0, 0, NULL);
popup_reset(nfc->popup);
}

4
applications/nfc/scenes/nfc_scene_save_success.c Executable file → Normal file
View File

@ -33,6 +33,10 @@ bool nfc_scene_save_success_on_event(void* context, SceneManagerEvent event) {
} else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetType)) {
consumed = scene_manager_search_and_switch_to_another_scene(
nfc->scene_manager, NfcSceneFileSelect);
} else if(scene_manager_has_previous_scene(
nfc->scene_manager, NfcSceneMifareDesfireMenu)) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneMifareDesfireMenu);
} else {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneStart);

17
applications/nfc/scenes/nfc_scene_saved_menu.c Executable file → Normal file
View File

@ -18,9 +18,22 @@ void nfc_scene_saved_menu_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
Submenu* submenu = nfc->submenu;
if(nfc->dev->format != NfcDeviceSaveFormatBankCard) {
if(nfc->dev->format == NfcDeviceSaveFormatUid ||
nfc->dev->format == NfcDeviceSaveFormatMifareDesfire ||
nfc->dev->format == NfcDeviceSaveFormatBankCard) {
submenu_add_item(
submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_saved_menu_submenu_callback, nfc);
submenu,
"Emulate UID",
SubmenuIndexEmulate,
nfc_scene_saved_menu_submenu_callback,
nfc);
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) {
submenu_add_item(
submenu,
"Emulate Ultralight",
SubmenuIndexEmulate,
nfc_scene_saved_menu_submenu_callback,
nfc);
}
submenu_add_item(
submenu, "Edit UID and name", SubmenuIndexEdit, nfc_scene_saved_menu_submenu_callback, nfc);

View File

@ -3,16 +3,17 @@
enum SubmenuIndex {
SubmenuIndexBankCard,
SubmenuIndexMifareUltralight,
SubmenuIdexReadMfClassic,
SubmenuIndexMifareDesfire,
};
void nfc_scene_scripts_menu_submenu_callback(void* context, uint32_t index) {
Nfc* nfc = (Nfc*)context;
Nfc* nfc = context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
}
void nfc_scene_scripts_menu_on_enter(void* context) {
Nfc* nfc = (Nfc*)context;
Nfc* nfc = context;
Submenu* submenu = nfc->submenu;
submenu_add_item(
@ -27,33 +28,55 @@ void nfc_scene_scripts_menu_on_enter(void* context) {
SubmenuIndexMifareUltralight,
nfc_scene_scripts_menu_submenu_callback,
nfc);
submenu_add_item(
submenu,
"Read Mifare Classic",
SubmenuIdexReadMfClassic,
nfc_scene_scripts_menu_submenu_callback,
nfc);
submenu_add_item(
submenu,
"Read Mifare DESFire",
SubmenuIndexMifareDesfire,
nfc_scene_scripts_menu_submenu_callback,
nfc);
submenu_set_selected_item(
nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneScriptsMenu));
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
}
bool nfc_scene_scripts_menu_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = (Nfc*)context;
Nfc* nfc = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubmenuIndexBankCard) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneScriptsMenu, SubmenuIndexBankCard);
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadEmvApp);
return true;
consumed = true;
} else if(event.event == SubmenuIndexMifareUltralight) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneScriptsMenu, SubmenuIndexMifareUltralight);
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadMifareUl);
return true;
consumed = true;
} else if(event.event == SubmenuIdexReadMfClassic) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneScriptsMenu, SubmenuIdexReadMfClassic);
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadMifareClassic);
consumed = true;
} else if(event.event == SubmenuIndexMifareDesfire) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneScriptsMenu, SubmenuIndexMifareDesfire);
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadMifareDesfire);
consumed = true;
}
}
return false;
return consumed;
}
void nfc_scene_scripts_menu_on_exit(void* context) {
Nfc* nfc = (Nfc*)context;
Nfc* nfc = context;
submenu_reset(nfc->submenu);
}

View File

@ -49,21 +49,15 @@ bool nfc_scene_start_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubmenuIndexRead) {
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, SubmenuIndexRead);
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadCard);
consumed = true;
} else if(event.event == SubmenuIndexRunScript) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneStart, SubmenuIndexRunScript);
scene_manager_next_scene(nfc->scene_manager, NfcSceneScriptsMenu);
consumed = true;
} else if(event.event == SubmenuIndexSaved) {
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, SubmenuIndexSaved);
scene_manager_next_scene(nfc->scene_manager, NfcSceneFileSelect);
consumed = true;
} else if(event.event == SubmenuIndexAddManualy) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneStart, SubmenuIndexAddManualy);
scene_manager_next_scene(nfc->scene_manager, NfcSceneSetType);
consumed = true;
} else if(event.event == SubmenuIndexDebug) {
@ -71,6 +65,7 @@ bool nfc_scene_start_on_event(void* context, SceneManagerEvent event) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneDebug);
consumed = true;
}
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, event.event);
}
return consumed;
}

View File

@ -0,0 +1,194 @@
#include "dict_attack.h"
#include <m-string.h>
#include <gui/elements.h>
typedef enum {
DictAttackStateSearchCard,
DictAttackStateSearchKeys,
DictAttackStateCardRemoved,
DictAttackStateSuccess,
DictAttackStateFail,
} DictAttackState;
struct DictAttack {
View* view;
DictAttackResultCallback callback;
void* context;
};
typedef struct {
DictAttackState state;
MfClassicType type;
uint8_t current_sector;
uint8_t total_sectors;
uint8_t keys_a_found;
uint8_t keys_a_total;
uint8_t keys_b_found;
uint8_t keys_b_total;
} DictAttackViewModel;
static void dict_attack_draw_callback(Canvas* canvas, void* model) {
DictAttackViewModel* m = model;
if(m->state == DictAttackStateSearchCard) {
canvas_set_font(canvas, FontPrimary);
canvas_draw_str_aligned(
canvas, 64, 32, AlignCenter, AlignCenter, "Detecting Mifare Classic");
} else if(m->state == DictAttackStateCardRemoved) {
canvas_set_font(canvas, FontPrimary);
canvas_draw_str_aligned(
canvas, 64, 32, AlignCenter, AlignTop, "Place card back to flipper");
} else {
char draw_str[32];
if(m->state == DictAttackStateSearchKeys) {
snprintf(
draw_str, sizeof(draw_str), "Searching keys for sector %d", m->current_sector);
canvas_draw_str_aligned(canvas, 64, 2, AlignCenter, AlignTop, draw_str);
} else if(m->state == DictAttackStateSuccess) {
canvas_draw_str_aligned(canvas, 64, 2, AlignCenter, AlignTop, "Complete!");
elements_button_right(canvas, "Save");
} else if(m->state == DictAttackStateFail) {
canvas_draw_str_aligned(
canvas, 64, 2, AlignCenter, AlignTop, "Failed to read any sector");
}
uint16_t keys_found = m->keys_a_found + m->keys_b_found;
uint16_t keys_total = m->keys_a_total + m->keys_b_total;
float progress = (float)(m->current_sector) / (float)(m->total_sectors);
elements_progress_bar(canvas, 5, 12, 120, progress);
canvas_set_font(canvas, FontSecondary);
snprintf(draw_str, sizeof(draw_str), "Total keys found: %d/%d", keys_found, keys_total);
canvas_draw_str_aligned(canvas, 1, 23, AlignLeft, AlignTop, draw_str);
snprintf(
draw_str, sizeof(draw_str), "A keys found: %d/%d", m->keys_a_found, m->keys_a_total);
canvas_draw_str_aligned(canvas, 1, 34, AlignLeft, AlignTop, draw_str);
snprintf(
draw_str, sizeof(draw_str), "B keys found: %d/%d", m->keys_b_found, m->keys_b_total);
canvas_draw_str_aligned(canvas, 1, 45, AlignLeft, AlignTop, draw_str);
}
}
static bool dict_attack_input_callback(InputEvent* event, void* context) {
DictAttack* dict_attack = context;
bool consumed = false;
DictAttackState state;
with_view_model(
dict_attack->view, (DictAttackViewModel * model) {
state = model->state;
return false;
});
if(state == DictAttackStateSuccess && event->type == InputTypeShort &&
event->key == InputKeyRight) {
if(dict_attack->callback) {
dict_attack->callback(dict_attack->context);
}
consumed = true;
}
return consumed;
}
DictAttack* dict_attack_alloc() {
DictAttack* dict_attack = malloc(sizeof(DictAttack));
dict_attack->view = view_alloc();
view_allocate_model(dict_attack->view, ViewModelTypeLocking, sizeof(DictAttackViewModel));
view_set_draw_callback(dict_attack->view, dict_attack_draw_callback);
view_set_input_callback(dict_attack->view, dict_attack_input_callback);
view_set_context(dict_attack->view, dict_attack);
return dict_attack;
}
void dict_attack_free(DictAttack* dict_attack) {
furi_assert(dict_attack);
view_free(dict_attack->view);
free(dict_attack);
}
void dict_attack_reset(DictAttack* dict_attack) {
furi_assert(dict_attack);
with_view_model(
dict_attack->view, (DictAttackViewModel * model) {
memset(model, 0, sizeof(DictAttackViewModel));
return true;
});
}
View* dict_attack_get_view(DictAttack* dict_attack) {
furi_assert(dict_attack);
return dict_attack->view;
}
void dict_attack_set_result_callback(
DictAttack* dict_attack,
DictAttackResultCallback callback,
void* context) {
furi_assert(dict_attack);
furi_assert(callback);
dict_attack->callback = callback;
dict_attack->context = context;
}
void dict_attack_card_detected(DictAttack* dict_attack, MfClassicType type) {
furi_assert(dict_attack);
with_view_model(
dict_attack->view, (DictAttackViewModel * model) {
model->state = DictAttackStateSearchKeys;
if(type == MfClassicType1k) {
model->total_sectors = 16;
model->keys_a_total = 16;
model->keys_b_total = 16;
} else if(type == MfClassicType4k) {
model->total_sectors = 40;
model->keys_a_total = 40;
model->keys_b_total = 40;
}
return true;
});
}
void dict_attack_card_removed(DictAttack* dict_attack) {
furi_assert(dict_attack);
with_view_model(
dict_attack->view, (DictAttackViewModel * model) {
if(model->state == DictAttackStateSearchKeys) {
model->state = DictAttackStateCardRemoved;
} else {
model->state = DictAttackStateSearchCard;
}
return true;
});
}
void dict_attack_inc_curr_sector(DictAttack* dict_attack) {
furi_assert(dict_attack);
with_view_model(
dict_attack->view, (DictAttackViewModel * model) {
model->current_sector++;
return true;
});
}
void dict_attack_inc_found_key(DictAttack* dict_attack, MfClassicKey key) {
furi_assert(dict_attack);
with_view_model(
dict_attack->view, (DictAttackViewModel * model) {
model->state = DictAttackStateSearchKeys;
if(key == MfClassicKeyA) {
model->keys_a_found++;
} else if(key == MfClassicKeyB) {
model->keys_b_found++;
}
return true;
});
}
void dict_attack_set_result(DictAttack* dict_attack, bool success) {
furi_assert(dict_attack);
with_view_model(
dict_attack->view, (DictAttackViewModel * model) {
if(success) {
model->state = DictAttackStateSuccess;
} else {
model->state = DictAttackStateFail;
}
return true;
});
}

View File

@ -0,0 +1,33 @@
#pragma once
#include <stdint.h>
#include <gui/view.h>
#include <gui/modules/widget.h>
#include <lib/nfc_protocols/mifare_classic.h>
typedef struct DictAttack DictAttack;
typedef void (*DictAttackResultCallback)(void* context);
DictAttack* dict_attack_alloc();
void dict_attack_free(DictAttack* dict_attack);
void dict_attack_reset(DictAttack* dict_attack);
View* dict_attack_get_view(DictAttack* dict_attack);
void dict_attack_set_result_callback(
DictAttack* dict_attack,
DictAttackResultCallback callback,
void* context);
void dict_attack_card_detected(DictAttack* dict_attack, MfClassicType type);
void dict_attack_card_removed(DictAttack* dict_attack);
void dict_attack_inc_curr_sector(DictAttack* dict_attack);
void dict_attack_inc_found_key(DictAttack* dict_attack, MfClassicKey key);
void dict_attack_set_result(DictAttack* dict_attack, bool success);

View File

@ -9,7 +9,7 @@ extern "C" {
typedef struct NotificationApp NotificationApp;
typedef struct {
float frequency;
float pwm;
float volume;
} NotificationMessageDataSound;
typedef struct {

View File

@ -139,12 +139,12 @@ void notification_vibro_off() {
furi_hal_vibro_on(false);
}
void notification_sound_on(float pwm, float freq) {
hal_pwm_set(pwm, freq, &SPEAKER_TIM, SPEAKER_CH);
void notification_sound_on(float freq, float volume) {
furi_hal_speaker_start(freq, volume);
}
void notification_sound_off() {
hal_pwm_stop(&SPEAKER_TIM, SPEAKER_CH);
furi_hal_speaker_stop();
}
// display timer
@ -236,8 +236,8 @@ void notification_process_notification_message(
break;
case NotificationMessageTypeSoundOn:
notification_sound_on(
notification_message->data.sound.pwm * speaker_volume_setting,
notification_message->data.sound.frequency);
notification_message->data.sound.frequency,
notification_message->data.sound.volume * speaker_volume_setting);
reset_mask |= reset_sound_mask;
break;
case NotificationMessageTypeSoundOff:

View File

@ -17,7 +17,7 @@ for octave in range(9):
print(f"const NotificationMessage message_note_{name}{octave}" + " = {\n"
"\t.type = NotificationMessageTypeSoundOn,\n"
f"\t.data.sound.frequency = {round(note, 2)}f,\n"
"\t.data.sound.pwm = 0.5f,\n"
"\t.data.sound.volume = 1.0f,\n"
"};")
note = note * cf
@ -29,545 +29,545 @@ for octave in range(9):
const NotificationMessage message_click = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 1.0f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_c0 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 16.35f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_cs0 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 17.32f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_d0 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 18.35f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_ds0 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 19.45f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_e0 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 20.6f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_f0 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 21.83f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_fs0 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 23.12f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_g0 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 24.5f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_gs0 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 25.96f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_a0 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 27.5f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_as0 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 29.14f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_b0 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 30.87f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_c1 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 32.7f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_cs1 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 34.65f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_d1 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 36.71f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_ds1 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 38.89f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_e1 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 41.2f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_f1 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 43.65f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_fs1 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 46.25f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_g1 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 49.0f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_gs1 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 51.91f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_a1 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 55.0f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_as1 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 58.27f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_b1 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 61.74f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_c2 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 65.41f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_cs2 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 69.3f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_d2 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 73.42f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_ds2 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 77.78f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_e2 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 82.41f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_f2 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 87.31f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_fs2 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 92.5f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_g2 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 98.0f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_gs2 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 103.83f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_a2 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 110.0f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_as2 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 116.54f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_b2 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 123.47f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_c3 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 130.81f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_cs3 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 138.59f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_d3 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 146.83f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_ds3 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 155.56f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_e3 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 164.81f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_f3 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 174.61f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_fs3 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 185.0f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_g3 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 196.0f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_gs3 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 207.65f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_a3 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 220.0f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_as3 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 233.08f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_b3 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 246.94f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_c4 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 261.63f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_cs4 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 277.18f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_d4 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 293.66f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_ds4 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 311.13f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_e4 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 329.63f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_f4 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 349.23f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_fs4 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 369.99f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_g4 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 392.0f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_gs4 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 415.3f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_a4 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 440.0f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_as4 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 466.16f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_b4 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 493.88f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_c5 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 523.25f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_cs5 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 554.37f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_d5 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 587.33f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_ds5 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 622.25f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_e5 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 659.26f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_f5 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 698.46f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_fs5 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 739.99f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_g5 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 783.99f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_gs5 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 830.61f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_a5 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 880.0f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_as5 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 932.33f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_b5 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 987.77f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_c6 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 1046.5f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_cs6 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 1108.73f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_d6 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 1174.66f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_ds6 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 1244.51f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_e6 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 1318.51f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_f6 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 1396.91f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_fs6 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 1479.98f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_g6 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 1567.98f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_gs6 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 1661.22f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_a6 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 1760.0f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_as6 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 1864.66f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_b6 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 1975.53f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_c7 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 2093.0f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_cs7 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 2217.46f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_d7 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 2349.32f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_ds7 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 2489.02f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_e7 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 2637.02f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_f7 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 2793.83f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_fs7 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 2959.96f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_g7 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 3135.96f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_gs7 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 3322.44f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_a7 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 3520.0f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_as7 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 3729.31f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_b7 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 3951.07f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_c8 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 4186.01f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_cs8 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 4434.92f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_d8 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 4698.64f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_ds8 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 4978.03f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_e8 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 5274.04f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_f8 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 5587.65f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_fs8 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 5919.91f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_g8 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 6271.93f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_gs8 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 6644.88f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_a8 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 7040.0f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_as8 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 7458.62f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};
const NotificationMessage message_note_b8 = {
.type = NotificationMessageTypeSoundOn,
.data.sound.frequency = 7902.13f,
.data.sound.pwm = 0.5f,
.data.sound.volume = 1.0f,
};

View File

@ -43,7 +43,7 @@ const char* const volume_text[VOLUME_COUNT] = {
"75%",
"100%",
};
const float volume_value[VOLUME_COUNT] = {0.0f, 0.04f, 0.1f, 0.2f, 1.0f};
const float volume_value[VOLUME_COUNT] = {0.0f, 0.25f, 0.5f, 0.75f, 1.0f};
#define DELAY_COUNT 6
const char* const delay_text[DELAY_COUNT] = {

View File

@ -26,6 +26,10 @@ static const char* test_float_key = "Float data";
static const float test_float_data[] = {1.5f, 1000.0f};
static const float test_float_updated_data[] = {1.2f};
static const char* test_bool_key = "Bool data";
static const bool test_bool_data[] = {true, false};
static const bool test_bool_updated_data[] = {false, true, true};
static const char* test_hex_key = "Hex data";
static const uint8_t test_hex_data[] = {0xDE, 0xAD, 0xBE};
static const uint8_t test_hex_updated_data[] = {0xFE, 0xCA};
@ -38,6 +42,7 @@ static const char* test_data_nix = "Filetype: Flipper File test\n"
"Int32 data: 1234 -6345 7813 0\n"
"Uint32 data: 1234 0 5678 9098 7654321\n"
"Float data: 1.5 1000.0\n"
"Bool data: true false\n"
"Hex data: DE AD BE";
#define READ_TEST_WIN "ff_win.test"
@ -48,6 +53,7 @@ static const char* test_data_win = "Filetype: Flipper File test\r\n"
"Int32 data: 1234 -6345 7813 0\r\n"
"Uint32 data: 1234 0 5678 9098 7654321\r\n"
"Float data: 1.5 1000.0\r\n"
"Bool data: true false\r\n"
"Hex data: DE AD BE";
#define READ_TEST_FLP "ff_flp.test"
@ -129,6 +135,11 @@ static bool test_read(const char* file_name) {
if(memcmp(scratchpad, test_float_data, sizeof(float) * COUNT_OF(test_float_data)) != 0)
break;
if(!flipper_format_get_value_count(file, test_bool_key, &uint32_value)) break;
if(uint32_value != COUNT_OF(test_bool_data)) break;
if(!flipper_format_read_bool(file, test_bool_key, scratchpad, uint32_value)) break;
if(memcmp(scratchpad, test_bool_data, sizeof(bool) * COUNT_OF(test_bool_data)) != 0) break;
if(!flipper_format_get_value_count(file, test_hex_key, &uint32_value)) break;
if(uint32_value != COUNT_OF(test_hex_data)) break;
if(!flipper_format_read_hex(file, test_hex_key, scratchpad, uint32_value)) break;
@ -195,6 +206,15 @@ static bool test_read_updated(const char* file_name) {
sizeof(float) * COUNT_OF(test_float_updated_data)) != 0)
break;
if(!flipper_format_get_value_count(file, test_bool_key, &uint32_value)) break;
if(uint32_value != COUNT_OF(test_bool_updated_data)) break;
if(!flipper_format_read_bool(file, test_bool_key, scratchpad, uint32_value)) break;
if(memcmp(
scratchpad,
test_bool_updated_data,
sizeof(bool) * COUNT_OF(test_bool_updated_data)) != 0)
break;
if(!flipper_format_get_value_count(file, test_hex_key, &uint32_value)) break;
if(uint32_value != COUNT_OF(test_hex_updated_data)) break;
if(!flipper_format_read_hex(file, test_hex_key, scratchpad, uint32_value)) break;
@ -235,6 +255,9 @@ static bool test_write(const char* file_name) {
if(!flipper_format_write_float(
file, test_float_key, test_float_data, COUNT_OF(test_float_data)))
break;
if(!flipper_format_write_bool(
file, test_bool_key, test_bool_data, COUNT_OF(test_bool_data)))
break;
if(!flipper_format_write_hex(file, test_hex_key, test_hex_data, COUNT_OF(test_hex_data)))
break;
result = true;
@ -299,6 +322,9 @@ static bool test_update(const char* file_name) {
if(!flipper_format_update_float(
file, test_float_key, test_float_updated_data, COUNT_OF(test_float_updated_data)))
break;
if(!flipper_format_update_bool(
file, test_bool_key, test_bool_updated_data, COUNT_OF(test_bool_updated_data)))
break;
if(!flipper_format_update_hex(
file, test_hex_key, test_hex_updated_data, COUNT_OF(test_hex_updated_data)))
break;
@ -328,6 +354,9 @@ static bool test_update_backward(const char* file_name) {
if(!flipper_format_update_float(
file, test_float_key, test_float_data, COUNT_OF(test_float_data)))
break;
if(!flipper_format_update_bool(
file, test_bool_key, test_bool_data, COUNT_OF(test_bool_data)))
break;
if(!flipper_format_update_hex(file, test_hex_key, test_hex_data, COUNT_OF(test_hex_data)))
break;

View File

@ -191,7 +191,7 @@ static int32_t u2f_hid_worker(void* context) {
FURI_LOG_D(WORKER_TAG, "Init");
FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config();
furi_hal_usb_set_config(&usb_hid_u2f);
furi_hal_usb_set_config(&usb_hid_u2f, NULL);
u2f_hid->lock_timer = osTimerNew(u2f_hid_lock_timeout_callback, osTimerOnce, u2f_hid, NULL);
@ -270,7 +270,7 @@ static int32_t u2f_hid_worker(void* context) {
osTimerDelete(u2f_hid->lock_timer);
furi_hal_hid_u2f_set_callback(NULL, NULL);
furi_hal_usb_set_config(usb_mode_prev);
furi_hal_usb_set_config(usb_mode_prev, NULL);
FURI_LOG_D(WORKER_TAG, "End");
return 0;

View File

@ -1,3 +1,3 @@
#pragma once
#define PROTOBUF_MAJOR_VERSION 0
#define PROTOBUF_MINOR_VERSION 1
#define PROTOBUF_MINOR_VERSION 2

@ -1 +1 @@
Subproject commit 93b9cf3af76664a27646494341a63281a9022740
Subproject commit 232e7e9a50b12a95f950fabb515204775e51b04a

View File

@ -1,3 +1,7 @@
ID 1234:5678 Apple:Keyboard
REM You can change these values to VID/PID of original Apple keyboard
REM to bypass Keyboard Setup Assistant
REM This is BadUSB demo script for macOS
REM Open terminal window

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +0,0 @@
#include <furi_hal.h>
#include <stm32wbxx_ll_utils.h>
void furi_hal_init() {
furi_hal_i2c_init();
furi_hal_light_init();
furi_hal_spi_init();
furi_hal_version_init();
}
void delay(float milliseconds) {
LL_mDelay((uint32_t)milliseconds);
}
void delay_us(float microseconds) {
microseconds = microseconds / 1000;
if(microseconds < 1) {
microseconds = 1;
}
LL_mDelay((uint32_t)microseconds);
}

View File

@ -1,215 +0,0 @@
#include <furi_hal_gpio.h>
#include <stddef.h>
#include <assert.h>
#define GET_SYSCFG_EXTI_PORT(gpio) \
(((gpio) == (GPIOA)) ? LL_SYSCFG_EXTI_PORTA : \
((gpio) == (GPIOB)) ? LL_SYSCFG_EXTI_PORTB : \
((gpio) == (GPIOC)) ? LL_SYSCFG_EXTI_PORTC : \
((gpio) == (GPIOD)) ? LL_SYSCFG_EXTI_PORTD : \
((gpio) == (GPIOE)) ? LL_SYSCFG_EXTI_PORTE : \
LL_SYSCFG_EXTI_PORTH)
#define GPIO_PIN_MAP(pin, prefix) \
(((pin) == (LL_GPIO_PIN_0)) ? prefix##0 : \
((pin) == (LL_GPIO_PIN_1)) ? prefix##1 : \
((pin) == (LL_GPIO_PIN_2)) ? prefix##2 : \
((pin) == (LL_GPIO_PIN_3)) ? prefix##3 : \
((pin) == (LL_GPIO_PIN_4)) ? prefix##4 : \
((pin) == (LL_GPIO_PIN_5)) ? prefix##5 : \
((pin) == (LL_GPIO_PIN_6)) ? prefix##6 : \
((pin) == (LL_GPIO_PIN_7)) ? prefix##7 : \
((pin) == (LL_GPIO_PIN_8)) ? prefix##8 : \
((pin) == (LL_GPIO_PIN_9)) ? prefix##9 : \
((pin) == (LL_GPIO_PIN_10)) ? prefix##10 : \
((pin) == (LL_GPIO_PIN_11)) ? prefix##11 : \
((pin) == (LL_GPIO_PIN_12)) ? prefix##12 : \
((pin) == (LL_GPIO_PIN_13)) ? prefix##13 : \
((pin) == (LL_GPIO_PIN_14)) ? prefix##14 : \
prefix##15)
#define GET_SYSCFG_EXTI_LINE(pin) GPIO_PIN_MAP(pin, LL_SYSCFG_EXTI_LINE)
#define GET_EXTI_LINE(pin) GPIO_PIN_MAP(pin, LL_EXTI_LINE_)
static volatile GpioInterrupt gpio_interrupt[GPIO_NUMBER];
static uint8_t hal_gpio_get_pin_num(const GpioPin* gpio) {
uint8_t pin_num = 0;
for(pin_num = 0; pin_num < GPIO_NUMBER; pin_num++) {
if(gpio->pin & (1 << pin_num)) break;
}
return pin_num;
}
void hal_gpio_init_simple(const GpioPin* gpio, const GpioMode mode) {
hal_gpio_init(gpio, mode, GpioPullNo, GpioSpeedLow);
}
void hal_gpio_init(
const GpioPin* gpio,
const GpioMode mode,
const GpioPull pull,
const GpioSpeed speed) {
// we cannot set alternate mode in this function
assert(mode != GpioModeAltFunctionPushPull);
assert(mode != GpioModeAltFunctionOpenDrain);
hal_gpio_init_ex(gpio, mode, pull, speed, GpioAltFnUnused);
}
void hal_gpio_init_ex(
const GpioPin* gpio,
const GpioMode mode,
const GpioPull pull,
const GpioSpeed speed,
const GpioAltFn alt_fn) {
uint32_t sys_exti_port = GET_SYSCFG_EXTI_PORT(gpio->port);
uint32_t sys_exti_line = GET_SYSCFG_EXTI_LINE(gpio->pin);
uint32_t exti_line = GET_EXTI_LINE(gpio->pin);
// Configure gpio with interrupts disabled
__disable_irq();
// Set gpio speed
switch(speed) {
case GpioSpeedLow:
LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_LOW);
break;
case GpioSpeedMedium:
LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_MEDIUM);
break;
case GpioSpeedHigh:
LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_HIGH);
break;
case GpioSpeedVeryHigh:
LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_VERY_HIGH);
break;
}
// Set gpio pull mode
switch(pull) {
case GpioPullNo:
LL_GPIO_SetPinPull(gpio->port, gpio->pin, LL_GPIO_PULL_NO);
break;
case GpioPullUp:
LL_GPIO_SetPinPull(gpio->port, gpio->pin, LL_GPIO_PULL_UP);
break;
case GpioPullDown:
LL_GPIO_SetPinPull(gpio->port, gpio->pin, LL_GPIO_PULL_DOWN);
break;
}
// Set gpio mode
if(mode >= GpioModeInterruptRise) {
// Set pin in interrupt mode
LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_INPUT);
LL_SYSCFG_SetEXTISource(sys_exti_port, sys_exti_line);
if(mode == GpioModeInterruptRise || mode == GpioModeInterruptRiseFall) {
LL_EXTI_EnableIT_0_31(exti_line);
LL_EXTI_EnableRisingTrig_0_31(exti_line);
}
if(mode == GpioModeInterruptFall || mode == GpioModeInterruptRiseFall) {
LL_EXTI_EnableIT_0_31(exti_line);
LL_EXTI_EnableFallingTrig_0_31(exti_line);
}
if(mode == GpioModeEventRise || mode == GpioModeEventRiseFall) {
LL_EXTI_EnableEvent_0_31(exti_line);
LL_EXTI_EnableRisingTrig_0_31(exti_line);
}
if(mode == GpioModeEventFall || mode == GpioModeEventRiseFall) {
LL_EXTI_EnableEvent_0_31(exti_line);
LL_EXTI_EnableFallingTrig_0_31(exti_line);
}
} else {
// Disable interrupts if set
if(LL_SYSCFG_GetEXTISource(sys_exti_line) == sys_exti_port &&
LL_EXTI_IsEnabledIT_0_31(exti_line)) {
LL_EXTI_DisableIT_0_31(exti_line);
LL_EXTI_DisableRisingTrig_0_31(exti_line);
LL_EXTI_DisableFallingTrig_0_31(exti_line);
}
// Prepare alternative part if any
if(mode == GpioModeAltFunctionPushPull || mode == GpioModeAltFunctionOpenDrain) {
// set alternate function
if(hal_gpio_get_pin_num(gpio) < 8) {
LL_GPIO_SetAFPin_0_7(gpio->port, gpio->pin, alt_fn);
} else {
LL_GPIO_SetAFPin_8_15(gpio->port, gpio->pin, alt_fn);
}
}
// Set not interrupt pin modes
switch(mode) {
case GpioModeInput:
LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_INPUT);
break;
case GpioModeOutputPushPull:
LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_PUSHPULL);
LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_OUTPUT);
break;
case GpioModeAltFunctionPushPull:
LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_PUSHPULL);
LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ALTERNATE);
break;
case GpioModeOutputOpenDrain:
LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_OPENDRAIN);
LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_OUTPUT);
break;
case GpioModeAltFunctionOpenDrain:
LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_OPENDRAIN);
LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ALTERNATE);
break;
case GpioModeAnalog:
LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ANALOG);
break;
default:
break;
}
}
__enable_irq();
}
void hal_gpio_add_int_callback(const GpioPin* gpio, GpioExtiCallback cb, void* ctx) {
assert(gpio);
assert(cb);
__disable_irq();
uint8_t pin_num = hal_gpio_get_pin_num(gpio);
gpio_interrupt[pin_num].callback = cb;
gpio_interrupt[pin_num].context = ctx;
gpio_interrupt[pin_num].ready = true;
__enable_irq();
}
void hal_gpio_enable_int_callback(const GpioPin* gpio) {
assert(gpio);
__disable_irq();
uint8_t pin_num = hal_gpio_get_pin_num(gpio);
if(gpio_interrupt[pin_num].callback) {
gpio_interrupt[pin_num].ready = true;
}
__enable_irq();
}
void hal_gpio_disable_int_callback(const GpioPin* gpio) {
assert(gpio);
__disable_irq();
uint8_t pin_num = hal_gpio_get_pin_num(gpio);
gpio_interrupt[pin_num].ready = false;
__enable_irq();
}
void hal_gpio_remove_int_callback(const GpioPin* gpio) {
assert(gpio);
__disable_irq();
uint8_t pin_num = hal_gpio_get_pin_num(gpio);
gpio_interrupt[pin_num].callback = NULL;
gpio_interrupt[pin_num].context = NULL;
gpio_interrupt[pin_num].ready = false;
__enable_irq();
}

View File

@ -1,264 +0,0 @@
#pragma once
#include "main.h"
#include "stdbool.h"
#include <stm32wbxx_ll_gpio.h>
#include <stm32wbxx_ll_system.h>
#include <stm32wbxx_ll_exti.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Number of gpio on one port
*/
#define GPIO_NUMBER (16U)
/**
* Interrupt callback prototype
*/
typedef void (*GpioExtiCallback)(void* ctx);
/**
* Gpio interrupt type
*/
typedef struct {
GpioExtiCallback callback;
void* context;
volatile bool ready;
} GpioInterrupt;
/**
* Gpio modes
*/
typedef enum {
GpioModeInput,
GpioModeOutputPushPull,
GpioModeOutputOpenDrain,
GpioModeAltFunctionPushPull,
GpioModeAltFunctionOpenDrain,
GpioModeAnalog,
GpioModeInterruptRise,
GpioModeInterruptFall,
GpioModeInterruptRiseFall,
GpioModeEventRise,
GpioModeEventFall,
GpioModeEventRiseFall,
} GpioMode;
/**
* Gpio pull modes
*/
typedef enum {
GpioPullNo,
GpioPullUp,
GpioPullDown,
} GpioPull;
/**
* Gpio speed modes
*/
typedef enum {
GpioSpeedLow,
GpioSpeedMedium,
GpioSpeedHigh,
GpioSpeedVeryHigh,
} GpioSpeed;
/**
* Gpio alternate functions
*/
typedef enum {
GpioAltFn0MCO = 0, /*!< MCO Alternate Function mapping */
GpioAltFn0LSCO = 0, /*!< LSCO Alternate Function mapping */
GpioAltFn0JTMS_SWDIO = 0, /*!< JTMS-SWDIO Alternate Function mapping */
GpioAltFn0JTCK_SWCLK = 0, /*!< JTCK-SWCLK Alternate Function mapping */
GpioAltFn0JTDI = 0, /*!< JTDI Alternate Function mapping */
GpioAltFn0RTC_OUT = 0, /*!< RCT_OUT Alternate Function mapping */
GpioAltFn0JTD_TRACE = 0, /*!< JTDO-TRACESWO Alternate Function mapping */
GpioAltFn0NJTRST = 0, /*!< NJTRST Alternate Function mapping */
GpioAltFn0RTC_REFIN = 0, /*!< RTC_REFIN Alternate Function mapping */
GpioAltFn0TRACED0 = 0, /*!< TRACED0 Alternate Function mapping */
GpioAltFn0TRACED1 = 0, /*!< TRACED1 Alternate Function mapping */
GpioAltFn0TRACED2 = 0, /*!< TRACED2 Alternate Function mapping */
GpioAltFn0TRACED3 = 0, /*!< TRACED3 Alternate Function mapping */
GpioAltFn0TRIG_INOUT = 0, /*!< TRIG_INOUT Alternate Function mapping */
GpioAltFn0TRACECK = 0, /*!< TRACECK Alternate Function mapping */
GpioAltFn0SYS = 0, /*!< System Function mapping */
GpioAltFn1TIM1 = 1, /*!< TIM1 Alternate Function mapping */
GpioAltFn1TIM2 = 1, /*!< TIM2 Alternate Function mapping */
GpioAltFn1LPTIM1 = 1, /*!< LPTIM1 Alternate Function mapping */
GpioAltFn2TIM2 = 2, /*!< TIM2 Alternate Function mapping */
GpioAltFn2TIM1 = 2, /*!< TIM1 Alternate Function mapping */
GpioAltFn3SAI1 = 3, /*!< SAI1_CK1 Alternate Function mapping */
GpioAltFn3SPI2 = 3, /*!< SPI2 Alternate Function mapping */
GpioAltFn3TIM1 = 3, /*!< TIM1 Alternate Function mapping */
GpioAltFn4I2C1 = 4, /*!< I2C1 Alternate Function mapping */
GpioAltFn4I2C3 = 4, /*!< I2C3 Alternate Function mapping */
GpioAltFn5SPI1 = 5, /*!< SPI1 Alternate Function mapping */
GpioAltFn5SPI2 = 5, /*!< SPI2 Alternate Function mapping */
GpioAltFn6MCO = 6, /*!< MCO Alternate Function mapping */
GpioAltFn6LSCO = 6, /*!< LSCO Alternate Function mapping */
GpioAltFn6RF_DTB0 = 6, /*!< RF_DTB0 Alternate Function mapping */
GpioAltFn6RF_DTB1 = 6, /*!< RF_DTB1 Alternate Function mapping */
GpioAltFn6RF_DTB2 = 6, /*!< RF_DTB2 Alternate Function mapping */
GpioAltFn6RF_DTB3 = 6, /*!< RF_DTB3 Alternate Function mapping */
GpioAltFn6RF_DTB4 = 6, /*!< RF_DTB4 Alternate Function mapping */
GpioAltFn6RF_DTB5 = 6, /*!< RF_DTB5 Alternate Function mapping */
GpioAltFn6RF_DTB6 = 6, /*!< RF_DTB6 Alternate Function mapping */
GpioAltFn6RF_DTB7 = 6, /*!< RF_DTB7 Alternate Function mapping */
GpioAltFn6RF_DTB8 = 6, /*!< RF_DTB8 Alternate Function mapping */
GpioAltFn6RF_DTB9 = 6, /*!< RF_DTB9 Alternate Function mapping */
GpioAltFn6RF_DTB10 = 6, /*!< RF_DTB10 Alternate Function mapping */
GpioAltFn6RF_DTB11 = 6, /*!< RF_DTB11 Alternate Function mapping */
GpioAltFn6RF_DTB12 = 6, /*!< RF_DTB12 Alternate Function mapping */
GpioAltFn6RF_DTB13 = 6, /*!< RF_DTB13 Alternate Function mapping */
GpioAltFn6RF_DTB14 = 6, /*!< RF_DTB14 Alternate Function mapping */
GpioAltFn6RF_DTB15 = 6, /*!< RF_DTB15 Alternate Function mapping */
GpioAltFn6RF_DTB16 = 6, /*!< RF_DTB16 Alternate Function mapping */
GpioAltFn6RF_DTB17 = 6, /*!< RF_DTB17 Alternate Function mapping */
GpioAltFn6RF_DTB18 = 6, /*!< RF_DTB18 Alternate Function mapping */
GpioAltFn6RF_MISO = 6, /*!< RF_MISO Alternate Function mapping */
GpioAltFn6RF_MOSI = 6, /*!< RF_MOSI Alternate Function mapping */
GpioAltFn6RF_SCK = 6, /*!< RF_SCK Alternate Function mapping */
GpioAltFn6RF_NSS = 6, /*!< RF_NSS Alternate Function mapping */
GpioAltFn7USART1 = 7, /*!< USART1 Alternate Function mapping */
GpioAltFn8LPUART1 = 8, /*!< LPUART1 Alternate Function mapping */
GpioAltFn8IR = 8, /*!< IR Alternate Function mapping */
GpioAltFn9TSC = 9, /*!< TSC Alternate Function mapping */
GpioAltFn10QUADSPI = 10, /*!< QUADSPI Alternate Function mapping */
GpioAltFn10USB = 10, /*!< USB Alternate Function mapping */
GpioAltFn11LCD = 11, /*!< LCD Alternate Function mapping */
GpioAltFn12COMP1 = 12, /*!< COMP1 Alternate Function mapping */
GpioAltFn12COMP2 = 12, /*!< COMP2 Alternate Function mapping */
GpioAltFn12TIM1 = 12, /*!< TIM1 Alternate Function mapping */
GpioAltFn13SAI1 = 13, /*!< SAI1 Alternate Function mapping */
GpioAltFn14TIM2 = 14, /*!< TIM2 Alternate Function mapping */
GpioAltFn14TIM16 = 14, /*!< TIM16 Alternate Function mapping */
GpioAltFn14TIM17 = 14, /*!< TIM17 Alternate Function mapping */
GpioAltFn14LPTIM2 = 14, /*!< LPTIM2 Alternate Function mapping */
GpioAltFn15EVENTOUT = 15, /*!< EVENTOUT Alternate Function mapping */
GpioAltFnUnused = 16, /*!< just dummy value */
} GpioAltFn;
/**
* Gpio structure
*/
typedef struct {
GPIO_TypeDef* port;
uint16_t pin;
} GpioPin;
/**
* GPIO initialization function, simple version
* @param gpio GpioPin
* @param mode GpioMode
*/
void hal_gpio_init_simple(const GpioPin* gpio, const GpioMode mode);
/**
* GPIO initialization function, normal version
* @param gpio GpioPin
* @param mode GpioMode
* @param pull GpioPull
* @param speed GpioSpeed
*/
void hal_gpio_init(
const GpioPin* gpio,
const GpioMode mode,
const GpioPull pull,
const GpioSpeed speed);
/**
* GPIO initialization function, extended version
* @param gpio GpioPin
* @param mode GpioMode
* @param pull GpioPull
* @param speed GpioSpeed
* @param alt_fn GpioAltFn
*/
void hal_gpio_init_ex(
const GpioPin* gpio,
const GpioMode mode,
const GpioPull pull,
const GpioSpeed speed,
const GpioAltFn alt_fn);
/**
* Add and enable interrupt
* @param gpio GpioPin
* @param cb GpioExtiCallback
* @param ctx context for callback
*/
void hal_gpio_add_int_callback(const GpioPin* gpio, GpioExtiCallback cb, void* ctx);
/**
* Enable interrupt
* @param gpio GpioPin
*/
void hal_gpio_enable_int_callback(const GpioPin* gpio);
/**
* Disable interrupt
* @param gpio GpioPin
*/
void hal_gpio_disable_int_callback(const GpioPin* gpio);
/**
* Remove interrupt
* @param gpio GpioPin
*/
void hal_gpio_remove_int_callback(const GpioPin* gpio);
/**
* GPIO write pin
* @param gpio GpioPin
* @param state true / false
*/
static inline void hal_gpio_write(const GpioPin* gpio, const bool state) {
// writing to BSSR is an atomic operation
if(state == true) {
gpio->port->BSRR = gpio->pin;
} else {
gpio->port->BSRR = (uint32_t)gpio->pin << GPIO_NUMBER;
}
}
/**
* GPIO read pin
* @param gpio GpioPin
* @return true / false
*/
static inline bool hal_gpio_read(const GpioPin* gpio) {
if((gpio->port->IDR & gpio->pin) != 0x00U) {
return true;
} else {
return false;
}
}
/**
* Get RFID IN level
* @return false = LOW, true = HIGH
*/
bool hal_gpio_get_rfid_in_level();
#ifdef __cplusplus
}
#endif

View File

@ -1,205 +0,0 @@
#include <furi_hal_i2c.h>
#include <furi_hal_version.h>
#include <stm32wbxx_ll_i2c.h>
#include <stm32wbxx_ll_gpio.h>
#include <stm32wbxx_ll_cortex.h>
#include <assert.h>
void furi_hal_i2c_init() {
furi_hal_i2c_bus_power.callback(&furi_hal_i2c_bus_power, FuriHalI2cBusEventInit);
}
void furi_hal_i2c_acquire(FuriHalI2cBusHandle* handle) {
handle->bus->callback(handle->bus, FuriHalI2cBusEventLock);
assert(handle->bus->current_handle == NULL);
handle->bus->current_handle = handle;
handle->bus->callback(handle->bus, FuriHalI2cBusEventActivate);
handle->callback(handle, FuriHalI2cBusHandleEventActivate);
}
void furi_hal_i2c_release(FuriHalI2cBusHandle* handle) {
assert(handle->bus->current_handle == handle);
handle->callback(handle, FuriHalI2cBusHandleEventDeactivate);
handle->bus->callback(handle->bus, FuriHalI2cBusEventDeactivate);
handle->bus->current_handle = NULL;
handle->bus->callback(handle->bus, FuriHalI2cBusEventUnlock);
}
bool furi_hal_i2c_tx(
FuriHalI2cBusHandle* handle,
uint8_t address,
const uint8_t* data,
uint8_t size,
uint32_t timeout) {
assert(handle->bus->current_handle == handle);
uint32_t time_left = timeout;
bool ret = true;
while(LL_I2C_IsActiveFlag_BUSY(handle->bus->i2c))
;
LL_I2C_HandleTransfer(
handle->bus->i2c,
address,
LL_I2C_ADDRSLAVE_7BIT,
size,
LL_I2C_MODE_AUTOEND,
LL_I2C_GENERATE_START_WRITE);
while(!LL_I2C_IsActiveFlag_STOP(handle->bus->i2c) || size > 0) {
if(LL_I2C_IsActiveFlag_TXIS(handle->bus->i2c)) {
LL_I2C_TransmitData8(handle->bus->i2c, (*data));
data++;
size--;
time_left = timeout;
}
if(LL_SYSTICK_IsActiveCounterFlag()) {
if(--time_left == 0) {
ret = false;
break;
}
}
}
LL_I2C_ClearFlag_STOP(handle->bus->i2c);
return ret;
}
bool furi_hal_i2c_rx(
FuriHalI2cBusHandle* handle,
uint8_t address,
uint8_t* data,
uint8_t size,
uint32_t timeout) {
assert(handle->bus->current_handle == handle);
uint32_t time_left = timeout;
bool ret = true;
while(LL_I2C_IsActiveFlag_BUSY(handle->bus->i2c))
;
LL_I2C_HandleTransfer(
handle->bus->i2c,
address,
LL_I2C_ADDRSLAVE_7BIT,
size,
LL_I2C_MODE_AUTOEND,
LL_I2C_GENERATE_START_READ);
while(!LL_I2C_IsActiveFlag_STOP(handle->bus->i2c) || size > 0) {
if(LL_I2C_IsActiveFlag_RXNE(handle->bus->i2c)) {
*data = LL_I2C_ReceiveData8(handle->bus->i2c);
data++;
size--;
time_left = timeout;
}
if(LL_SYSTICK_IsActiveCounterFlag()) {
if(--time_left == 0) {
ret = false;
break;
}
}
}
LL_I2C_ClearFlag_STOP(handle->bus->i2c);
return ret;
}
bool furi_hal_i2c_trx(
FuriHalI2cBusHandle* handle,
uint8_t address,
const uint8_t* tx_data,
uint8_t tx_size,
uint8_t* rx_data,
uint8_t rx_size,
uint32_t timeout) {
if(furi_hal_i2c_tx(handle, address, tx_data, tx_size, timeout) &&
furi_hal_i2c_rx(handle, address, rx_data, rx_size, timeout)) {
return true;
} else {
return false;
}
}
bool furi_hal_i2c_read_reg_8(
FuriHalI2cBusHandle* handle,
uint8_t i2c_addr,
uint8_t reg_addr,
uint8_t* data,
uint32_t timeout) {
assert(handle);
return furi_hal_i2c_trx(handle, i2c_addr, &reg_addr, 1, data, 1, timeout);
}
bool furi_hal_i2c_read_reg_16(
FuriHalI2cBusHandle* handle,
uint8_t i2c_addr,
uint8_t reg_addr,
uint16_t* data,
uint32_t timeout) {
assert(handle);
uint8_t reg_data[2];
bool ret = furi_hal_i2c_trx(handle, i2c_addr, &reg_addr, 1, reg_data, 2, timeout);
*data = (reg_data[0] << 8) | (reg_data[1]);
return ret;
}
bool furi_hal_i2c_read_mem(
FuriHalI2cBusHandle* handle,
uint8_t i2c_addr,
uint8_t mem_addr,
uint8_t* data,
uint8_t len,
uint32_t timeout) {
assert(handle);
return furi_hal_i2c_trx(handle, i2c_addr, &mem_addr, 1, data, len, timeout);
}
bool furi_hal_i2c_write_reg_8(
FuriHalI2cBusHandle* handle,
uint8_t i2c_addr,
uint8_t reg_addr,
uint8_t data,
uint32_t timeout) {
assert(handle);
uint8_t tx_data[2];
tx_data[0] = reg_addr;
tx_data[1] = data;
return furi_hal_i2c_tx(handle, i2c_addr, (const uint8_t*)&tx_data, 2, timeout);
}
bool furi_hal_i2c_write_reg_16(
FuriHalI2cBusHandle* handle,
uint8_t i2c_addr,
uint8_t reg_addr,
uint16_t data,
uint32_t timeout) {
assert(handle);
uint8_t tx_data[3];
tx_data[0] = reg_addr;
tx_data[1] = (data >> 8) & 0xFF;
tx_data[2] = data & 0xFF;
return furi_hal_i2c_tx(handle, i2c_addr, (const uint8_t*)&tx_data, 3, timeout);
}

View File

@ -1,195 +0,0 @@
/**
* @file furi_hal_i2c.h
* I2C HAL API
*/
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include <furi_hal_i2c_config.h>
#ifdef __cplusplus
extern "C" {
#endif
/** Init I2C
*/
void furi_hal_i2c_init();
/** Acquire i2c bus handle
*
* @return Instance of FuriHalI2cBus
*/
void furi_hal_i2c_acquire(FuriHalI2cBusHandle* handle);
/** Release i2c bus handle
*
* @param bus instance of FuriHalI2cBus aquired in `furi_hal_i2c_acquire`
*/
void furi_hal_i2c_release(FuriHalI2cBusHandle* handle);
/** Perform I2C tx transfer
*
* @param handle pointer to FuriHalI2cBusHandle instance
* @param address I2C slave address
* @param data pointer to data buffer
* @param size size of data buffer
* @param timeout timeout in ticks
*
* @return true on successful transfer, false otherwise
*/
bool furi_hal_i2c_tx(
FuriHalI2cBusHandle* handle,
const uint8_t address,
const uint8_t* data,
const uint8_t size,
uint32_t timeout);
/** Perform I2C rx transfer
*
* @param handle pointer to FuriHalI2cBusHandle instance
* @param address I2C slave address
* @param data pointer to data buffer
* @param size size of data buffer
* @param timeout timeout in ticks
*
* @return true on successful transfer, false otherwise
*/
bool furi_hal_i2c_rx(
FuriHalI2cBusHandle* handle,
const uint8_t address,
uint8_t* data,
const uint8_t size,
uint32_t timeout);
/** Perform I2C tx and rx transfers
*
* @param handle pointer to FuriHalI2cBusHandle instance
* @param address I2C slave address
* @param tx_data pointer to tx data buffer
* @param tx_size size of tx data buffer
* @param rx_data pointer to rx data buffer
* @param rx_size size of rx data buffer
* @param timeout timeout in ticks
*
* @return true on successful transfer, false otherwise
*/
bool furi_hal_i2c_trx(
FuriHalI2cBusHandle* handle,
const uint8_t address,
const uint8_t* tx_data,
const uint8_t tx_size,
uint8_t* rx_data,
const uint8_t rx_size,
uint32_t timeout);
/** Perform I2C device register read (8-bit)
*
* @param handle pointer to FuriHalI2cBusHandle instance
* @param i2c_addr I2C slave address
* @param reg_addr register address
* @param data pointer to register value
* @param timeout timeout in ticks
*
* @return true on successful transfer, false otherwise
*/
bool furi_hal_i2c_read_reg_8(
FuriHalI2cBusHandle* handle,
uint8_t i2c_addr,
uint8_t reg_addr,
uint8_t* data,
uint32_t timeout);
/** Perform I2C device register read (16-bit)
*
* @param handle pointer to FuriHalI2cBusHandle instance
* @param i2c_addr I2C slave address
* @param reg_addr register address
* @param data pointer to register value
* @param timeout timeout in ticks
*
* @return true on successful transfer, false otherwise
*/
bool furi_hal_i2c_read_reg_16(
FuriHalI2cBusHandle* handle,
uint8_t i2c_addr,
uint8_t reg_addr,
uint16_t* data,
uint32_t timeout);
/** Perform I2C device memory read
*
* @param handle pointer to FuriHalI2cBusHandle instance
* @param i2c_addr I2C slave address
* @param mem_addr memory start address
* @param data pointer to data buffer
* @param len size of data buffer
* @param timeout timeout in ticks
*
* @return true on successful transfer, false otherwise
*/
bool furi_hal_i2c_read_mem(
FuriHalI2cBusHandle* handle,
uint8_t i2c_addr,
uint8_t mem_addr,
uint8_t* data,
uint8_t len,
uint32_t timeout);
/** Perform I2C device register write (8-bit)
*
* @param handle pointer to FuriHalI2cBusHandle instance
* @param i2c_addr I2C slave address
* @param reg_addr register address
* @param data register value
* @param timeout timeout in ticks
*
* @return true on successful transfer, false otherwise
*/
bool furi_hal_i2c_write_reg_8(
FuriHalI2cBusHandle* handle,
uint8_t i2c_addr,
uint8_t reg_addr,
uint8_t data,
uint32_t timeout);
/** Perform I2C device register write (16-bit)
*
* @param handle pointer to FuriHalI2cBusHandle instance
* @param i2c_addr I2C slave address
* @param reg_addr register address
* @param data register value
* @param timeout timeout in ticks
*
* @return true on successful transfer, false otherwise
*/
bool furi_hal_i2c_write_reg_16(
FuriHalI2cBusHandle* handle,
uint8_t i2c_addr,
uint8_t reg_addr,
uint16_t data,
uint32_t timeout);
/** Perform I2C device memory
*
* @param handle pointer to FuriHalI2cBusHandle instance
* @param i2c_addr I2C slave address
* @param mem_addr memory start address
* @param data pointer to data buffer
* @param len size of data buffer
* @param timeout timeout in ticks
*
* @return true on successful transfer, false otherwise
*/
bool furi_hal_i2c_write_mem(
FuriHalI2cBusHandle* handle,
uint8_t i2c_addr,
uint8_t mem_addr,
uint8_t* data,
uint8_t len,
uint32_t timeout);
#ifdef __cplusplus
}
#endif

View File

@ -1,149 +0,0 @@
#include "furi_hal_i2c_config.h"
#include <furi_hal_resources.h>
#include <furi_hal_version.h>
#include <stm32wbxx_ll_rcc.h>
#include <stm32wbxx_ll_bus.h>
/** Timing register value is computed with the STM32CubeMX Tool,
* Standard Mode @100kHz with I2CCLK = 64 MHz,
* rise time = 0ns, fall time = 0ns
*/
#define FURI_HAL_I2C_CONFIG_POWER_I2C_TIMINGS_100 0x10707DBC
/** Timing register value is computed with the STM32CubeMX Tool,
* Fast Mode @400kHz with I2CCLK = 64 MHz,
* rise time = 0ns, fall time = 0ns
*/
#define FURI_HAL_I2C_CONFIG_POWER_I2C_TIMINGS_400 0x00602173
static void furi_hal_i2c_bus_power_event(FuriHalI2cBus* bus, FuriHalI2cBusEvent event) {
if(event == FuriHalI2cBusEventInit) {
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);
LL_RCC_SetI2CClockSource(LL_RCC_I2C1_CLKSOURCE_PCLK1);
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C1);
bus->current_handle = NULL;
} else if(event == FuriHalI2cBusEventDeinit) {
} else if(event == FuriHalI2cBusEventLock) {
} else if(event == FuriHalI2cBusEventUnlock) {
} else if(event == FuriHalI2cBusEventActivate) {
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C1);
} else if(event == FuriHalI2cBusEventDeactivate) {
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C1);
}
}
FuriHalI2cBus furi_hal_i2c_bus_power = {
.i2c = I2C1,
.current_handle = NULL,
.callback = furi_hal_i2c_bus_power_event,
};
static void furi_hal_i2c_bus_external_event(FuriHalI2cBus* bus, FuriHalI2cBusEvent event) {
if(event == FuriHalI2cBusEventActivate) {
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C3);
LL_RCC_SetI2CClockSource(LL_RCC_I2C3_CLKSOURCE_PCLK1);
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C3);
} else if(event == FuriHalI2cBusEventDeactivate) {
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C3);
}
}
FuriHalI2cBus furi_hal_i2c_bus_external = {
.i2c = I2C3,
.current_handle = NULL,
.callback = furi_hal_i2c_bus_external_event,
};
void furi_hal_i2c_bus_handle_power_event(
FuriHalI2cBusHandle* handle,
FuriHalI2cBusHandleEvent event) {
if(event == FuriHalI2cBusHandleEventActivate) {
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
hal_gpio_init_ex(
&gpio_i2c_power_sda,
GpioModeAltFunctionOpenDrain,
GpioPullNo,
GpioSpeedLow,
GpioAltFn4I2C1);
hal_gpio_init_ex(
&gpio_i2c_power_scl,
GpioModeAltFunctionOpenDrain,
GpioPullNo,
GpioSpeedLow,
GpioAltFn4I2C1);
LL_I2C_InitTypeDef I2C_InitStruct = {0};
I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;
I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE;
I2C_InitStruct.DigitalFilter = 0;
I2C_InitStruct.OwnAddress1 = 0;
I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
if(furi_hal_version_get_hw_version() > 10) {
I2C_InitStruct.Timing = FURI_HAL_I2C_CONFIG_POWER_I2C_TIMINGS_400;
} else {
I2C_InitStruct.Timing = FURI_HAL_I2C_CONFIG_POWER_I2C_TIMINGS_100;
}
LL_I2C_Init(handle->bus->i2c, &I2C_InitStruct);
LL_I2C_EnableAutoEndMode(handle->bus->i2c);
LL_I2C_SetOwnAddress2(handle->bus->i2c, 0, LL_I2C_OWNADDRESS2_NOMASK);
LL_I2C_DisableOwnAddress2(handle->bus->i2c);
LL_I2C_DisableGeneralCall(handle->bus->i2c);
LL_I2C_EnableClockStretching(handle->bus->i2c);
LL_I2C_Enable(handle->bus->i2c);
} else if(event == FuriHalI2cBusHandleEventDeactivate) {
LL_I2C_Disable(handle->bus->i2c);
hal_gpio_write(&gpio_i2c_power_sda, 1);
hal_gpio_write(&gpio_i2c_power_scl, 1);
hal_gpio_init_ex(
&gpio_i2c_power_sda, GpioModeAnalog, GpioPullNo, GpioSpeedLow, GpioAltFnUnused);
hal_gpio_init_ex(
&gpio_i2c_power_scl, GpioModeAnalog, GpioPullNo, GpioSpeedLow, GpioAltFnUnused);
}
}
FuriHalI2cBusHandle furi_hal_i2c_handle_power = {
.bus = &furi_hal_i2c_bus_power,
.callback = furi_hal_i2c_bus_handle_power_event,
};
void furi_hal_i2c_bus_handle_external_event(
FuriHalI2cBusHandle* handle,
FuriHalI2cBusHandleEvent event) {
if(event == FuriHalI2cBusHandleEventActivate) {
hal_gpio_init_ex(
&gpio_ext_pc0, GpioModeAltFunctionOpenDrain, GpioPullNo, GpioSpeedLow, GpioAltFn4I2C3);
hal_gpio_init_ex(
&gpio_ext_pc1, GpioModeAltFunctionOpenDrain, GpioPullNo, GpioSpeedLow, GpioAltFn4I2C3);
LL_I2C_InitTypeDef I2C_InitStruct = {0};
I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;
I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE;
I2C_InitStruct.DigitalFilter = 0;
I2C_InitStruct.OwnAddress1 = 0;
I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
I2C_InitStruct.Timing = FURI_HAL_I2C_CONFIG_POWER_I2C_TIMINGS_100;
LL_I2C_Init(handle->bus->i2c, &I2C_InitStruct);
LL_I2C_EnableAutoEndMode(handle->bus->i2c);
LL_I2C_SetOwnAddress2(handle->bus->i2c, 0, LL_I2C_OWNADDRESS2_NOMASK);
LL_I2C_DisableOwnAddress2(handle->bus->i2c);
LL_I2C_DisableGeneralCall(handle->bus->i2c);
LL_I2C_EnableClockStretching(handle->bus->i2c);
LL_I2C_Enable(handle->bus->i2c);
} else if(event == FuriHalI2cBusHandleEventDeactivate) {
LL_I2C_Disable(handle->bus->i2c);
hal_gpio_write(&gpio_ext_pc0, 1);
hal_gpio_write(&gpio_ext_pc1, 1);
hal_gpio_init_ex(&gpio_ext_pc0, GpioModeAnalog, GpioPullNo, GpioSpeedLow, GpioAltFnUnused);
hal_gpio_init_ex(&gpio_ext_pc1, GpioModeAnalog, GpioPullNo, GpioSpeedLow, GpioAltFnUnused);
}
}
FuriHalI2cBusHandle furi_hal_i2c_handle_external = {
.bus = &furi_hal_i2c_bus_external,
.callback = furi_hal_i2c_bus_handle_external_event,
};

View File

@ -1,31 +0,0 @@
#pragma once
#include <furi_hal_i2c_types.h>
#ifdef __cplusplus
extern "C" {
#endif
/** Internal(power) i2c bus, I2C1, under reset when not used */
extern FuriHalI2cBus furi_hal_i2c_bus_power;
/** External i2c bus, I2C3, under reset when not used */
extern FuriHalI2cBus furi_hal_i2c_bus_external;
/** Handle for internal(power) i2c bus
* Bus: furi_hal_i2c_bus_external
* Pins: PA9(SCL) / PA10(SDA), float on release
* Params: 400khz
*/
extern FuriHalI2cBusHandle furi_hal_i2c_handle_power;
/** Handle for external i2c bus
* Bus: furi_hal_i2c_bus_external
* Pins: PC0(SCL) / PC1(SDA), float on release
* Params: 100khz
*/
extern FuriHalI2cBusHandle furi_hal_i2c_handle_external;
#ifdef __cplusplus
}
#endif

View File

@ -1,51 +0,0 @@
#pragma once
#include <stm32wbxx_ll_i2c.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct FuriHalI2cBus FuriHalI2cBus;
typedef struct FuriHalI2cBusHandle FuriHalI2cBusHandle;
/** FuriHal i2c bus states */
typedef enum {
FuriHalI2cBusEventInit, /**< Bus initialization event, called on system start */
FuriHalI2cBusEventDeinit, /**< Bus deinitialization event, called on system stop */
FuriHalI2cBusEventLock, /**< Bus lock event, called before activation */
FuriHalI2cBusEventUnlock, /**< Bus unlock event, called after deactivation */
FuriHalI2cBusEventActivate, /**< Bus activation event, called before handle activation */
FuriHalI2cBusEventDeactivate, /**< Bus deactivation event, called after handle deactivation */
} FuriHalI2cBusEvent;
/** FuriHal i2c bus event callback */
typedef void (*FuriHalI2cBusEventCallback)(FuriHalI2cBus* bus, FuriHalI2cBusEvent event);
/** FuriHal i2c bus */
struct FuriHalI2cBus {
I2C_TypeDef* i2c;
FuriHalI2cBusHandle* current_handle;
FuriHalI2cBusEventCallback callback;
};
/** FuriHal i2c handle states */
typedef enum {
FuriHalI2cBusHandleEventActivate, /**< Handle activate: connect gpio and apply bus config */
FuriHalI2cBusHandleEventDeactivate, /**< Handle deactivate: disconnect gpio and reset bus config */
} FuriHalI2cBusHandleEvent;
/** FuriHal i2c handle event callback */
typedef void (*FuriHalI2cBusHandleEventCallback)(
FuriHalI2cBusHandle* handle,
FuriHalI2cBusHandleEvent event);
/** FuriHal i2c handle */
struct FuriHalI2cBusHandle {
FuriHalI2cBus* bus;
FuriHalI2cBusHandleEventCallback callback;
};
#ifdef __cplusplus
}
#endif

View File

@ -1,49 +0,0 @@
#include <furi_hal_light.h>
#include <lp5562.h>
#define LED_CURRENT_RED 50
#define LED_CURRENT_GREEN 50
#define LED_CURRENT_BLUE 50
#define LED_CURRENT_WHITE 150
void furi_hal_light_init() {
furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
lp5562_reset(&furi_hal_i2c_handle_power);
lp5562_set_channel_current(&furi_hal_i2c_handle_power, LP5562ChannelRed, LED_CURRENT_RED);
lp5562_set_channel_current(&furi_hal_i2c_handle_power, LP5562ChannelGreen, LED_CURRENT_GREEN);
lp5562_set_channel_current(&furi_hal_i2c_handle_power, LP5562ChannelBlue, LED_CURRENT_BLUE);
lp5562_set_channel_current(&furi_hal_i2c_handle_power, LP5562ChannelWhite, LED_CURRENT_WHITE);
lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelRed, 0x00);
lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelGreen, 0x00);
lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelBlue, 0x00);
lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelWhite, 0x00);
lp5562_enable(&furi_hal_i2c_handle_power);
lp5562_configure(&furi_hal_i2c_handle_power);
furi_hal_i2c_release(&furi_hal_i2c_handle_power);
}
void furi_hal_light_set(Light light, uint8_t value) {
furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
switch(light) {
case LightRed:
lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelRed, value);
break;
case LightGreen:
lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelGreen, value);
break;
case LightBlue:
lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelBlue, value);
break;
case LightBacklight:
lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelWhite, value);
break;
default:
break;
}
furi_hal_i2c_release(&furi_hal_i2c_handle_power);
}

View File

@ -1,17 +0,0 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include <furi_hal_resources.h>
#ifdef __cplusplus
extern "C" {
#endif
void furi_hal_light_init();
void furi_hal_light_set(Light light, uint8_t value);
#ifdef __cplusplus
}
#endif

View File

@ -1,44 +0,0 @@
#include "furi_hal_resources.h"
#include "main.h"
const GpioPin vibro_gpio = {.port = VIBRO_GPIO_Port, .pin = VIBRO_Pin};
const GpioPin ibutton_gpio = {.port = iBTN_GPIO_Port, .pin = iBTN_Pin};
const GpioPin gpio_cc1101_g0 = {.port = CC1101_G0_GPIO_Port, .pin = CC1101_G0_Pin};
const GpioPin gpio_rf_sw_0 = {.port = RF_SW_0_GPIO_Port, .pin = RF_SW_0_Pin};
const GpioPin gpio_subghz_cs = {.port = CC1101_CS_GPIO_Port, .pin = CC1101_CS_Pin};
const GpioPin gpio_display_cs = {.port = DISPLAY_CS_GPIO_Port, .pin = DISPLAY_CS_Pin};
const GpioPin gpio_display_rst = {.port = DISPLAY_RST_GPIO_Port, .pin = DISPLAY_RST_Pin};
const GpioPin gpio_display_di = {.port = DISPLAY_DI_GPIO_Port, .pin = DISPLAY_DI_Pin};
const GpioPin gpio_sdcard_cs = {.port = SD_CS_GPIO_Port, .pin = SD_CS_Pin};
const GpioPin gpio_nfc_cs = {.port = NFC_CS_GPIO_Port, .pin = NFC_CS_Pin};
const GpioPin gpio_spi_d_miso = {.port = SPI_D_MISO_GPIO_Port, .pin = SPI_D_MISO_Pin};
const GpioPin gpio_spi_d_mosi = {.port = SPI_D_MOSI_GPIO_Port, .pin = SPI_D_MOSI_Pin};
const GpioPin gpio_spi_d_sck = {.port = SPI_D_SCK_GPIO_Port, .pin = SPI_D_SCK_Pin};
const GpioPin gpio_spi_r_miso = {.port = SPI_R_MISO_GPIO_Port, .pin = SPI_R_MISO_Pin};
const GpioPin gpio_spi_r_mosi = {.port = SPI_R_MOSI_GPIO_Port, .pin = SPI_R_MOSI_Pin};
const GpioPin gpio_spi_r_sck = {.port = SPI_R_SCK_GPIO_Port, .pin = SPI_R_SCK_Pin};
const GpioPin gpio_ext_pc0 = {.port = GPIOC, .pin = LL_GPIO_PIN_0};
const GpioPin gpio_ext_pc1 = {.port = GPIOC, .pin = LL_GPIO_PIN_1};
const GpioPin gpio_ext_pc3 = {.port = GPIOC, .pin = LL_GPIO_PIN_3};
const GpioPin gpio_ext_pb2 = {.port = GPIOB, .pin = LL_GPIO_PIN_2};
const GpioPin gpio_ext_pb3 = {.port = GPIOB, .pin = LL_GPIO_PIN_3};
const GpioPin gpio_ext_pa4 = {.port = GPIOA, .pin = LL_GPIO_PIN_4};
const GpioPin gpio_ext_pa6 = {.port = GPIOA, .pin = LL_GPIO_PIN_6};
const GpioPin gpio_ext_pa7 = {.port = GPIOA, .pin = LL_GPIO_PIN_7};
const GpioPin gpio_rfid_pull = {.port = RFID_PULL_GPIO_Port, .pin = RFID_PULL_Pin};
const GpioPin gpio_rfid_carrier_out = {.port = RFID_OUT_GPIO_Port, .pin = RFID_OUT_Pin};
const GpioPin gpio_rfid_data_in = {.port = RFID_RF_IN_GPIO_Port, .pin = RFID_RF_IN_Pin};
const GpioPin gpio_infrared_rx = {.port = IR_RX_GPIO_Port, .pin = IR_RX_Pin};
const GpioPin gpio_infrared_tx = {.port = IR_TX_GPIO_Port, .pin = IR_TX_Pin};
const GpioPin gpio_usart_tx = {.port = USART1_TX_Port, .pin = USART1_TX_Pin};
const GpioPin gpio_usart_rx = {.port = USART1_RX_Port, .pin = USART1_RX_Pin};
const GpioPin gpio_i2c_power_sda = {.port = GPIOA, .pin = LL_GPIO_PIN_10};
const GpioPin gpio_i2c_power_scl = {.port = GPIOA, .pin = LL_GPIO_PIN_9};

View File

@ -1,73 +0,0 @@
#pragma once
#include <stm32wbxx.h>
#include <stm32wbxx_ll_gpio.h>
#include <furi_hal_gpio.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Input Keys */
typedef enum {
InputKeyUp,
InputKeyDown,
InputKeyRight,
InputKeyLeft,
InputKeyOk,
InputKeyBack,
} InputKey;
/* Light */
typedef enum {
LightRed,
LightGreen,
LightBlue,
LightBacklight,
} Light;
extern const GpioPin vibro_gpio;
extern const GpioPin ibutton_gpio;
extern const GpioPin gpio_cc1101_g0;
extern const GpioPin gpio_rf_sw_0;
extern const GpioPin gpio_subghz_cs;
extern const GpioPin gpio_display_cs;
extern const GpioPin gpio_display_rst;
extern const GpioPin gpio_display_di;
extern const GpioPin gpio_sdcard_cs;
extern const GpioPin gpio_nfc_cs;
extern const GpioPin gpio_spi_d_miso;
extern const GpioPin gpio_spi_d_mosi;
extern const GpioPin gpio_spi_d_sck;
extern const GpioPin gpio_spi_r_miso;
extern const GpioPin gpio_spi_r_mosi;
extern const GpioPin gpio_spi_r_sck;
extern const GpioPin gpio_ext_pc0;
extern const GpioPin gpio_ext_pc1;
extern const GpioPin gpio_ext_pc3;
extern const GpioPin gpio_ext_pb2;
extern const GpioPin gpio_ext_pb3;
extern const GpioPin gpio_ext_pa4;
extern const GpioPin gpio_ext_pa6;
extern const GpioPin gpio_ext_pa7;
extern const GpioPin gpio_rfid_pull;
extern const GpioPin gpio_rfid_carrier_out;
extern const GpioPin gpio_rfid_data_in;
extern const GpioPin gpio_infrared_rx;
extern const GpioPin gpio_infrared_tx;
extern const GpioPin gpio_usart_tx;
extern const GpioPin gpio_usart_rx;
extern const GpioPin gpio_i2c_power_sda;
extern const GpioPin gpio_i2c_power_scl;
#ifdef __cplusplus
}
#endif

View File

@ -1,151 +0,0 @@
#include "furi_hal_spi.h"
#include "furi_hal_resources.h"
#include <stdbool.h>
#include <string.h>
#include <assert.h>
#include <stm32wbxx_ll_spi.h>
#include <stm32wbxx_ll_utils.h>
#include <stm32wbxx_ll_cortex.h>
void furi_hal_spi_init() {
furi_hal_spi_bus_init(&furi_hal_spi_bus_r);
furi_hal_spi_bus_init(&furi_hal_spi_bus_d);
furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_subghz);
furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc);
furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_display);
furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_fast);
furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_slow);
}
void furi_hal_spi_bus_init(FuriHalSpiBus* bus) {
assert(bus);
bus->callback(bus, FuriHalSpiBusEventInit);
}
void furi_hal_spi_bus_deinit(FuriHalSpiBus* bus) {
assert(bus);
bus->callback(bus, FuriHalSpiBusEventDeinit);
}
void furi_hal_spi_bus_handle_init(FuriHalSpiBusHandle* handle) {
assert(handle);
handle->callback(handle, FuriHalSpiBusHandleEventInit);
}
void furi_hal_spi_bus_handle_deinit(FuriHalSpiBusHandle* handle) {
assert(handle);
handle->callback(handle, FuriHalSpiBusHandleEventDeinit);
}
void furi_hal_spi_acquire(FuriHalSpiBusHandle* handle) {
assert(handle);
handle->bus->callback(handle->bus, FuriHalSpiBusEventLock);
handle->bus->callback(handle->bus, FuriHalSpiBusEventActivate);
assert(handle->bus->current_handle == NULL);
handle->bus->current_handle = handle;
handle->callback(handle, FuriHalSpiBusHandleEventActivate);
}
void furi_hal_spi_release(FuriHalSpiBusHandle* handle) {
assert(handle);
assert(handle->bus->current_handle == handle);
// Handle event and unset handle
handle->callback(handle, FuriHalSpiBusHandleEventDeactivate);
handle->bus->current_handle = NULL;
// Bus events
handle->bus->callback(handle->bus, FuriHalSpiBusEventDeactivate);
handle->bus->callback(handle->bus, FuriHalSpiBusEventUnlock);
}
static void furi_hal_spi_bus_end_txrx(FuriHalSpiBusHandle* handle, uint32_t timeout) {
while(LL_SPI_GetTxFIFOLevel(handle->bus->spi) != LL_SPI_TX_FIFO_EMPTY)
;
while(LL_SPI_IsActiveFlag_BSY(handle->bus->spi))
;
while(LL_SPI_GetRxFIFOLevel(handle->bus->spi) != LL_SPI_RX_FIFO_EMPTY) {
LL_SPI_ReceiveData8(handle->bus->spi);
}
}
bool furi_hal_spi_bus_rx(
FuriHalSpiBusHandle* handle,
uint8_t* buffer,
size_t size,
uint32_t timeout) {
assert(handle);
assert(handle->bus->current_handle == handle);
assert(buffer);
assert(size > 0);
return furi_hal_spi_bus_trx(handle, buffer, buffer, size, timeout);
}
bool furi_hal_spi_bus_tx(
FuriHalSpiBusHandle* handle,
uint8_t* buffer,
size_t size,
uint32_t timeout) {
assert(handle);
assert(handle->bus->current_handle == handle);
assert(buffer);
assert(size > 0);
bool ret = true;
while(size > 0) {
if(LL_SPI_IsActiveFlag_TXE(handle->bus->spi)) {
LL_SPI_TransmitData8(handle->bus->spi, *buffer);
buffer++;
size--;
}
}
furi_hal_spi_bus_end_txrx(handle, timeout);
LL_SPI_ClearFlag_OVR(handle->bus->spi);
return ret;
}
bool furi_hal_spi_bus_trx(
FuriHalSpiBusHandle* handle,
uint8_t* tx_buffer,
uint8_t* rx_buffer,
size_t size,
uint32_t timeout) {
assert(handle);
assert(handle->bus->current_handle == handle);
assert(tx_buffer);
assert(rx_buffer);
assert(size > 0);
bool ret = true;
size_t tx_size = size;
bool tx_allowed = true;
while(size > 0) {
if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE(handle->bus->spi) && tx_allowed) {
LL_SPI_TransmitData8(handle->bus->spi, *tx_buffer);
tx_buffer++;
tx_size--;
tx_allowed = false;
}
if(LL_SPI_IsActiveFlag_RXNE(handle->bus->spi)) {
*rx_buffer = LL_SPI_ReceiveData8(handle->bus->spi);
rx_buffer++;
size--;
tx_allowed = true;
}
}
furi_hal_spi_bus_end_txrx(handle, timeout);
return ret;
}

View File

@ -1,290 +0,0 @@
#include <furi_hal_spi_config.h>
#include <furi_hal_resources.h>
/* SPI Presets */
const LL_SPI_InitTypeDef furi_hal_spi_preset_2edge_low_8m = {
.Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT,
.ClockPolarity = LL_SPI_POLARITY_LOW,
.ClockPhase = LL_SPI_PHASE_2EDGE,
.NSS = LL_SPI_NSS_SOFT,
.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV8,
.BitOrder = LL_SPI_MSB_FIRST,
.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE,
.CRCPoly = 7,
};
const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_8m = {
.Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT,
.ClockPolarity = LL_SPI_POLARITY_LOW,
.ClockPhase = LL_SPI_PHASE_1EDGE,
.NSS = LL_SPI_NSS_SOFT,
.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV8,
.BitOrder = LL_SPI_MSB_FIRST,
.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE,
.CRCPoly = 7,
};
const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_4m = {
.Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT,
.ClockPolarity = LL_SPI_POLARITY_LOW,
.ClockPhase = LL_SPI_PHASE_1EDGE,
.NSS = LL_SPI_NSS_SOFT,
.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV16,
.BitOrder = LL_SPI_MSB_FIRST,
.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE,
.CRCPoly = 7,
};
const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_16m = {
.Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT,
.ClockPolarity = LL_SPI_POLARITY_LOW,
.ClockPhase = LL_SPI_PHASE_1EDGE,
.NSS = LL_SPI_NSS_SOFT,
.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2,
.BitOrder = LL_SPI_MSB_FIRST,
.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE,
.CRCPoly = 7,
};
const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_2m = {
.Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT,
.ClockPolarity = LL_SPI_POLARITY_LOW,
.ClockPhase = LL_SPI_PHASE_1EDGE,
.NSS = LL_SPI_NSS_SOFT,
.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV32,
.BitOrder = LL_SPI_MSB_FIRST,
.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE,
.CRCPoly = 7,
};
/* SPI Buses */
static void furi_hal_spi_bus_r_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) {
if(event == FuriHalSpiBusEventInit) {
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1);
bus->current_handle = NULL;
} else if(event == FuriHalSpiBusEventDeinit) {
} else if(event == FuriHalSpiBusEventLock) {
} else if(event == FuriHalSpiBusEventUnlock) {
} else if(event == FuriHalSpiBusEventActivate) {
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI1);
} else if(event == FuriHalSpiBusEventDeactivate) {
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1);
}
}
FuriHalSpiBus furi_hal_spi_bus_r = {
.spi = SPI1,
.callback = furi_hal_spi_bus_r_event_callback,
};
static void furi_hal_spi_bus_d_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) {
if(event == FuriHalSpiBusEventInit) {
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2);
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2);
bus->current_handle = NULL;
} else if(event == FuriHalSpiBusEventDeinit) {
} else if(event == FuriHalSpiBusEventLock) {
} else if(event == FuriHalSpiBusEventUnlock) {
} else if(event == FuriHalSpiBusEventActivate) {
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI2);
} else if(event == FuriHalSpiBusEventDeactivate) {
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2);
}
}
FuriHalSpiBus furi_hal_spi_bus_d = {
.spi = SPI2,
.callback = furi_hal_spi_bus_d_event_callback,
};
/* SPI Bus Handles */
inline static void furi_hal_spi_bus_r_handle_event_callback(
FuriHalSpiBusHandle* handle,
FuriHalSpiBusHandleEvent event,
const LL_SPI_InitTypeDef* preset) {
if(event == FuriHalSpiBusHandleEventInit) {
hal_gpio_write(handle->cs, true);
hal_gpio_init(handle->cs, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
} else if(event == FuriHalSpiBusHandleEventDeinit) {
hal_gpio_write(handle->cs, true);
hal_gpio_init(handle->cs, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
} else if(event == FuriHalSpiBusHandleEventActivate) {
LL_SPI_Init(handle->bus->spi, (LL_SPI_InitTypeDef*)preset);
LL_SPI_SetRxFIFOThreshold(handle->bus->spi, LL_SPI_RX_FIFO_TH_QUARTER);
LL_SPI_Enable(handle->bus->spi);
hal_gpio_init_ex(
handle->miso,
GpioModeAltFunctionPushPull,
GpioPullNo,
GpioSpeedVeryHigh,
GpioAltFn5SPI1);
hal_gpio_init_ex(
handle->mosi,
GpioModeAltFunctionPushPull,
GpioPullNo,
GpioSpeedVeryHigh,
GpioAltFn5SPI1);
hal_gpio_init_ex(
handle->sck,
GpioModeAltFunctionPushPull,
GpioPullNo,
GpioSpeedVeryHigh,
GpioAltFn5SPI1);
hal_gpio_write(handle->cs, false);
} else if(event == FuriHalSpiBusHandleEventDeactivate) {
hal_gpio_write(handle->cs, true);
hal_gpio_init(handle->miso, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
hal_gpio_init(handle->mosi, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
hal_gpio_init(handle->sck, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
LL_SPI_Disable(handle->bus->spi);
}
}
static void furi_hal_spi_bus_handle_subghz_event_callback(
FuriHalSpiBusHandle* handle,
FuriHalSpiBusHandleEvent event) {
furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_8m);
}
FuriHalSpiBusHandle furi_hal_spi_bus_handle_subghz = {
.bus = &furi_hal_spi_bus_r,
.callback = furi_hal_spi_bus_handle_subghz_event_callback,
.miso = &gpio_spi_r_miso,
.mosi = &gpio_spi_r_mosi,
.sck = &gpio_spi_r_sck,
.cs = &gpio_subghz_cs,
};
static void furi_hal_spi_bus_handle_nfc_event_callback(
FuriHalSpiBusHandle* handle,
FuriHalSpiBusHandleEvent event) {
furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_2edge_low_8m);
}
FuriHalSpiBusHandle furi_hal_spi_bus_handle_nfc = {
.bus = &furi_hal_spi_bus_r,
.callback = furi_hal_spi_bus_handle_nfc_event_callback,
.miso = &gpio_spi_r_miso,
.mosi = &gpio_spi_r_mosi,
.sck = &gpio_spi_r_sck,
.cs = &gpio_nfc_cs,
};
static void furi_hal_spi_bus_handle_external_event_callback(
FuriHalSpiBusHandle* handle,
FuriHalSpiBusHandleEvent event) {
furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_2m);
}
FuriHalSpiBusHandle furi_hal_spi_bus_handle_external = {
.bus = &furi_hal_spi_bus_r,
.callback = furi_hal_spi_bus_handle_external_event_callback,
.miso = &gpio_ext_pa6,
.mosi = &gpio_ext_pa7,
.sck = &gpio_ext_pb3,
.cs = &gpio_ext_pa4,
};
inline static void furi_hal_spi_bus_d_handle_event_callback(
FuriHalSpiBusHandle* handle,
FuriHalSpiBusHandleEvent event,
const LL_SPI_InitTypeDef* preset) {
if(event == FuriHalSpiBusHandleEventInit) {
hal_gpio_write(handle->cs, true);
hal_gpio_init(handle->cs, GpioModeOutputPushPull, GpioPullUp, GpioSpeedVeryHigh);
hal_gpio_init_ex(
handle->miso,
GpioModeAltFunctionPushPull,
GpioPullNo,
GpioSpeedVeryHigh,
GpioAltFn5SPI2);
hal_gpio_init_ex(
handle->mosi,
GpioModeAltFunctionPushPull,
GpioPullNo,
GpioSpeedVeryHigh,
GpioAltFn5SPI2);
hal_gpio_init_ex(
handle->sck,
GpioModeAltFunctionPushPull,
GpioPullNo,
GpioSpeedVeryHigh,
GpioAltFn5SPI2);
} else if(event == FuriHalSpiBusHandleEventDeinit) {
hal_gpio_write(handle->cs, true);
hal_gpio_init(handle->cs, GpioModeAnalog, GpioPullUp, GpioSpeedLow);
} else if(event == FuriHalSpiBusHandleEventActivate) {
LL_SPI_Init(handle->bus->spi, (LL_SPI_InitTypeDef*)preset);
LL_SPI_SetRxFIFOThreshold(handle->bus->spi, LL_SPI_RX_FIFO_TH_QUARTER);
LL_SPI_Enable(handle->bus->spi);
hal_gpio_write(handle->cs, false);
} else if(event == FuriHalSpiBusHandleEventDeactivate) {
hal_gpio_write(handle->cs, true);
LL_SPI_Disable(handle->bus->spi);
}
}
static void furi_hal_spi_bus_handle_display_event_callback(
FuriHalSpiBusHandle* handle,
FuriHalSpiBusHandleEvent event) {
furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_4m);
}
FuriHalSpiBusHandle furi_hal_spi_bus_handle_display = {
.bus = &furi_hal_spi_bus_d,
.callback = furi_hal_spi_bus_handle_display_event_callback,
.miso = &gpio_spi_d_miso,
.mosi = &gpio_spi_d_mosi,
.sck = &gpio_spi_d_sck,
.cs = &gpio_display_cs,
};
static void furi_hal_spi_bus_handle_sd_fast_event_callback(
FuriHalSpiBusHandle* handle,
FuriHalSpiBusHandleEvent event) {
furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_16m);
}
FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast = {
.bus = &furi_hal_spi_bus_d,
.callback = furi_hal_spi_bus_handle_sd_fast_event_callback,
.miso = &gpio_spi_d_miso,
.mosi = &gpio_spi_d_mosi,
.sck = &gpio_spi_d_sck,
.cs = &gpio_sdcard_cs,
};
static void furi_hal_spi_bus_handle_sd_slow_event_callback(
FuriHalSpiBusHandle* handle,
FuriHalSpiBusHandleEvent event) {
furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_2m);
}
FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow = {
.bus = &furi_hal_spi_bus_d,
.callback = furi_hal_spi_bus_handle_sd_slow_event_callback,
.miso = &gpio_spi_d_miso,
.mosi = &gpio_spi_d_mosi,
.sck = &gpio_spi_d_sck,
.cs = &gpio_sdcard_cs,
};

View File

@ -1,61 +0,0 @@
#pragma once
#include <furi_hal_spi_types.h>
#ifdef __cplusplus
extern "C" {
#endif
/** Preset for ST25R916 */
extern const LL_SPI_InitTypeDef furi_hal_spi_preset_2edge_low_8m;
/** Preset for CC1101 */
extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_8m;
/** Preset for ST7567 (Display) */
extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_4m;
/** Preset for SdCard in fast mode */
extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_16m;
/** Preset for SdCard in slow mode */
extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_2m;
/** Furi Hal Spi Bus R (Radio: CC1101, Nfc, External)*/
extern FuriHalSpiBus furi_hal_spi_bus_r;
/** Furi Hal Spi Bus D (Display, SdCard) */
extern FuriHalSpiBus furi_hal_spi_bus_d;
/** CC1101 on `furi_hal_spi_bus_r` */
extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_subghz;
/** ST25R3916 on `furi_hal_spi_bus_r` */
extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_nfc;
/** External on `furi_hal_spi_bus_r`
* Preset: `furi_hal_spi_preset_1edge_low_2m`
*
* miso: pa6
* mosi: pa7
* sck: pb3
* cs: pa4 (software controlled)
*
* @warning not initialized by default, call `furi_hal_spi_bus_handle_init` to initialize
* Bus pins are floating on inactive state, CS high after initialization
*
*/
extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_external;
/** ST7567(Display) on `furi_hal_spi_bus_d` */
extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_display;
/** SdCard in fast mode on `furi_hal_spi_bus_d` */
extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast;
/** SdCard in slow mode on `furi_hal_spi_bus_d` */
extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow;
#ifdef __cplusplus
}
#endif

View File

@ -1,64 +0,0 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
#include <furi_hal_gpio.h>
#include <stm32wbxx_ll_spi.h>
#include <stm32wbxx_ll_rcc.h>
#include <stm32wbxx_ll_bus.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct FuriHalSpiBus FuriHalSpiBus;
typedef struct FuriHalSpiBusHandle FuriHalSpiBusHandle;
/** FuriHal spi bus states */
typedef enum {
FuriHalSpiBusEventInit, /**< Bus initialization event, called on system start */
FuriHalSpiBusEventDeinit, /**< Bus deinitialization event, called on system stop */
FuriHalSpiBusEventLock, /**< Bus lock event, called before activation */
FuriHalSpiBusEventUnlock, /**< Bus unlock event, called after deactivation */
FuriHalSpiBusEventActivate, /**< Bus activation event, called before handle activation */
FuriHalSpiBusEventDeactivate, /**< Bus deactivation event, called after handle deactivation */
} FuriHalSpiBusEvent;
/** FuriHal spi bus event callback */
typedef void (*FuriHalSpiBusEventCallback)(FuriHalSpiBus* bus, FuriHalSpiBusEvent event);
/** FuriHal spi bus */
struct FuriHalSpiBus {
SPI_TypeDef* spi;
FuriHalSpiBusEventCallback callback;
FuriHalSpiBusHandle* current_handle;
};
/** FuriHal spi handle states */
typedef enum {
FuriHalSpiBusHandleEventInit, /**< Handle init, called on system start, initialize gpio for idle state */
FuriHalSpiBusHandleEventDeinit, /**< Handle deinit, called on system stop, deinitialize gpio for default state */
FuriHalSpiBusHandleEventActivate, /**< Handle activate: connect gpio and apply bus config */
FuriHalSpiBusHandleEventDeactivate, /**< Handle deactivate: disconnect gpio and reset bus config */
} FuriHalSpiBusHandleEvent;
/** FuriHal spi handle event callback */
typedef void (*FuriHalSpiBusHandleEventCallback)(
FuriHalSpiBusHandle* handle,
FuriHalSpiBusHandleEvent event);
/** FuriHal spi handle */
struct FuriHalSpiBusHandle {
FuriHalSpiBus* bus;
FuriHalSpiBusHandleEventCallback callback;
const GpioPin* miso;
const GpioPin* mosi;
const GpioPin* sck;
const GpioPin* cs;
};
#ifdef __cplusplus
}
#endif

View File

@ -1,268 +0,0 @@
#include <furi_hal_version.h>
#include <stm32wbxx.h>
#include <stm32wbxx_ll_rtc.h>
#include <stm32wbxx_ll_system.h>
#include <stdio.h>
#define FURI_HAL_VERSION_OTP_HEADER_MAGIC 0xBABE
#define FURI_HAL_VERSION_OTP_ADDRESS OTP_AREA_BASE
/** OTP V0 Structure: prototypes and early EVT */
typedef struct {
uint8_t board_version;
uint8_t board_target;
uint8_t board_body;
uint8_t board_connect;
uint32_t header_timestamp;
char name[FURI_HAL_VERSION_NAME_LENGTH];
} FuriHalVersionOTPv0;
/** OTP V1 Structure: late EVT, DVT */
typedef struct {
/* First 64 bits: header */
uint16_t header_magic;
uint8_t header_version;
uint8_t header_reserved;
uint32_t header_timestamp;
/* Second 64 bits: board info */
uint8_t board_version; /** Board version */
uint8_t board_target; /** Board target firmware */
uint8_t board_body; /** Board body */
uint8_t board_connect; /** Board interconnect */
uint8_t board_color; /** Board color */
uint8_t board_region; /** Board region */
uint16_t board_reserved; /** Reserved for future use, 0x0000 */
/* Third 64 bits: Unique Device Name */
char name[FURI_HAL_VERSION_NAME_LENGTH]; /** Unique Device Name */
} FuriHalVersionOTPv1;
/** OTP V2 Structure: DVT2, PVT, Production */
typedef struct {
/* Early First 64 bits: header */
uint16_t header_magic;
uint8_t header_version;
uint8_t header_reserved;
uint32_t header_timestamp;
/* Early Second 64 bits: board info */
uint8_t board_version; /** Board version */
uint8_t board_target; /** Board target firmware */
uint8_t board_body; /** Board body */
uint8_t board_connect; /** Board interconnect */
uint8_t board_display; /** Board display */
uint8_t board_reserved2_0; /** Reserved for future use, 0x00 */
uint16_t board_reserved2_1; /** Reserved for future use, 0x0000 */
/* Late Third 64 bits: device info */
uint8_t board_color; /** Board color */
uint8_t board_region; /** Board region */
uint16_t board_reserved3_0; /** Reserved for future use, 0x0000 */
uint32_t board_reserved3_1; /** Reserved for future use, 0x00000000 */
/* Late Fourth 64 bits: Unique Device Name */
char name[FURI_HAL_VERSION_NAME_LENGTH]; /** Unique Device Name */
} FuriHalVersionOTPv2;
/** Represenation Model: */
typedef struct {
uint32_t timestamp;
uint8_t board_version; /** Board version */
uint8_t board_target; /** Board target firmware */
uint8_t board_body; /** Board body */
uint8_t board_connect; /** Board interconnect */
uint8_t board_color; /** Board color */
uint8_t board_region; /** Board region */
uint8_t board_display; /** Board display */
char name[FURI_HAL_VERSION_ARRAY_NAME_LENGTH]; /** \0 terminated name */
char device_name[FURI_HAL_VERSION_DEVICE_NAME_LENGTH]; /** device name for special needs */
uint8_t ble_mac[6];
} FuriHalVersion;
static FuriHalVersion furi_hal_version = {0};
static void furi_hal_version_set_name(const char* name) {
furi_hal_version.device_name[0] = 0;
}
static void furi_hal_version_load_otp_default() {
furi_hal_version_set_name(NULL);
}
static void furi_hal_version_load_otp_v0() {
const FuriHalVersionOTPv0* otp = (FuriHalVersionOTPv0*)FURI_HAL_VERSION_OTP_ADDRESS;
furi_hal_version.timestamp = otp->header_timestamp;
furi_hal_version.board_version = otp->board_version;
furi_hal_version.board_target = otp->board_target;
furi_hal_version.board_body = otp->board_body;
furi_hal_version.board_connect = otp->board_connect;
furi_hal_version_set_name(otp->name);
}
static void furi_hal_version_load_otp_v1() {
const FuriHalVersionOTPv1* otp = (FuriHalVersionOTPv1*)FURI_HAL_VERSION_OTP_ADDRESS;
furi_hal_version.timestamp = otp->header_timestamp;
furi_hal_version.board_version = otp->board_version;
furi_hal_version.board_target = otp->board_target;
furi_hal_version.board_body = otp->board_body;
furi_hal_version.board_connect = otp->board_connect;
furi_hal_version.board_color = otp->board_color;
furi_hal_version.board_region = otp->board_region;
furi_hal_version_set_name(otp->name);
}
static void furi_hal_version_load_otp_v2() {
const FuriHalVersionOTPv2* otp = (FuriHalVersionOTPv2*)FURI_HAL_VERSION_OTP_ADDRESS;
// 1st block, programmed afer baking
furi_hal_version.timestamp = otp->header_timestamp;
// 2nd block, programmed afer baking
furi_hal_version.board_version = otp->board_version;
furi_hal_version.board_target = otp->board_target;
furi_hal_version.board_body = otp->board_body;
furi_hal_version.board_connect = otp->board_connect;
furi_hal_version.board_display = otp->board_display;
// 3rd and 4th blocks, programmed on FATP stage
if(otp->board_color != 0xFF) {
furi_hal_version.board_color = otp->board_color;
furi_hal_version.board_region = otp->board_region;
furi_hal_version_set_name(otp->name);
} else {
furi_hal_version.board_color = 0;
furi_hal_version.board_region = 0;
furi_hal_version_set_name(NULL);
}
}
void furi_hal_version_init() {
switch(furi_hal_version_get_otp_version()) {
case FuriHalVersionOtpVersionUnknown:
furi_hal_version_load_otp_default();
break;
case FuriHalVersionOtpVersionEmpty:
furi_hal_version_load_otp_default();
break;
case FuriHalVersionOtpVersion0:
furi_hal_version_load_otp_v0();
break;
case FuriHalVersionOtpVersion1:
furi_hal_version_load_otp_v1();
break;
case FuriHalVersionOtpVersion2:
furi_hal_version_load_otp_v2();
break;
default:
furi_hal_version_load_otp_default();
}
}
bool furi_hal_version_do_i_belong_here() {
return furi_hal_version_get_hw_target() == 7;
}
const char* furi_hal_version_get_model_name() {
return "Flipper Zero";
}
const FuriHalVersionOtpVersion furi_hal_version_get_otp_version() {
if(*(uint64_t*)FURI_HAL_VERSION_OTP_ADDRESS == 0xFFFFFFFF) {
return FuriHalVersionOtpVersionEmpty;
} else {
if(((FuriHalVersionOTPv1*)FURI_HAL_VERSION_OTP_ADDRESS)->header_magic ==
FURI_HAL_VERSION_OTP_HEADER_MAGIC) {
// Version 1+
uint8_t version = ((FuriHalVersionOTPv1*)FURI_HAL_VERSION_OTP_ADDRESS)->header_version;
if(version >= FuriHalVersionOtpVersion1 && version <= FuriHalVersionOtpVersion2) {
return version;
} else {
return FuriHalVersionOtpVersionUnknown;
}
} else if(((FuriHalVersionOTPv0*)FURI_HAL_VERSION_OTP_ADDRESS)->board_version <= 10) {
// Version 0
return FuriHalVersionOtpVersion0;
} else {
// Version Unknown
return FuriHalVersionOtpVersionUnknown;
}
}
}
const uint8_t furi_hal_version_get_hw_version() {
return furi_hal_version.board_version;
}
const uint8_t furi_hal_version_get_hw_target() {
return furi_hal_version.board_target;
}
const uint8_t furi_hal_version_get_hw_body() {
return furi_hal_version.board_body;
}
const FuriHalVersionColor furi_hal_version_get_hw_color() {
return furi_hal_version.board_color;
}
const uint8_t furi_hal_version_get_hw_connect() {
return furi_hal_version.board_connect;
}
const FuriHalVersionRegion furi_hal_version_get_hw_region() {
return furi_hal_version.board_region;
}
const FuriHalVersionDisplay furi_hal_version_get_hw_display() {
return furi_hal_version.board_display;
}
const uint32_t furi_hal_version_get_hw_timestamp() {
return furi_hal_version.timestamp;
}
const char* furi_hal_version_get_name_ptr() {
return *furi_hal_version.name == 0x00 ? NULL : furi_hal_version.name;
}
const char* furi_hal_version_get_device_name_ptr() {
return furi_hal_version.device_name + 1;
}
const char* furi_hal_version_get_ble_local_device_name_ptr() {
return furi_hal_version.device_name;
}
const uint8_t* furi_hal_version_get_ble_mac() {
return furi_hal_version.ble_mac;
}
const struct Version* furi_hal_version_get_firmware_version(void) {
return version_get();
}
const struct Version* furi_hal_version_get_bootloader_version(void) {
#ifdef NO_BOOTLOADER
return 0;
#else
/* Backup register which points to structure in flash memory */
return (const struct Version*)LL_RTC_BAK_GetRegister(RTC, LL_RTC_BKP_DR1);
#endif
}
size_t furi_hal_version_uid_size() {
return 64 / 8;
}
const uint8_t* furi_hal_version_uid() {
return (const uint8_t*)UID64_BASE;
}

View File

@ -1,108 +0,0 @@
#pragma once
#include <stm32wbxx.h>
#include <stm32wbxx_ll_gpio.h>
#include <stm32wbxx_ll_spi.h>
#define BUTTON_BACK_GPIO_Port GPIOC
#define BUTTON_BACK_Pin LL_GPIO_PIN_13
#define BUTTON_DOWN_GPIO_Port GPIOC
#define BUTTON_DOWN_Pin LL_GPIO_PIN_6
#define BUTTON_LEFT_GPIO_Port GPIOB
#define BUTTON_LEFT_Pin LL_GPIO_PIN_11
#define BUTTON_OK_GPIO_Port GPIOH
#define BUTTON_OK_Pin LL_GPIO_PIN_3
#define BUTTON_RIGHT_GPIO_Port GPIOB
#define BUTTON_RIGHT_Pin LL_GPIO_PIN_12
#define BUTTON_UP_GPIO_Port GPIOB
#define BUTTON_UP_Pin LL_GPIO_PIN_10
#define CC1101_CS_GPIO_Port GPIOD
#define CC1101_CS_Pin LL_GPIO_PIN_0
#define CC1101_G0_GPIO_Port GPIOA
#define CC1101_G0_Pin LL_GPIO_PIN_1
#define DISPLAY_CS_GPIO_Port GPIOC
#define DISPLAY_CS_Pin LL_GPIO_PIN_11
#define DISPLAY_DI_GPIO_Port GPIOB
#define DISPLAY_DI_Pin LL_GPIO_PIN_1
#define DISPLAY_RST_GPIO_Port GPIOB
#define DISPLAY_RST_Pin LL_GPIO_PIN_0
#define IR_RX_GPIO_Port GPIOA
#define IR_RX_Pin LL_GPIO_PIN_0
#define IR_TX_GPIO_Port GPIOB
#define IR_TX_Pin LL_GPIO_PIN_9
#define NFC_CS_GPIO_Port GPIOE
#define NFC_CS_Pin LL_GPIO_PIN_4
#define PA4_GPIO_Port GPIOA
#define PA4_Pin LL_GPIO_PIN_4
#define PA6_GPIO_Port GPIOA
#define PA6_Pin LL_GPIO_PIN_6
#define PA7_GPIO_Port GPIOA
#define PA7_Pin LL_GPIO_PIN_7
#define PB2_GPIO_Port GPIOB
#define PB2_Pin LL_GPIO_PIN_2
#define PB3_GPIO_Port GPIOB
#define PB3_Pin LL_GPIO_PIN_3
#define PC0_GPIO_Port GPIOC
#define PC0_Pin LL_GPIO_PIN_0
#define PC1_GPIO_Port GPIOC
#define PC1_Pin LL_GPIO_PIN_1
#define PC3_GPIO_Port GPIOC
#define PC3_Pin LL_GPIO_PIN_3
#define PERIPH_POWER_GPIO_Port GPIOA
#define PERIPH_POWER_Pin LL_GPIO_PIN_3
#define QUARTZ_32MHZ_IN_GPIO_Port GPIOC
#define QUARTZ_32MHZ_IN_Pin LL_GPIO_PIN_14
#define QUARTZ_32MHZ_OUT_GPIO_Port GPIOC
#define QUARTZ_32MHZ_OUT_Pin LL_GPIO_PIN_15
#define RFID_OUT_GPIO_Port GPIOB
#define RFID_OUT_Pin LL_GPIO_PIN_13
#define RFID_PULL_GPIO_Port GPIOA
#define RFID_PULL_Pin LL_GPIO_PIN_2
#define RFID_RF_IN_GPIO_Port GPIOC
#define RFID_RF_IN_Pin LL_GPIO_PIN_5
#define RFID_TUNE_GPIO_Port GPIOA
#define RFID_TUNE_Pin LL_GPIO_PIN_8
#define RF_SW_0_GPIO_Port GPIOC
#define RF_SW_0_Pin LL_GPIO_PIN_4
#define SD_CD_GPIO_Port GPIOC
#define SD_CD_Pin LL_GPIO_PIN_10
#define SD_CS_GPIO_Port GPIOC
#define SD_CS_Pin LL_GPIO_PIN_12
#define SPEAKER_GPIO_Port GPIOB
#define SPEAKER_Pin LL_GPIO_PIN_8
#define VIBRO_GPIO_Port GPIOA
#define VIBRO_Pin LL_GPIO_PIN_15
#define iBTN_GPIO_Port GPIOB
#define iBTN_Pin LL_GPIO_PIN_14
#define USART1_TX_Pin LL_GPIO_PIN_6
#define USART1_TX_Port GPIOB
#define USART1_RX_Pin LL_GPIO_PIN_7
#define USART1_RX_Port GPIOB
#define SPI_D_MISO_GPIO_Port GPIOC
#define SPI_D_MISO_Pin LL_GPIO_PIN_2
#define SPI_D_MOSI_GPIO_Port GPIOB
#define SPI_D_MOSI_Pin LL_GPIO_PIN_15
#define SPI_D_SCK_GPIO_Port GPIOD
#define SPI_D_SCK_Pin LL_GPIO_PIN_1
#define SPI_R_MISO_GPIO_Port GPIOB
#define SPI_R_MISO_Pin LL_GPIO_PIN_4
#define SPI_R_MOSI_GPIO_Port GPIOB
#define SPI_R_MOSI_Pin LL_GPIO_PIN_5
#define SPI_R_SCK_GPIO_Port GPIOA
#define SPI_R_SCK_Pin LL_GPIO_PIN_5

View File

@ -1,187 +0,0 @@
/**
*****************************************************************************
**
** File : stm32wb55xx_flash_cm4.ld
**
** Abstract : System Workbench Minimal System calls file
**
** For more information about which c-functions
** need which of these lowlevel functions
** please consult the Newlib libc-manual
**
** Environment : System Workbench for MCU
**
** Distribution: The file is distributed “as is,” without any warranty
** of any kind.
**
*****************************************************************************
**
** <h2><center>&copy; COPYRIGHT(c) 2019 Ac6</center></h2>
**
** Redistribution and use in source and binary forms, with or without modification,
** are permitted provided that the following conditions are met:
** 1. Redistributions of source code must retain the above copyright notice,
** this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright notice,
** this list of conditions and the following disclaimer in the documentation
** and/or other materials provided with the distribution.
** 3. Neither the name of Ac6 nor the names of its contributors
** may be used to endorse or promote products derived from this software
** without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
*****************************************************************************
*/
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x20030000; /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 32K
RAM1 (xrw) : ORIGIN = 0x20000008, LENGTH = 0x2FFF8
RAM_SHARED (xrw) : ORIGIN = 0x20030000, LENGTH = 10K
}
/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
/* The program code and other data goes into FLASH */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >FLASH
/* Constant data goes into FLASH */
.rodata :
{
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
} >FLASH
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH
/* used by the startup to initialize data */
_sidata = LOADADDR(.data);
/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM1 AT> FLASH
/* Uninitialized data section */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM1
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(8);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(8);
} >RAM1
/* Remove information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
MAPPING_TABLE (NOLOAD) : { *(MAPPING_TABLE) } >RAM_SHARED
MB_MEM1 (NOLOAD) : { *(MB_MEM1) } >RAM_SHARED
MB_MEM2 (NOLOAD) : { _sMB_MEM2 = . ; *(MB_MEM2) ; _eMB_MEM2 = . ; } >RAM_SHARED
}

View File

@ -1,264 +0,0 @@
#include <target.h>
#include <stm32wbxx.h>
#include <stm32wbxx_ll_system.h>
#include <stm32wbxx_ll_bus.h>
#include <stm32wbxx_ll_utils.h>
#include <stm32wbxx_ll_rcc.h>
#include <stm32wbxx_ll_rtc.h>
#include <stm32wbxx_ll_pwr.h>
#include <stm32wbxx_ll_gpio.h>
#include <stm32wbxx_hal_flash.h>
#include <lib/toolbox/version.h>
#include <furi_hal.h>
#include <u8g2.h>
#include <u8g2_glue.h>
const uint8_t I_DFU_128x50[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x07, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x38, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0xC0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8F, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7F, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x75, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x0A, 0x00, 0x00, 0x0F, 0x60, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xE0, 0x0F, 0x00, 0xC0, 0xE0, 0x4F, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x30, 0x1E, 0x90, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x18, 0x00, 0x8C, 0x01, 0xA0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x81, 0xFF, 0x19, 0x00, 0x63, 0x00, 0xC0, 0xF0, 0x07,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x60, 0x5E, 0x1F, 0x80, 0x18, 0x00, 0xE0, 0x0E, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x18, 0xAF, 0x0F, 0x40, 0x06, 0x00, 0xF8, 0x01, 0x20,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x06, 0x57, 0x01, 0x20, 0x01, 0x00, 0x78, 0x00, 0x3E,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x81, 0xAF, 0x02, 0x90, 0x00, 0x00, 0x38, 0x80, 0x41,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x80, 0x57, 0x01, 0x48, 0x00, 0x00, 0x10, 0x60, 0x40,
0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x10, 0x80, 0xAB, 0x00, 0x24, 0x00, 0x00, 0x08, 0x10, 0x40,
0x3F, 0x00, 0x00, 0x00, 0x00, 0x38, 0x0C, 0xC0, 0x57, 0x01, 0x12, 0x00, 0x00, 0x04, 0x08, 0x40,
0xC0, 0x0F, 0x00, 0x00, 0xC0, 0x07, 0x03, 0xF0, 0xAB, 0x00, 0x0A, 0x00, 0x00, 0x02, 0x04, 0x40,
0x00, 0xF0, 0x1F, 0x80, 0x3F, 0xC0, 0x00, 0xFC, 0x55, 0x01, 0x05, 0xE0, 0x00, 0x01, 0x04, 0x40,
0x00, 0x00, 0xE0, 0x7F, 0x00, 0x30, 0x00, 0xFF, 0xAB, 0x00, 0x05, 0xE0, 0x80, 0x00, 0x02, 0x40,
0x0F, 0x00, 0x00, 0x00, 0x80, 0x0F, 0xE0, 0xCF, 0x55, 0x81, 0x02, 0xF0, 0x40, 0x00, 0x02, 0x40,
0xF0, 0x0F, 0x00, 0x00, 0x7F, 0x00, 0xFE, 0xC3, 0xAB, 0x80, 0x02, 0x78, 0x20, 0x00, 0x01, 0x40,
0x00, 0xF0, 0xFF, 0xFF, 0x00, 0xF0, 0xFF, 0xC0, 0xD5, 0x81, 0x01, 0x7E, 0x10, 0x80, 0x00, 0x20,
0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x0F, 0xE0, 0xFA, 0x83, 0xC1, 0x3F, 0x08, 0x80, 0x00, 0x20,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0xD8, 0x07, 0x83, 0xF1, 0x1F, 0x04, 0x40, 0x00, 0x20,
0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0x0F, 0x80, 0xC7, 0x01, 0x83, 0xF1, 0x0F, 0x00, 0x20, 0x00, 0x10,
0xE0, 0xFF, 0xFF, 0xFF, 0x3F, 0xC0, 0x7F, 0x40, 0x80, 0x83, 0xE1, 0x01, 0x00, 0x20, 0x00, 0x18,
0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x3F, 0x00, 0x20, 0xFC, 0x83, 0x01, 0x00, 0x00, 0x10, 0x00, 0x18,
0xFF, 0xFF, 0xFF, 0x3F, 0xF0, 0x00, 0x00, 0x10, 0xD7, 0x01, 0x03, 0x00, 0x00, 0x08, 0x00, 0x1C,
0xFF, 0xFF, 0x01, 0x00, 0x0F, 0x00, 0x00, 0x88, 0xAB, 0x02, 0xE3, 0x01, 0x00, 0x08, 0x00, 0x0C,
0xFF, 0x07, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xC4, 0x55, 0x05, 0x1E, 0x00, 0x00, 0x04, 0x00, 0x0E,
0x7F, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xA3, 0xAB, 0x02, 0x06, 0x00, 0x00, 0x02, 0x00, 0x0F,
0x0F, 0x00, 0x80, 0x03, 0x00, 0x00, 0xC0, 0x10, 0x57, 0x05, 0x02, 0x00, 0x00, 0x01, 0x80, 0x07,
0x03, 0x00, 0x70, 0x00, 0x00, 0x00, 0x30, 0x08, 0xAB, 0x0A, 0x02, 0x00, 0xC0, 0x00, 0xC0, 0x07,
0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x84, 0x57, 0x15, 0x01, 0x00, 0x30, 0x00, 0xE0, 0x07,
0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0xC3, 0xFF, 0x2A, 0x01, 0x00, 0x0C, 0x00, 0xF0, 0x0F,
0x00, 0xC0, 0x00, 0x00, 0x00, 0xE0, 0xC0, 0xE0, 0xFE, 0x55, 0x01, 0x82, 0x03, 0x00, 0xF8, 0x15,
0x00, 0x30, 0x00, 0x00, 0x00, 0x1C, 0x30, 0x78, 0xFE, 0xAA, 0x01, 0x7C, 0x00, 0x00, 0xFC, 0x23,
0x00, 0x0E, 0x00, 0x00, 0xC0, 0x03, 0x0C, 0x3C, 0x7F, 0x5D, 0x01, 0x00, 0x00, 0x00, 0xFF, 0x45,
0xC0, 0x01, 0x00, 0x00, 0x3E, 0x00, 0x02, 0x8F, 0xBF, 0xAE, 0x03, 0x00, 0x00, 0xC0, 0xFF, 0x82,
0x30, 0x00, 0x00, 0xC0, 0x01, 0x80, 0xC1, 0x43, 0xFE, 0x5D, 0x01, 0x00, 0x00, 0xF0, 0xFF, 0x05,
0x0F, 0x00, 0x80, 0x3F, 0x00, 0x60, 0xF0, 0x31, 0xF6, 0xAE, 0x03, 0x00, 0x00, 0xFA, 0xAF, 0x02,
0xFC, 0xFF, 0x7F, 0x00, 0x00, 0x18, 0x7C, 0x08, 0x23, 0xFF, 0x05, 0x00, 0x00, 0xFD, 0x55, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x1F, 0x84, 0x30, 0xFE, 0x0A, 0x00, 0x00, 0xAA, 0xAA, 0x00,
0x00, 0x00, 0x00, 0x00, 0x80, 0xF1, 0x07, 0x43, 0x18, 0xFF, 0x15, 0x00, 0x00, 0x54, 0x15, 0x00,
0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x80, 0x20, 0x8C, 0xFF, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00,
};
// Boot request enum
#define BOOT_REQUEST_TAINTED 0x00000000
#define BOOT_REQUEST_CLEAN 0xDADEDADE
#define BOOT_REQUEST_DFU 0xDF00B000
// Boot to DFU pin
#define BOOT_DFU_PORT GPIOB
#define BOOT_DFU_PIN LL_GPIO_PIN_11
// USB pins
#define BOOT_USB_PORT GPIOA
#define BOOT_USB_DM_PIN LL_GPIO_PIN_11
#define BOOT_USB_DP_PIN LL_GPIO_PIN_12
#define BOOT_USB_PIN (BOOT_USB_DM_PIN | BOOT_USB_DP_PIN)
#define RTC_CLOCK_IS_READY() (LL_RCC_LSE_IsReady() && LL_RCC_LSI1_IsReady())
void target_led_control(char* c) {
furi_hal_light_set(LightRed, 0x00);
furi_hal_light_set(LightGreen, 0x00);
furi_hal_light_set(LightBlue, 0x00);
do {
if(*c == 'R') {
furi_hal_light_set(LightRed, 0xFF);
} else if(*c == 'G') {
furi_hal_light_set(LightGreen, 0xFF);
} else if(*c == 'B') {
furi_hal_light_set(LightBlue, 0xFF);
} else if(*c == '.') {
LL_mDelay(125);
furi_hal_light_set(LightRed, 0x00);
furi_hal_light_set(LightGreen, 0x00);
furi_hal_light_set(LightBlue, 0x00);
LL_mDelay(125);
} else if(*c == '-') {
LL_mDelay(250);
furi_hal_light_set(LightRed, 0x00);
furi_hal_light_set(LightGreen, 0x00);
furi_hal_light_set(LightBlue, 0x00);
LL_mDelay(250);
} else if(*c == '|') {
furi_hal_light_set(LightRed, 0x00);
furi_hal_light_set(LightGreen, 0x00);
furi_hal_light_set(LightBlue, 0x00);
}
c++;
} while(*c != 0);
}
void target_clock_init() {
LL_Init1msTick(4000000);
LL_SetSystemCoreClock(4000000);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOD);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOE);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOH);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2);
}
void target_gpio_init() {
// USB D+
LL_GPIO_SetPinMode(BOOT_USB_PORT, BOOT_USB_DP_PIN, LL_GPIO_MODE_OUTPUT);
LL_GPIO_SetPinSpeed(BOOT_USB_PORT, BOOT_USB_DP_PIN, LL_GPIO_SPEED_FREQ_VERY_HIGH);
LL_GPIO_SetPinOutputType(BOOT_USB_PORT, BOOT_USB_DP_PIN, LL_GPIO_OUTPUT_OPENDRAIN);
// USB D-
LL_GPIO_SetPinMode(BOOT_USB_PORT, BOOT_USB_DM_PIN, LL_GPIO_MODE_OUTPUT);
LL_GPIO_SetPinSpeed(BOOT_USB_PORT, BOOT_USB_DM_PIN, LL_GPIO_SPEED_FREQ_VERY_HIGH);
LL_GPIO_SetPinOutputType(BOOT_USB_PORT, BOOT_USB_DM_PIN, LL_GPIO_OUTPUT_OPENDRAIN);
// Button: back
LL_GPIO_SetPinMode(BOOT_DFU_PORT, BOOT_DFU_PIN, LL_GPIO_MODE_INPUT);
LL_GPIO_SetPinPull(BOOT_DFU_PORT, BOOT_DFU_PIN, LL_GPIO_PULL_UP);
}
void target_rtc_init() {
// LSE and RTC
LL_PWR_EnableBkUpAccess();
if(!RTC_CLOCK_IS_READY()) {
// Start LSI1 needed for CSS
LL_RCC_LSI1_Enable();
// Try to start LSE normal way
LL_RCC_LSE_SetDriveCapability(LL_RCC_LSEDRIVE_HIGH);
LL_RCC_LSE_Enable();
uint32_t c = 0;
while(!RTC_CLOCK_IS_READY() && c < 200) {
LL_mDelay(10);
c++;
}
// Plan B: reset backup domain
if(!RTC_CLOCK_IS_READY()) {
target_led_control("-R.R.R.");
LL_RCC_ForceBackupDomainReset();
LL_RCC_ReleaseBackupDomainReset();
NVIC_SystemReset();
}
// Set RTC domain clock to LSE
LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSE);
// Enable LSE CSS
LL_RCC_LSE_EnableCSS();
}
// Enable clocking
LL_RCC_EnableRTC();
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_RTCAPB);
}
void target_version_save(void) {
LL_RTC_BAK_SetRegister(RTC, LL_RTC_BKP_DR1, (uint32_t)version_get());
}
void target_usb_wire_reset() {
LL_GPIO_ResetOutputPin(BOOT_USB_PORT, BOOT_USB_PIN);
}
void target_display_init() {
// Prepare gpio
hal_gpio_init_simple(&gpio_display_rst, GpioModeOutputPushPull);
hal_gpio_init_simple(&gpio_display_di, GpioModeOutputPushPull);
// Initialize
u8g2_t fb;
u8g2_Setup_st756x_flipper(&fb, U8G2_R0, u8x8_hw_spi_stm32, u8g2_gpio_and_delay_stm32);
u8g2_InitDisplay(&fb);
// Create payload
u8g2_ClearBuffer(&fb);
u8g2_SetDrawColor(&fb, 0x01);
u8g2_DrawXBM(&fb, 0, 64 - 50, 128, 50, I_DFU_128x50);
#ifndef SLIM_BOOTLOADER
u8g2_SetFont(&fb, u8g2_font_helvB08_tf);
u8g2_DrawStr(&fb, 2, 8, "Update & Recovery Mode");
u8g2_DrawStr(&fb, 2, 21, "DFU started");
#endif
// Send buffer
u8g2_SetPowerSave(&fb, 0);
u8g2_SendBuffer(&fb);
}
void target_init() {
target_clock_init();
target_gpio_init();
furi_hal_init();
target_led_control("RGB");
target_rtc_init();
target_version_save();
target_usb_wire_reset();
// Errata 2.2.9, Flash OPTVERR flag is always set after system reset
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
}
int target_is_dfu_requested() {
if(LL_RTC_BAK_GetRegister(RTC, LL_RTC_BKP_DR0) == BOOT_REQUEST_TAINTED) {
// Default system state is tainted
// We must ensure that MCU is cleanly booted
LL_RTC_BAK_SetRegister(RTC, LL_RTC_BKP_DR0, BOOT_REQUEST_CLEAN);
NVIC_SystemReset();
} else if(LL_RTC_BAK_GetRegister(RTC, LL_RTC_BKP_DR0) == BOOT_REQUEST_DFU) {
return 1;
}
LL_mDelay(100);
if(!LL_GPIO_IsInputPinSet(BOOT_DFU_PORT, BOOT_DFU_PIN)) {
return 1;
}
return 0;
}
void target_switch(void* offset) {
asm volatile("ldr r3, [%0] \n"
"msr msp, r3 \n"
"ldr r3, [%1] \n"
"mov pc, r3 \n"
:
: "r"(offset), "r"(offset + 0x4)
: "r3");
}
void target_switch2dfu() {
target_led_control("B");
furi_hal_light_set(LightBacklight, 0xFF);
target_display_init();
// Mark system as tainted, it will be soon
LL_RTC_BAK_SetRegister(RTC, LL_RTC_BKP_DR0, BOOT_REQUEST_TAINTED);
// Remap memory to system bootloader
LL_SYSCFG_SetRemapMemory(LL_SYSCFG_REMAP_SYSTEMFLASH);
// Jump
target_switch(0x0);
}
void target_switch2os() {
target_led_control("G");
SCB->VTOR = OS_OFFSET;
target_switch((void*)(BOOT_ADDRESS + OS_OFFSET));
}

View File

@ -1,50 +0,0 @@
TOOLCHAIN = arm
BOOT_ADDRESS = 0x08000000
FW_ADDRESS = 0x08008000
OS_OFFSET = 0x00008000
FLASH_ADDRESS = 0x08000000
OPENOCD_OPTS = -f interface/stlink.cfg -c "transport select hla_swd" -f ../debug/stm32wbx.cfg -c "init"
BOOT_CFLAGS = -DBOOT_ADDRESS=$(BOOT_ADDRESS) -DFW_ADDRESS=$(FW_ADDRESS) -DOS_OFFSET=$(OS_OFFSET)
MCU_FLAGS = -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard
CFLAGS += $(MCU_FLAGS) $(BOOT_CFLAGS) -DSTM32WB55xx -Wall -fdata-sections -ffunction-sections
LDFLAGS += $(MCU_FLAGS) -specs=nosys.specs -specs=nano.specs
HARDWARE_TARGET = 6
CUBE_DIR = $(PROJECT_ROOT)/lib/STM32CubeWB
# ST HAL
CFLAGS += -DUSE_FULL_LL_DRIVER
ASM_SOURCES += $(CUBE_DIR)/Drivers/CMSIS/Device/ST/STM32WBxx/Source/Templates/gcc/startup_stm32wb55xx_cm4.s
C_SOURCES += $(CUBE_DIR)/Drivers/CMSIS/Device/ST/STM32WBxx/Source/Templates/system_stm32wbxx.c
C_SOURCES += $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_utils.c
C_SOURCES += $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_gpio.c
C_SOURCES += $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_i2c.c
C_SOURCES += $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_spi.c
CFLAGS += -I$(CUBE_DIR)/Drivers/CMSIS/Include
CFLAGS += -I$(CUBE_DIR)/Drivers/CMSIS/Device/ST/STM32WBxx/Include
CFLAGS += -I$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Inc
LDFLAGS += -T$(TARGET_DIR)/stm32wb55xx_flash_cm4.ld
# Drivers
DRIVERS_DIR = $(PROJECT_ROOT)//lib/drivers
CFLAGS += -I$(DRIVERS_DIR)
C_SOURCES += $(DRIVERS_DIR)/lp5562.c
# API-HAL
CFLAGS += -I$(TARGET_DIR)/furi_hal
C_SOURCES += $(wildcard $(TARGET_DIR)/furi_hal/*.c)
# Version generation
C_SOURCES += $(PROJECT_ROOT)/lib/toolbox/version.c
ASM_SOURCES += $(wildcard $(TARGET_DIR)/*.s)
C_SOURCES += $(wildcard $(TARGET_DIR)/*.c)
CPP_SOURCES += $(wildcard $(TARGET_DIR)/*.cpp)
SVD_FILE = $(PROJECT_ROOT)/debug/STM32WB55_CM4.svd

5
core/furi/common_defines.h Normal file → Executable file
View File

@ -1,7 +1,6 @@
#pragma once
#ifndef MAX
#define MAX(a, b) \
({ \
__typeof__(a) _a = (a); \
@ -72,6 +71,10 @@
(((x)&0xFF000000) >> 24))
#endif
#ifndef FURI_BIT
#define FURI_BIT(x, n) ((x) >> (n)&1)
#endif
#ifndef FURI_CRITICAL_ENTER
#define FURI_CRITICAL_ENTER() \
uint32_t primask_bit = __get_PRIMASK(); \

View File

@ -16,7 +16,6 @@ typedef void (*InterruptCallback)(void*, void*);
/** Interupt type */
typedef enum {
InterruptTypeComparatorTrigger,
InterruptTypeTimerUpdate,
InterruptTypeLast,
} InterruptType;

View File

@ -1,138 +0,0 @@
#pragma once
#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
#include <stdint.h>
extern uint32_t SystemCoreClock;
#endif
#ifndef CMSIS_device_header
#define CMSIS_device_header "stm32wbxx.h"
#endif /* CMSIS_device_header */
#define configENABLE_FPU 1
#define configENABLE_MPU 0
#define configUSE_PREEMPTION 1
#define configSUPPORT_STATIC_ALLOCATION 0
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configCPU_CLOCK_HZ (SystemCoreClock)
#define configTICK_RATE_HZ ((TickType_t)1024)
#define configMAX_PRIORITIES (56)
#define configMINIMAL_STACK_SIZE ((uint16_t)128)
/* Heap size determined automatically by linker */
// #define configTOTAL_HEAP_SIZE ((size_t)0)
#define configMAX_TASK_NAME_LEN (16)
#define configGENERATE_RUN_TIME_STATS 0
#define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0
#define configUSE_MUTEXES 1
#define configQUEUE_REGISTRY_SIZE 8
#define configCHECK_FOR_STACK_OVERFLOW 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configENABLE_BACKWARD_COMPATIBILITY 0
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
#define configUSE_TICKLESS_IDLE 2
#define configRECORD_STACK_HIGH_ADDRESS 1
#define configUSE_NEWLIB_REENTRANT 0
/* Defaults to size_t for backward compatibility, but can be changed
if lengths will always be less than the number of bytes in a size_t. */
#define configMESSAGE_BUFFER_LENGTH_TYPE size_t
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 1
#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 4
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
/* Software timer definitions. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY (2)
#define configTIMER_QUEUE_LENGTH 32
#define configTIMER_TASK_STACK_DEPTH 256
#define configTIMER_SERVICE_TASK_NAME "TimersSrv"
#define configIDLE_TASK_NAME "(-_-)"
/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#define INCLUDE_xTaskGetHandle 1
#define INCLUDE_eTaskGetState 1
#define INCLUDE_uxTaskGetStackHighWaterMark 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskCleanUpResources 0
#define INCLUDE_vTaskDelay 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_xQueueGetMutexHolder 1
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_xTimerPendFunctionCall 1
/* CMSIS-RTOS V2 flags */
#define configUSE_OS2_THREAD_SUSPEND_RESUME 1
#define configUSE_OS2_THREAD_ENUMERATE 1
#define configUSE_OS2_EVENTFLAGS_FROM_ISR 1
#define configUSE_OS2_THREAD_FLAGS 1
#define configUSE_OS2_TIMER 1
#define configUSE_OS2_MUTEX 1
/* CMSIS-RTOS */
#define configTASK_NOTIFICATION_ARRAY_ENTRIES 2
#define CMSIS_TASK_NOTIFY_INDEX 1
/*
* The CMSIS-RTOS V2 FreeRTOS wrapper is dependent on the heap implementation used
* by the application thus the correct define need to be enabled below
*/
#define USE_FreeRTOS_HEAP_4
/* Cortex-M specific definitions. */
#ifdef __NVIC_PRIO_BITS
/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
#define configPRIO_BITS __NVIC_PRIO_BITS
#else
#define configPRIO_BITS 4
#endif
/* The lowest interrupt priority that can be used in a call to a "set priority"
function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15
/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
/* Interrupt priorities used by the kernel port layer itself. These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY \
(configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY \
(configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
/* Normal assert() semantics without relying on the provision of an assert.h
header file. */
#include <furi/check.h>
#define configASSERT(x) \
if((x) == 0) { \
furi_crash("FreeRTOS Assert"); \
}
/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
standard names. */
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define USE_CUSTOM_SYSTICK_HANDLER_IMPLEMENTATION 1
#define configOVERRIDE_DEFAULT_TICK_CONFIGURATION \
1 /* required only for Keil but does not hurt otherwise */

View File

@ -1,52 +0,0 @@
/**
******************************************************************************
* @file comp.h
* @brief This file contains all the function prototypes for
* the comp.c file
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __COMP_H__
#define __COMP_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern COMP_HandleTypeDef hcomp1;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_COMP1_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __COMP_H__ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@ -1,49 +0,0 @@
/**
******************************************************************************
* @file gpio.h
* @brief This file contains all the function prototypes for
* the gpio.c file
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __GPIO_H__
#define __GPIO_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_GPIO_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /*__ GPIO_H__ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@ -1,149 +0,0 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "stm32wbxx_hal.h"
void Error_Handler(void);
#define BUTTON_BACK_EXTI_IRQn EXTI15_10_IRQn
#define BUTTON_BACK_GPIO_Port GPIOC
#define BUTTON_BACK_Pin GPIO_PIN_13
#define BUTTON_DOWN_EXTI_IRQn EXTI6_IRQn
#define BUTTON_DOWN_GPIO_Port GPIOC
#define BUTTON_DOWN_Pin GPIO_PIN_6
#define BUTTON_LEFT_EXTI_IRQn EXTI15_10_IRQn
#define BUTTON_LEFT_GPIO_Port GPIOB
#define BUTTON_LEFT_Pin GPIO_PIN_11
#define BUTTON_OK_EXTI_IRQn EXTI3_IRQn
#define BUTTON_OK_GPIO_Port GPIOH
#define BUTTON_OK_Pin GPIO_PIN_3
#define BUTTON_RIGHT_EXTI_IRQn EXTI15_10_IRQn
#define BUTTON_RIGHT_GPIO_Port GPIOB
#define BUTTON_RIGHT_Pin GPIO_PIN_12
#define BUTTON_UP_EXTI_IRQn EXTI15_10_IRQn
#define BUTTON_UP_GPIO_Port GPIOB
#define BUTTON_UP_Pin GPIO_PIN_10
#define CC1101_CS_GPIO_Port GPIOD
#define CC1101_CS_Pin GPIO_PIN_0
#define CC1101_G0_GPIO_Port GPIOA
#define CC1101_G0_Pin GPIO_PIN_1
#define DISPLAY_CS_GPIO_Port GPIOC
#define DISPLAY_CS_Pin GPIO_PIN_11
#define DISPLAY_DI_GPIO_Port GPIOB
#define DISPLAY_DI_Pin GPIO_PIN_1
#define DISPLAY_RST_GPIO_Port GPIOB
#define DISPLAY_RST_Pin GPIO_PIN_0
#define IR_RX_GPIO_Port GPIOA
#define IR_RX_Pin GPIO_PIN_0
#define IR_TX_GPIO_Port GPIOB
#define IR_TX_Pin GPIO_PIN_9
#define NFC_CS_GPIO_Port GPIOE
#define NFC_CS_Pin GPIO_PIN_4
#define PA4_GPIO_Port GPIOA
#define PA4_Pin GPIO_PIN_4
#define PA6_GPIO_Port GPIOA
#define PA6_Pin GPIO_PIN_6
#define PA7_GPIO_Port GPIOA
#define PA7_Pin GPIO_PIN_7
#define PB2_GPIO_Port GPIOB
#define PB2_Pin GPIO_PIN_2
#define PB3_GPIO_Port GPIOB
#define PB3_Pin GPIO_PIN_3
#define PC0_GPIO_Port GPIOC
#define PC0_Pin GPIO_PIN_0
#define PC1_GPIO_Port GPIOC
#define PC1_Pin GPIO_PIN_1
#define PC3_GPIO_Port GPIOC
#define PC3_Pin GPIO_PIN_3
#define PERIPH_POWER_GPIO_Port GPIOA
#define PERIPH_POWER_Pin GPIO_PIN_3
#define QUARTZ_32MHZ_IN_GPIO_Port GPIOC
#define QUARTZ_32MHZ_IN_Pin GPIO_PIN_14
#define QUARTZ_32MHZ_OUT_GPIO_Port GPIOC
#define QUARTZ_32MHZ_OUT_Pin GPIO_PIN_15
#define RFID_OUT_GPIO_Port GPIOB
#define RFID_OUT_Pin GPIO_PIN_13
#define RFID_PULL_GPIO_Port GPIOA
#define RFID_PULL_Pin GPIO_PIN_2
#define RFID_RF_IN_GPIO_Port GPIOC
#define RFID_RF_IN_Pin GPIO_PIN_5
#define RFID_TUNE_GPIO_Port GPIOA
#define RFID_TUNE_Pin GPIO_PIN_8
#define RF_SW_0_GPIO_Port GPIOC
#define RF_SW_0_Pin GPIO_PIN_4
#define SD_CD_GPIO_Port GPIOC
#define SD_CD_Pin GPIO_PIN_10
#define SD_CS_GPIO_Port GPIOC
#define SD_CS_Pin GPIO_PIN_12
#define SPEAKER_GPIO_Port GPIOB
#define SPEAKER_Pin GPIO_PIN_8
#define VIBRO_GPIO_Port GPIOA
#define VIBRO_Pin GPIO_PIN_15
#define iBTN_GPIO_Port GPIOB
#define iBTN_Pin GPIO_PIN_14
#define USART1_TX_Pin GPIO_PIN_6
#define USART1_TX_Port GPIOB
#define USART1_RX_Pin GPIO_PIN_7
#define USART1_RX_Port GPIOB
#define SPI_D_MISO_GPIO_Port GPIOC
#define SPI_D_MISO_Pin GPIO_PIN_2
#define SPI_D_MOSI_GPIO_Port GPIOB
#define SPI_D_MOSI_Pin GPIO_PIN_15
#define SPI_D_SCK_GPIO_Port GPIOD
#define SPI_D_SCK_Pin GPIO_PIN_1
#define SPI_R_MISO_GPIO_Port GPIOB
#define SPI_R_MISO_Pin GPIO_PIN_4
#define SPI_R_MOSI_GPIO_Port GPIOB
#define SPI_R_MOSI_Pin GPIO_PIN_5
#define SPI_R_SCK_GPIO_Port GPIOA
#define SPI_R_SCK_Pin GPIO_PIN_5
extern TIM_HandleTypeDef htim1;
extern TIM_HandleTypeDef htim2;
extern TIM_HandleTypeDef htim16;
#define TIM_A htim1
#define TIM_B htim2
#define TIM_C htim16
#define SPEAKER_TIM htim16
#define SPEAKER_CH TIM_CHANNEL_1
#define LFRFID_TIM htim1
#define LFRFID_CH TIM_CHANNEL_1
#define INFRARED_TX_TIM htim1
#define INFRARED_TX_CH TIM_CHANNEL_3
// only for reference
// INFRARED RX timer dont exist in F2
// and timer need more data to init (NVIC IRQn to set priority)
#define INFRARED_RX_TIM htim2
#define INFRARED_RX_FALLING_CH TIM_CHANNEL_1
#define INFRARED_RX_RISING_CH TIM_CHANNEL_2
#define NFC_IRQ_Pin RFID_PULL_Pin
#define NFC_IRQ_GPIO_Port RFID_PULL_GPIO_Port
#ifdef __cplusplus
}
#endif

View File

@ -1,51 +0,0 @@
#ifndef _STM32_H_
#define _STM32_H_
/* modify bitfield */
#define _BMD(reg, msk, val) (reg) = (((reg) & ~(msk)) | (val))
/* set bitfield */
#define _BST(reg, bits) (reg) = ((reg) | (bits))
/* clear bitfield */
#define _BCL(reg, bits) (reg) = ((reg) & ~(bits))
/* wait until bitfield set */
#define _WBS(reg, bits) while(((reg) & (bits)) == 0)
/* wait until bitfield clear */
#define _WBC(reg, bits) while(((reg) & (bits)) != 0)
/* wait for bitfield value */
#define _WVL(reg, msk, val) while(((reg) & (msk)) != (val))
/* bit value */
#define _BV(bit) (0x01 << (bit))
#if defined(STM32F0)
#include "STM32F0xx/Include/stm32f0xx.h"
#elif defined(STM32F1)
#include "STM32F1xx/Include/stm32f1xx.h"
#elif defined(STM32F2)
#include "STM32F2xx/Include/stm32f2xx.h"
#elif defined(STM32F3)
#include "STM32F3xx/Include/stm32f3xx.h"
#elif defined(STM32F4)
#include "STM32F4xx/Include/stm32f4xx.h"
#elif defined(STM32F7)
#include "STM32F7xx/Include/stm32f7xx.h"
#elif defined(STM32H7)
#include "STM32H7xx/Include/stm32h7xx.h"
#elif defined(STM32L0)
#include "STM32L0xx/Include/stm32l0xx.h"
#elif defined(STM32L1)
#include "STM32L1xx/Include/stm32l1xx.h"
#elif defined(STM32L4)
#include "STM32L4xx/Include/stm32l4xx.h"
#elif defined(STM32L5)
#include "STM32L5xx/Include/stm32l5xx.h"
#elif defined(STM32G0)
#include "STM32G0xx/Include/stm32g0xx.h"
#elif defined(STM32G4)
#include "STM32G4xx/Include/stm32g4xx.h"
#elif defined(STM32WB)
#include "STM32WBxx/Include/stm32wbxx.h"
#else
#error "STM32 family not defined"
#endif
#endif // _STM32_H_

View File

@ -1,40 +0,0 @@
/**
******************************************************************************
* @file stm32_assert.h
* @brief STM32 assert file.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32_ASSERT_H
#define __STM32_ASSERT_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef USE_FULL_ASSERT
#define assert_param(expr) ((expr) ? (void)0U : assert_failed())
void assert_failed();
#else
#define assert_param(expr) ((void)0U)
#endif /* USE_FULL_ASSERT */
#ifdef __cplusplus
}
#endif
#endif /* __STM32_ASSERT_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@ -1,345 +0,0 @@
/**
******************************************************************************
* @file stm32wbxx_hal_conf.h
* @author MCD Application Team
* @brief HAL configuration file.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32WBxx_HAL_CONF_H
#define __STM32WBxx_HAL_CONF_H
#ifdef __cplusplus
extern "C" {
#endif
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* ########################## Module Selection ############################## */
/**
* @brief This is the list of modules to be used in the HAL driver
*/
#define HAL_MODULE_ENABLED
/*#define HAL_ADC_MODULE_ENABLED */
#define HAL_CRYP_MODULE_ENABLED
#define HAL_COMP_MODULE_ENABLED
/*#define HAL_CRC_MODULE_ENABLED */
#define HAL_HSEM_MODULE_ENABLED
/*#define HAL_I2C_MODULE_ENABLED */
/*#define HAL_IPCC_MODULE_ENABLED */
/*#define HAL_IRDA_MODULE_ENABLED */
/*#define HAL_IWDG_MODULE_ENABLED */
/*#define HAL_LCD_MODULE_ENABLED */
/*#define HAL_LPTIM_MODULE_ENABLED */
#define HAL_PCD_MODULE_ENABLED
#define HAL_PKA_MODULE_ENABLED
/*#define HAL_QSPI_MODULE_ENABLED */
#define HAL_RNG_MODULE_ENABLED
/*#define HAL_RTC_MODULE_ENABLED */
/*#define HAL_SAI_MODULE_ENABLED */
/*#define HAL_SMBUS_MODULE_ENABLED */
/*#define HAL_SMARTCARD_MODULE_ENABLED */
/*#define HAL_SPI_MODULE_ENABLED */
#define HAL_TIM_MODULE_ENABLED
/*#define HAL_TSC_MODULE_ENABLED */
/*#define HAL_UART_MODULE_ENABLED */
/*#define HAL_USART_MODULE_ENABLED */
/*#define HAL_WWDG_MODULE_ENABLED */
#define HAL_EXTI_MODULE_ENABLED
#define HAL_CORTEX_MODULE_ENABLED
#define HAL_DMA_MODULE_ENABLED
#define HAL_FLASH_MODULE_ENABLED
#define HAL_GPIO_MODULE_ENABLED
#define HAL_PWR_MODULE_ENABLED
#define HAL_RCC_MODULE_ENABLED
#define USE_HAL_ADC_REGISTER_CALLBACKS 0u
#define USE_HAL_COMP_REGISTER_CALLBACKS 0u
#define USE_HAL_CRYP_REGISTER_CALLBACKS 0u
#define USE_HAL_I2C_REGISTER_CALLBACKS 0u
#define USE_HAL_IRDA_REGISTER_CALLBACKS 0u
#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0u
#define USE_HAL_PCD_REGISTER_CALLBACKS 0u
#define USE_HAL_PKA_REGISTER_CALLBACKS 0u
#define USE_HAL_QSPI_REGISTER_CALLBACKS 0u
#define USE_HAL_RNG_REGISTER_CALLBACKS 0u
#define USE_HAL_RTC_REGISTER_CALLBACKS 0u
#define USE_HAL_SAI_REGISTER_CALLBACKS 0u
#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0u
#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0u
#define USE_HAL_SPI_REGISTER_CALLBACKS 0u
#define USE_HAL_TIM_REGISTER_CALLBACKS 0u
#define USE_HAL_TSC_REGISTER_CALLBACKS 0u
#define USE_HAL_UART_REGISTER_CALLBACKS 0u
#define USE_HAL_USART_REGISTER_CALLBACKS 0u
#define USE_HAL_WWDG_REGISTER_CALLBACKS 0u
/* ########################## Oscillator Values adaptation ####################*/
/**
* @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
* This value is used by the RCC HAL module to compute the system frequency
* (when HSE is used as system clock source, directly or through the PLL).
*/
#if !defined(HSE_VALUE)
#define HSE_VALUE 32000000U /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */
#if !defined(HSE_STARTUP_TIMEOUT)
#define HSE_STARTUP_TIMEOUT ((uint32_t)100) /*!< Time out for HSE start up, in ms */
#endif /* HSE_STARTUP_TIMEOUT */
/**
* @brief Internal Multiple Speed oscillator (MSI) default value.
* This value is the default MSI range value after Reset.
*/
#if !defined(MSI_VALUE)
#define MSI_VALUE ((uint32_t)4000000) /*!< Value of the Internal oscillator in Hz*/
#endif /* MSI_VALUE */
/**
* @brief Internal High Speed oscillator (HSI) value.
* This value is used by the RCC HAL module to compute the system frequency
* (when HSI is used as system clock source, directly or through the PLL).
*/
#if !defined(HSI_VALUE)
#define HSI_VALUE 16000000U /*!< Value of the Internal oscillator in Hz*/
#endif /* HSI_VALUE */
/**
* @brief Internal Low Speed oscillator (LSI1) value.
*/
#if !defined(LSI1_VALUE)
#define LSI1_VALUE ((uint32_t)32000) /*!< LSI1 Typical Value in Hz*/
#endif /* LSI1_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
The real value may vary depending on the variations
in voltage and temperature.*/
/**
* @brief Internal Low Speed oscillator (LSI2) value.
*/
#if !defined(LSI2_VALUE)
#define LSI2_VALUE ((uint32_t)32000) /*!< LSI2 Typical Value in Hz*/
#endif /* LSI2_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
The real value may vary depending on the variations
in voltage and temperature.*/
/**
* @brief External Low Speed oscillator (LSE) value.
* This value is used by the UART, RTC HAL module to compute the system frequency
*/
#if !defined(LSE_VALUE)
#define LSE_VALUE 32768U /*!< Value of the External oscillator in Hz*/
#endif /* LSE_VALUE */
/**
* @brief Internal Multiple Speed oscillator (HSI48) default value.
* This value is the default HSI48 range value after Reset.
*/
#if !defined(HSI48_VALUE)
#define HSI48_VALUE ((uint32_t)48000000) /*!< Value of the Internal oscillator in Hz*/
#endif /* HSI48_VALUE */
#if !defined(LSE_STARTUP_TIMEOUT)
#define LSE_STARTUP_TIMEOUT 1000U /*!< Time out for LSE start up, in ms */
#endif /* HSE_STARTUP_TIMEOUT */
/**
* @brief External clock source for SAI1 peripheral
* This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source
* frequency.
*/
#if !defined(EXTERNAL_SAI1_CLOCK_VALUE)
#define EXTERNAL_SAI1_CLOCK_VALUE \
((uint32_t)2097000) /*!< Value of the SAI1 External clock source in Hz*/
#endif /* EXTERNAL_SAI1_CLOCK_VALUE */
/* Tip: To avoid modifying this file each time you need to use different HSE,
=== you can define the HSE value in your toolchain compiler preprocessor. */
/* ########################### System Configuration ######################### */
/**
* @brief This is the HAL system configuration section
*/
#define VDD_VALUE 3300U /*!< Value of VDD in mv */
#define TICK_INT_PRIORITY 0U /*!< tick interrupt priority */
#define USE_RTOS 0U
#define PREFETCH_ENABLE 1U
#define INSTRUCTION_CACHE_ENABLE 1U
#define DATA_CACHE_ENABLE 1U
/* ########################## Assert Selection ############################## */
/**
* @brief Uncomment the line below to expanse the "assert_param" macro in the
* HAL drivers code
*/
#define USE_FULL_ASSERT 1U
/* ################## SPI peripheral configuration ########################## */
/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver
* Activated: CRC code is present inside driver
* Deactivated: CRC code cleaned from driver
*/
#define USE_SPI_CRC 0U
/* Includes ------------------------------------------------------------------*/
/**
* @brief Include module's header file
*/
#ifdef HAL_DMA_MODULE_ENABLED
#include "stm32wbxx_hal_dma.h"
#endif /* HAL_DMA_MODULE_ENABLED */
#ifdef HAL_ADC_MODULE_ENABLED
#include "stm32wbxx_hal_adc.h"
#endif /* HAL_ADC_MODULE_ENABLED */
#ifdef HAL_COMP_MODULE_ENABLED
#include "stm32wbxx_hal_comp.h"
#endif /* HAL_COMP_MODULE_ENABLED */
#ifdef HAL_CORTEX_MODULE_ENABLED
#include "stm32wbxx_hal_cortex.h"
#endif /* HAL_CORTEX_MODULE_ENABLED */
#ifdef HAL_CRC_MODULE_ENABLED
#include "stm32wbxx_hal_crc.h"
#endif /* HAL_CRC_MODULE_ENABLED */
#ifdef HAL_CRYP_MODULE_ENABLED
#include "stm32wbxx_hal_cryp.h"
#endif /* HAL_CRYP_MODULE_ENABLED */
#ifdef HAL_EXTI_MODULE_ENABLED
#include "stm32wbxx_hal_exti.h"
#endif /* HAL_EXTI_MODULE_ENABLED */
#ifdef HAL_FLASH_MODULE_ENABLED
#include "stm32wbxx_hal_flash.h"
#endif /* HAL_FLASH_MODULE_ENABLED */
#ifdef HAL_GPIO_MODULE_ENABLED
#include "stm32wbxx_hal_gpio.h"
#endif /* HAL_GPIO_MODULE_ENABLED */
#ifdef HAL_HSEM_MODULE_ENABLED
#include "stm32wbxx_hal_hsem.h"
#endif /* HAL_HSEM_MODULE_ENABLED */
#ifdef HAL_I2C_MODULE_ENABLED
#include "stm32wbxx_hal_i2c.h"
#endif /* HAL_I2C_MODULE_ENABLED */
#ifdef HAL_IPCC_MODULE_ENABLED
#include "stm32wbxx_hal_ipcc.h"
#endif /* HAL_IPCC_MODULE_ENABLED */
#ifdef HAL_IRDA_MODULE_ENABLED
#include "stm32wbxx_hal_irda.h"
#endif /* HAL_IRDA_MODULE_ENABLED */
#ifdef HAL_IWDG_MODULE_ENABLED
#include "stm32wbxx_hal_iwdg.h"
#endif /* HAL_IWDG_MODULE_ENABLED */
#ifdef HAL_LCD_MODULE_ENABLED
#include "stm32wbxx_hal_lcd.h"
#endif /* HAL_LCD_MODULE_ENABLED */
#ifdef HAL_LPTIM_MODULE_ENABLED
#include "stm32wbxx_hal_lptim.h"
#endif /* HAL_LPTIM_MODULE_ENABLED */
#ifdef HAL_PCD_MODULE_ENABLED
#include "stm32wbxx_hal_pcd.h"
#endif /* HAL_PCD_MODULE_ENABLED */
#ifdef HAL_PKA_MODULE_ENABLED
#include "stm32wbxx_hal_pka.h"
#endif /* HAL_PKA_MODULE_ENABLED */
#ifdef HAL_PWR_MODULE_ENABLED
#include "stm32wbxx_hal_pwr.h"
#endif /* HAL_PWR_MODULE_ENABLED */
#ifdef HAL_QSPI_MODULE_ENABLED
#include "stm32wbxx_hal_qspi.h"
#endif /* HAL_QSPI_MODULE_ENABLED */
#ifdef HAL_RCC_MODULE_ENABLED
#include "stm32wbxx_hal_rcc.h"
#endif /* HAL_RCC_MODULE_ENABLED */
#ifdef HAL_RNG_MODULE_ENABLED
#include "stm32wbxx_hal_rng.h"
#endif /* HAL_RNG_MODULE_ENABLED */
#ifdef HAL_RTC_MODULE_ENABLED
#include "stm32wbxx_hal_rtc.h"
#endif /* HAL_RTC_MODULE_ENABLED */
#ifdef HAL_SAI_MODULE_ENABLED
#include "stm32wbxx_hal_sai.h"
#endif /* HAL_SAI_MODULE_ENABLED */
#ifdef HAL_SMARTCARD_MODULE_ENABLED
#include "stm32wbxx_hal_smartcard.h"
#endif /* HAL_SMARTCARD_MODULE_ENABLED */
#ifdef HAL_SMBUS_MODULE_ENABLED
#include "stm32wbxx_hal_smbus.h"
#endif /* HAL_SMBUS_MODULE_ENABLED */
#ifdef HAL_SPI_MODULE_ENABLED
#include "stm32wbxx_hal_spi.h"
#endif /* HAL_SPI_MODULE_ENABLED */
#ifdef HAL_TIM_MODULE_ENABLED
#include "stm32wbxx_hal_tim.h"
#endif /* HAL_TIM_MODULE_ENABLED */
#ifdef HAL_TSC_MODULE_ENABLED
#include "stm32wbxx_hal_tsc.h"
#endif /* HAL_TSC_MODULE_ENABLED */
#ifdef HAL_UART_MODULE_ENABLED
#include "stm32wbxx_hal_uart.h"
#endif /* HAL_UART_MODULE_ENABLED */
#ifdef HAL_USART_MODULE_ENABLED
#include "stm32wbxx_hal_usart.h"
#endif /* HAL_USART_MODULE_ENABLED */
#ifdef HAL_WWDG_MODULE_ENABLED
#include "stm32wbxx_hal_wwdg.h"
#endif /* HAL_WWDG_MODULE_ENABLED */
/* Exported macro ------------------------------------------------------------*/
#ifdef USE_FULL_ASSERT
#define assert_param(expr) ((expr) ? (void)0U : assert_failed())
void assert_failed();
#else
#define assert_param(expr) ((void)0U)
#endif /* USE_FULL_ASSERT */
#ifdef __cplusplus
}
#endif
#endif /* __STM32WBxx_HAL_CONF_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@ -1,69 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32wbxx_it.h
* @brief This file contains the headers of the interrupt handlers.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32WBxx_IT_H
#define __STM32WBxx_IT_H
#ifdef __cplusplus
extern "C" {
#endif
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
/* USER CODE END ET */
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
/* USER CODE END EM */
/* Exported functions prototypes ---------------------------------------------*/
void SysTick_Handler(void);
void ADC1_IRQHandler(void);
void USB_LP_IRQHandler(void);
void COMP_IRQHandler(void);
void TIM1_UP_TIM16_IRQHandler(void);
void TIM1_TRG_COM_TIM17_IRQHandler(void);
void TIM1_CC_IRQHandler(void);
void TIM2_IRQHandler(void);
void HSEM_IRQHandler(void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */
#ifdef __cplusplus
}
#endif
#endif /* __STM32WBxx_IT_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@ -1,58 +0,0 @@
/**
******************************************************************************
* @file tim.h
* @brief This file contains all the function prototypes for
* the tim.c file
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __TIM_H__
#define __TIM_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern TIM_HandleTypeDef htim1;
extern TIM_HandleTypeDef htim2;
extern TIM_HandleTypeDef htim16;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_TIM1_Init(void);
void MX_TIM2_Init(void);
void MX_TIM16_Init(void);
void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __TIM_H__ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@ -1,93 +0,0 @@
/**
******************************************************************************
* @file comp.c
* @brief This file provides code for the configuration
* of the COMP instances.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "comp.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
COMP_HandleTypeDef hcomp1;
/* COMP1 init function */
void MX_COMP1_Init(void) {
hcomp1.Instance = COMP1;
hcomp1.Init.InputMinus = COMP_INPUT_MINUS_1_4VREFINT;
hcomp1.Init.InputPlus = COMP_INPUT_PLUS_IO1;
hcomp1.Init.OutputPol = COMP_OUTPUTPOL_NONINVERTED;
hcomp1.Init.Hysteresis = COMP_HYSTERESIS_HIGH;
hcomp1.Init.BlankingSrce = COMP_BLANKINGSRC_NONE;
hcomp1.Init.Mode = COMP_POWERMODE_MEDIUMSPEED;
hcomp1.Init.WindowMode = COMP_WINDOWMODE_DISABLE;
hcomp1.Init.TriggerMode = COMP_TRIGGERMODE_IT_RISING_FALLING;
if(HAL_COMP_Init(&hcomp1) != HAL_OK) {
Error_Handler();
}
}
void HAL_COMP_MspInit(COMP_HandleTypeDef* compHandle) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(compHandle->Instance == COMP1) {
/* USER CODE BEGIN COMP1_MspInit 0 */
/* USER CODE END COMP1_MspInit 0 */
__HAL_RCC_GPIOC_CLK_ENABLE();
/**COMP1 GPIO Configuration
PC5 ------> COMP1_INP
*/
GPIO_InitStruct.Pin = RFID_RF_IN_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(RFID_RF_IN_GPIO_Port, &GPIO_InitStruct);
/* COMP1 interrupt Init */
HAL_NVIC_SetPriority(COMP_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(COMP_IRQn);
/* USER CODE BEGIN COMP1_MspInit 1 */
/* USER CODE END COMP1_MspInit 1 */
}
}
void HAL_COMP_MspDeInit(COMP_HandleTypeDef* compHandle) {
if(compHandle->Instance == COMP1) {
/* USER CODE BEGIN COMP1_MspDeInit 0 */
/* USER CODE END COMP1_MspDeInit 0 */
/**COMP1 GPIO Configuration
PC5 ------> COMP1_INP
*/
HAL_GPIO_DeInit(RFID_RF_IN_GPIO_Port, RFID_RF_IN_Pin);
/* COMP1 interrupt Deinit */
HAL_NVIC_DisableIRQ(COMP_IRQn);
/* USER CODE BEGIN COMP1_MspDeInit 1 */
/* USER CODE END COMP1_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

Some files were not shown because too many files have changed in this diff Show More