Update apps

This commit is contained in:
Willy-JL
2023-08-30 18:59:32 +02:00
parent 160ab755a2
commit ee37769ee2
308 changed files with 2314 additions and 801 deletions

View File

@@ -4,6 +4,7 @@
#include <input/input.h>
#include <notification/notification.h>
#include <notification/notification_messages.h>
#include <dolphin/dolphin.h>
static int matrix[6][7] = {0};
static int cursorx = 3;
@@ -234,6 +235,8 @@ int32_t four_in_row_app(void* p) {
return 255;
}
dolphin_deed(DolphinDeedPluginGameStart);
// Создаем новый view port
ViewPort* view_port = view_port_alloc();
// Создаем callback отрисовки, без контекста

View File

@@ -7,7 +7,6 @@ App(
"gui",
],
stack_size=1 * 1024,
order=90,
fap_icon="4inrow_10px.png",
fap_category="Games",
fap_author="leo-need-more-coffee",

View File

@@ -6,6 +6,6 @@ App(
stack_size=10 * 1024,
fap_category="GPIO",
fap_icon="mouse_10px.png",
fap_version="0.6",
fap_version="0.8",
sources=["*.c", "*.cc"],
)

View File

@@ -12,178 +12,219 @@
static const float CURSOR_SPEED = 1024.0 / (M_PI / 4);
static const float STABILIZE_BIAS = 16.0;
float g_yaw = 0;
float g_pitch = 0;
float g_dYaw = 0;
float g_dPitch = 0;
bool firstRead = true;
bool stabilize = true;
CalibrationData calibration;
cardboard::OrientationTracker tracker(10000000l); // 10 ms / 100 Hz
uint64_t ippms, ippms2;
class TrackingState {
private:
float yaw;
float pitch;
float dYaw;
float dPitch;
bool firstRead;
bool stabilize;
CalibrationData calibration;
cardboard::OrientationTracker tracker;
uint64_t ippus, ippus2;
static inline float clamp(float val)
{
while (val <= -M_PI) {
val += 2 * M_PI;
}
while (val >= M_PI) {
val -= 2 * M_PI;
}
return val;
}
static inline float highpass(float oldVal, float newVal)
{
if (!stabilize) {
return newVal;
}
float delta = clamp(oldVal - newVal);
float alpha = (float) std::max(0.0, 1 - std::pow(std::fabs(delta) * CURSOR_SPEED / STABILIZE_BIAS, 3.0));
return newVal + alpha * delta;
}
void sendCurrentState(MouseMoveCallback mouse_move, void *context)
{
float dX = g_dYaw * CURSOR_SPEED;
float dY = g_dPitch * CURSOR_SPEED;
// Scale the shift down to fit the protocol.
if (dX > 127) {
dY *= 127.0 / dX;
dX = 127;
}
if (dX < -127) {
dY *= -127.0 / dX;
dX = -127;
}
if (dY > 127) {
dX *= 127.0 / dY;
dY = 127;
}
if (dY < -127) {
dX *= -127.0 / dY;
dY = -127;
private:
float clamp(float val) {
while (val <= -M_PI) {
val += 2 * M_PI;
}
while (val >= M_PI) {
val -= 2 * M_PI;
}
return val;
}
const int8_t x = (int8_t)std::floor(dX + 0.5);
const int8_t y = (int8_t)std::floor(dY + 0.5);
mouse_move(x, y, context);
// Only subtract the part of the error that was already sent.
if (x != 0) {
g_dYaw -= x / CURSOR_SPEED;
}
if (y != 0) {
g_dPitch -= y / CURSOR_SPEED;
}
}
void onOrientation(cardboard::Vector4& quaternion)
{
float q1 = quaternion[0]; // X * sin(T/2)
float q2 = quaternion[1]; // Y * sin(T/2)
float q3 = quaternion[2]; // Z * sin(T/2)
float q0 = quaternion[3]; // cos(T/2)
float yaw = std::atan2(2 * (q0 * q3 - q1 * q2), (1 - 2 * (q1 * q1 + q3 * q3)));
float pitch = std::asin(2 * (q0 * q1 + q2 * q3));
// float roll = std::atan2(2 * (q0 * q2 - q1 * q3), (1 - 2 * (q1 * q1 + q2 * q2)));
if (yaw == NAN || pitch == NAN) {
// NaN case, skip it
return;
float highpass(float oldVal, float newVal) {
if (!stabilize) {
return newVal;
}
float delta = clamp(oldVal - newVal);
float alpha = (float) std::max(0.0, 1 - std::pow(std::fabs(delta) * CURSOR_SPEED / STABILIZE_BIAS, 3.0));
return newVal + alpha * delta;
}
if (firstRead) {
g_yaw = yaw;
g_pitch = pitch;
firstRead = false;
} else {
const float newYaw = highpass(g_yaw, yaw);
const float newPitch = highpass(g_pitch, pitch);
void sendCurrentState(MouseMoveCallback mouse_move, void *context) {
float dX = dYaw * CURSOR_SPEED;
float dY = dPitch * CURSOR_SPEED;
float dYaw = clamp(g_yaw - newYaw);
float dPitch = g_pitch - newPitch;
g_yaw = newYaw;
g_pitch = newPitch;
// Scale the shift down to fit the protocol.
if (dX > 127) {
dY *= 127.0 / dX;
dX = 127;
}
if (dX < -127) {
dY *= -127.0 / dX;
dX = -127;
}
if (dY > 127) {
dX *= 127.0 / dY;
dY = 127;
}
if (dY < -127) {
dX *= -127.0 / dY;
dY = -127;
}
// Accumulate the error locally.
g_dYaw += dYaw;
g_dPitch += dPitch;
const int8_t x = (int8_t)std::floor(dX + 0.5);
const int8_t y = (int8_t)std::floor(dY + 0.5);
mouse_move(x, y, context);
// Only subtract the part of the error that was already sent.
if (x != 0) {
dYaw -= x / CURSOR_SPEED;
}
if (y != 0) {
dPitch -= y / CURSOR_SPEED;
}
}
}
void onOrientation(cardboard::Vector4& quaternion) {
float q1 = quaternion[0]; // X * sin(T/2)
float q2 = quaternion[1]; // Y * sin(T/2)
float q3 = quaternion[2]; // Z * sin(T/2)
float q0 = quaternion[3]; // cos(T/2)
float yaw = std::atan2(2 * (q0 * q3 - q1 * q2), (1 - 2 * (q1 * q1 + q3 * q3)));
float pitch = std::asin(2 * (q0 * q1 + q2 * q3));
// float roll = std::atan2(2 * (q0 * q2 - q1 * q3), (1 - 2 * (q1 * q1 + q2 * q2)));
if (yaw == NAN || pitch == NAN) {
// NaN case, skip it
return;
}
if (firstRead) {
this->yaw = yaw;
this->pitch = pitch;
firstRead = false;
} else {
const float newYaw = highpass(this->yaw, yaw);
const float newPitch = highpass(this->pitch, pitch);
float dYaw = clamp(this->yaw - newYaw);
float dPitch = this->pitch - newPitch;
this->yaw = newYaw;
this->pitch = newPitch;
// Accumulate the error locally.
this->dYaw += dYaw;
this->dPitch += dPitch;
}
}
public:
TrackingState()
: yaw(0)
, pitch(0)
, dYaw(0)
, dPitch(0)
, firstRead(true)
, stabilize(true)
, tracker(10000000l) { // 10 ms / 100 Hz
ippus = furi_hal_cortex_instructions_per_microsecond();
ippus2 = ippus / 2;
}
void beginCalibration() {
calibration.reset();
}
bool stepCalibration() {
if (calibration.isComplete())
return true;
double vec[6];
if (imu_read(vec) & GYR_DATA_READY) {
cardboard::Vector3 data(vec[3], vec[4], vec[5]);
furi_delay_ms(9); // Artificially limit to ~100Hz
return calibration.add(data);
}
return false;
}
void saveCalibration() {
CalibrationMedian store;
cardboard::Vector3 median = calibration.getMedian();
store.x = median[0];
store.y = median[1];
store.z = median[2];
CALIBRATION_DATA_SAVE(&store);
}
void loadCalibration() {
CalibrationMedian store;
cardboard::Vector3 median = calibration.getMedian();
if (CALIBRATION_DATA_LOAD(&store)) {
median[0] = store.x;
median[1] = store.y;
median[2] = store.z;
}
tracker.SetCalibration(median);
}
void beginTracking() {
loadCalibration();
tracker.Resume();
}
void stepTracking(MouseMoveCallback mouse_move, void *context) {
double vec[6];
int ret = imu_read(vec);
if (ret != 0) {
uint64_t t = (DWT->CYCCNT * 1000llu + ippus2) / ippus;
if (ret & ACC_DATA_READY) {
cardboard::AccelerometerData adata
= { .system_timestamp = t, .sensor_timestamp_ns = t,
.data = cardboard::Vector3(vec[0], vec[1], vec[2]) };
tracker.OnAccelerometerData(adata);
}
if (ret & GYR_DATA_READY) {
cardboard::GyroscopeData gdata
= { .system_timestamp = t, .sensor_timestamp_ns = t,
.data = cardboard::Vector3(vec[3], vec[4], vec[5]) };
cardboard::Vector4 pose = tracker.OnGyroscopeData(gdata);
onOrientation(pose);
sendCurrentState(mouse_move, context);
}
}
}
void stopTracking() {
tracker.Pause();
}
};
static TrackingState g_state;
extern "C" {
void calibration_begin() {
calibration.reset();
g_state.beginCalibration();
FURI_LOG_I(TAG, "Calibrating");
}
bool calibration_step() {
if (calibration.isComplete())
return true;
double vec[6];
if (imu_read(vec) & GYR_DATA_READY) {
cardboard::Vector3 data(vec[3], vec[4], vec[5]);
furi_delay_ms(9); // Artificially limit to ~100Hz
return calibration.add(data);
}
return false;
return g_state.stepCalibration();
}
void calibration_end() {
CalibrationMedian store;
cardboard::Vector3 median = calibration.getMedian();
store.x = median[0];
store.y = median[1];
store.z = median[2];
CALIBRATION_DATA_SAVE(&store);
g_state.saveCalibration();
}
void tracking_begin() {
CalibrationMedian store;
cardboard::Vector3 median = calibration.getMedian();
if (CALIBRATION_DATA_LOAD(&store)) {
median[0] = store.x;
median[1] = store.y;
median[2] = store.z;
}
ippms = furi_hal_cortex_instructions_per_microsecond();
ippms2 = ippms / 2;
tracker.SetCalibration(median);
tracker.Resume();
g_state.beginTracking();
}
void tracking_step(MouseMoveCallback mouse_move, void *context) {
double vec[6];
int ret = imu_read(vec);
if (ret != 0) {
uint64_t t = (DWT->CYCCNT * 1000llu + ippms2) / ippms;
if (ret & ACC_DATA_READY) {
cardboard::AccelerometerData adata
= { .system_timestamp = t, .sensor_timestamp_ns = t,
.data = cardboard::Vector3(vec[0], vec[1], vec[2]) };
tracker.OnAccelerometerData(adata);
}
if (ret & GYR_DATA_READY) {
cardboard::GyroscopeData gdata
= { .system_timestamp = t, .sensor_timestamp_ns = t,
.data = cardboard::Vector3(vec[3], vec[4], vec[5]) };
cardboard::Vector4 pose = tracker.OnGyroscopeData(gdata);
onOrientation(pose);
sendCurrentState(mouse_move, context);
}
}
g_state.stepTracking(mouse_move, context);
}
void tracking_end() {
tracker.Pause();
g_state.stopTracking();
}
}

View File

@@ -89,7 +89,7 @@ Vector4 OrientationTracker::OnGyroscopeData(const GyroscopeData& event)
sensor_fusion_->ProcessGyroscopeSample(data);
return OrientationTracker::GetPose(data.sensor_timestamp_ns + sampling_period_ns_);
return GetPose(data.sensor_timestamp_ns + sampling_period_ns_);
}
} // namespace cardboard

View File

@@ -59,13 +59,14 @@ namespace {
// angle = norm(a)
// axis = a.normalized()
// If norm(a) == 0, it returns an identity rotation.
static inline Rotation RotationFromVector(const Vector3& a)
static inline void RotationFromVector(const Vector3& a, Rotation& r)
{
const double norm_a = Length(a);
if (norm_a < kEpsilon) {
return Rotation::Identity();
r = Rotation::Identity();
return;
}
return Rotation::FromAxisAndAngle(a / norm_a, norm_a);
r = Rotation::FromAxisAndAngle(a / norm_a, norm_a);
}
} // namespace
@@ -199,7 +200,8 @@ void SensorFusionEkf::ComputeMeasurementJacobian()
Vector3 delta = Vector3::Zero();
delta[dof] = kFiniteDifferencingEpsilon;
const Rotation epsilon_rotation = RotationFromVector(delta);
Rotation epsilon_rotation;
RotationFromVector(delta, epsilon_rotation);
const Vector3 delta_rotation
= ComputeInnovation(epsilon_rotation * current_state_.sensor_from_start_rotation);
@@ -263,7 +265,8 @@ void SensorFusionEkf::ProcessAccelerometerSample(const AccelerometerData& sample
* state_covariance_;
// Updates pose and associate covariance matrix.
const Rotation rotation_from_state_update = RotationFromVector(state_update_);
Rotation rotation_from_state_update;
RotationFromVector(state_update_, rotation_from_state_update);
current_state_.sensor_from_start_rotation
= rotation_from_state_update * current_state_.sensor_from_start_rotation;

View File

@@ -132,6 +132,11 @@ void bt_mouse_connection_status_changed_callback(BtStatus status, void* context)
BtMouse* bt_mouse = context;
bt_mouse->connected = (status == BtStatusConnected);
if(!bt_mouse->notifications) {
tracking_end();
return;
}
if(bt_mouse->connected) {
notification_internal_message(bt_mouse->notifications, &sequence_set_blue_255);
tracking_begin();
@@ -140,9 +145,6 @@ void bt_mouse_connection_status_changed_callback(BtStatus status, void* context)
tracking_end();
notification_internal_message(bt_mouse->notifications, &sequence_reset_blue);
}
//with_view_model(
// bt_mouse->view, void * model, { model->connected = connected; }, true);
}
bool bt_mouse_move(int8_t dx, int8_t dy, void* context) {
@@ -160,46 +162,6 @@ bool bt_mouse_move(int8_t dx, int8_t dy, void* context) {
return true;
}
void bt_mouse_enter_callback(void* context) {
furi_assert(context);
BtMouse* bt_mouse = context;
bt_mouse->bt = furi_record_open(RECORD_BT);
bt_mouse->notifications = furi_record_open(RECORD_NOTIFICATION);
bt_set_status_changed_callback(
bt_mouse->bt, bt_mouse_connection_status_changed_callback, bt_mouse);
furi_assert(bt_set_profile(bt_mouse->bt, BtProfileHidKeyboard));
furi_hal_bt_start_advertising();
}
bool bt_mouse_custom_callback(uint32_t event, void* context) {
UNUSED(event);
furi_assert(context);
BtMouse* bt_mouse = context;
tracking_step(bt_mouse_move, context);
furi_delay_ms(3); // Magic! Removing this will break the buttons
view_dispatcher_send_custom_event(bt_mouse->view_dispatcher, 0);
return true;
}
void bt_mouse_exit_callback(void* context) {
furi_assert(context);
BtMouse* bt_mouse = context;
tracking_end();
notification_internal_message(bt_mouse->notifications, &sequence_reset_blue);
furi_hal_bt_stop_advertising();
bt_set_profile(bt_mouse->bt, BtProfileSerial);
furi_record_close(RECORD_NOTIFICATION);
bt_mouse->notifications = NULL;
furi_record_close(RECORD_BT);
bt_mouse->bt = NULL;
}
static int8_t clamp(int t) {
if(t < -128) {
return -128;
@@ -279,6 +241,50 @@ void bt_mouse_thread_stop(BtMouse* bt_mouse) {
furi_thread_join(bt_mouse->thread);
furi_thread_free(bt_mouse->thread);
furi_mutex_free(bt_mouse->mutex);
bt_mouse->mutex = NULL;
bt_mouse->thread = NULL;
}
void bt_mouse_enter_callback(void* context) {
furi_assert(context);
BtMouse* bt_mouse = context;
bt_mouse->bt = furi_record_open(RECORD_BT);
bt_mouse->notifications = furi_record_open(RECORD_NOTIFICATION);
bt_set_status_changed_callback(
bt_mouse->bt, bt_mouse_connection_status_changed_callback, bt_mouse);
furi_assert(bt_set_profile(bt_mouse->bt, BtProfileHidKeyboard));
furi_hal_bt_start_advertising();
bt_mouse_thread_start(bt_mouse);
}
bool bt_mouse_custom_callback(uint32_t event, void* context) {
UNUSED(event);
furi_assert(context);
BtMouse* bt_mouse = context;
tracking_step(bt_mouse_move, context);
furi_delay_ms(3); // Magic! Removing this will break the buttons
view_dispatcher_send_custom_event(bt_mouse->view_dispatcher, 0);
return true;
}
void bt_mouse_exit_callback(void* context) {
furi_assert(context);
BtMouse* bt_mouse = context;
bt_mouse_thread_stop(bt_mouse);
tracking_end();
notification_internal_message(bt_mouse->notifications, &sequence_reset_blue);
furi_hal_bt_stop_advertising();
bt_set_profile(bt_mouse->bt, BtProfileSerial);
furi_record_close(RECORD_NOTIFICATION);
bt_mouse->notifications = NULL;
furi_record_close(RECORD_BT);
bt_mouse->bt = NULL;
}
BtMouse* bt_mouse_alloc(ViewDispatcher* view_dispatcher) {
@@ -293,13 +299,11 @@ BtMouse* bt_mouse_alloc(ViewDispatcher* view_dispatcher) {
view_set_enter_callback(bt_mouse->view, bt_mouse_enter_callback);
view_set_custom_callback(bt_mouse->view, bt_mouse_custom_callback);
view_set_exit_callback(bt_mouse->view, bt_mouse_exit_callback);
bt_mouse_thread_start(bt_mouse);
return bt_mouse;
}
void bt_mouse_free(BtMouse* bt_mouse) {
furi_assert(bt_mouse);
bt_mouse_thread_stop(bt_mouse);
view_free(bt_mouse->view);
free(bt_mouse);
}

View File

@@ -5,7 +5,6 @@ App(
entry_point="arkanoid_game_app",
requires=["gui"],
stack_size=1 * 1024,
order=20,
fap_icon="arkanoid_10px.png",
fap_category="Games",
fap_author="@xMasterX & @gotnull",

View File

@@ -5,6 +5,7 @@
#include <gui/view.h>
#include <notification/notification.h>
#include <notification/notification_messages.h>
#include <dolphin/dolphin.h>
#define TAG "Arkanoid"
@@ -397,6 +398,9 @@ int32_t arkanoid_game_app(void* p) {
Gui* gui = furi_record_open(RECORD_GUI);
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
// Call dolphin deed on game start
dolphin_deed(DolphinDeedPluginGameStart);
GameEvent event;
for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);

View File

@@ -6,7 +6,6 @@ App(
cdefines=["APP_ASTEROIDS"],
requires=["gui"],
stack_size=8 * 1024,
order=50,
fap_icon="appicon.png",
fap_icon_assets="assets",
fap_category="Games",

View File

@@ -5,7 +5,8 @@ App(
entry_point="avr_isp_app",
requires=["gui"],
stack_size=4 * 1024,
order=20,
fap_description="Application for flashing AVR microcontrollers",
fap_version="1.0",
fap_icon="avr_app_icon_10x10.png",
fap_category="GPIO",
fap_icon_assets="images",

View File

@@ -1,7 +1,8 @@
#pragma once
#include "helpers/avr_isp_types.h"
#include <avr_isp_icons.h>
#include "avr_isp_icons.h"
#include <assets_icons.h>
#include "scenes/avr_isp_scene.h"
#include <gui/gui.h>
@@ -41,4 +42,4 @@ typedef struct {
AvrIspError error;
} AvrIspApp;
bool avr_isp_load_from_file(AvrIspApp* app);
bool avr_isp_load_from_file(AvrIspApp* app);

View File

@@ -174,7 +174,7 @@ static void avr_isp_commit(AvrIsp* instance, uint16_t addr, uint8_t data) {
while((furi_get_tick() - starttime) < 30) {
if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FLASH_HI(addr)) != 0xFF) {
break;
}
};
}
}
}
@@ -357,7 +357,7 @@ uint8_t avr_isp_read_lock_byte(AvrIsp* instance) {
data = avr_isp_spi_transaction(instance, AVR_ISP_READ_LOCK_BYTE);
if(avr_isp_spi_transaction(instance, AVR_ISP_READ_LOCK_BYTE) == data) {
break;
}
};
data = 0x00;
}
return data;
@@ -377,7 +377,7 @@ bool avr_isp_write_lock_byte(AvrIsp* instance, uint8_t lock) {
if(avr_isp_spi_transaction(instance, AVR_ISP_READ_LOCK_BYTE) == lock) {
ret = true;
break;
}
};
}
}
return ret;
@@ -392,7 +392,7 @@ uint8_t avr_isp_read_fuse_low(AvrIsp* instance) {
data = avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_LOW);
if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_LOW) == data) {
break;
}
};
data = 0x00;
}
return data;
@@ -412,7 +412,7 @@ bool avr_isp_write_fuse_low(AvrIsp* instance, uint8_t lfuse) {
if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_LOW) == lfuse) {
ret = true;
break;
}
};
}
}
return ret;
@@ -427,7 +427,7 @@ uint8_t avr_isp_read_fuse_high(AvrIsp* instance) {
data = avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_HIGH);
if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_HIGH) == data) {
break;
}
};
data = 0x00;
}
return data;
@@ -447,7 +447,7 @@ bool avr_isp_write_fuse_high(AvrIsp* instance, uint8_t hfuse) {
if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_HIGH) == hfuse) {
ret = true;
break;
}
};
}
}
return ret;
@@ -462,7 +462,7 @@ uint8_t avr_isp_read_fuse_extended(AvrIsp* instance) {
data = avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_EXTENDED);
if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_EXTENDED) == data) {
break;
}
};
data = 0x00;
}
return data;
@@ -482,7 +482,7 @@ bool avr_isp_write_fuse_extended(AvrIsp* instance, uint8_t efuse) {
if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_EXTENDED) == efuse) {
ret = true;
break;
}
};
}
}
return ret;

View File

@@ -350,12 +350,12 @@ static void avr_isp_worker_rw_get_dump_flash(AvrIspWorkerRW* instance, const cha
sizeof(data));
flipper_i32hex_file_bin_to_i32hex_set_data(
flipper_hex_flash, data, avr_isp_chip_arr[instance->chip_arr_ind].pagesize);
//FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_flash));
FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_flash));
instance->progress_flash =
(float)(i) / ((float)avr_isp_chip_arr[instance->chip_arr_ind].flashsize / 2.0f);
}
flipper_i32hex_file_bin_to_i32hex_set_end_line(flipper_hex_flash);
//FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_flash));
FURI_LOG_D(TAG, "%s", flipper_i32hex_file_get_string(flipper_hex_flash));
flipper_i32hex_file_close(flipper_hex_flash);
instance->progress_flash = 1.0f;
}

View File

@@ -111,7 +111,7 @@ static uint8_t avr_isp_prog_getch(AvrIspProg* instance) {
uint8_t data[1] = {0};
while(furi_stream_buffer_receive(instance->stream_rx, &data, sizeof(int8_t), 30) == 0) {
if(instance->exit) break;
}
};
return data[0];
}
@@ -196,7 +196,7 @@ static void avr_isp_prog_set_cfg(AvrIspProg* instance) {
instance->cfg->lockbytes = instance->buff[6];
instance->cfg->fusebytes = instance->buff[7];
instance->cfg->flashpoll = instance->buff[8];
// ignore (instance->buff[9] == instance->buff[8]) //FLASH polling value. Same as <EFBFBD>flashpoll<EFBFBD>
// ignore (instance->buff[9] == instance->buff[8]) //FLASH polling value. Same as flashpoll
instance->cfg->eeprompoll = instance->buff[10] << 8 | instance->buff[11];
instance->cfg->pagesize = instance->buff[12] << 8 | instance->buff[13];
instance->cfg->eepromsize = instance->buff[14] << 8 | instance->buff[15];
@@ -348,7 +348,7 @@ static void avr_isp_prog_commit(AvrIspProg* instance, uint16_t addr, uint8_t dat
while((furi_get_tick() - starttime) < 30) {
if(avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_FLASH_HI(addr)) != 0xFF) {
break;
}
};
}
}
}

View File

@@ -1,5 +1,6 @@
#include "avr_isp_view_chip_detect.h"
#include <avr_isp_icons.h>
#include "avr_isp_icons.h"
#include <assets_icons.h>
#include <gui/elements.h>
#include "../helpers/avr_isp_worker_rw.h"

View File

@@ -1,5 +1,6 @@
#include "avr_isp_view_programmer.h"
#include <avr_isp_icons.h>
#include "avr_isp_icons.h"
#include <assets_icons.h>
#include "../helpers/avr_isp_worker.h"
#include <gui/elements.h>

View File

@@ -1,6 +1,7 @@
#include "barcode_app.h"
#include "barcode_app_icons.h"
#include <assets_icons.h>
/**
* Opens a file browser dialog and returns the filepath of the selected file

View File

@@ -5,7 +5,6 @@ App(
entry_point="blackjack_app",
requires=["gui", "storage", "canvas"],
stack_size=2 * 1024,
order=30,
fap_icon="blackjack_10px.png",
fap_category="Games",
fap_icon_assets="assets",

View File

@@ -1,6 +1,7 @@
#include <gui/gui.h>
#include <stdlib.h>
#include <dolphin/dolphin.h>
#include <dialogs/dialogs.h>
#include <gui/canvas_i.h>
@@ -14,6 +15,7 @@
#include "ui.h"
#include "blackjack_icons.h"
#include <assets_icons.h>
#define DEALER_MAX 17
@@ -275,6 +277,7 @@ void dealer_tick(GameState* game_state) {
if(dealer_score >= DEALER_MAX) {
if(dealer_score > 21 || dealer_score < player_score) {
dolphin_deed(DolphinDeedPluginGameWin);
enqueue(
&(game_state->queue_state),
game_state,
@@ -568,6 +571,9 @@ int32_t blackjack_app(void* p) {
AppEvent event;
// Call dolphin deed on game start
dolphin_deed(DolphinDeedPluginGameStart);
for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
furi_mutex_acquire(game_state->mutex, FuriWaitForever);
@@ -625,4 +631,4 @@ free_and_exit:
furi_message_queue_free(event_queue);
return return_code;
}
}

View File

@@ -7,7 +7,6 @@ App(
"gui",
],
stack_size=1 * 1024,
order=90,
fap_icon="bomb.png",
fap_category="Games",
fap_icon_assets="assets",

View File

@@ -6,6 +6,8 @@
#include <notification/notification.h>
#include <notification/notification_messages.h>
#include "bomberduck_icons.h"
#include <assets_icons.h>
#include <dolphin/dolphin.h>
int max(int a, int b) {
return (a > b) ? a : b;
@@ -381,6 +383,7 @@ int32_t bomberduck_app(void* p) {
return 255;
}
dolphin_deed(DolphinDeedPluginGameStart);
// Создаем новый view port
ViewPort* view_port = view_port_alloc();
// Создаем callback отрисовки, без контекста
@@ -454,8 +457,9 @@ int32_t bomberduck_app(void* p) {
notification_message(notification, &end);
world.running = 0;
world.level += 1;
// if(world.level % 5 == 0) {
// }
if(world.level % 5 == 0) {
dolphin_deed(DolphinDeedPluginGameWin);
}
}
for(int i = 0; i < world.bombs_count; i++) {
if(furi_get_tick() - world.bombs[i].planted >

View File

@@ -9,7 +9,6 @@ App(
fap_icon="bpm_10px.png",
fap_category="Media",
fap_icon_assets="icons",
order=15,
fap_author="@panki27",
fap_weburl="https://github.com/panki27/bpm-tapper",
fap_version="1.0",

View File

@@ -10,7 +10,6 @@ App(
stack_size=2 * 1024,
fap_icon="caesar_cipher_icon.png",
fap_category="Tools",
order=20,
fap_author="@panki27",
fap_weburl="https://github.com/panki27/caesar-cipher",
fap_version="1.0",

View File

@@ -6,7 +6,6 @@ App(
cdefines=["APP_CALCULATOR"],
requires=["gui"],
stack_size=1 * 1024,
order=45,
fap_icon="calcIcon.png",
fap_category="Tools",
fap_author="@n-o-T-I-n-s-a-n-e",

View File

@@ -9,7 +9,6 @@ App(
fap_icon="icons/camera_suite.png",
fap_weburl="https://github.com/CodyTolene/Flipper-Zero-Cam",
name="[ESP32] Camera Suite",
order=1,
requires=["gui", "storage"],
stack_size=8 * 1024,
)

View File

@@ -3,6 +3,7 @@
#include <furi_hal.h>
#include <input/input.h>
#include <gui/elements.h>
#include <dolphin/dolphin.h>
#include "../helpers/camera_suite_haptic.h"
#include "../helpers/camera_suite_speaker.h"
#include "../helpers/camera_suite_led.h"

View File

@@ -3,6 +3,7 @@
#include <furi_hal.h>
#include <input/input.h>
#include <gui/elements.h>
#include <dolphin/dolphin.h>
struct CameraSuiteViewGuide {
View* view;

View File

@@ -7,7 +7,6 @@ App(
"gui",
],
stack_size=4 * 1024,
order=10,
fap_icon="flipchess_10px.png",
fap_icon_assets="icons",
fap_icon_assets_symbol="flipchess",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 446 B

View File

@@ -4,6 +4,7 @@
#include <input/input.h>
#include <gui/elements.h>
#include "flipchess_icons.h"
#include <assets_icons.h>
struct FlipChessStartscreen {
View* view;

View File

@@ -10,7 +10,6 @@ App(
"gui",
],
stack_size=2 * 1024,
order=20,
fap_icon="cntdown_timer.png",
fap_category="Tools",
fap_author="@0w0mewo",

View File

@@ -8,7 +8,8 @@ App(
"dialogs",
],
stack_size=4 * 1024,
order=20,
fap_description="Enables use of Flipper as a debug probe for ARM devices, implements the CMSIS-DAP protocol",
fap_version="1.0",
fap_icon="dap_link.png",
fap_category="GPIO",
fap_private_libs=[

View File

@@ -15,7 +15,7 @@
#include "usb/dap_v2_usb.h"
#include <dialogs/dialogs.h>
#include "dap_link_icons.h"
#include "assets_icons.h"
#include <assets_icons.h>
/***************************************************************************/
/****************************** DAP COMMON *********************************/
@@ -525,4 +525,4 @@ int32_t dap_link_app(void* p) {
dap_app_free(app);
return 0;
}
}

View File

@@ -1,5 +1,6 @@
#include "dap_main_view.h"
#include "dap_link_icons.h"
#include <assets_icons.h>
#include <gui/elements.h>
// extern const Icon I_ArrowDownEmpty_12x18;

View File

@@ -1,4 +0,0 @@
dist/*
.vscode
.clang-format
.editorconfig

View File

@@ -8,7 +8,6 @@ App(
"music_player",
],
stack_size=4 * 1024,
order=75,
fap_icon="doom_10px.png",
fap_category="Games",
fap_icon_assets="assets",

View File

@@ -1,7 +1,8 @@
#include <gui/gui.h>
#include <furi_hal.h>
#include "constants.h"
#include <doom_icons.h>
#include "doom_icons.h"
#include <assets_icons.h>
#include "assets.h"
#define CHECK_BIT(var, pos) ((var) & (1 << (pos)))

View File

@@ -13,6 +13,7 @@
#include "level.h"
#include <notification/notification.h>
#include <notification/notification_messages.h>
#include <dolphin/dolphin.h>
#define SOUND
@@ -156,9 +157,6 @@ void spawnEntity(uint8_t type, uint8_t x, uint8_t y, PluginState* const plugin_s
plugin_state->entity[plugin_state->num_entities] = create_medikit(x, y);
plugin_state->num_entities++;
break;
default:
break;
}
}
@@ -462,9 +460,6 @@ void updateEntities(const uint8_t level[], Canvas* const canvas, PluginState* co
}
break;
}
default:
break;
}
i++;
@@ -993,6 +988,9 @@ int32_t doom_app() {
music_player_worker_load_rtttl_from_string(plugin_state->music_instance->worker, dsintro);
music_player_worker_start(plugin_state->music_instance->worker);
#endif
// Call dolphin deed on game start
dolphin_deed(DolphinDeedPluginGameStart);
for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
furi_mutex_acquire(plugin_state->mutex, FuriWaitForever);

View File

@@ -393,7 +393,7 @@ bool music_player_worker_load_rtttl_from_file(MusicPlayerWorker* instance, const
if(!storage_file_open(file, file_path, FSAM_READ, FSOM_OPEN_EXISTING)) {
FURI_LOG_E(TAG, "Unable to open file");
break;
}
};
uint16_t ret = 0;
do {

View File

@@ -10,9 +10,8 @@ App(
],
fap_icon="phone.png",
stack_size=8 * 1024,
order=20,
fap_category="Tools",
fap_author="@litui & @xMasterX",
fap_version="1.0",
fap_version="1.1",
fap_description="DTMF (Dual-Tone Multi-Frequency) dialer, Bluebox, and Redbox.",
)

View File

@@ -86,4 +86,4 @@ int32_t dtmf_dolphin_app(void* p) {
app_free(app);
return 0;
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 306 B

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

@@ -6,7 +6,6 @@ App(
cdefines=["APP_CAMERA"],
requires=["gui"],
stack_size=8 * 1024,
order=1,
fap_icon="icon.png",
fap_category="GPIO",
fap_description="ESP32-CAM live feed and photo capture, use left/right for orientation/mode, up/down for brightness and center for saving a screenshot. [Unplug the USB cable to test with Mayhem]",

View File

@@ -6,7 +6,6 @@ App(
cdefines=["APP_EVIL_PORTAL"],
requires=["gui"],
stack_size=1 * 1024,
order=90,
fap_icon="icons/evil_portal_10px.png",
fap_category="GPIO",
fap_description="ESP32-CAM evil portal. When users try to connect to this access point they will be served a fake login screen. User credentials are sent to the Flipper and logged on the SD card. [Unplug the USB cable to test with Mayhem]",

View File

@@ -6,7 +6,6 @@ App(
cdefines=["APP_WIFI_MARAUDER"],
requires=["gui"],
stack_size=4 * 1024,
order=2,
fap_icon="wifi_10px.png",
fap_category="GPIO",
fap_description="ESP32-CAM version of Marauder. Includes all functionality from the original plus some options to trigger the camera and flashlight. [Unplug the USB cable to test with Mayhem]",

View File

@@ -6,7 +6,6 @@ App(
cdefines=["APP_UART_TERMINAL"],
requires=["gui"],
stack_size=1 * 1024,
order=90,
fap_icon_assets="assets",
fap_icon="icon.png",
fap_category="GPIO",

View File

@@ -6,7 +6,6 @@ App(
cdefines=["APP_QRCODE"],
requires=["gui"],
stack_size=8 * 1024,
order=1,
fap_icon="icon.png",
fap_category="GPIO",
fap_description="ESP32-CAM Motion detection. It generates a beep when motion is detected. Can be extended to trigger more stuff in the code. [Unplug the USB cable to test with Mayhem]",

View File

@@ -6,7 +6,6 @@ App(
cdefines=["APP_QRCODE"],
requires=["gui"],
stack_size=8 * 1024,
order=1,
fap_icon="icon.png",
fap_category="GPIO",
fap_description="ESP32-CAM simple app to start a remote camera. [Unplug the USB cable to test with Mayhem]",

View File

@@ -6,7 +6,6 @@ App(
cdefines=["APP_QRCODE"],
requires=["gui"],
stack_size=8 * 1024,
order=1,
fap_icon="icon.png",
fap_category="GPIO",
fap_description="ESP32-CAM simple app to show a payload from QR codes. Can be extended to trigger more stuff in the code. [Unplug the USB cable to test with Mayhem]",

View File

@@ -5,7 +5,6 @@ App(
entry_point="esp8266_deauth_app",
requires=["gui"],
stack_size=2 * 1024,
order=100,
fap_icon="wifi_10px.png",
fap_category="WiFi",
fap_author="@SequoiaSan & @xMasterX",

View File

@@ -6,7 +6,6 @@ App(
entry_point="esp_flasher_app",
requires=["gui"],
stack_size=4 * 1024,
order=90,
fap_icon="update_10px.png",
fap_category="GPIO",
fap_private_libs=[

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 B

View File

@@ -192,10 +192,46 @@ bool crypto_ctx_encrypt(ESubGhzChatCryptoCtx* ctx, uint8_t* in, size_t in_len, u
TAG_BYTES) == 0);
#endif /* FURI_HAL_CRYPTO_ADVANCED_AVAIL */
// increase internal counter
// update replay dict and increase internal counter
if(ret) {
ESubGhzChatReplayDict_set_at(ctx->replay_dict, ctx->run_id, ctx->counter);
ctx->counter++;
}
return ret;
}
size_t crypto_ctx_dump_replay_dict(
ESubGhzChatCryptoCtx* ctx,
CryptoCtxReplayDictWriter writer,
void* writer_ctx) {
size_t ret = 0;
ESubGhzChatReplayDict_it_t i;
for(ESubGhzChatReplayDict_it(i, ctx->replay_dict); !ESubGhzChatReplayDict_end_p(i);
ESubGhzChatReplayDict_next(i), ret++) {
ESubGhzChatReplayDict_itref_t* ref = ESubGhzChatReplayDict_ref(i);
if(!writer(ref->key, ref->value, writer_ctx)) {
break;
}
}
return ret;
}
size_t crypto_ctx_read_replay_dict(
ESubGhzChatCryptoCtx* ctx,
CryptoCtxReplayDictReader reader,
void* reader_ctx) {
size_t ret = 0;
uint64_t run_id;
uint32_t counter;
while(reader(&run_id, &counter, reader_ctx)) {
ESubGhzChatReplayDict_set_at(ctx->replay_dict, run_id, counter);
ret++;
}
return ret;
}

View File

@@ -34,6 +34,18 @@ void crypto_ctx_get_key(ESubGhzChatCryptoCtx* ctx, uint8_t* key);
bool crypto_ctx_decrypt(ESubGhzChatCryptoCtx* ctx, uint8_t* in, size_t in_len, uint8_t* out);
bool crypto_ctx_encrypt(ESubGhzChatCryptoCtx* ctx, uint8_t* in, size_t in_len, uint8_t* out);
typedef bool (*CryptoCtxReplayDictWriter)(uint64_t run_id, uint32_t counter, void* context);
typedef bool (*CryptoCtxReplayDictReader)(uint64_t* run_id, uint32_t* counter, void* context);
size_t crypto_ctx_dump_replay_dict(
ESubGhzChatCryptoCtx* ctx,
CryptoCtxReplayDictWriter writer,
void* writer_ctx);
size_t crypto_ctx_read_replay_dict(
ESubGhzChatCryptoCtx* ctx,
CryptoCtxReplayDictReader reader,
void* reader_ctx);
#ifdef __cplusplus
}
#endif

View File

@@ -1,14 +1,13 @@
#include <furi_hal.h>
#include <gui/elements.h>
#include <gui/gui.h>
#include <lib/subghz/devices/cc1101_int/cc1101_int_interconnect.h>
#include "helpers/radio_device_loader.h"
#include "esubghz_chat_i.h"
#define CHAT_LEAVE_DELAY 10
#define TICK_INTERVAL 50
#define MESSAGE_COMPLETION_TIMEOUT 500
#define TIMEOUT_BETWEEN_MESSAGES 500
#define KBD_UNLOCK_CNT 3
#define KBD_UNLOCK_TIMEOUT 1000
@@ -125,15 +124,23 @@ void tx_msg_input(ESubGhzChatState* state) {
subghz_tx_rx_worker_write(state->subghz_worker, state->tx_buffer, tx_size);
}
/* Displays whether or not encryption has been enabled in the text box. Also
* clears the text input buffer to remove the password and starts the Sub-GHz
* worker. After starting the worker a join message is transmitted. */
/* Displays information on frequency, encryption and radio type in the text
* box. Also clears the text input buffer to remove the password and starts the
* Sub-GHz worker. After starting the worker a join message is transmitted. */
void enter_chat(ESubGhzChatState* state) {
furi_string_cat_printf(state->chat_box_store, "Frequency: %lu", state->frequency);
furi_string_cat_printf(
state->chat_box_store, "\nEncrypted: %s", (state->encrypted ? "yes" : "no"));
subghz_tx_rx_worker_start(state->subghz_worker, state->subghz_device, state->frequency);
if(strcmp(state->subghz_device->name, "cc1101_ext") == 0) {
furi_string_cat_printf(state->chat_box_store, "\nRadio: External");
} else {
furi_string_cat_printf(state->chat_box_store, "\nRadio: Internal");
}
/* concatenate the name prefix and join message */
furi_string_set(state->msg_input, state->name_prefix);
furi_string_cat_str(state->msg_input, " joined chat.");
@@ -523,6 +530,9 @@ int32_t esubghz_chat(void) {
goto err_alloc_crypto;
}
/* set the default frequency */
state->frequency = DEFAULT_FREQ;
/* set the have_read callback of the Sub-GHz worker */
subghz_tx_rx_worker_set_callback_have_read(state->subghz_worker, have_read_cb, state);
@@ -531,7 +541,12 @@ int32_t esubghz_chat(void) {
/* init internal device */
subghz_devices_init();
state->subghz_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME);
state->subghz_device =
radio_device_loader_set(state->subghz_device, SubGhzRadioDeviceTypeExternalCC1101);
subghz_devices_reset(state->subghz_device);
subghz_devices_idle(state->subghz_device);
/* set chat name prefix */
furi_string_printf(state->name_prefix, "%s", furi_hal_version_get_name_ptr());
@@ -582,8 +597,8 @@ int32_t esubghz_chat(void) {
Gui* gui = furi_record_open(RECORD_GUI);
view_dispatcher_attach_to_gui(state->view_dispatcher, gui, ViewDispatcherTypeFullscreen);
/* switch to the frequency input scene */
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_FreqInput);
/* switch to the key menu scene */
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_KeyMenu);
/* run the view dispatcher, this call only returns when we close the
* application */
@@ -627,6 +642,8 @@ int32_t esubghz_chat(void) {
crypto_explicit_bzero(state->nfc_dev_data, sizeof(NfcDeviceData));
/* deinit devices */
radio_device_loader_end(state->subghz_device);
subghz_devices_deinit();
/* exit suppress charge mode */

View File

@@ -18,8 +18,8 @@
#include "crypto_wrapper.h"
#include "scenes/esubghz_chat_scene.h"
#include <assets_icons.h>
#include "esubghz_chat_icons.h"
#include <assets_icons.h>
#define APPLICATION_NAME "ESubGhzChat"

View File

@@ -0,0 +1,25 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#define NFC_MAX_BYTES 256
#define NFC_CONFIG_PAGES 4
struct FreqNfcEntry {
uint32_t frequency;
uint32_t unused1;
uint32_t unused2;
uint32_t unused3;
} __attribute__((packed));
struct ReplayDictNfcEntry {
uint64_t run_id;
uint32_t counter;
uint32_t unused;
} __attribute__((packed));
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,65 @@
#include "radio_device_loader.h"
#include <applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h>
#include <lib/subghz/devices/cc1101_int/cc1101_int_interconnect.h>
static void radio_device_loader_power_on() {
uint8_t attempts = 0;
while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) {
furi_hal_power_enable_otg();
//CC1101 power-up time
furi_delay_ms(10);
}
}
static void radio_device_loader_power_off() {
if(furi_hal_power_is_otg_enabled()) furi_hal_power_disable_otg();
}
bool radio_device_loader_is_connect_external(const char* name) {
bool is_connect = false;
bool is_otg_enabled = furi_hal_power_is_otg_enabled();
if(!is_otg_enabled) {
radio_device_loader_power_on();
}
const SubGhzDevice* device = subghz_devices_get_by_name(name);
if(device) {
is_connect = subghz_devices_is_connect(device);
}
if(!is_otg_enabled) {
radio_device_loader_power_off();
}
return is_connect;
}
const SubGhzDevice* radio_device_loader_set(
const SubGhzDevice* current_radio_device,
SubGhzRadioDeviceType radio_device_type) {
const SubGhzDevice* radio_device;
if(radio_device_type == SubGhzRadioDeviceTypeExternalCC1101 &&
radio_device_loader_is_connect_external(SUBGHZ_DEVICE_CC1101_EXT_NAME)) {
radio_device_loader_power_on();
radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_EXT_NAME);
subghz_devices_begin(radio_device);
} else if(current_radio_device == NULL) {
radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME);
} else {
radio_device_loader_end(current_radio_device);
radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME);
}
return radio_device;
}
void radio_device_loader_end(const SubGhzDevice* radio_device) {
furi_assert(radio_device);
radio_device_loader_power_off();
// Code below is not used (and will cause crash) since its called from tx_rx worker end!
//if(radio_device != subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME)) {
// subghz_devices_end(radio_device);
//}
}

View File

@@ -0,0 +1,15 @@
#pragma once
#include <lib/subghz/devices/devices.h>
/** SubGhzRadioDeviceType */
typedef enum {
SubGhzRadioDeviceTypeInternal,
SubGhzRadioDeviceTypeExternalCC1101,
} SubGhzRadioDeviceType;
const SubGhzDevice* radio_device_loader_set(
const SubGhzDevice* current_radio_device,
SubGhzRadioDeviceType radio_device_type);
void radio_device_loader_end(const SubGhzDevice* radio_device);

View File

@@ -1,12 +1,11 @@
#include "../esubghz_chat_i.h"
/* Sends FreqEntered event to scene manager and displays the frequency in the
* text box. */
/* Sends FreqEntered event to scene manager and enters the chat. */
static void freq_input_cb(void* context) {
furi_assert(context);
ESubGhzChatState* state = context;
furi_string_cat_printf(state->chat_box_store, "Frequency: %lu", state->frequency);
enter_chat(state);
view_dispatcher_send_custom_event(state->view_dispatcher, ESubGhzChatEvent_FreqEntered);
}
@@ -49,7 +48,7 @@ void scene_on_enter_freq_input(void* context) {
furi_assert(context);
ESubGhzChatState* state = context;
snprintf(state->text_input_store, TEXT_INPUT_STORE_SIZE, "%lu", (uint32_t)DEFAULT_FREQ);
snprintf(state->text_input_store, TEXT_INPUT_STORE_SIZE, "%lu", state->frequency);
text_input_reset(state->text_input);
text_input_set_result_callback(
state->text_input,
@@ -76,9 +75,9 @@ bool scene_on_event_freq_input(void* context, SceneManagerEvent event) {
switch(event.type) {
case SceneManagerEventTypeCustom:
switch(event.event) {
/* switch to password input scene */
/* switch to message input scene */
case ESubGhzChatEvent_FreqEntered:
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_KeyMenu);
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_ChatInput);
consumed = true;
break;
}

View File

@@ -1,7 +1,7 @@
#include "../esubghz_chat_i.h"
/* Sets the entered bytes as the key, enters the chat and sends a HexKeyEntered
* event to the scene manager. */
/* Sets the entered bytes as the key and sends a HexKeyEntered event to the
* scene manager. */
static void hex_key_input_cb(void* context) {
furi_assert(context);
ESubGhzChatState* state = context;
@@ -20,8 +20,6 @@ static void hex_key_input_cb(void* context) {
state->encrypted = true;
enter_chat(state);
view_dispatcher_send_custom_event(state->view_dispatcher, ESubGhzChatEvent_HexKeyEntered);
}
@@ -55,9 +53,9 @@ bool scene_on_event_hex_key_input(void* context, SceneManagerEvent event) {
switch(event.type) {
case SceneManagerEventTypeCustom:
switch(event.event) {
/* switch to message input scene */
/* switch to frequency input scene */
case ESubGhzChatEvent_HexKeyEntered:
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_ChatInput);
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_FreqInput);
consumed = true;
break;
}

View File

@@ -17,7 +17,6 @@ static void key_menu_cb(void* context, uint32_t index) {
switch(index) {
case ESubGhzChatKeyMenuItems_NoEncryption:
state->encrypted = false;
enter_chat(state);
view_dispatcher_send_custom_event(
state->view_dispatcher, ESubGhzChatEvent_KeyMenuNoEncryption);
@@ -49,7 +48,6 @@ static void key_menu_cb(void* context, uint32_t index) {
/* set encrypted flag and enter the chat */
state->encrypted = true;
enter_chat(state);
view_dispatcher_send_custom_event(state->view_dispatcher, ESubGhzChatEvent_KeyMenuGenKey);
break;
@@ -73,33 +71,37 @@ void scene_on_enter_key_menu(void* context) {
menu_reset(state->menu);
/* clear the crypto CTX in case we got back from password or hex key
* input */
crypto_ctx_clear(state->crypto_ctx);
menu_add_item(
state->menu,
"No encryption",
&I_chat_10px,
&I_chat_14px,
ESubGhzChatKeyMenuItems_NoEncryption,
key_menu_cb,
state);
menu_add_item(
state->menu,
"Password",
&I_keyboard_10px,
&I_keyboard_14px,
ESubGhzChatKeyMenuItems_Password,
key_menu_cb,
state);
menu_add_item(
state->menu, "Hex Key", &I_hex_10px, ESubGhzChatKeyMenuItems_HexKey, key_menu_cb, state);
state->menu, "Hex Key", &I_hex_14px, ESubGhzChatKeyMenuItems_HexKey, key_menu_cb, state);
menu_add_item(
state->menu,
"Generate Key",
&I_u2f_10px,
&I_u2f_14px,
ESubGhzChatKeyMenuItems_GenKey,
key_menu_cb,
state);
menu_add_item(
state->menu,
"Read Key from NFC",
&I_Nfc_10px,
&I_Nfc_14px,
ESubGhzChatKeyMenuItems_ReadKeyFromNfc,
key_menu_cb,
state);
@@ -119,10 +121,10 @@ bool scene_on_event_key_menu(void* context, SceneManagerEvent event) {
switch(event.type) {
case SceneManagerEventTypeCustom:
switch(event.event) {
/* switch to message input scene */
/* switch to frequency input scene */
case ESubGhzChatEvent_KeyMenuNoEncryption:
case ESubGhzChatEvent_KeyMenuGenKey:
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_ChatInput);
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_FreqInput);
consumed = true;
break;

View File

@@ -1,4 +1,5 @@
#include "../esubghz_chat_i.h"
#include "../helpers/nfc_helpers.h"
typedef enum {
KeyReadPopupState_Idle,
@@ -28,18 +29,46 @@ static void key_read_popup_timeout_cb(void* context) {
if(cur_state == KeyReadPopupState_Fail) {
view_dispatcher_send_custom_event(
state->view_dispatcher, ESubGhzChatEvent_KeyReadPopupFailed);
/* done displaying our success, enter chat */
/* done displaying our success */
} else if(cur_state == KeyReadPopupState_Success) {
enter_chat(state);
view_dispatcher_send_custom_event(
state->view_dispatcher, ESubGhzChatEvent_KeyReadPopupSucceeded);
}
}
struct ReplayDictNfcReaderContext {
uint8_t* cur;
uint8_t* max;
};
static bool replay_dict_nfc_reader(uint64_t* run_id, uint32_t* counter, void* context) {
struct ReplayDictNfcReaderContext* ctx = (struct ReplayDictNfcReaderContext*)context;
if(ctx->cur + sizeof(struct ReplayDictNfcEntry) > ctx->max) {
return false;
}
struct ReplayDictNfcEntry* entry = (struct ReplayDictNfcEntry*)ctx->cur;
*run_id = entry->run_id;
*counter = __ntohl(entry->counter);
ctx->cur += sizeof(struct ReplayDictNfcEntry);
return true;
}
static bool key_read_popup_handle_key_read(ESubGhzChatState* state) {
NfcDeviceData* dev_data = state->nfc_dev_data;
if(dev_data->mf_ul_data.data_read < KEY_BITS / 8) {
/* check for config pages */
if(dev_data->mf_ul_data.data_read < NFC_CONFIG_PAGES * 4) {
return false;
}
size_t data_read = dev_data->mf_ul_data.data_read - (NFC_CONFIG_PAGES * 4);
/* check if key was transmitted */
if(data_read < KEY_BITS / 8) {
return false;
}
@@ -55,6 +84,21 @@ static bool key_read_popup_handle_key_read(ESubGhzChatState* state) {
return false;
}
/* read the frequency */
if(data_read >= (KEY_BITS / 8) + sizeof(struct FreqNfcEntry)) {
struct FreqNfcEntry* freq_entry =
(struct FreqNfcEntry*)(dev_data->mf_ul_data.data + (KEY_BITS / 8));
state->frequency = __ntohl(freq_entry->frequency);
}
/* read the replay dict */
struct ReplayDictNfcReaderContext rd_ctx = {
.cur = dev_data->mf_ul_data.data + (KEY_BITS / 8) + sizeof(struct FreqNfcEntry),
.max =
dev_data->mf_ul_data.data + (data_read < NFC_MAX_BYTES ? data_read : NFC_MAX_BYTES)};
crypto_ctx_read_replay_dict(state->crypto_ctx, replay_dict_nfc_reader, &rd_ctx);
/* set encrypted flag */
state->encrypted = true;
@@ -183,9 +227,9 @@ bool scene_on_event_key_read_popup(void* context, SceneManagerEvent event) {
consumed = true;
break;
/* success, go to chat input */
/* success, go to frequency input */
case ESubGhzChatEvent_KeyReadPopupSucceeded:
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_ChatInput);
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_FreqInput);
consumed = true;
break;

View File

@@ -1,4 +1,25 @@
#include "../esubghz_chat_i.h"
#include "../helpers/nfc_helpers.h"
struct ReplayDictNfcWriterContext {
uint8_t* cur;
uint8_t* max;
};
static bool replay_dict_nfc_writer(uint64_t run_id, uint32_t counter, void* context) {
struct ReplayDictNfcWriterContext* ctx = (struct ReplayDictNfcWriterContext*)context;
struct ReplayDictNfcEntry entry = {.run_id = run_id, .counter = __htonl(counter), .unused = 0};
if(ctx->cur + sizeof(entry) > ctx->max) {
return false;
}
memcpy(ctx->cur, &entry, sizeof(entry));
ctx->cur += sizeof(entry);
return true;
}
static void prepare_nfc_dev_data(ESubGhzChatState* state) {
NfcDeviceData* dev_data = state->nfc_dev_data;
@@ -20,9 +41,32 @@ static void prepare_nfc_dev_data(ESubGhzChatState* state) {
dev_data->mf_ul_data.version.storage_size = 0x11;
dev_data->mf_ul_data.version.protocol_type = 0x03;
/* Add 16 to the size for config pages */
dev_data->mf_ul_data.data_size = (KEY_BITS / 8) + 16;
size_t data_written = 0;
/* write key */
crypto_ctx_get_key(state->crypto_ctx, dev_data->mf_ul_data.data);
data_written += (KEY_BITS / 8);
/* write frequency */
struct FreqNfcEntry* freq_entry =
(struct FreqNfcEntry*)(dev_data->mf_ul_data.data + data_written);
freq_entry->frequency = __htonl(state->frequency);
freq_entry->unused1 = 0;
freq_entry->unused2 = 0;
freq_entry->unused3 = 0;
data_written += sizeof(struct FreqNfcEntry);
/* write the replay dict */
struct ReplayDictNfcWriterContext wr_ctx = {
.cur = dev_data->mf_ul_data.data + data_written,
.max = dev_data->mf_ul_data.data + NFC_MAX_BYTES};
size_t n_entries =
crypto_ctx_dump_replay_dict(state->crypto_ctx, replay_dict_nfc_writer, &wr_ctx);
data_written += n_entries * sizeof(struct ReplayDictNfcEntry);
/* calculate size of data, add 16 for config pages */
dev_data->mf_ul_data.data_size = data_written + (NFC_CONFIG_PAGES * 4);
}
/* Prepares the key share popup scene. */

View File

@@ -1,14 +1,12 @@
#include "../esubghz_chat_i.h"
/* Sends PassEntered event to scene manager and enters the chat. */
/* Sends PassEntered event to scene manager. */
static void pass_input_cb(void* context) {
furi_assert(context);
ESubGhzChatState* state = context;
crypto_explicit_bzero(state->text_input_store, sizeof(state->text_input_store));
enter_chat(state);
view_dispatcher_send_custom_event(state->view_dispatcher, ESubGhzChatEvent_PassEntered);
}
@@ -83,9 +81,9 @@ bool scene_on_event_pass_input(void* context, SceneManagerEvent event) {
switch(event.type) {
case SceneManagerEventTypeCustom:
switch(event.event) {
/* switch to message input scene */
/* switch to frequency input scene */
case ESubGhzChatEvent_PassEntered:
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_ChatInput);
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_FreqInput);
consumed = true;
break;
}

View File

@@ -6,7 +6,6 @@ App(
cdefines=["APP_ETCH_A_SKETCH"],
requires=["gui"],
stack_size=2 * 1024,
order=175,
fap_icon="etch-a-sketch-icon.png",
fap_category="Media",
fap_icon_assets="assets",

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 bigbrodude6119
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -6,7 +6,9 @@ App(
cdefines=["APP_EVIL_PORTAL"],
requires=["gui"],
stack_size=1 * 1024,
order=90,
fap_author="bigbrodude6119",
fap_description="Create an evil captive portal Wi-Fi access point",
fap_icon_assets="icons",
fap_icon="icons/evil_portal_10px.png",
fap_category="WiFi",
)

View File

@@ -32,10 +32,15 @@ Evil_PortalApp* evil_portal_app_alloc() {
app->command_index = 0;
app->portal_logs = furi_string_alloc();
app->gui = furi_record_open(RECORD_GUI);
app->dialogs = furi_record_open(RECORD_DIALOGS);
app->file_path = furi_string_alloc();
app->gui = furi_record_open(RECORD_GUI);
app->view_dispatcher = view_dispatcher_alloc();
app->loading = loading_alloc();
app->scene_manager = scene_manager_alloc(&evil_portal_scene_handlers, app);
view_dispatcher_enable_queue(app->view_dispatcher);
view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
@@ -49,12 +54,18 @@ Evil_PortalApp* evil_portal_app_alloc() {
view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
app->view_stack = view_stack_alloc();
app->var_item_list = variable_item_list_alloc();
view_dispatcher_add_view(
app->view_dispatcher,
Evil_PortalAppViewVarItemList,
variable_item_list_get_view(app->var_item_list));
app->text_input = text_input_alloc();
view_dispatcher_add_view(
app->view_dispatcher, Evil_PortalAppViewTextInput, text_input_get_view(app->text_input));
for(int i = 0; i < NUM_MENU_ITEMS; ++i) {
app->selected_option_index[i] = 0;
}
@@ -89,6 +100,10 @@ void evil_portal_app_free(Evil_PortalApp* app) {
text_box_free(app->text_box);
furi_string_free(app->text_box_store);
text_input_free(app->text_input);
view_stack_free(app->view_stack);
loading_free(app->loading);
// View dispatcher
view_dispatcher_free(app->view_dispatcher);
@@ -98,36 +113,32 @@ void evil_portal_app_free(Evil_PortalApp* app) {
// Close records
furi_record_close(RECORD_GUI);
furi_record_close(RECORD_DIALOGS);
furi_string_free(app->file_path);
free(app);
}
int32_t evil_portal_app(void* p) {
UNUSED(p);
Evil_PortalApp* evil_portal_app = evil_portal_app_alloc();
// turn off 5v, so it gets reset on startup
if(furi_hal_power_is_otg_enabled()) {
furi_hal_power_disable_otg();
}
// Enable 5v on startup
uint8_t attempts = 0;
bool otg_was_enabled = furi_hal_power_is_otg_enabled();
while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) {
furi_hal_power_enable_otg();
furi_delay_ms(10);
}
furi_delay_ms(200);
Evil_PortalApp* evil_portal_app = evil_portal_app_alloc();
evil_portal_app->uart = evil_portal_uart_init(evil_portal_app);
view_dispatcher_run(evil_portal_app->view_dispatcher);
evil_portal_app_free(evil_portal_app);
if(furi_hal_power_is_otg_enabled()) {
if(furi_hal_power_is_otg_enabled() && !otg_was_enabled) {
furi_hal_power_disable_otg();
}

View File

@@ -8,4 +8,4 @@ typedef struct Evil_PortalApp Evil_PortalApp;
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -4,19 +4,22 @@
#include "evil_portal_custom_event.h"
#include "evil_portal_uart.h"
#include "scenes/evil_portal_scene.h"
#include "evil_portal_icons.h"
#include <assets_icons.h>
#include <gui/gui.h>
#include <gui/modules/loading.h>
#include <gui/modules/text_box.h>
#include <gui/modules/text_input.h>
#include <gui/modules/variable_item_list.h>
#include <gui/scene_manager.h>
#include <gui/view_dispatcher.h>
#include <assets_icons.h>
#include <gui/view_stack.h>
#include <dialogs/dialogs.h>
#include <xtreme.h>
#define NUM_MENU_ITEMS (4)
#define NUM_MENU_ITEMS (6)
#define EVIL_PORTAL_TEXT_BOX_STORE_SIZE (4096)
#define UART_CH \
@@ -27,14 +30,13 @@
#define SET_AP_CMD "setap"
#define RESET_CMD "reset"
#define EVIL_PORTAL_INDEX_EXTENSION ".html"
#define EVIL_PORTAL_BASE_FOLDER STORAGE_APP_DATA_PATH_PREFIX
#define HTML_EXTENSION ".html"
#define HTML_FOLDER APP_DATA_PATH("html")
struct Evil_PortalApp {
Gui* gui;
ViewDispatcher* view_dispatcher;
SceneManager* scene_manager;
DialogsApp* dialogs;
FuriString* portal_logs;
const char* command_queue[1];
@@ -47,6 +49,11 @@ struct Evil_PortalApp {
VariableItemList* var_item_list;
Evil_PortalUart* uart;
TextInput* text_input;
DialogsApp* dialogs;
FuriString* file_path;
Loading* loading;
ViewStack* view_stack;
int selected_menu_index;
int selected_option_index[NUM_MENU_ITEMS];
@@ -59,6 +66,7 @@ struct Evil_PortalApp {
bool sent_html;
bool sent_reset;
int BAUDRATE;
char text_store[2][128 + 1];
uint8_t* index_html;
uint8_t* ap_name;
@@ -68,4 +76,5 @@ typedef enum {
Evil_PortalAppViewVarItemList,
Evil_PortalAppViewConsoleOutput,
Evil_PortalAppViewStartPortal,
Evil_PortalAppViewTextInput,
} Evil_PortalAppView;

View File

@@ -5,4 +5,5 @@ typedef enum {
Evil_PortalEventStartConsole,
Evil_PortalEventStartKeyboard,
Evil_PortalEventStartPortal,
Evil_PortalEventTextInput,
} Evil_PortalCustomEvent;

View File

@@ -8,31 +8,21 @@ static void evil_portal_close_storage() {
furi_record_close(RECORD_STORAGE);
}
bool evil_portal_read_index_html(void* context) {
FuriString* file_path = furi_string_alloc_set(EVIL_PORTAL_BASE_FOLDER);
DialogsFileBrowserOptions browser_options;
dialog_file_browser_set_basic_options(
&browser_options,
EVIL_PORTAL_INDEX_EXTENSION,
NULL); // TODO configure icon
browser_options.base_path = EVIL_PORTAL_BASE_FOLDER;
void evil_portal_read_index_html(void* context) {
Evil_PortalApp* app = context;
bool res = dialog_file_browser_show(app->dialogs, file_path, file_path, &browser_options);
if(!res) {
furi_string_free(file_path);
return false;
}
Storage* storage = evil_portal_open_storage();
FileInfo fi;
if(storage_common_stat(storage, furi_string_get_cstr(file_path), &fi) == FSE_OK) {
if(!storage_common_exists(storage, EVIL_PORTAL_INDEX_SAVE_PATH)) {
FuriString* tmp = furi_string_alloc_set(EVIL_PORTAL_INDEX_DEFAULT_PATH);
evil_portal_replace_index_html(tmp);
furi_string_free(tmp);
}
if(storage_common_stat(storage, EVIL_PORTAL_INDEX_SAVE_PATH, &fi) == FSE_OK) {
File* index_html = storage_file_alloc(storage);
if(storage_file_open(
index_html, furi_string_get_cstr(file_path), FSAM_READ, FSOM_OPEN_EXISTING)) {
index_html, EVIL_PORTAL_INDEX_SAVE_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) {
app->index_html = malloc((size_t)fi.size);
uint8_t* buf_ptr = app->index_html;
size_t read = 0;
@@ -45,7 +35,6 @@ bool evil_portal_read_index_html(void* context) {
}
free(buf_ptr);
}
furi_string_free(file_path);
storage_file_close(index_html);
storage_file_free(index_html);
} else {
@@ -57,7 +46,33 @@ bool evil_portal_read_index_html(void* context) {
}
evil_portal_close_storage();
return true;
}
void evil_portal_replace_index_html(FuriString* path) {
Storage* storage = evil_portal_open_storage();
FS_Error error;
error = storage_common_remove(storage, EVIL_PORTAL_INDEX_SAVE_PATH);
if(error != FSE_OK) {
FURI_LOG_D("EVIL PORTAL", "Error removing file");
} else {
FURI_LOG_D("EVIL PORTAL", "Error removed file");
}
error = storage_common_copy(storage, furi_string_get_cstr(path), EVIL_PORTAL_INDEX_SAVE_PATH);
if(error != FSE_OK) {
FURI_LOG_D("EVIL PORTAL", "Error copying file");
}
evil_portal_close_storage();
}
void evil_portal_create_html_folder_if_not_exists() {
Storage* storage = evil_portal_open_storage();
if(storage_common_stat(storage, HTML_FOLDER, NULL) == FSE_NOT_EXIST) {
FURI_LOG_D("Evil Portal", "Directory %s doesn't exist. Will create new.", HTML_FOLDER);
if(!storage_simply_mkdir(storage, HTML_FOLDER)) {
FURI_LOG_E("Evil Portal", "Error creating directory %s", HTML_FOLDER);
}
}
evil_portal_close_storage();
}
void evil_portal_read_ap_name(void* context) {
@@ -89,6 +104,19 @@ void evil_portal_read_ap_name(void* context) {
evil_portal_close_storage();
}
void evil_portal_write_ap_name(void* context) {
Evil_PortalApp* app = context;
Storage* storage = evil_portal_open_storage();
File* ap_name = storage_file_alloc(storage);
if(storage_file_open(ap_name, EVIL_PORTAL_AP_SAVE_PATH, FSAM_WRITE, FSOM_CREATE_ALWAYS)) {
storage_file_write(ap_name, app->text_store[0], strlen(app->text_store[0]));
}
storage_file_close(ap_name);
storage_file_free(ap_name);
evil_portal_close_storage();
}
char* sequential_file_resolve_path(
Storage* storage,
const char* dir,

View File

@@ -1,5 +1,4 @@
#include "../evil_portal_app_i.h"
#include <dialogs/dialogs.h>
#include <flipper_format/flipper_format_i.h>
#include <lib/toolbox/stream/file_stream.h>
#include <stdlib.h>
@@ -8,11 +7,15 @@
#define PORTAL_FILE_DIRECTORY_PATH EXT_PATH("apps_data/evil_portal")
#define EVIL_PORTAL_INDEX_SAVE_PATH PORTAL_FILE_DIRECTORY_PATH "/index.html"
#define EVIL_PORTAL_INDEX_DEFAULT_PATH PORTAL_FILE_DIRECTORY_PATH "/html/xtreme.html"
#define EVIL_PORTAL_AP_SAVE_PATH PORTAL_FILE_DIRECTORY_PATH "/ap.config.txt"
#define EVIL_PORTAL_LOG_SAVE_PATH PORTAL_FILE_DIRECTORY_PATH "/logs"
bool evil_portal_read_index_html(void* context);
void evil_portal_read_index_html(void* context);
void evil_portal_read_ap_name(void* context);
void evil_portal_write_ap_name(void* context);
void evil_portal_replace_index_html(FuriString* path);
void evil_portal_create_html_folder_if_not_exists();
void write_logs(FuriString* portal_logs);
char* sequential_file_resolve_path(
Storage* storage,

View File

@@ -1,2 +1,4 @@
ADD_SCENE(evil_portal, start, Start)
ADD_SCENE(evil_portal, console_output, ConsoleOutput)
ADD_SCENE(evil_portal, rename, Rename)
ADD_SCENE(evil_portal, select_html, SelectHtml)

View File

@@ -22,8 +22,6 @@ void evil_portal_console_output_handle_rx_data_cb(uint8_t* buf, size_t len, void
void evil_portal_scene_console_output_on_enter(void* context) {
Evil_PortalApp* app = context;
bool portal_file_set = false;
TextBox* text_box = app->text_box;
text_box_reset(app->text_box);
text_box_set_font(text_box, TextBoxFontText);
@@ -64,25 +62,24 @@ void evil_portal_scene_console_output_on_enter(void* context) {
}
}
if(0 == strncmp(SET_HTML_CMD, app->selected_tx_string, strlen(SET_HTML_CMD))) {
portal_file_set = evil_portal_read_index_html(context);
if(0 == strncmp("setapname", app->selected_tx_string, strlen("setapname"))) {
scene_manager_next_scene(app->scene_manager, Evil_PortalSceneRename);
return;
}
if(portal_file_set) {
app->command_queue[0] = SET_AP_CMD;
app->has_command_queue = true;
app->command_index = 0;
if(app->show_stopscan_tip) {
const char* msg = "Starting portal\nIf no response press\nBACK to return\n";
furi_string_cat_str(app->text_box_store, msg);
app->text_box_store_strlen += strlen(msg);
}
} else {
if(app->show_stopscan_tip) {
const char* msg = "No portal selected\nShowing current logs\nPress "
"BACK to return\n";
furi_string_cat_str(app->text_box_store, msg);
app->text_box_store_strlen += strlen(msg);
}
if(0 == strncmp("selecthtml", app->selected_tx_string, strlen("selecthtml"))) {
scene_manager_next_scene(app->scene_manager, Evil_PortalSceneSelectHtml);
return;
}
if(0 == strncmp(SET_HTML_CMD, app->selected_tx_string, strlen(SET_HTML_CMD))) {
app->command_queue[0] = SET_AP_CMD;
app->has_command_queue = true;
app->command_index = 0;
if(app->show_stopscan_tip) {
const char* msg = "Starting portal\nIf no response press\nBACK to return\n";
furi_string_cat_str(app->text_box_store, msg);
app->text_box_store_strlen += strlen(msg);
}
}
@@ -107,13 +104,7 @@ void evil_portal_scene_console_output_on_enter(void* context) {
if(app->is_command && app->selected_tx_string) {
if(0 == strncmp(SET_HTML_CMD, app->selected_tx_string, strlen(SET_HTML_CMD))) {
if(!portal_file_set) {
scene_manager_set_scene_state(
app->scene_manager, Evil_PortalSceneConsoleOutput, 0);
view_dispatcher_switch_to_view(
app->view_dispatcher, Evil_PortalAppViewConsoleOutput);
return;
}
evil_portal_read_index_html(context);
FuriString* data = furi_string_alloc();
furi_string_cat(data, "sethtml=");

View File

@@ -0,0 +1,42 @@
#include "../evil_portal_app_i.h"
#include "../helpers/evil_portal_storage.h"
void evil_portal_text_input_callback(void* context) {
furi_assert(context);
Evil_PortalApp* app = context;
view_dispatcher_send_custom_event(app->view_dispatcher, Evil_PortalEventTextInput);
}
void evil_portal_scene_rename_on_enter(void* context) {
Evil_PortalApp* app = context;
TextInput* text_input = app->text_input;
size_t enter_name_length = 25;
evil_portal_read_ap_name(app);
text_input_set_header_text(text_input, "AP Name/SSID");
strncpy(app->text_store[0], (char*)app->ap_name, enter_name_length);
text_input_set_result_callback(
text_input,
evil_portal_text_input_callback,
context,
app->text_store[0],
enter_name_length,
false);
view_dispatcher_switch_to_view(app->view_dispatcher, Evil_PortalAppViewTextInput);
}
bool evil_portal_scene_rename_on_event(void* context, SceneManagerEvent event) {
Evil_PortalApp* app = context;
SceneManager* scene_manager = app->scene_manager;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
evil_portal_write_ap_name(app);
scene_manager_search_and_switch_to_previous_scene(scene_manager, Evil_PortalSceneStart);
consumed = true;
}
return consumed;
}
void evil_portal_scene_rename_on_exit(void* context) {
Evil_PortalApp* app = context;
variable_item_list_reset(app->var_item_list);
}

View File

@@ -0,0 +1,54 @@
#include "../evil_portal_app_i.h"
#include "../helpers/evil_portal_storage.h"
void evil_portal_show_loading_popup(Evil_PortalApp* app, bool show) {
TaskHandle_t timer_task = xTaskGetHandle(configTIMER_SERVICE_TASK_NAME);
ViewStack* view_stack = app->view_stack;
Loading* loading = app->loading;
if(show) {
// Raise timer priority so that animations can play
vTaskPrioritySet(timer_task, configMAX_PRIORITIES - 1);
view_stack_add_view(view_stack, loading_get_view(loading));
} else {
view_stack_remove_view(view_stack, loading_get_view(loading));
// Restore default timer priority
vTaskPrioritySet(timer_task, configTIMER_TASK_PRIORITY);
}
}
void evil_portal_scene_select_html_on_enter(void* context) {
Evil_PortalApp* app = context;
DialogsFileBrowserOptions browser_options;
evil_portal_create_html_folder_if_not_exists();
dialog_file_browser_set_basic_options(&browser_options, HTML_EXTENSION, &I_evil_portal_10px);
browser_options.base_path = HTML_FOLDER;
FuriString* path;
path = furi_string_alloc();
furi_string_set(path, HTML_FOLDER);
bool success = dialog_file_browser_show(app->dialogs, app->file_path, path, &browser_options);
furi_string_free(path);
if(success) {
//Replace HTML File
evil_portal_show_loading_popup(app, true);
evil_portal_replace_index_html(app->file_path);
evil_portal_show_loading_popup(app, false);
}
scene_manager_search_and_switch_to_previous_scene(app->scene_manager, Evil_PortalSceneStart);
}
bool evil_portal_scene_select_html_on_event(void* context, SceneManagerEvent event) {
UNUSED(context);
UNUSED(event);
bool consumed = true;
return consumed;
}
void evil_portal_scene_select_html_on_exit(void* context) {
UNUSED(context);
}

View File

@@ -33,6 +33,12 @@ const Evil_PortalItem items[NUM_MENU_ITEMS] = {
// console
{"Save logs", {""}, 1, {"savelogs"}, NO_ARGS, FOCUS_CONSOLE_START, SHOW_STOPSCAN_TIP},
// set AP name
{"Set AP name", {""}, 1, {"setapname"}, NO_ARGS, FOCUS_CONSOLE_START, SHOW_STOPSCAN_TIP},
// select HTML Portal File
{"Select HTML", {""}, 1, {"selecthtml"}, NO_ARGS, FOCUS_CONSOLE_START, SHOW_STOPSCAN_TIP},
// help
{"Help", {""}, 1, {"help"}, NO_ARGS, FOCUS_CONSOLE_START, SHOW_STOPSCAN_TIP},
};

View File

@@ -5,7 +5,6 @@ App(
entry_point="flappy_game_app",
requires=["gui"],
stack_size=4 * 1024,
order=100,
fap_icon="flappy_10px.png",
fap_category="Games",
fap_icon_assets="assets",

View File

@@ -1,9 +1,11 @@
#include <stdlib.h>
#include <flappy_bird_icons.h>
#include "flappy_bird_icons.h"
#include <assets_icons.h>
#include <furi.h>
#include <gui/gui.h>
#include <input/input.h>
#include <dolphin/dolphin.h>
#define TAG "Flappy"
#define DEBUG false
@@ -311,6 +313,9 @@ int32_t flappy_game_app(void* p) {
Gui* gui = furi_record_open(RECORD_GUI);
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
// Call dolphin deed on game start
dolphin_deed(DolphinDeedPluginGameStart);
GameEvent event;
for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);

View File

@@ -8,7 +8,6 @@ App(
"gui",
],
stack_size=2 * 1024,
order=20,
fap_icon="flash10px.png",
fap_category="GPIO",
fap_author="@xMasterX",

View File

@@ -7,7 +7,6 @@ App(
"gui",
],
stack_size=3 * 1024,
order=10,
fap_icon="flipbip_10px.png",
fap_private_libs=[
Lib(

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@@ -5,7 +5,6 @@ App(
entry_point="i2ctools_app",
requires=["gui"],
stack_size=2 * 1024,
order=175,
fap_icon="i2ctools.png",
fap_category="GPIO",
fap_icon_assets="images",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 294 B

View File

@@ -1,7 +1,8 @@
#include <furi.h>
#include <furi_hal.h>
#include <gui/gui.h>
#include <i2ctools_icons.h>
#include "i2ctools_icons.h"
#include <assets_icons.h>
#define INFOS_TEXT "INFOS"

View File

@@ -1,7 +1,7 @@
#include <furi.h>
#include <furi_hal.h>
#include <gui/gui.h>
#include <i2ctools_icons.h>
#include "i2ctools_icons.h"
#include <assets_icons.h>
#define APP_NAME "I2C Tools"
@@ -41,4 +41,4 @@ typedef struct {
void draw_main_view(Canvas* canvas, i2cMainView* main_view);
i2cMainView* i2c_main_view_alloc();
void i2c_main_view_free(i2cMainView* main_view);
void i2c_main_view_free(i2cMainView* main_view);

View File

@@ -1,10 +1,10 @@
#include <furi.h>
#include <furi_hal.h>
#include <gui/gui.h>
#include <i2ctools_icons.h>
#include "i2ctools_icons.h"
#include <assets_icons.h>
#include "../i2cscanner.h"
#define SCAN_TEXT "SCAN"
void draw_scanner_view(Canvas* canvas, i2cScanner* i2c_scanner);
void draw_scanner_view(Canvas* canvas, i2cScanner* i2c_scanner);

View File

@@ -1,10 +1,10 @@
#include <furi.h>
#include <furi_hal.h>
#include <gui/gui.h>
#include <i2ctools_icons.h>
#include "i2ctools_icons.h"
#include <assets_icons.h>
#include "../i2csender.h"
#define SEND_TEXT "SEND"
void draw_sender_view(Canvas* canvas, i2cSender* i2c_sender);
void draw_sender_view(Canvas* canvas, i2cSender* i2c_sender);

View File

@@ -1,10 +1,10 @@
#include <furi.h>
#include <furi_hal.h>
#include <gui/gui.h>
#include <i2ctools_icons.h>
#include "i2ctools_icons.h"
#include <assets_icons.h>
#include "../i2csniffer.h"
#define SNIFF_TEXT "SNIFF"
void draw_sniffer_view(Canvas* canvas, i2cSniffer* i2c_sniffer);
void draw_sniffer_view(Canvas* canvas, i2cSniffer* i2c_sniffer);

View File

@@ -5,7 +5,6 @@ App(
entry_point="flizzer_tracker_app",
cdefines=["APP_FLIZZER_TRACKER"],
stack_size=2 * 1024,
order=90,
fap_version=(0, 2),
fap_description="An advanced Flipper Zero chiptune tracker with 4 channels",
fap_author="LTVA",

View File

@@ -7,7 +7,8 @@
#include "view/pattern_editor.h"
#include "font.h"
#include <flizzer_tracker_icons.h>
#include "flizzer_tracker_icons.h"
#include <assets_icons.h>
void draw_callback(Canvas* canvas, void* ctx) {
TrackerViewModel* model = (TrackerViewModel*)ctx;

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