action_subghz.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. // Methods for Sub-GHz transmission
  2. // subghz
  3. #include <lib/subghz/transmitter.h>
  4. #include <lib/subghz/devices/devices.h>
  5. #include <lib/subghz/devices/cc1101_configs.h>
  6. #include <lib/subghz/protocols/raw.h>
  7. #include <lib/subghz/subghz_protocol_registry.h>
  8. #include <flipper_format/flipper_format.h>
  9. #include "action_i.h"
  10. #include "quac.h"
  11. static FuriHalSubGhzPreset action_subghz_get_preset_name(const char* preset_name) {
  12. FuriHalSubGhzPreset preset = FuriHalSubGhzPresetIDLE;
  13. if(!strcmp(preset_name, "FuriHalSubGhzPresetOok270Async")) {
  14. preset = FuriHalSubGhzPresetOok270Async;
  15. } else if(!strcmp(preset_name, "FuriHalSubGhzPresetOok650Async")) {
  16. preset = FuriHalSubGhzPresetOok650Async;
  17. } else if(!strcmp(preset_name, "FuriHalSubGhzPreset2FSKDev238Async")) {
  18. preset = FuriHalSubGhzPreset2FSKDev238Async;
  19. } else if(!strcmp(preset_name, "FuriHalSubGhzPreset2FSKDev476Async")) {
  20. preset = FuriHalSubGhzPreset2FSKDev476Async;
  21. } else if(!strcmp(preset_name, "FuriHalSubGhzPresetCustom")) {
  22. preset = FuriHalSubGhzPresetCustom;
  23. } else {
  24. FURI_LOG_E(TAG, "SUBGHZ: Unknown preset!");
  25. }
  26. return preset;
  27. }
  28. // Lifted from flipperzero-firmware/applications/main/subghz/subghz_cli.c
  29. void action_subghz_tx(void* context, FuriString* action_path, FuriString* error) {
  30. App* app = context;
  31. FuriString* file_name = action_path;
  32. uint32_t repeat = 1; //
  33. // uint32_t device_ind = 0; // 0 - CC1101_INT, 1 - CC1101_EXT
  34. FlipperFormat* fff_data_file = flipper_format_file_alloc(app->storage);
  35. FlipperFormat* fff_data_raw = flipper_format_string_alloc();
  36. FuriString* temp_str;
  37. temp_str = furi_string_alloc();
  38. uint32_t temp_data32;
  39. bool check_file = false;
  40. const SubGhzDevice* device = NULL;
  41. uint32_t frequency = 0;
  42. SubGhzTransmitter* transmitter = NULL;
  43. FURI_LOG_I(TAG, "SUBGHZ: Action starting...");
  44. subghz_devices_init();
  45. SubGhzEnvironment* environment = subghz_environment_alloc();
  46. if(!subghz_environment_load_keystore(environment, SUBGHZ_KEYSTORE_DIR_NAME)) {
  47. FURI_LOG_E(TAG, "Load_keystore keeloq_mfcodes ERROR");
  48. }
  49. if(!subghz_environment_load_keystore(environment, SUBGHZ_KEYSTORE_DIR_USER_NAME)) {
  50. FURI_LOG_E(TAG, "Load_keystore keeloq_mfcodes_user ERROR");
  51. }
  52. subghz_environment_set_came_atomo_rainbow_table_file_name(
  53. environment, SUBGHZ_CAME_ATOMO_DIR_NAME);
  54. subghz_environment_set_alutech_at_4n_rainbow_table_file_name(
  55. environment, SUBGHZ_ALUTECH_AT_4N_DIR_NAME);
  56. subghz_environment_set_nice_flor_s_rainbow_table_file_name(
  57. environment, SUBGHZ_NICE_FLOR_S_DIR_NAME);
  58. subghz_environment_set_protocol_registry(environment, (void*)&subghz_protocol_registry);
  59. do {
  60. // SUBGHZ_DEVICE_CC1101_INT_NAME = "cc1101_int"
  61. device = subghz_devices_get_by_name("cc1101_int");
  62. if(!subghz_devices_is_connect(device)) {
  63. // power off
  64. if(furi_hal_power_is_otg_enabled()) furi_hal_power_disable_otg();
  65. device = subghz_devices_get_by_name("cc1101_int");
  66. // device_ind = 0;
  67. }
  68. if(!flipper_format_file_open_existing(fff_data_file, furi_string_get_cstr(file_name))) {
  69. FURI_LOG_E(TAG, "Error opening %s", furi_string_get_cstr(file_name));
  70. ACTION_SET_ERROR("SUBGHZ: Error opening %s", furi_string_get_cstr(file_name));
  71. break;
  72. }
  73. if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) {
  74. FURI_LOG_E(TAG, "Missing or incorrect header");
  75. ACTION_SET_ERROR("SUBGHZ: Missing or incorrect header");
  76. break;
  77. }
  78. if(((!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_KEY_FILE_TYPE)) ||
  79. (!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_RAW_FILE_TYPE))) &&
  80. temp_data32 == SUBGHZ_KEY_FILE_VERSION) {
  81. } else {
  82. FURI_LOG_E(TAG, "Type or version mismatch");
  83. ACTION_SET_ERROR("SUBGHZ: Type or version mismatch");
  84. break;
  85. }
  86. if(!flipper_format_read_uint32(fff_data_file, "Frequency", &frequency, 1)) {
  87. FURI_LOG_E(TAG, "Missing Frequency");
  88. ACTION_SET_ERROR("SUBGHZ: Missing frequency");
  89. break;
  90. }
  91. if(!subghz_devices_is_frequency_valid(device, frequency)) {
  92. FURI_LOG_E(TAG, "Frequency not supported");
  93. ACTION_SET_ERROR("SUBGHZ: Frequency not supported");
  94. break;
  95. }
  96. if(!flipper_format_read_string(fff_data_file, "Preset", temp_str)) {
  97. FURI_LOG_E(TAG, "Missing Preset");
  98. ACTION_SET_ERROR("SUBGHZ: Missing preset");
  99. break;
  100. }
  101. if(action_subghz_get_preset_name(furi_string_get_cstr(temp_str)) ==
  102. FuriHalSubGhzPresetIDLE) {
  103. ACTION_SET_ERROR("SUBGHZ: Unknown preset");
  104. break;
  105. }
  106. subghz_devices_begin(device);
  107. subghz_devices_reset(device);
  108. if(!strcmp(furi_string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) {
  109. uint8_t* custom_preset_data;
  110. uint32_t custom_preset_data_size;
  111. if(!flipper_format_get_value_count(fff_data_file, "Custom_preset_data", &temp_data32))
  112. break;
  113. if(!temp_data32 || (temp_data32 % 2)) {
  114. FURI_LOG_E(TAG, "Custom_preset_data size error");
  115. ACTION_SET_ERROR("SUBGHZ: Custom_preset_data size error");
  116. break;
  117. }
  118. custom_preset_data_size = sizeof(uint8_t) * temp_data32;
  119. custom_preset_data = malloc(custom_preset_data_size);
  120. if(!flipper_format_read_hex(
  121. fff_data_file,
  122. "Custom_preset_data",
  123. custom_preset_data,
  124. custom_preset_data_size)) {
  125. FURI_LOG_E(TAG, "Custom_preset_data read error");
  126. ACTION_SET_ERROR("SUBGHZ: Custom_preset_data read error");
  127. break;
  128. }
  129. subghz_devices_load_preset(
  130. device,
  131. action_subghz_get_preset_name(furi_string_get_cstr(temp_str)),
  132. custom_preset_data);
  133. free(custom_preset_data);
  134. } else {
  135. subghz_devices_load_preset(
  136. device, action_subghz_get_preset_name(furi_string_get_cstr(temp_str)), NULL);
  137. }
  138. subghz_devices_set_frequency(device, frequency);
  139. // Load Protocol
  140. if(!flipper_format_read_string(fff_data_file, "Protocol", temp_str)) {
  141. FURI_LOG_E(TAG, "Missing protocol");
  142. ACTION_SET_ERROR("SUBGHZ: Missing protocol");
  143. break;
  144. }
  145. SubGhzProtocolStatus status;
  146. bool is_init_protocol = true;
  147. if(!strcmp(furi_string_get_cstr(temp_str), "RAW")) {
  148. FURI_LOG_I(TAG, "Protocol = RAW");
  149. subghz_protocol_raw_gen_fff_data(
  150. fff_data_raw, furi_string_get_cstr(file_name), subghz_devices_get_name(device));
  151. transmitter =
  152. subghz_transmitter_alloc_init(environment, furi_string_get_cstr(temp_str));
  153. if(transmitter == NULL) {
  154. FURI_LOG_E(TAG, "Error transmitter");
  155. is_init_protocol = false;
  156. }
  157. if(is_init_protocol) {
  158. status = subghz_transmitter_deserialize(transmitter, fff_data_raw);
  159. if(status != SubGhzProtocolStatusOk) {
  160. FURI_LOG_E(TAG, "Error deserialize protocol");
  161. is_init_protocol = false;
  162. }
  163. }
  164. } else { // if not RAW protocol
  165. FURI_LOG_I(TAG, "Protocol != RAW");
  166. flipper_format_insert_or_update_uint32(fff_data_file, "Repeat", &repeat, 1);
  167. transmitter =
  168. subghz_transmitter_alloc_init(environment, furi_string_get_cstr(temp_str));
  169. if(transmitter == NULL) {
  170. FURI_LOG_E(TAG, "Error transmitter");
  171. is_init_protocol = false;
  172. }
  173. if(is_init_protocol) {
  174. status = subghz_transmitter_deserialize(transmitter, fff_data_file);
  175. if(status != SubGhzProtocolStatusOk) {
  176. FURI_LOG_E(TAG, "Error deserialize protocol");
  177. is_init_protocol = false;
  178. }
  179. }
  180. flipper_format_delete_key(fff_data_file, "Repeat");
  181. }
  182. if(is_init_protocol) {
  183. check_file = true;
  184. } else {
  185. subghz_devices_sleep(device);
  186. subghz_devices_end(device);
  187. subghz_transmitter_free(transmitter);
  188. }
  189. } while(false);
  190. flipper_format_free(fff_data_file);
  191. if(check_file) {
  192. furi_hal_power_suppress_charge_enter();
  193. FURI_LOG_I(
  194. TAG,
  195. "Listening at %s. Frequency=%lu, Protocol=%s",
  196. furi_string_get_cstr(file_name),
  197. frequency,
  198. furi_string_get_cstr(temp_str));
  199. do {
  200. // delay in downloading files and other preparatory processes
  201. furi_delay_ms(200);
  202. if(subghz_devices_start_async_tx(device, subghz_transmitter_yield, transmitter)) {
  203. while(!(subghz_devices_is_async_complete_tx(
  204. device))) { // || cli_cmd_interrupt_received
  205. furi_delay_ms(333);
  206. }
  207. subghz_devices_stop_async_tx(device);
  208. } else {
  209. FURI_LOG_W(TAG, "Transmission on this frequency is restricted in your region");
  210. }
  211. if(!strcmp(furi_string_get_cstr(temp_str), "RAW")) {
  212. subghz_transmitter_stop(transmitter);
  213. repeat--;
  214. if(repeat) subghz_transmitter_deserialize(transmitter, fff_data_raw);
  215. }
  216. } while(repeat && !strcmp(furi_string_get_cstr(temp_str), "RAW"));
  217. subghz_devices_sleep(device);
  218. subghz_devices_end(device);
  219. // power off
  220. if(furi_hal_power_is_otg_enabled()) furi_hal_power_disable_otg();
  221. furi_hal_power_suppress_charge_exit();
  222. subghz_transmitter_free(transmitter);
  223. }
  224. FURI_LOG_I(TAG, "SUBGHZ: Action complete.");
  225. flipper_format_free(fff_data_raw);
  226. furi_string_free(temp_str);
  227. subghz_devices_deinit();
  228. subghz_environment_free(environment);
  229. }