This commit is contained in:
VerstreuteSeele
2023-01-27 12:38:44 +01:00
16 changed files with 254 additions and 19 deletions
@@ -11,4 +11,5 @@ App(
stack_size=1 * 1024,
order=130,
fap_category="Debug",
fap_libs=["assets"],
)
@@ -0,0 +1,148 @@
#include "battery_info.h"
#include <furi.h>
#include <gui/elements.h>
#include <assets_icons.h>
#define LOW_CHARGE_THRESHOLD 10
#define HIGH_DRAIN_CURRENT_THRESHOLD 100
struct BatteryInfo {
View* view;
};
static void draw_stat(Canvas* canvas, int x, int y, const Icon* icon, char* val) {
canvas_draw_frame(canvas, x - 7, y + 7, 30, 13);
canvas_draw_icon(canvas, x, y, icon);
canvas_set_color(canvas, ColorWhite);
canvas_draw_box(canvas, x - 4, y + 16, 24, 6);
canvas_set_color(canvas, ColorBlack);
canvas_draw_str_aligned(canvas, x + 8, y + 22, AlignCenter, AlignBottom, val);
};
static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) {
char emote[20] = {};
char header[20] = {};
char value[20] = {};
int32_t drain_current = data->gauge_current * (-1000);
uint32_t charge_current = data->gauge_current * 1000;
// Draw battery
canvas_draw_icon(canvas, x, y, &I_BatteryBody_52x28);
if(charge_current > 0) {
canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceCharging_29x14);
} else if(drain_current > HIGH_DRAIN_CURRENT_THRESHOLD) {
canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceConfused_29x14);
} else if(data->charge < LOW_CHARGE_THRESHOLD) {
canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceNopower_29x14);
} else {
canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceNormal_29x14);
}
// Draw bubble
elements_bubble(canvas, 53, 0, 71, 39);
// Set text
if(charge_current > 0) {
snprintf(emote, sizeof(emote), "%s", "Yummy!");
snprintf(header, sizeof(header), "%s", "Charging at");
snprintf(
value,
sizeof(value),
"%lu.%luV %lumA",
(uint32_t)(data->vbus_voltage),
(uint32_t)(data->vbus_voltage * 10) % 10,
charge_current);
} else if(drain_current > 0) {
snprintf(
emote,
sizeof(emote),
"%s",
drain_current > HIGH_DRAIN_CURRENT_THRESHOLD ? "Oh no!" : "Om-nom-nom!");
snprintf(header, sizeof(header), "%s", "Consumption is");
snprintf(
value,
sizeof(value),
"%ld %s",
drain_current,
drain_current > HIGH_DRAIN_CURRENT_THRESHOLD ? "mA!" : "mA");
} else if(drain_current != 0) {
snprintf(header, 20, "...");
} else if(data->charging_voltage < 4.2) {
// Non-default battery charging limit, mention it
snprintf(emote, sizeof(emote), "Charged!");
snprintf(header, sizeof(header), "Limited to");
snprintf(
value,
sizeof(value),
"%lu.%luV",
(uint32_t)(data->charging_voltage),
(uint32_t)(data->charging_voltage * 10) % 10);
} else {
snprintf(header, sizeof(header), "Charged!");
}
canvas_draw_str_aligned(canvas, 92, y + 3, AlignCenter, AlignCenter, emote);
canvas_draw_str_aligned(canvas, 92, y + 15, AlignCenter, AlignCenter, header);
canvas_draw_str_aligned(canvas, 92, y + 27, AlignCenter, AlignCenter, value);
};
static void battery_info_draw_callback(Canvas* canvas, void* context) {
furi_assert(context);
BatteryInfoModel* model = context;
canvas_clear(canvas);
canvas_set_color(canvas, ColorBlack);
draw_battery(canvas, model, 0, 5);
char batt_level[10];
char temperature[10];
char voltage[10];
char health[10];
snprintf(batt_level, sizeof(batt_level), "%lu%%", (uint32_t)model->charge);
snprintf(temperature, sizeof(temperature), "%lu C", (uint32_t)model->gauge_temperature);
snprintf(
voltage,
sizeof(voltage),
"%lu.%01lu V",
(uint32_t)model->gauge_voltage,
(uint32_t)(model->gauge_voltage * 10) % 10UL);
snprintf(health, sizeof(health), "%d%%", model->health);
draw_stat(canvas, 8, 42, &I_Battery_16x16, batt_level);
draw_stat(canvas, 40, 42, &I_Temperature_16x16, temperature);
draw_stat(canvas, 72, 42, &I_Voltage_16x16, voltage);
draw_stat(canvas, 104, 42, &I_Health_16x16, health);
}
BatteryInfo* battery_info_alloc() {
BatteryInfo* battery_info = malloc(sizeof(BatteryInfo));
battery_info->view = view_alloc();
view_set_context(battery_info->view, battery_info);
view_allocate_model(battery_info->view, ViewModelTypeLocking, sizeof(BatteryInfoModel));
view_set_draw_callback(battery_info->view, battery_info_draw_callback);
return battery_info;
}
void battery_info_free(BatteryInfo* battery_info) {
furi_assert(battery_info);
view_free(battery_info->view);
free(battery_info);
}
View* battery_info_get_view(BatteryInfo* battery_info) {
furi_assert(battery_info);
return battery_info->view;
}
void battery_info_set_data(BatteryInfo* battery_info, BatteryInfoModel* data) {
furi_assert(battery_info);
furi_assert(data);
with_view_model(
battery_info->view,
BatteryInfoModel * model,
{ memcpy(model, data, sizeof(BatteryInfoModel)); },
true);
}
@@ -0,0 +1,23 @@
#pragma once
#include <gui/view.h>
typedef struct BatteryInfo BatteryInfo;
typedef struct {
float vbus_voltage;
float gauge_voltage;
float gauge_current;
float gauge_temperature;
float charging_voltage;
uint8_t charge;
uint8_t health;
} BatteryInfoModel;
BatteryInfo* battery_info_alloc();
void battery_info_free(BatteryInfo* battery_info);
View* battery_info_get_view(BatteryInfo* battery_info);
void battery_info_set_data(BatteryInfo* battery_info, BatteryInfoModel* data);
@@ -31,9 +31,6 @@ uint32_t bt_debug_start_view(void* context) {
BtDebugApp* bt_debug_app_alloc() {
BtDebugApp* app = malloc(sizeof(BtDebugApp));
// Load settings
bt_settings_load(&app->settings);
// Gui
app->gui = furi_record_open(RECORD_GUI);
@@ -105,13 +102,15 @@ int32_t bt_debug_app(void* p) {
}
BtDebugApp* app = bt_debug_app_alloc();
// Was bt active?
const bool was_active = furi_hal_bt_is_active();
// Stop advertising
furi_hal_bt_stop_advertising();
view_dispatcher_run(app->view_dispatcher);
// Restart advertising
if(app->settings.enabled) {
if(was_active) {
furi_hal_bt_start_advertising();
}
bt_debug_app_free(app);
@@ -4,15 +4,14 @@
#include <gui/gui.h>
#include <gui/view.h>
#include <gui/view_dispatcher.h>
#include <gui/modules/submenu.h>
#include <dialogs/dialogs.h>
#include <gui/modules/submenu.h>
#include "views/bt_carrier_test.h"
#include "views/bt_packet_test.h"
#include <bt/bt_settings.h>
typedef struct {
BtSettings settings;
Gui* gui;
ViewDispatcher* view_dispatcher;
Submenu* submenu;
@@ -5,6 +5,7 @@ App(
entry_point="display_test_app",
cdefines=["APP_DISPLAY_TEST"],
requires=["gui"],
fap_libs=["misc"],
stack_size=1 * 1024,
order=120,
fap_category="Debug",
@@ -91,7 +91,6 @@ static void display_test_reload_config(DisplayTest* instance) {
instance->config_contrast,
instance->config_regulation_ratio,
instance->config_bias);
gui_update(instance->gui);
}
static void display_config_set_bias(VariableItem* item) {
@@ -44,7 +44,11 @@ bool rpc_debug_app_scene_input_error_code_on_event(void* context, SceneManagerEv
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == RpcDebugAppCustomEventInputErrorCode) {
rpc_system_app_set_error_code(app->rpc, (uint32_t)atol(app->text_store));
char* end;
int error_code = strtol(app->text_store, &end, 10);
if(!*end) {
rpc_system_app_set_error_code(app->rpc, error_code);
}
scene_manager_previous_scene(app->scene_manager);
consumed = true;
}
@@ -466,6 +466,10 @@ static void mf_classic_generator_test(uint8_t uid_len, MfClassicType type) {
nfc_device_free(nfc_keys);
}
MU_TEST(mf_mini_file_test) {
mf_classic_generator_test(4, MfClassicTypeMini);
}
MU_TEST(mf_classic_1k_4b_file_test) {
mf_classic_generator_test(4, MfClassicType1k);
}
@@ -486,6 +490,7 @@ MU_TEST_SUITE(nfc) {
nfc_test_alloc();
MU_RUN_TEST(nfca_file_test);
MU_RUN_TEST(mf_mini_file_test);
MU_RUN_TEST(mf_classic_1k_4b_file_test);
MU_RUN_TEST(mf_classic_4k_4b_file_test);
MU_RUN_TEST(mf_classic_1k_7b_file_test);
+8
View File
@@ -5,6 +5,10 @@
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
bool enabled;
} BtSettings;
@@ -12,3 +16,7 @@ typedef struct {
bool bt_settings_load(BtSettings* bt_settings);
bool bt_settings_save(BtSettings* bt_settings);
#ifdef __cplusplus
}
#endif
+2 -3
View File
@@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,12.3,,
Version,+,12.4,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,,
@@ -2138,7 +2138,7 @@ Function,-,posix_memalign,int,"void**, size_t, size_t"
Function,-,pow,double,"double, double"
Function,-,pow10,double,double
Function,-,pow10f,float,float
Function,-,power_enable_low_battery_level_notification,void,"Power*, _Bool"
Function,+,power_enable_low_battery_level_notification,void,"Power*, _Bool"
Function,+,power_get_info,void,"Power*, PowerInfo*"
Function,+,power_get_pubsub,FuriPubSub*,Power*
Function,+,power_get_settings_events_pubsub,FuriPubSub*,Power*
@@ -4410,7 +4410,6 @@ Function,+,validator_is_file_callback,_Bool,"const char*, FuriString*, void*"
Function,+,validator_is_file_free,void,ValidatorIsFile*
Function,+,value_index_bool,uint8_t,"const _Bool, const _Bool[], uint8_t"
Function,+,value_index_float,uint8_t,"const float, const float[], uint8_t"
Function,+,value_index_int32,uint8_t,"const int32_t, const int32_t[], uint8_t"
Function,+,value_index_uint32,uint8_t,"const uint32_t, const uint32_t[], uint8_t"
Function,+,variable_item_get_context,void*,VariableItem*
Function,+,variable_item_get_current_value_index,uint8_t,VariableItem*
1 entry status name type params
2 Version + 12.3 12.4
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
2138 Function - pow double double, double
2139 Function - pow10 double double
2140 Function - pow10f float float
2141 Function - + power_enable_low_battery_level_notification void Power*, _Bool
2142 Function + power_get_info void Power*, PowerInfo*
2143 Function + power_get_pubsub FuriPubSub* Power*
2144 Function + power_get_settings_events_pubsub FuriPubSub* Power*
4410 Function + validator_is_file_free void ValidatorIsFile*
4411 Function + value_index_bool uint8_t const _Bool, const _Bool[], uint8_t
4412 Function + value_index_float uint8_t const float, const float[], uint8_t
Function + value_index_int32 uint8_t const int32_t, const int32_t[], uint8_t
4413 Function + value_index_uint32 uint8_t const uint32_t, const uint32_t[], uint8_t
4414 Function + variable_item_get_context void* VariableItem*
4415 Function + variable_item_get_current_value_index uint8_t VariableItem*
+29 -6
View File
@@ -142,21 +142,44 @@ static bool emv_decode_response(uint8_t* buff, uint16_t len, EmvApplication* app
success = true;
FURI_LOG_T(TAG, "found EMV_TAG_AFL %x (len=%d)", tag, tlen);
break;
case EMV_TAG_CARD_NUM: // Track 2 Equivalent Data. 0xD0 delimits PAN from expiry (YYMM)
case EMV_TAG_TRACK_1_EQUIV: {
char track_1_equiv[80];
memcpy(track_1_equiv, &buff[i], tlen);
track_1_equiv[tlen] = '\0';
success = true;
FURI_LOG_T(TAG, "found EMV_TAG_TRACK_1_EQUIV %x : %s", tag, track_1_equiv);
break;
}
case EMV_TAG_TRACK_2_EQUIV: {
// 0xD0 delimits PAN from expiry (YYMM)
for(int x = 1; x < tlen; x++) {
if(buff[i + x + 1] > 0xD0) {
memcpy(app->card_number, &buff[i], x + 1);
app->card_number_len = x + 1;
app->exp_year = (buff[i + x + 1] << 4) | (buff[i + x + 2] >> 4);
app->exp_month = (buff[i + x + 2] << 4) | (buff[i + x + 3] >> 4);
break;
}
}
// Convert 4-bit to ASCII representation
char track_2_equiv[41];
uint8_t track_2_equiv_len = 0;
for(int x = 0; x < tlen; x++) {
char top = (buff[i + x] >> 4) + '0';
char bottom = (buff[i + x] & 0x0F) + '0';
track_2_equiv[x * 2] = top;
track_2_equiv_len++;
if(top == '?') break;
track_2_equiv[x * 2 + 1] = bottom;
track_2_equiv_len++;
if(bottom == '?') break;
}
track_2_equiv[track_2_equiv_len] = '\0';
success = true;
FURI_LOG_T(
TAG,
"found EMV_TAG_CARD_NUM %x (len=%d)",
EMV_TAG_CARD_NUM,
app->card_number_len);
FURI_LOG_T(TAG, "found EMV_TAG_TRACK_2_EQUIV %x : %s", tag, track_2_equiv);
break;
}
case EMV_TAG_PAN:
memcpy(app->card_number, &buff[i], tlen);
app->card_number_len = tlen;
+2 -1
View File
@@ -11,7 +11,8 @@
#define EMV_TAG_CARD_NAME 0x50
#define EMV_TAG_FCI 0xBF0C
#define EMV_TAG_LOG_CTRL 0x9F4D
#define EMV_TAG_CARD_NUM 0x57
#define EMV_TAG_TRACK_1_EQUIV 0x56
#define EMV_TAG_TRACK_2_EQUIV 0x57
#define EMV_TAG_PAN 0x5A
#define EMV_TAG_AFL 0x94
#define EMV_TAG_EXP_DATE 0x5F24
+22
View File
@@ -605,6 +605,14 @@ void mf_classic_read_sector(FuriHalNfcTxRxContext* tx_rx, MfClassicData* data, u
if(mf_classic_read_block(tx_rx, &crypto, i, &block_tmp)) {
mf_classic_set_block_read(data, i, &block_tmp);
blocks_read++;
} else if(i > start_block) {
// Try to re-auth to read block in case prevous block was protected from read
furi_hal_nfc_sleep();
if(!mf_classic_auth(tx_rx, i, key, MfClassicKeyA, &crypto, false, 0)) break;
if(mf_classic_read_block(tx_rx, &crypto, i, &block_tmp)) {
mf_classic_set_block_read(data, i, &block_tmp);
blocks_read++;
}
}
furi_hal_nfc_sleep();
} else {
@@ -618,12 +626,21 @@ void mf_classic_read_sector(FuriHalNfcTxRxContext* tx_rx, MfClassicData* data, u
if(!key_b_found) break;
FURI_LOG_D(TAG, "Try to read blocks with key B");
key = nfc_util_bytes2num(sec_tr->key_b, sizeof(sec_tr->key_b));
if(!mf_classic_auth(tx_rx, start_block, key, MfClassicKeyB, &crypto, false, 0)) break;
for(size_t i = start_block; i < start_block + total_blocks; i++) {
if(!mf_classic_is_block_read(data, i)) {
if(!mf_classic_auth(tx_rx, i, key, MfClassicKeyB, &crypto, false, 0)) continue;
if(mf_classic_read_block(tx_rx, &crypto, i, &block_tmp)) {
mf_classic_set_block_read(data, i, &block_tmp);
blocks_read++;
} else if(i > start_block) {
// Try to re-auth to read block in case prevous block was protected from read
furi_hal_nfc_sleep();
if(!mf_classic_auth(tx_rx, i, key, MfClassicKeyB, &crypto, false, 0)) break;
if(mf_classic_read_block(tx_rx, &crypto, i, &block_tmp)) {
mf_classic_set_block_read(data, i, &block_tmp);
blocks_read++;
}
}
furi_hal_nfc_sleep();
} else {
@@ -676,6 +693,11 @@ static bool mf_classic_read_sector_with_reader(
// Read blocks
for(uint8_t i = 0; i < sector->total_blocks; i++) {
if(mf_classic_read_block(tx_rx, crypto, first_block + i, &sector->block[i])) continue;
if(i == 0) continue;
// Try to auth to read next block in case previous is locked
furi_hal_nfc_sleep();
if(!mf_classic_auth(tx_rx, first_block + i, key, key_type, crypto, false, 0)) continue;
mf_classic_read_block(tx_rx, crypto, first_block + i, &sector->block[i]);
}
// Save sector keys in last block
+2
View File
@@ -6,6 +6,7 @@
#define MF_CLASSIC_BLOCK_SIZE (16)
#define MF_CLASSIC_TOTAL_BLOCKS_MAX (256)
#define MF_MINI_TOTAL_SECTORS_NUM (5)
#define MF_CLASSIC_1K_TOTAL_SECTORS_NUM (16)
#define MF_CLASSIC_4K_TOTAL_SECTORS_NUM (40)
#define MF_MINI_TOTAL_SECTORS_NUM (5)
@@ -22,6 +23,7 @@ typedef enum {
MfClassicTypeMini,
MfClassicType1k,
MfClassicType4k,
MfClassicTypeMini,
} MfClassicType;
typedef enum {
+1
View File
@@ -21,6 +21,7 @@ env.Append(
File("saved_struct.h"),
File("version.h"),
File("float_tools.h"),
File("value_index.h"),
File("tar/tar_archive.h"),
File("stream/stream.h"),
File("stream/file_stream.h"),