Skip to content

Commit 3683bf4

Browse files
authored
Merge branch 'dev' into fix-subghz-cli-repeat-parsing
2 parents af371c3 + 04fa7a9 commit 3683bf4

File tree

151 files changed

+3846
-341
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

151 files changed

+3846
-341
lines changed

.vscode/example/settings.json.tmpl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"SConstruct": "python",
1313
"*.fam": "python"
1414
},
15+
"clangd.checkUpdates": false,
1516
"clangd.path": "${workspaceFolder}/toolchain/current/bin/clangd@FBT_PLATFORM_EXECUTABLE_EXT@",
1617
"clangd.arguments": [
1718
"--query-driver=**/arm-none-eabi-*",

applications/debug/unit_tests/resources/unit_tests/js/basic.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ tests.assert_eq(false, doesSdkSupport(["abobus", "other-nonexistent-feature"]));
1212

1313
tests.assert_eq("flipperdevices", flipper.firmwareVendor);
1414
tests.assert_eq(0, flipper.jsSdkVersion[0]);
15-
tests.assert_eq(1, flipper.jsSdkVersion[1]);
15+
tests.assert_eq(2, flipper.jsSdkVersion[1]);

applications/debug/unit_tests/tests/furi/furi_event_loop_test.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,55 @@ static int32_t test_furi_event_loop_consumer(void* p) {
446446
return 0;
447447
}
448448

449+
typedef struct {
450+
FuriEventLoop* event_loop;
451+
FuriSemaphore* semaphore;
452+
size_t counter;
453+
} SelfUnsubTestTimerContext;
454+
455+
static void test_self_unsub_semaphore_callback(FuriEventLoopObject* object, void* context) {
456+
furi_event_loop_unsubscribe(context, object); // shouldn't crash here
457+
}
458+
459+
static void test_self_unsub_timer_callback(void* arg) {
460+
SelfUnsubTestTimerContext* context = arg;
461+
462+
if(context->counter == 0) {
463+
furi_semaphore_release(context->semaphore);
464+
} else if(context->counter == 1) {
465+
furi_event_loop_stop(context->event_loop);
466+
}
467+
468+
context->counter++;
469+
}
470+
471+
void test_furi_event_loop_self_unsubscribe(void) {
472+
FuriEventLoop* event_loop = furi_event_loop_alloc();
473+
474+
FuriSemaphore* semaphore = furi_semaphore_alloc(1, 0);
475+
furi_event_loop_subscribe_semaphore(
476+
event_loop,
477+
semaphore,
478+
FuriEventLoopEventIn,
479+
test_self_unsub_semaphore_callback,
480+
event_loop);
481+
482+
SelfUnsubTestTimerContext timer_context = {
483+
.event_loop = event_loop,
484+
.semaphore = semaphore,
485+
.counter = 0,
486+
};
487+
FuriEventLoopTimer* timer = furi_event_loop_timer_alloc(
488+
event_loop, test_self_unsub_timer_callback, FuriEventLoopTimerTypePeriodic, &timer_context);
489+
furi_event_loop_timer_start(timer, furi_ms_to_ticks(20));
490+
491+
furi_event_loop_run(event_loop);
492+
493+
furi_event_loop_timer_free(timer);
494+
furi_semaphore_free(semaphore);
495+
furi_event_loop_free(event_loop);
496+
}
497+
449498
void test_furi_event_loop(void) {
450499
TestFuriEventLoopData data = {};
451500

applications/debug/unit_tests/tests/furi/furi_test.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ void test_furi_concurrent_access(void);
88
void test_furi_pubsub(void);
99
void test_furi_memmgr(void);
1010
void test_furi_event_loop(void);
11+
void test_furi_event_loop_self_unsubscribe(void);
1112
void test_errno_saving(void);
1213
void test_furi_primitives(void);
1314
void test_stdin(void);
@@ -46,6 +47,10 @@ MU_TEST(mu_test_furi_event_loop) {
4647
test_furi_event_loop();
4748
}
4849

50+
MU_TEST(mu_test_furi_event_loop_self_unsubscribe) {
51+
test_furi_event_loop_self_unsubscribe();
52+
}
53+
4954
MU_TEST(mu_test_errno_saving) {
5055
test_errno_saving();
5156
}
@@ -68,6 +73,7 @@ MU_TEST_SUITE(test_suite) {
6873
MU_RUN_TEST(mu_test_furi_pubsub);
6974
MU_RUN_TEST(mu_test_furi_memmgr);
7075
MU_RUN_TEST(mu_test_furi_event_loop);
76+
MU_RUN_TEST(mu_test_furi_event_loop_self_unsubscribe);
7177
MU_RUN_TEST(mu_test_stdio);
7278
MU_RUN_TEST(mu_test_errno_saving);
7379
MU_RUN_TEST(mu_test_furi_primitives);

applications/debug/unit_tests/tests/nfc/nfc_test.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ static void mf_ultralight_reader_test(const char* path) {
262262
nfc_listener_start(mfu_listener, NULL, NULL);
263263

264264
MfUltralightData* mfu_data = mf_ultralight_alloc();
265-
MfUltralightError error = mf_ultralight_poller_sync_read_card(poller, mfu_data);
265+
MfUltralightError error = mf_ultralight_poller_sync_read_card(poller, mfu_data, NULL);
266266
mu_assert(error == MfUltralightErrorNone, "mf_ultralight_poller_sync_read_card() failed");
267267

268268
nfc_listener_stop(mfu_listener);
@@ -315,7 +315,7 @@ MU_TEST(ntag_213_locked_reader) {
315315
nfc_listener_start(mfu_listener, NULL, NULL);
316316

317317
MfUltralightData* mfu_data = mf_ultralight_alloc();
318-
MfUltralightError error = mf_ultralight_poller_sync_read_card(poller, mfu_data);
318+
MfUltralightError error = mf_ultralight_poller_sync_read_card(poller, mfu_data, NULL);
319319
mu_assert(error == MfUltralightErrorNone, "mf_ultralight_poller_sync_read_card() failed");
320320

321321
nfc_listener_stop(mfu_listener);
@@ -353,7 +353,7 @@ static void mf_ultralight_write(void) {
353353
MfUltralightData* mfu_data = mf_ultralight_alloc();
354354

355355
// Initial read
356-
MfUltralightError error = mf_ultralight_poller_sync_read_card(poller, mfu_data);
356+
MfUltralightError error = mf_ultralight_poller_sync_read_card(poller, mfu_data, NULL);
357357
mu_assert(error == MfUltralightErrorNone, "mf_ultralight_poller_sync_read_card() failed");
358358

359359
mu_assert(
@@ -371,7 +371,7 @@ static void mf_ultralight_write(void) {
371371
}
372372

373373
// Verification read
374-
error = mf_ultralight_poller_sync_read_card(poller, mfu_data);
374+
error = mf_ultralight_poller_sync_read_card(poller, mfu_data, NULL);
375375
mu_assert(error == MfUltralightErrorNone, "mf_ultralight_poller_sync_read_card() failed");
376376

377377
nfc_listener_stop(mfu_listener);

applications/main/bad_usb/helpers/bad_usb_hid.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,31 @@ bool hid_usb_kb_release(void* inst, uint16_t button) {
3737
return furi_hal_hid_kb_release(button);
3838
}
3939

40+
bool hid_usb_mouse_press(void* inst, uint8_t button) {
41+
UNUSED(inst);
42+
return furi_hal_hid_mouse_press(button);
43+
}
44+
45+
bool hid_usb_mouse_release(void* inst, uint8_t button) {
46+
UNUSED(inst);
47+
return furi_hal_hid_mouse_release(button);
48+
}
49+
50+
bool hid_usb_mouse_scroll(void* inst, int8_t delta) {
51+
UNUSED(inst);
52+
return furi_hal_hid_mouse_scroll(delta);
53+
}
54+
55+
bool hid_usb_mouse_move(void* inst, int8_t dx, int8_t dy) {
56+
UNUSED(inst);
57+
return furi_hal_hid_mouse_move(dx, dy);
58+
}
59+
60+
bool hid_usb_mouse_release_all(void* inst) {
61+
UNUSED(inst);
62+
return furi_hal_hid_mouse_release(0);
63+
}
64+
4065
bool hid_usb_consumer_press(void* inst, uint16_t button) {
4166
UNUSED(inst);
4267
return furi_hal_hid_consumer_key_press(button);
@@ -51,6 +76,7 @@ bool hid_usb_release_all(void* inst) {
5176
UNUSED(inst);
5277
bool state = furi_hal_hid_kb_release_all();
5378
state &= furi_hal_hid_consumer_key_release_all();
79+
state &= hid_usb_mouse_release_all(inst);
5480
return state;
5581
}
5682

@@ -67,6 +93,10 @@ static const BadUsbHidApi hid_api_usb = {
6793

6894
.kb_press = hid_usb_kb_press,
6995
.kb_release = hid_usb_kb_release,
96+
.mouse_press = hid_usb_mouse_press,
97+
.mouse_release = hid_usb_mouse_release,
98+
.mouse_scroll = hid_usb_mouse_scroll,
99+
.mouse_move = hid_usb_mouse_move,
70100
.consumer_press = hid_usb_consumer_press,
71101
.consumer_release = hid_usb_consumer_release,
72102
.release_all = hid_usb_release_all,
@@ -157,6 +187,27 @@ bool hid_ble_kb_release(void* inst, uint16_t button) {
157187
return ble_profile_hid_kb_release(ble_hid->profile, button);
158188
}
159189

190+
bool hid_ble_mouse_press(void* inst, uint8_t button) {
191+
BleHidInstance* ble_hid = inst;
192+
furi_assert(ble_hid);
193+
return ble_profile_hid_mouse_press(ble_hid->profile, button);
194+
}
195+
bool hid_ble_mouse_release(void* inst, uint8_t button) {
196+
BleHidInstance* ble_hid = inst;
197+
furi_assert(ble_hid);
198+
return ble_profile_hid_mouse_release(ble_hid->profile, button);
199+
}
200+
bool hid_ble_mouse_scroll(void* inst, int8_t delta) {
201+
BleHidInstance* ble_hid = inst;
202+
furi_assert(ble_hid);
203+
return ble_profile_hid_mouse_scroll(ble_hid->profile, delta);
204+
}
205+
bool hid_ble_mouse_move(void* inst, int8_t dx, int8_t dy) {
206+
BleHidInstance* ble_hid = inst;
207+
furi_assert(ble_hid);
208+
return ble_profile_hid_mouse_move(ble_hid->profile, dx, dy);
209+
}
210+
160211
bool hid_ble_consumer_press(void* inst, uint16_t button) {
161212
BleHidInstance* ble_hid = inst;
162213
furi_assert(ble_hid);
@@ -174,6 +225,7 @@ bool hid_ble_release_all(void* inst) {
174225
furi_assert(ble_hid);
175226
bool state = ble_profile_hid_kb_release_all(ble_hid->profile);
176227
state &= ble_profile_hid_consumer_key_release_all(ble_hid->profile);
228+
state &= ble_profile_hid_mouse_release_all(ble_hid->profile);
177229
return state;
178230
}
179231

@@ -191,6 +243,10 @@ static const BadUsbHidApi hid_api_ble = {
191243

192244
.kb_press = hid_ble_kb_press,
193245
.kb_release = hid_ble_kb_release,
246+
.mouse_press = hid_ble_mouse_press,
247+
.mouse_release = hid_ble_mouse_release,
248+
.mouse_scroll = hid_ble_mouse_scroll,
249+
.mouse_move = hid_ble_mouse_move,
194250
.consumer_press = hid_ble_consumer_press,
195251
.consumer_release = hid_ble_consumer_release,
196252
.release_all = hid_ble_release_all,

applications/main/bad_usb/helpers/bad_usb_hid.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ typedef struct {
2020

2121
bool (*kb_press)(void* inst, uint16_t button);
2222
bool (*kb_release)(void* inst, uint16_t button);
23+
bool (*mouse_press)(void* inst, uint8_t button);
24+
bool (*mouse_release)(void* inst, uint8_t button);
25+
bool (*mouse_scroll)(void* inst, int8_t delta);
26+
bool (*mouse_move)(void* inst, int8_t dx, int8_t dy);
2327
bool (*consumer_press)(void* inst, uint16_t button);
2428
bool (*consumer_release)(void* inst, uint16_t button);
2529
bool (*release_all)(void* inst);

applications/main/bad_usb/helpers/ducky_script.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,16 @@ static int32_t ducky_parse_line(BadUsbScript* bad_usb, FuriString* line) {
193193
return cmd_result;
194194
}
195195

196+
// Mouse Keys
197+
uint16_t key = ducky_get_mouse_keycode_by_name(line_tmp);
198+
if(key != HID_MOUSE_INVALID) {
199+
bad_usb->hid->mouse_press(bad_usb->hid_inst, key);
200+
bad_usb->hid->mouse_release(bad_usb->hid_inst, key);
201+
return 0;
202+
}
203+
196204
// Special keys + modifiers
197-
uint16_t key = ducky_get_keycode(bad_usb, line_tmp, false);
205+
key = ducky_get_keycode(bad_usb, line_tmp, false);
198206
if(key == HID_KEYBOARD_NONE) {
199207
return ducky_error(bad_usb, "No keycode defined for %s", line_tmp);
200208
}

applications/main/bad_usb/helpers/ducky_script_commands.c

Lines changed: 84 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <furi_hal.h>
2+
#include <lib/toolbox/strint.h>
23
#include "ducky_script.h"
34
#include "ducky_script_i.h"
45

@@ -124,34 +125,58 @@ static int32_t ducky_fnc_altstring(BadUsbScript* bad_usb, const char* line, int3
124125

125126
static int32_t ducky_fnc_hold(BadUsbScript* bad_usb, const char* line, int32_t param) {
126127
UNUSED(param);
127-
128128
line = &line[ducky_get_command_len(line) + 1];
129-
uint16_t key = ducky_get_keycode(bad_usb, line, true);
130-
if(key == HID_KEYBOARD_NONE) {
131-
return ducky_error(bad_usb, "No keycode defined for %s", line);
132-
}
133-
bad_usb->key_hold_nb++;
129+
134130
if(bad_usb->key_hold_nb > (HID_KB_MAX_KEYS - 1)) {
135-
return ducky_error(bad_usb, "Too many keys are hold");
131+
return ducky_error(bad_usb, "Too many keys are held");
136132
}
137-
bad_usb->hid->kb_press(bad_usb->hid_inst, key);
138-
return 0;
133+
134+
// Handle Mouse Keys here
135+
uint16_t key = ducky_get_mouse_keycode_by_name(line);
136+
if(key != HID_MOUSE_NONE) {
137+
bad_usb->key_hold_nb++;
138+
bad_usb->hid->mouse_press(bad_usb->hid_inst, key);
139+
return 0;
140+
}
141+
142+
// Handle Keyboard keys here
143+
key = ducky_get_keycode(bad_usb, line, true);
144+
if(key != HID_KEYBOARD_NONE) {
145+
bad_usb->key_hold_nb++;
146+
bad_usb->hid->kb_press(bad_usb->hid_inst, key);
147+
return 0;
148+
}
149+
150+
// keyboard and mouse were none
151+
return ducky_error(bad_usb, "Unknown keycode for %s", line);
139152
}
140153

141154
static int32_t ducky_fnc_release(BadUsbScript* bad_usb, const char* line, int32_t param) {
142155
UNUSED(param);
143-
144156
line = &line[ducky_get_command_len(line) + 1];
145-
uint16_t key = ducky_get_keycode(bad_usb, line, true);
146-
if(key == HID_KEYBOARD_NONE) {
147-
return ducky_error(bad_usb, "No keycode defined for %s", line);
148-
}
157+
149158
if(bad_usb->key_hold_nb == 0) {
150-
return ducky_error(bad_usb, "No keys are hold");
159+
return ducky_error(bad_usb, "No keys are held");
151160
}
152-
bad_usb->key_hold_nb--;
153-
bad_usb->hid->kb_release(bad_usb->hid_inst, key);
154-
return 0;
161+
162+
// Handle Mouse Keys here
163+
uint16_t key = ducky_get_mouse_keycode_by_name(line);
164+
if(key != HID_MOUSE_NONE) {
165+
bad_usb->key_hold_nb--;
166+
bad_usb->hid->mouse_release(bad_usb->hid_inst, key);
167+
return 0;
168+
}
169+
170+
//Handle Keyboard Keys here
171+
key = ducky_get_keycode(bad_usb, line, true);
172+
if(key != HID_KEYBOARD_NONE) {
173+
bad_usb->key_hold_nb--;
174+
bad_usb->hid->kb_release(bad_usb->hid_inst, key);
175+
return 0;
176+
}
177+
178+
// keyboard and mouse were none
179+
return ducky_error(bad_usb, "No keycode defined for %s", line);
155180
}
156181

157182
static int32_t ducky_fnc_media(BadUsbScript* bad_usb, const char* line, int32_t param) {
@@ -191,6 +216,43 @@ static int32_t ducky_fnc_waitforbutton(BadUsbScript* bad_usb, const char* line,
191216
return SCRIPT_STATE_WAIT_FOR_BTN;
192217
}
193218

219+
static int32_t ducky_fnc_mouse_scroll(BadUsbScript* bad_usb, const char* line, int32_t param) {
220+
UNUSED(param);
221+
222+
line = &line[strcspn(line, " ") + 1];
223+
int32_t mouse_scroll_dist = 0;
224+
225+
if(strint_to_int32(line, NULL, &mouse_scroll_dist, 10) != StrintParseNoError) {
226+
return ducky_error(bad_usb, "Invalid Number %s", line);
227+
}
228+
229+
bad_usb->hid->mouse_scroll(bad_usb->hid_inst, mouse_scroll_dist);
230+
231+
return 0;
232+
}
233+
234+
static int32_t ducky_fnc_mouse_move(BadUsbScript* bad_usb, const char* line, int32_t param) {
235+
UNUSED(param);
236+
237+
line = &line[strcspn(line, " ") + 1];
238+
int32_t mouse_move_x = 0;
239+
int32_t mouse_move_y = 0;
240+
241+
if(strint_to_int32(line, NULL, &mouse_move_x, 10) != StrintParseNoError) {
242+
return ducky_error(bad_usb, "Invalid Number %s", line);
243+
}
244+
245+
line = &line[strcspn(line, " ") + 1];
246+
247+
if(strint_to_int32(line, NULL, &mouse_move_y, 10) != StrintParseNoError) {
248+
return ducky_error(bad_usb, "Invalid Number %s", line);
249+
}
250+
251+
bad_usb->hid->mouse_move(bad_usb->hid_inst, mouse_move_x, mouse_move_y);
252+
253+
return 0;
254+
}
255+
194256
static const DuckyCmd ducky_commands[] = {
195257
{"REM", NULL, -1},
196258
{"ID", NULL, -1},
@@ -213,6 +275,10 @@ static const DuckyCmd ducky_commands[] = {
213275
{"WAIT_FOR_BUTTON_PRESS", ducky_fnc_waitforbutton, -1},
214276
{"MEDIA", ducky_fnc_media, -1},
215277
{"GLOBE", ducky_fnc_globe, -1},
278+
{"MOUSEMOVE", ducky_fnc_mouse_move, -1},
279+
{"MOUSE_MOVE", ducky_fnc_mouse_move, -1},
280+
{"MOUSESCROLL", ducky_fnc_mouse_scroll, -1},
281+
{"MOUSE_SCROLL", ducky_fnc_mouse_scroll, -1},
216282
};
217283

218284
#define TAG "BadUsb"

0 commit comments

Comments
 (0)