ducky_script_commands.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. #include "../bad_kb_app_i.h"
  2. #include <furi_hal.h>
  3. #include <furi_hal_usb_hid.h>
  4. #include "ble_hid.h"
  5. #include "ducky_script.h"
  6. #include "ducky_script_i.h"
  7. typedef int32_t (*DuckyCmdCallback)(BadKbScript* bad_kb, const char* line, int32_t param);
  8. typedef struct {
  9. char* name;
  10. DuckyCmdCallback callback;
  11. int32_t param;
  12. } DuckyCmd;
  13. static int32_t ducky_fnc_delay(BadKbScript* bad_kb, const char* line, int32_t param) {
  14. UNUSED(param);
  15. line = &line[ducky_get_command_len(line) + 1];
  16. uint32_t delay_val = 0;
  17. bool state = ducky_get_number(line, &delay_val);
  18. if((state) && (delay_val > 0)) {
  19. return (int32_t)delay_val;
  20. }
  21. return ducky_error(bad_kb, "Invalid number %s", line);
  22. }
  23. static int32_t ducky_fnc_defdelay(BadKbScript* bad_kb, const char* line, int32_t param) {
  24. UNUSED(param);
  25. line = &line[ducky_get_command_len(line) + 1];
  26. bool state = ducky_get_number(line, &bad_kb->defdelay);
  27. if(!state) {
  28. return ducky_error(bad_kb, "Invalid number %s", line);
  29. }
  30. return 0;
  31. }
  32. static int32_t ducky_fnc_strdelay(BadKbScript* bad_kb, const char* line, int32_t param) {
  33. UNUSED(param);
  34. line = &line[ducky_get_command_len(line) + 1];
  35. bool state = ducky_get_number(line, &bad_kb->stringdelay);
  36. if(!state) {
  37. return ducky_error(bad_kb, "Invalid number %s", line);
  38. }
  39. return 0;
  40. }
  41. static int32_t ducky_fnc_defstrdelay(BadKbScript* bad_kb, const char* line, int32_t param) {
  42. UNUSED(param);
  43. line = &line[ducky_get_command_len(line) + 1];
  44. bool state = ducky_get_number(line, &bad_kb->defstringdelay);
  45. if(!state) {
  46. return ducky_error(bad_kb, "Invalid number %s", line);
  47. }
  48. return 0;
  49. }
  50. static int32_t ducky_fnc_string(BadKbScript* bad_kb, const char* line, int32_t param) {
  51. line = &line[ducky_get_command_len(line) + 1];
  52. furi_string_set_str(bad_kb->string_print, line);
  53. if(param == 1) {
  54. furi_string_cat(bad_kb->string_print, "\n");
  55. }
  56. if(bad_kb->stringdelay == 0 &&
  57. bad_kb->defstringdelay == 0) { // stringdelay not set - run command immediately
  58. bool state = ducky_string(bad_kb, furi_string_get_cstr(bad_kb->string_print));
  59. if(!state) {
  60. return ducky_error(bad_kb, "Invalid string %s", line);
  61. }
  62. } else { // stringdelay is set - run command in thread to keep handling external events
  63. return SCRIPT_STATE_STRING_START;
  64. }
  65. return 0;
  66. }
  67. static int32_t ducky_fnc_repeat(BadKbScript* bad_kb, const char* line, int32_t param) {
  68. UNUSED(param);
  69. line = &line[ducky_get_command_len(line) + 1];
  70. bool state = ducky_get_number(line, &bad_kb->repeat_cnt);
  71. if((!state) || (bad_kb->repeat_cnt == 0)) {
  72. return ducky_error(bad_kb, "Invalid number %s", line);
  73. }
  74. return 0;
  75. }
  76. static int32_t ducky_fnc_sysrq(BadKbScript* bad_kb, const char* line, int32_t param) {
  77. UNUSED(param);
  78. line = &line[ducky_get_command_len(line) + 1];
  79. uint16_t key = ducky_get_keycode(bad_kb, line, true);
  80. if(bad_kb->bt) {
  81. ble_profile_hid_kb_press(
  82. bad_kb->app->ble_hid, KEY_MOD_LEFT_ALT | HID_KEYBOARD_PRINT_SCREEN);
  83. ble_profile_hid_kb_press(bad_kb->app->ble_hid, key);
  84. furi_delay_ms(bt_timeout);
  85. ble_profile_hid_kb_release_all(bad_kb->app->ble_hid);
  86. } else {
  87. furi_hal_hid_kb_press(KEY_MOD_LEFT_ALT | HID_KEYBOARD_PRINT_SCREEN);
  88. furi_hal_hid_kb_press(key);
  89. furi_hal_hid_kb_release_all();
  90. }
  91. return 0;
  92. }
  93. static int32_t ducky_fnc_altchar(BadKbScript* bad_kb, const char* line, int32_t param) {
  94. UNUSED(param);
  95. line = &line[ducky_get_command_len(line) + 1];
  96. ducky_numlock_on(bad_kb);
  97. bool state = ducky_altchar(bad_kb, line);
  98. if(!state) {
  99. return ducky_error(bad_kb, "Invalid altchar %s", line);
  100. }
  101. return 0;
  102. }
  103. static int32_t ducky_fnc_altstring(BadKbScript* bad_kb, const char* line, int32_t param) {
  104. UNUSED(param);
  105. line = &line[ducky_get_command_len(line) + 1];
  106. ducky_numlock_on(bad_kb);
  107. bool state = ducky_altstring(bad_kb, line);
  108. if(!state) {
  109. return ducky_error(bad_kb, "Invalid altstring %s", line);
  110. }
  111. return 0;
  112. }
  113. static int32_t ducky_fnc_hold(BadKbScript* bad_kb, const char* line, int32_t param) {
  114. UNUSED(param);
  115. line = &line[ducky_get_command_len(line) + 1];
  116. uint16_t key = ducky_get_keycode(bad_kb, line, true);
  117. if(key == HID_KEYBOARD_NONE) {
  118. return ducky_error(bad_kb, "No keycode defined for %s", line);
  119. }
  120. bad_kb->key_hold_nb++;
  121. if(bad_kb->key_hold_nb > (HID_KB_MAX_KEYS - 1)) {
  122. return ducky_error(bad_kb, "Too many keys are hold");
  123. }
  124. if(bad_kb->bt) {
  125. ble_profile_hid_kb_press(bad_kb->app->ble_hid, key);
  126. } else {
  127. furi_hal_hid_kb_press(key);
  128. }
  129. return 0;
  130. }
  131. static int32_t ducky_fnc_release(BadKbScript* bad_kb, const char* line, int32_t param) {
  132. UNUSED(param);
  133. line = &line[ducky_get_command_len(line) + 1];
  134. uint16_t key = ducky_get_keycode(bad_kb, line, true);
  135. if(key == HID_KEYBOARD_NONE) {
  136. return ducky_error(bad_kb, "No keycode defined for %s", line);
  137. }
  138. if(bad_kb->key_hold_nb == 0) {
  139. return ducky_error(bad_kb, "No keys are hold");
  140. }
  141. bad_kb->key_hold_nb--;
  142. if(bad_kb->bt) {
  143. ble_profile_hid_kb_release(bad_kb->app->ble_hid, key);
  144. } else {
  145. furi_hal_hid_kb_release(key);
  146. }
  147. return 0;
  148. }
  149. static int32_t ducky_fnc_media(BadKbScript* bad_kb, const char* line, int32_t param) {
  150. UNUSED(param);
  151. line = &line[ducky_get_command_len(line) + 1];
  152. uint16_t key = ducky_get_media_keycode_by_name(line);
  153. if(key == HID_CONSUMER_UNASSIGNED) {
  154. return ducky_error(bad_kb, "No keycode defined for %s", line);
  155. }
  156. if(bad_kb->bt) {
  157. ble_profile_hid_kb_press(bad_kb->app->ble_hid, key);
  158. furi_delay_ms(bt_timeout);
  159. ble_profile_hid_kb_release(bad_kb->app->ble_hid, key);
  160. } else {
  161. furi_hal_hid_kb_press(key);
  162. furi_hal_hid_kb_release(key);
  163. }
  164. return 0;
  165. }
  166. static int32_t ducky_fnc_globe(BadKbScript* bad_kb, const char* line, int32_t param) {
  167. UNUSED(param);
  168. line = &line[ducky_get_command_len(line) + 1];
  169. uint16_t key = ducky_get_keycode(bad_kb, line, true);
  170. if(key == HID_KEYBOARD_NONE) {
  171. return ducky_error(bad_kb, "No keycode defined for %s", line);
  172. }
  173. if(bad_kb->bt) {
  174. ble_profile_hid_consumer_key_press(bad_kb->app->ble_hid, HID_CONSUMER_FN_GLOBE);
  175. ble_profile_hid_kb_press(bad_kb->app->ble_hid, key);
  176. furi_delay_ms(bt_timeout);
  177. ble_profile_hid_kb_release(bad_kb->app->ble_hid, key);
  178. ble_profile_hid_consumer_key_release(bad_kb->app->ble_hid, HID_CONSUMER_FN_GLOBE);
  179. } else {
  180. furi_hal_hid_consumer_key_press(HID_CONSUMER_FN_GLOBE);
  181. furi_hal_hid_kb_press(key);
  182. furi_hal_hid_kb_release(key);
  183. furi_hal_hid_consumer_key_release(HID_CONSUMER_FN_GLOBE);
  184. }
  185. return 0;
  186. }
  187. static int32_t ducky_fnc_waitforbutton(BadKbScript* bad_kb, const char* line, int32_t param) {
  188. UNUSED(param);
  189. UNUSED(bad_kb);
  190. UNUSED(line);
  191. return SCRIPT_STATE_WAIT_FOR_BTN;
  192. }
  193. static const DuckyCmd ducky_commands[] = {
  194. {"REM", NULL, -1},
  195. {"ID", NULL, -1},
  196. {"BT_ID", NULL, -1},
  197. {"DELAY", ducky_fnc_delay, -1},
  198. {"STRING", ducky_fnc_string, 0},
  199. {"STRINGLN", ducky_fnc_string, 1},
  200. {"DEFAULT_DELAY", ducky_fnc_defdelay, -1},
  201. {"DEFAULTDELAY", ducky_fnc_defdelay, -1},
  202. {"STRINGDELAY", ducky_fnc_strdelay, -1},
  203. {"STRING_DELAY", ducky_fnc_strdelay, -1},
  204. {"DEFAULT_STRING_DELAY", ducky_fnc_defstrdelay, -1},
  205. {"DEFAULTSTRINGDELAY", ducky_fnc_defstrdelay, -1},
  206. {"REPEAT", ducky_fnc_repeat, -1},
  207. {"SYSRQ", ducky_fnc_sysrq, -1},
  208. {"ALTCHAR", ducky_fnc_altchar, -1},
  209. {"ALTSTRING", ducky_fnc_altstring, -1},
  210. {"ALTCODE", ducky_fnc_altstring, -1},
  211. {"HOLD", ducky_fnc_hold, -1},
  212. {"RELEASE", ducky_fnc_release, -1},
  213. {"WAIT_FOR_BUTTON_PRESS", ducky_fnc_waitforbutton, -1},
  214. {"MEDIA", ducky_fnc_media, -1},
  215. {"GLOBE", ducky_fnc_globe, -1},
  216. };
  217. #define TAG "BadKb"
  218. #define WORKER_TAG TAG "Worker"
  219. int32_t ducky_execute_cmd(BadKbScript* bad_kb, const char* line) {
  220. size_t cmd_word_len = strcspn(line, " ");
  221. for(size_t i = 0; i < COUNT_OF(ducky_commands); i++) {
  222. size_t cmd_compare_len = strlen(ducky_commands[i].name);
  223. if(cmd_compare_len != cmd_word_len) {
  224. continue;
  225. }
  226. if(strncmp(line, ducky_commands[i].name, cmd_compare_len) == 0) {
  227. if(ducky_commands[i].callback == NULL) {
  228. return 0;
  229. } else {
  230. return ((ducky_commands[i].callback)(bad_kb, line, ducky_commands[i].param));
  231. }
  232. }
  233. }
  234. return SCRIPT_STATE_CMD_UNKNOWN;
  235. }