js updates

by Willy-JL , oldip
This commit is contained in:
MX
2024-03-20 13:13:04 +03:00
parent 71111b0d2f
commit 6f560ef210
10 changed files with 342 additions and 170 deletions
@@ -26,6 +26,12 @@ if (badusb.isConnected()) {
badusb.println("Flipper Name: " + flipper.getName());
badusb.println("Battery level: " + to_string(flipper.getBatteryCharge()) + "%");
// Alt+Numpad method works only on Windows!!!
badusb.altPrintln("This was printed with Alt+Numpad method!");
// There's also badusb.print() and badusb.altPrint()
// which don't add the return at the end
notify.success();
} else {
print("USB not connected");
@@ -4,16 +4,20 @@ keyboard.setHeader("Example Text Input");
// Default text is optional
let text = keyboard.text(100, "Default text", true);
// Returns undefined when pressing back
print("Got text:", text);
keyboard.setHeader("Example Byte Input");
// Default data is optional
let data = keyboard.byte(6, Uint8Array([1, 2, 3, 4, 5, 6]));
data = Uint8Array(data);
let result = "0x";
for (let i = 0; i < data.byteLength; i++) {
if (data[i] < 0x10) result += "0";
result += to_hex_string(data[i]);
let result = keyboard.byte(6, Uint8Array([1, 2, 3, 4, 5, 6]));
// Returns undefined when pressing back
if (result !== undefined) {
let data = Uint8Array(result);
result = "0x";
for (let i = 0; i < data.byteLength; i++) {
if (data[i] < 0x10) result += "0";
result += to_hex_string(data[i]);
}
}
print("Got data:", result);
@@ -0,0 +1,19 @@
let sampleText = "Hello, World!";
let lengthOfText = "Length of text: " + to_string(sampleText.length);
print(lengthOfText);
let start = 7;
let end = 12;
let substringResult = sampleText.slice(start, end);
print(substringResult);
let searchStr = "World";
let result2 = to_string(sampleText.indexOf(searchStr));
print(result2);
let upperCaseText = "Text in upper case: " + to_upper_case(sampleText);
print(upperCaseText);
let lowerCaseText = "Text in lower case: " + to_lower_case(sampleText);
print(lowerCaseText);
@@ -7,5 +7,5 @@ submenu.addItem("Item 3", 2);
submenu.setHeader("Select an option:");
let result = submenu.show();
// Returns undefined when pressing back
print("Result:", result);
+86 -1
View File
@@ -195,7 +195,7 @@ static void js_require(struct mjs* mjs) {
}
static void js_global_to_string(struct mjs* mjs) {
double num = mjs_get_int(mjs, mjs_arg(mjs, 0));
double num = mjs_get_double(mjs, mjs_arg(mjs, 0));
char tmp_str[] = "-2147483648";
itoa(num, tmp_str, 10);
mjs_val_t ret = mjs_mk_string(mjs, tmp_str, ~0, true);
@@ -210,6 +210,88 @@ static void js_global_to_hex_string(struct mjs* mjs) {
mjs_return(mjs, ret);
}
static void js_parse_int(struct mjs* mjs) {
mjs_val_t arg = mjs_arg(mjs, 0);
if(!mjs_is_string(arg)) {
mjs_return(mjs, mjs_mk_number(mjs, 0));
return;
}
size_t str_len = 0;
const char* str = mjs_get_string(mjs, &arg, &str_len);
if((str_len == 0) || (str == NULL)) {
mjs_return(mjs, mjs_mk_number(mjs, 0));
return;
}
int32_t num = 0;
int32_t sign = 1;
size_t i = 0;
if(str[0] == '-') {
sign = -1;
i = 1;
} else if(str[0] == '+') {
i = 1;
}
for(; i < str_len; i++) {
if(str[i] >= '0' && str[i] <= '9') {
num = num * 10 + (str[i] - '0');
} else {
break;
}
}
num *= sign;
mjs_return(mjs, mjs_mk_number(mjs, num));
}
static void js_to_upper_case(struct mjs* mjs) {
mjs_val_t arg0 = mjs_arg(mjs, 0);
size_t str_len;
const char* str = NULL;
if(mjs_is_string(arg0)) {
str = mjs_get_string(mjs, &arg0, &str_len);
}
if(!str) {
mjs_return(mjs, MJS_UNDEFINED);
return;
}
char* upperStr = strdup(str);
for(size_t i = 0; i < str_len; i++) {
upperStr[i] = toupper(upperStr[i]);
}
mjs_val_t resultStr = mjs_mk_string(mjs, upperStr, ~0, true);
free(upperStr);
mjs_return(mjs, resultStr);
}
static void js_to_lower_case(struct mjs* mjs) {
mjs_val_t arg0 = mjs_arg(mjs, 0);
size_t str_len;
const char* str = NULL;
if(mjs_is_string(arg0)) {
str = mjs_get_string(mjs, &arg0, &str_len);
}
if(!str) {
mjs_return(mjs, MJS_UNDEFINED);
return;
}
char* lowerStr = strdup(str);
for(size_t i = 0; i < str_len; i++) {
lowerStr[i] = tolower(lowerStr[i]);
}
mjs_val_t resultStr = mjs_mk_string(mjs, lowerStr, ~0, true);
free(lowerStr);
mjs_return(mjs, resultStr);
}
#ifdef JS_DEBUG
static void js_dump_write_callback(void* ctx, const char* format, ...) {
File* file = ctx;
@@ -243,6 +325,9 @@ static int32_t js_thread(void* arg) {
mjs_set(mjs, global, "to_hex_string", ~0, MJS_MK_FN(js_global_to_hex_string));
mjs_set(mjs, global, "ffi_address", ~0, MJS_MK_FN(js_ffi_address));
mjs_set(mjs, global, "require", ~0, MJS_MK_FN(js_require));
mjs_set(mjs, global, "parse_int", ~0, MJS_MK_FN(js_parse_int));
mjs_set(mjs, global, "to_upper_case", ~0, MJS_MK_FN(js_to_upper_case));
mjs_set(mjs, global, "to_lower_case", ~0, MJS_MK_FN(js_to_lower_case));
mjs_val_t console_obj = mjs_mk_object(mjs);
mjs_set(mjs, console_obj, "log", ~0, MJS_MK_FN(js_console_log));
+67 -12
View File
@@ -52,6 +52,17 @@ static const struct {
{"F10", HID_KEYBOARD_F10},
{"F11", HID_KEYBOARD_F11},
{"F12", HID_KEYBOARD_F12},
{"NUM0", HID_KEYPAD_0},
{"NUM1", HID_KEYPAD_1},
{"NUM2", HID_KEYPAD_2},
{"NUM3", HID_KEYPAD_3},
{"NUM4", HID_KEYPAD_4},
{"NUM5", HID_KEYPAD_5},
{"NUM6", HID_KEYPAD_6},
{"NUM7", HID_KEYPAD_7},
{"NUM8", HID_KEYPAD_8},
{"NUM9", HID_KEYPAD_9},
};
static void js_badusb_quit_free(JsBadusbInst* badusb) {
@@ -130,12 +141,8 @@ static void js_badusb_setup(struct mjs* mjs) {
badusb->usb_if_prev = furi_hal_usb_get_config();
if(!furi_hal_usb_set_config(&usb_hid, badusb->hid_cfg)) {
mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "USB is locked, close companion app first");
badusb->usb_if_prev = NULL;
mjs_return(mjs, MJS_UNDEFINED);
return;
}
furi_hal_usb_unlock();
furi_hal_usb_set_config(&usb_hid, badusb->hid_cfg);
mjs_return(mjs, MJS_UNDEFINED);
}
@@ -318,7 +325,35 @@ static void js_badusb_release(struct mjs* mjs) {
mjs_return(mjs, MJS_UNDEFINED);
}
static void badusb_print(struct mjs* mjs, bool ln) {
// Make sure NUMLOCK is enabled for altchar
static void ducky_numlock_on() {
if((furi_hal_hid_get_led_state() & HID_KB_LED_NUM) == 0) {
furi_hal_hid_kb_press(HID_KEYBOARD_LOCK_NUM_LOCK);
furi_hal_hid_kb_release(HID_KEYBOARD_LOCK_NUM_LOCK);
}
}
// Simulate pressing a character using ALT+Numpad ASCII code
static void ducky_altchar(const char* ascii_code) {
// Hold the ALT key
furi_hal_hid_kb_press(KEY_MOD_LEFT_ALT);
// Press the corresponding numpad key for each digit of the ASCII code
for(size_t i = 0; ascii_code[i] != '\0'; i++) {
char digitChar[5] = {'N', 'U', 'M', ascii_code[i], '\0'}; // Construct the numpad key name
uint16_t numpad_keycode = get_keycode_by_name(digitChar, strlen(digitChar));
if(numpad_keycode == HID_KEYBOARD_NONE) {
continue; // Skip if keycode not found
}
furi_hal_hid_kb_press(numpad_keycode);
furi_hal_hid_kb_release(numpad_keycode);
}
// Release the ALT key
furi_hal_hid_kb_release(KEY_MOD_LEFT_ALT);
}
static void badusb_print(struct mjs* mjs, bool ln, bool alt) {
mjs_val_t obj_inst = mjs_get(mjs, mjs_get_this(mjs), INST_PROP_NAME, ~0);
JsBadusbInst* badusb = mjs_get_ptr(mjs, obj_inst);
furi_assert(badusb);
@@ -364,10 +399,20 @@ static void badusb_print(struct mjs* mjs, bool ln) {
return;
}
if(alt) {
ducky_numlock_on();
}
for(size_t i = 0; i < text_len; i++) {
uint16_t keycode = HID_ASCII_TO_KEY(text_str[i]);
furi_hal_hid_kb_press(keycode);
furi_hal_hid_kb_release(keycode);
if(alt) {
// Convert character to ascii numeric value
char ascii_str[4];
snprintf(ascii_str, sizeof(ascii_str), "%u", (uint8_t)text_str[i]);
ducky_altchar(ascii_str);
} else {
uint16_t keycode = HID_ASCII_TO_KEY(text_str[i]);
furi_hal_hid_kb_press(keycode);
furi_hal_hid_kb_release(keycode);
}
if(delay_val > 0) {
bool need_exit = js_delay_with_flags(mjs, delay_val);
if(need_exit) {
@@ -385,11 +430,19 @@ static void badusb_print(struct mjs* mjs, bool ln) {
}
static void js_badusb_print(struct mjs* mjs) {
badusb_print(mjs, false);
badusb_print(mjs, false, false);
}
static void js_badusb_println(struct mjs* mjs) {
badusb_print(mjs, true);
badusb_print(mjs, true, false);
}
static void js_badusb_alt_print(struct mjs* mjs) {
badusb_print(mjs, false, true);
}
static void js_badusb_alt_println(struct mjs* mjs) {
badusb_print(mjs, true, true);
}
static void* js_badusb_create(struct mjs* mjs, mjs_val_t* object) {
@@ -404,6 +457,8 @@ static void* js_badusb_create(struct mjs* mjs, mjs_val_t* object) {
mjs_set(mjs, badusb_obj, "release", ~0, MJS_MK_FN(js_badusb_release));
mjs_set(mjs, badusb_obj, "print", ~0, MJS_MK_FN(js_badusb_print));
mjs_set(mjs, badusb_obj, "println", ~0, MJS_MK_FN(js_badusb_println));
mjs_set(mjs, badusb_obj, "altPrint", ~0, MJS_MK_FN(js_badusb_alt_print));
mjs_set(mjs, badusb_obj, "altPrintln", ~0, MJS_MK_FN(js_badusb_alt_println));
*object = badusb_obj;
return badusb;
}
@@ -43,16 +43,6 @@ static bool check_arg_count(struct mjs* mjs, size_t count) {
return true;
}
static bool get_int_arg(struct mjs* mjs, size_t index, uint8_t* value, bool error) {
mjs_val_t int_obj = mjs_arg(mjs, index);
if(!mjs_is_number(int_obj)) {
if(error) ret_bad_args(mjs, "Argument must be a number");
return false;
}
*value = mjs_get_int(mjs, int_obj);
return true;
}
static void js_blebeacon_is_active(struct mjs* mjs) {
JsBlebeaconInst* blebeacon = get_this_ctx(mjs);
if(!check_arg_count(mjs, 0)) return;
@@ -83,15 +73,24 @@ static void js_blebeacon_set_config(struct mjs* mjs) {
}
uint8_t power = GapAdvPowerLevel_0dBm;
get_int_arg(mjs, 1, &power, false);
mjs_val_t power_arg = mjs_arg(mjs, 1);
if(mjs_is_number(power_arg)) {
power = mjs_get_int32(mjs, power_arg);
}
power = CLAMP(power, GapAdvPowerLevel_6dBm, GapAdvPowerLevel_Neg40dBm);
uint8_t intv_min = 50;
get_int_arg(mjs, 2, &intv_min, false);
mjs_val_t intv_min_arg = mjs_arg(mjs, 2);
if(mjs_is_number(intv_min_arg)) {
intv_min = mjs_get_int32(mjs, intv_min_arg);
}
intv_min = MAX(intv_min, 20);
uint8_t intv_max = 150;
get_int_arg(mjs, 3, &intv_max, false);
mjs_val_t intv_max_arg = mjs_arg(mjs, 3);
if(mjs_is_number(intv_max_arg)) {
intv_max = mjs_get_int32(mjs, intv_max_arg);
}
intv_max = MAX(intv_max, intv_min);
GapExtraBeaconConfig config = {
@@ -6,48 +6,18 @@
#define membersof(x) (sizeof(x) / sizeof(x[0]))
typedef struct {
char* data;
TextInput* text_input;
ByteInput* byte_input;
ViewDispatcher* view_dispatcher;
uint8_t* byteinput;
char* header;
bool accepted;
} JsKeyboardInst;
typedef enum {
JsKeyboardViewTextInput,
JsKeyboardViewByteInput,
} JsKeyboardView;
static void ret_bad_args(struct mjs* mjs, const char* error) {
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "%s", error);
mjs_return(mjs, MJS_UNDEFINED);
}
static bool get_str_arg(struct mjs* mjs, size_t index, const char** value, bool error) {
mjs_val_t str_obj = mjs_arg(mjs, index);
if(!mjs_is_string(str_obj)) {
if(error) ret_bad_args(mjs, "Argument must be a string");
return false;
}
size_t str_len = 0;
*value = mjs_get_string(mjs, &str_obj, &str_len);
if((str_len == 0) || (*value == NULL)) {
if(error) ret_bad_args(mjs, "Bad string argument");
return false;
}
return true;
}
static bool get_int_arg(struct mjs* mjs, size_t index, size_t* value, bool error) {
mjs_val_t int_obj = mjs_arg(mjs, index);
if(!mjs_is_number(int_obj)) {
if(error) ret_bad_args(mjs, "Argument must be a number");
return false;
}
*value = mjs_get_int(mjs, int_obj);
return true;
}
static JsKeyboardInst* get_this_ctx(struct mjs* mjs) {
mjs_val_t obj_inst = mjs_get(mjs, mjs_get_this(mjs), INST_PROP_NAME, ~0);
JsKeyboardInst* storage = mjs_get_ptr(mjs, obj_inst);
@@ -55,24 +25,33 @@ static JsKeyboardInst* get_this_ctx(struct mjs* mjs) {
return storage;
}
void text_input_callback(void* context) {
static void keyboard_callback(void* context) {
JsKeyboardInst* keyboard = (JsKeyboardInst*)context;
keyboard->accepted = true;
view_dispatcher_stop(keyboard->view_dispatcher);
}
void byte_input_callback(void* context) {
static bool keyboard_exit(void* context) {
JsKeyboardInst* keyboard = (JsKeyboardInst*)context;
keyboard->accepted = false;
view_dispatcher_stop(keyboard->view_dispatcher);
return true;
}
static void js_keyboard_set_header(struct mjs* mjs) {
JsKeyboardInst* keyboard = get_this_ctx(mjs);
const char* header;
if(!get_str_arg(mjs, 0, &header, true)) return;
mjs_val_t header_arg = mjs_arg(mjs, 0);
const char* header = mjs_get_string(mjs, &header_arg, NULL);
if(!header) {
ret_bad_args(mjs, "Header must be a string");
return;
}
text_input_set_header_text(keyboard->text_input, header);
byte_input_set_header_text(keyboard->byte_input, header);
if(keyboard->header) {
free(keyboard->header);
}
keyboard->header = strdup(header);
mjs_return(mjs, MJS_UNDEFINED);
}
@@ -80,40 +59,70 @@ static void js_keyboard_set_header(struct mjs* mjs) {
static void js_keyboard_text(struct mjs* mjs) {
JsKeyboardInst* keyboard = get_this_ctx(mjs);
size_t input_length;
if(!get_int_arg(mjs, 0, &input_length, true)) return;
mjs_val_t input_length_arg = mjs_arg(mjs, 0);
if(!mjs_is_number(input_length_arg)) {
ret_bad_args(mjs, "Input length must be a number");
return;
}
int32_t input_length = mjs_get_int32(mjs, input_length_arg);
char* buffer = malloc(input_length);
const char* default_text = "";
mjs_val_t default_text_arg = mjs_arg(mjs, 1);
const char* default_text = mjs_get_string(mjs, &default_text_arg, NULL);
bool clear_default = false;
if(get_str_arg(mjs, 1, &default_text, false)) {
if(default_text) {
strlcpy(buffer, default_text, input_length);
mjs_val_t bool_obj = mjs_arg(mjs, 2);
clear_default = mjs_get_bool(mjs, bool_obj);
}
view_dispatcher_attach_to_gui(
keyboard->view_dispatcher, furi_record_open(RECORD_GUI), ViewDispatcherTypeFullscreen);
furi_record_close(RECORD_GUI);
if(keyboard->header) {
text_input_set_header_text(keyboard->text_input, keyboard->header);
}
text_input_set_result_callback(
keyboard->text_input, text_input_callback, keyboard, buffer, input_length, clear_default);
keyboard->text_input, keyboard_callback, keyboard, buffer, input_length, clear_default);
view_dispatcher_switch_to_view(keyboard->view_dispatcher, JsKeyboardViewTextInput);
text_input_set_minimum_length(keyboard->text_input, 0);
Gui* gui = furi_record_open(RECORD_GUI);
keyboard->view_dispatcher = view_dispatcher_alloc();
view_dispatcher_enable_queue(keyboard->view_dispatcher);
view_dispatcher_add_view(
keyboard->view_dispatcher, 0, text_input_get_view(keyboard->text_input));
view_dispatcher_set_event_callback_context(keyboard->view_dispatcher, keyboard);
view_dispatcher_set_navigation_event_callback(keyboard->view_dispatcher, keyboard_exit);
view_dispatcher_attach_to_gui(keyboard->view_dispatcher, gui, ViewDispatcherTypeFullscreen);
view_dispatcher_switch_to_view(keyboard->view_dispatcher, 0);
view_dispatcher_run(keyboard->view_dispatcher);
text_input_reset(keyboard->text_input);
view_dispatcher_remove_view(keyboard->view_dispatcher, 0);
view_dispatcher_free(keyboard->view_dispatcher);
keyboard->view_dispatcher = NULL;
furi_record_close(RECORD_GUI);
mjs_return(mjs, mjs_mk_string(mjs, buffer, ~0, true));
text_input_reset(keyboard->text_input);
if(keyboard->header) {
free(keyboard->header);
keyboard->header = NULL;
}
if(keyboard->accepted) {
mjs_return(mjs, mjs_mk_string(mjs, buffer, ~0, true));
} else {
mjs_return(mjs, MJS_UNDEFINED);
}
free(buffer);
}
static void js_keyboard_byte(struct mjs* mjs) {
JsKeyboardInst* keyboard = get_this_ctx(mjs);
size_t input_length;
if(!get_int_arg(mjs, 0, &input_length, true)) return;
mjs_val_t input_length_arg = mjs_arg(mjs, 0);
if(!mjs_is_number(input_length_arg)) {
ret_bad_args(mjs, "Input length must be a number");
return;
}
int32_t input_length = mjs_get_int32(mjs, input_length_arg);
uint8_t* buffer = malloc(input_length);
mjs_val_t default_data_arg = mjs_arg(mjs, 1);
@@ -126,21 +135,40 @@ static void js_keyboard_byte(struct mjs* mjs) {
memcpy(buffer, (uint8_t*)default_data, MIN((size_t)input_length, default_data_len));
}
view_dispatcher_attach_to_gui(
keyboard->view_dispatcher, furi_record_open(RECORD_GUI), ViewDispatcherTypeFullscreen);
furi_record_close(RECORD_GUI);
if(keyboard->header) {
byte_input_set_header_text(keyboard->byte_input, keyboard->header);
}
byte_input_set_result_callback(
keyboard->byte_input, byte_input_callback, NULL, keyboard, buffer, input_length);
keyboard->byte_input, keyboard_callback, NULL, keyboard, buffer, input_length);
view_dispatcher_switch_to_view(keyboard->view_dispatcher, JsKeyboardViewByteInput);
Gui* gui = furi_record_open(RECORD_GUI);
keyboard->view_dispatcher = view_dispatcher_alloc();
view_dispatcher_enable_queue(keyboard->view_dispatcher);
view_dispatcher_add_view(
keyboard->view_dispatcher, 0, byte_input_get_view(keyboard->byte_input));
view_dispatcher_set_event_callback_context(keyboard->view_dispatcher, keyboard);
view_dispatcher_set_navigation_event_callback(keyboard->view_dispatcher, keyboard_exit);
view_dispatcher_attach_to_gui(keyboard->view_dispatcher, gui, ViewDispatcherTypeFullscreen);
view_dispatcher_switch_to_view(keyboard->view_dispatcher, 0);
view_dispatcher_run(keyboard->view_dispatcher);
view_dispatcher_remove_view(keyboard->view_dispatcher, 0);
view_dispatcher_free(keyboard->view_dispatcher);
keyboard->view_dispatcher = NULL;
furi_record_close(RECORD_GUI);
if(keyboard->header) {
free(keyboard->header);
keyboard->header = NULL;
}
byte_input_set_result_callback(keyboard->byte_input, NULL, NULL, NULL, NULL, 0);
byte_input_set_header_text(keyboard->byte_input, "");
mjs_return(mjs, mjs_mk_array_buf(mjs, (char*)buffer, input_length));
if(keyboard->accepted) {
mjs_return(mjs, mjs_mk_array_buf(mjs, (char*)buffer, input_length));
} else {
mjs_return(mjs, MJS_UNDEFINED);
}
free(buffer);
}
@@ -153,28 +181,14 @@ static void* js_keyboard_create(struct mjs* mjs, mjs_val_t* object) {
mjs_set(mjs, keyboard_obj, "byte", ~0, MJS_MK_FN(js_keyboard_byte));
keyboard->byte_input = byte_input_alloc();
keyboard->text_input = text_input_alloc();
keyboard->view_dispatcher = view_dispatcher_alloc();
view_dispatcher_enable_queue(keyboard->view_dispatcher);
view_dispatcher_add_view(
keyboard->view_dispatcher,
JsKeyboardViewTextInput,
text_input_get_view(keyboard->text_input));
view_dispatcher_add_view(
keyboard->view_dispatcher,
JsKeyboardViewByteInput,
byte_input_get_view(keyboard->byte_input));
*object = keyboard_obj;
return keyboard;
}
static void js_keyboard_destroy(void* inst) {
JsKeyboardInst* keyboard = inst;
view_dispatcher_remove_view(keyboard->view_dispatcher, JsKeyboardViewByteInput);
byte_input_free(keyboard->byte_input);
view_dispatcher_remove_view(keyboard->view_dispatcher, JsKeyboardViewTextInput);
text_input_free(keyboard->text_input);
view_dispatcher_free(keyboard->view_dispatcher);
free(keyboard->data);
free(keyboard);
}
@@ -41,17 +41,6 @@ static FuriHalSubGhzPreset js_subghz_get_preset_name(const char* preset_name) {
return preset;
}
static int32_t get_int_arg(struct mjs* mjs, size_t index, int32_t* value) {
mjs_val_t int_obj = mjs_arg(mjs, index);
if(!mjs_is_number(int_obj)) {
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Argument must be a number");
mjs_return(mjs, MJS_UNDEFINED);
return false;
}
*value = mjs_get_int(mjs, int_obj);
return true;
}
static void js_subghz_set_rx(struct mjs* mjs) {
mjs_val_t obj_inst = mjs_get(mjs, mjs_get_this(mjs), INST_PROP_NAME, ~0);
JsSubghzInst* js_subghz = mjs_get_ptr(mjs, obj_inst);
@@ -137,8 +126,13 @@ static void js_subghz_set_frequency(struct mjs* mjs) {
return;
}
int32_t frequency;
if(!get_int_arg(mjs, 0, &frequency)) return;
mjs_val_t frequency_arg = mjs_arg(mjs, 0);
if(!mjs_is_number(frequency_arg)) {
mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Frequency must be a number");
mjs_return(mjs, MJS_UNDEFINED);
return;
}
int32_t frequency = mjs_get_int32(mjs, frequency_arg);
if(!subghz_devices_is_frequency_valid(js_subghz->radio_device, frequency)) {
mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Invalid frequency");
+46 -50
View File
@@ -7,12 +7,9 @@ typedef struct {
Submenu* submenu;
ViewDispatcher* view_dispatcher;
uint32_t result;
bool accepted;
} JsSubmenuInst;
typedef enum {
JsSubmenuViewSubmenu,
} JsSubmenuView;
static JsSubmenuInst* get_this_ctx(struct mjs* mjs) {
mjs_val_t obj_inst = mjs_get(mjs, mjs_get_this(mjs), INST_PROP_NAME, ~0);
JsSubmenuInst* storage = mjs_get_ptr(mjs, obj_inst);
@@ -34,47 +31,38 @@ static bool check_arg_count(struct mjs* mjs, size_t count) {
return true;
}
static bool get_str_arg(struct mjs* mjs, size_t index, const char** value) {
mjs_val_t str_obj = mjs_arg(mjs, index);
if(!mjs_is_string(str_obj)) {
ret_bad_args(mjs, "Argument must be a string");
return false;
}
size_t str_len = 0;
*value = mjs_get_string(mjs, &str_obj, &str_len);
if((str_len == 0) || (*value == NULL)) {
ret_bad_args(mjs, "Bad string argument");
return false;
}
return true;
}
static int32_t get_int_arg(struct mjs* mjs, size_t index, int32_t* value) {
mjs_val_t int_obj = mjs_arg(mjs, index);
if(!mjs_is_number(int_obj)) {
ret_bad_args(mjs, "Argument must be a number");
return false;
}
*value = mjs_get_int32(mjs, int_obj);
return true;
}
static void submenu_callback(void* context, uint32_t id) {
UNUSED(id);
JsSubmenuInst* submenu = context;
submenu->result = id;
submenu->accepted = true;
view_dispatcher_stop(submenu->view_dispatcher);
}
static bool submenu_exit(void* context) {
JsSubmenuInst* submenu = context;
submenu->result = 0;
submenu->accepted = false;
view_dispatcher_stop(submenu->view_dispatcher);
return true;
}
static void js_submenu_add_item(struct mjs* mjs) {
JsSubmenuInst* submenu = get_this_ctx(mjs);
if(!check_arg_count(mjs, 2)) return;
const char* label;
if(!get_str_arg(mjs, 0, &label)) return;
mjs_val_t label_arg = mjs_arg(mjs, 0);
const char* label = mjs_get_string(mjs, &label_arg, NULL);
if(!label) {
ret_bad_args(mjs, "Label must be a string");
return;
}
int32_t id;
if(!get_int_arg(mjs, 1, &id)) return;
mjs_val_t id_arg = mjs_arg(mjs, 1);
if(!mjs_is_number(id_arg)) {
ret_bad_args(mjs, "Id must be a number");
return;
}
int32_t id = mjs_get_int32(mjs, id_arg);
submenu_add_item(submenu->submenu, label, id, submenu_callback, submenu);
@@ -85,8 +73,12 @@ static void js_submenu_set_header(struct mjs* mjs) {
JsSubmenuInst* submenu = get_this_ctx(mjs);
if(!check_arg_count(mjs, 1)) return;
const char* header;
if(!get_str_arg(mjs, 0, &header)) return;
mjs_val_t header_arg = mjs_arg(mjs, 0);
const char* header = mjs_get_string(mjs, &header_arg, NULL);
if(!header) {
ret_bad_args(mjs, "Header must be a string");
return;
}
submenu_set_header(submenu->submenu, header);
@@ -96,19 +88,29 @@ static void js_submenu_set_header(struct mjs* mjs) {
static void js_submenu_show(struct mjs* mjs) {
JsSubmenuInst* submenu = get_this_ctx(mjs);
if(!check_arg_count(mjs, 0)) return;
submenu->result = 0;
view_dispatcher_attach_to_gui(
submenu->view_dispatcher, furi_record_open(RECORD_GUI), ViewDispatcherTypeFullscreen);
furi_record_close(RECORD_GUI);
view_dispatcher_switch_to_view(submenu->view_dispatcher, JsSubmenuViewSubmenu);
Gui* gui = furi_record_open(RECORD_GUI);
submenu->view_dispatcher = view_dispatcher_alloc();
view_dispatcher_enable_queue(submenu->view_dispatcher);
view_dispatcher_add_view(submenu->view_dispatcher, 0, submenu_get_view(submenu->submenu));
view_dispatcher_set_event_callback_context(submenu->view_dispatcher, submenu);
view_dispatcher_set_navigation_event_callback(submenu->view_dispatcher, submenu_exit);
view_dispatcher_attach_to_gui(submenu->view_dispatcher, gui, ViewDispatcherTypeFullscreen);
view_dispatcher_switch_to_view(submenu->view_dispatcher, 0);
view_dispatcher_run(submenu->view_dispatcher);
submenu_reset(submenu->submenu);
view_dispatcher_remove_view(submenu->view_dispatcher, 0);
view_dispatcher_free(submenu->view_dispatcher);
submenu->view_dispatcher = NULL;
furi_record_close(RECORD_GUI);
mjs_return(mjs, mjs_mk_number(mjs, submenu->result));
submenu_reset(submenu->submenu);
if(submenu->accepted) {
mjs_return(mjs, mjs_mk_number(mjs, submenu->result));
} else {
mjs_return(mjs, MJS_UNDEFINED);
}
}
static void* js_submenu_create(struct mjs* mjs, mjs_val_t* object) {
@@ -119,19 +121,13 @@ static void* js_submenu_create(struct mjs* mjs, mjs_val_t* object) {
mjs_set(mjs, submenu_obj, "setHeader", ~0, MJS_MK_FN(js_submenu_set_header));
mjs_set(mjs, submenu_obj, "show", ~0, MJS_MK_FN(js_submenu_show));
submenu->submenu = submenu_alloc();
submenu->view_dispatcher = view_dispatcher_alloc();
view_dispatcher_enable_queue(submenu->view_dispatcher);
view_dispatcher_add_view(
submenu->view_dispatcher, JsSubmenuViewSubmenu, submenu_get_view(submenu->submenu));
*object = submenu_obj;
return submenu;
}
static void js_submenu_destroy(void* inst) {
JsSubmenuInst* submenu = inst;
view_dispatcher_remove_view(submenu->view_dispatcher, JsSubmenuViewSubmenu);
submenu_free(submenu->submenu);
view_dispatcher_free(submenu->view_dispatcher);
free(submenu);
}