action_subghz.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  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. #define SUBGHZ_DEVICE_CC1101_EXT_NAME "cc1101_ext"
  12. #define SUBGHZ_DEVICE_CC1101_INT_NAME "cc1101_int"
  13. static FuriHalSubGhzPreset action_subghz_get_preset_name(const char* preset_name) {
  14. FuriHalSubGhzPreset preset = FuriHalSubGhzPresetIDLE;
  15. if(!strcmp(preset_name, "FuriHalSubGhzPresetOok270Async")) {
  16. preset = FuriHalSubGhzPresetOok270Async;
  17. } else if(!strcmp(preset_name, "FuriHalSubGhzPresetOok650Async")) {
  18. preset = FuriHalSubGhzPresetOok650Async;
  19. } else if(!strcmp(preset_name, "FuriHalSubGhzPreset2FSKDev238Async")) {
  20. preset = FuriHalSubGhzPreset2FSKDev238Async;
  21. } else if(!strcmp(preset_name, "FuriHalSubGhzPreset2FSKDev476Async")) {
  22. preset = FuriHalSubGhzPreset2FSKDev476Async;
  23. } else if(!strcmp(preset_name, "FuriHalSubGhzPresetCustom")) {
  24. preset = FuriHalSubGhzPresetCustom;
  25. } else {
  26. FURI_LOG_E(TAG, "SUBGHZ: Unknown preset!");
  27. }
  28. return preset;
  29. }
  30. static const SubGhzDevice* action_subghz_get_device(uint32_t* device_ind) {
  31. const SubGhzDevice* device = NULL;
  32. switch(*device_ind) {
  33. case 1:
  34. // Power on the external antenna
  35. uint8_t attempts = 5;
  36. while(--attempts > 0) {
  37. if(furi_hal_power_enable_otg()) break;
  38. }
  39. if(attempts == 0) {
  40. if(furi_hal_power_get_usb_voltage() < 4.5f) {
  41. FURI_LOG_E(
  42. TAG,
  43. "Error power otg enable. BQ2589 check otg fault = %d",
  44. furi_hal_power_check_otg_fault() ? 1 : 0);
  45. }
  46. }
  47. device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_EXT_NAME);
  48. break;
  49. default:
  50. device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME);
  51. break;
  52. }
  53. if(!subghz_devices_is_connect(device)) {
  54. // Power off
  55. if(furi_hal_power_is_otg_enabled()) {
  56. furi_hal_power_disable_otg();
  57. }
  58. if(*device_ind == 1) {
  59. FURI_LOG_W(TAG, "Can't connect to External antenna, using Internal");
  60. }
  61. device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME);
  62. *device_ind = 0;
  63. }
  64. return device;
  65. }
  66. // Lifted from flipperzero-firmware/applications/main/subghz/subghz_cli.c
  67. void action_subghz_tx(void* context, const FuriString* action_path, FuriString* error) {
  68. App* app = context;
  69. const char* file_name = furi_string_get_cstr(action_path);
  70. uint32_t repeat = 1; //
  71. uint32_t device_ind = app->settings.subghz_use_ext_antenna ? 1 : 0;
  72. FlipperFormat* fff_data_file = flipper_format_file_alloc(app->storage);
  73. FlipperFormat* fff_data_raw = flipper_format_string_alloc();
  74. FuriString* temp_str;
  75. temp_str = furi_string_alloc();
  76. uint32_t temp_data32;
  77. bool check_file = false;
  78. const SubGhzDevice* device = NULL;
  79. uint32_t frequency = 0;
  80. SubGhzTransmitter* transmitter = NULL;
  81. FURI_LOG_I(TAG, "SUBGHZ: Action starting...");
  82. subghz_devices_init();
  83. SubGhzEnvironment* environment = subghz_environment_alloc();
  84. if(!subghz_environment_load_keystore(environment, SUBGHZ_KEYSTORE_DIR_NAME)) {
  85. FURI_LOG_E(TAG, "Load_keystore keeloq_mfcodes ERROR");
  86. }
  87. if(!subghz_environment_load_keystore(environment, SUBGHZ_KEYSTORE_DIR_USER_NAME)) {
  88. FURI_LOG_E(TAG, "Load_keystore keeloq_mfcodes_user ERROR");
  89. }
  90. subghz_environment_set_came_atomo_rainbow_table_file_name(
  91. environment, SUBGHZ_CAME_ATOMO_DIR_NAME);
  92. subghz_environment_set_alutech_at_4n_rainbow_table_file_name(
  93. environment, SUBGHZ_ALUTECH_AT_4N_DIR_NAME);
  94. subghz_environment_set_nice_flor_s_rainbow_table_file_name(
  95. environment, SUBGHZ_NICE_FLOR_S_DIR_NAME);
  96. subghz_environment_set_protocol_registry(environment, (void*)&subghz_protocol_registry);
  97. do {
  98. device = action_subghz_get_device(&device_ind);
  99. if(device == NULL) {
  100. FURI_LOG_E(TAG, "Error device not found");
  101. ACTION_SET_ERROR("SUBGHZ: Device not found");
  102. break;
  103. }
  104. // // SUBGHZ_DEVICE_CC1101_INT_NAME = "cc1101_int"
  105. // device = subghz_devices_get_by_name("cc1101_int");
  106. // if(!subghz_devices_is_connect(device)) {
  107. // // power off
  108. // if(furi_hal_power_is_otg_enabled()) furi_hal_power_disable_otg();
  109. // device = subghz_devices_get_by_name("cc1101_int");
  110. // // device_ind = 0;
  111. // }
  112. if(!flipper_format_file_open_existing(fff_data_file, file_name)) {
  113. FURI_LOG_E(TAG, "Error opening %s", file_name);
  114. ACTION_SET_ERROR("SUBGHZ: Error opening %s", file_name);
  115. break;
  116. }
  117. if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) {
  118. FURI_LOG_E(TAG, "Missing or incorrect header");
  119. ACTION_SET_ERROR("SUBGHZ: Missing or incorrect header");
  120. break;
  121. }
  122. if(((!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_KEY_FILE_TYPE)) ||
  123. (!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_RAW_FILE_TYPE))) &&
  124. temp_data32 == SUBGHZ_KEY_FILE_VERSION) {
  125. } else {
  126. FURI_LOG_E(TAG, "Type or version mismatch");
  127. ACTION_SET_ERROR("SUBGHZ: Type or version mismatch");
  128. break;
  129. }
  130. if(!flipper_format_read_uint32(fff_data_file, "Frequency", &frequency, 1)) {
  131. FURI_LOG_E(TAG, "Missing Frequency");
  132. ACTION_SET_ERROR("SUBGHZ: Missing frequency");
  133. break;
  134. }
  135. if(!subghz_devices_is_frequency_valid(device, frequency)) {
  136. FURI_LOG_E(TAG, "Frequency not supported");
  137. ACTION_SET_ERROR("SUBGHZ: Frequency not supported");
  138. break;
  139. }
  140. if(!flipper_format_read_string(fff_data_file, "Preset", temp_str)) {
  141. FURI_LOG_E(TAG, "Missing Preset");
  142. ACTION_SET_ERROR("SUBGHZ: Missing preset");
  143. break;
  144. }
  145. if(action_subghz_get_preset_name(furi_string_get_cstr(temp_str)) ==
  146. FuriHalSubGhzPresetIDLE) {
  147. ACTION_SET_ERROR("SUBGHZ: Unknown preset");
  148. break;
  149. }
  150. subghz_devices_begin(device);
  151. subghz_devices_reset(device);
  152. if(!strcmp(furi_string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) {
  153. uint8_t* custom_preset_data;
  154. uint32_t custom_preset_data_size;
  155. if(!flipper_format_get_value_count(fff_data_file, "Custom_preset_data", &temp_data32))
  156. break;
  157. if(!temp_data32 || (temp_data32 % 2)) {
  158. FURI_LOG_E(TAG, "Custom_preset_data size error");
  159. ACTION_SET_ERROR("SUBGHZ: Custom_preset_data size error");
  160. break;
  161. }
  162. custom_preset_data_size = sizeof(uint8_t) * temp_data32;
  163. custom_preset_data = malloc(custom_preset_data_size);
  164. if(!flipper_format_read_hex(
  165. fff_data_file,
  166. "Custom_preset_data",
  167. custom_preset_data,
  168. custom_preset_data_size)) {
  169. FURI_LOG_E(TAG, "Custom_preset_data read error");
  170. ACTION_SET_ERROR("SUBGHZ: Custom_preset_data read error");
  171. break;
  172. }
  173. subghz_devices_load_preset(
  174. device,
  175. action_subghz_get_preset_name(furi_string_get_cstr(temp_str)),
  176. custom_preset_data);
  177. free(custom_preset_data);
  178. } else {
  179. subghz_devices_load_preset(
  180. device, action_subghz_get_preset_name(furi_string_get_cstr(temp_str)), NULL);
  181. }
  182. subghz_devices_set_frequency(device, frequency);
  183. // Load Protocol
  184. if(!flipper_format_read_string(fff_data_file, "Protocol", temp_str)) {
  185. FURI_LOG_E(TAG, "Missing protocol");
  186. ACTION_SET_ERROR("SUBGHZ: Missing protocol");
  187. break;
  188. }
  189. SubGhzProtocolStatus status;
  190. bool is_init_protocol = true;
  191. if(!strcmp(furi_string_get_cstr(temp_str), "RAW")) {
  192. FURI_LOG_I(TAG, "Protocol = RAW");
  193. subghz_protocol_raw_gen_fff_data(
  194. fff_data_raw, file_name, subghz_devices_get_name(device));
  195. transmitter =
  196. subghz_transmitter_alloc_init(environment, furi_string_get_cstr(temp_str));
  197. if(transmitter == NULL) {
  198. FURI_LOG_E(TAG, "Error transmitter");
  199. is_init_protocol = false;
  200. }
  201. if(is_init_protocol) {
  202. status = subghz_transmitter_deserialize(transmitter, fff_data_raw);
  203. if(status != SubGhzProtocolStatusOk) {
  204. FURI_LOG_E(TAG, "Error deserialize protocol");
  205. is_init_protocol = false;
  206. }
  207. }
  208. } else { // if not RAW protocol
  209. FURI_LOG_I(TAG, "Protocol != RAW");
  210. flipper_format_insert_or_update_uint32(fff_data_file, "Repeat", &repeat, 1);
  211. transmitter =
  212. subghz_transmitter_alloc_init(environment, furi_string_get_cstr(temp_str));
  213. if(transmitter == NULL) {
  214. FURI_LOG_E(TAG, "Error transmitter");
  215. is_init_protocol = false;
  216. }
  217. if(is_init_protocol) {
  218. status = subghz_transmitter_deserialize(transmitter, fff_data_file);
  219. if(status != SubGhzProtocolStatusOk) {
  220. FURI_LOG_E(TAG, "Error deserialize protocol");
  221. is_init_protocol = false;
  222. }
  223. }
  224. flipper_format_delete_key(fff_data_file, "Repeat");
  225. }
  226. if(is_init_protocol) {
  227. check_file = true;
  228. } else {
  229. subghz_devices_sleep(device);
  230. subghz_devices_end(device);
  231. subghz_transmitter_free(transmitter);
  232. }
  233. } while(false);
  234. flipper_format_free(fff_data_file);
  235. if(check_file) {
  236. furi_hal_power_suppress_charge_enter();
  237. FURI_LOG_I(
  238. TAG,
  239. "Transmitting at %s. Frequency=%lu, Protocol=%s",
  240. file_name,
  241. frequency,
  242. furi_string_get_cstr(temp_str));
  243. do {
  244. // delay in downloading files and other preparatory processes
  245. furi_delay_ms(200);
  246. if(subghz_devices_start_async_tx(device, subghz_transmitter_yield, transmitter)) {
  247. while(!(subghz_devices_is_async_complete_tx(
  248. device))) { // || cli_cmd_interrupt_received
  249. furi_delay_ms(333);
  250. }
  251. subghz_devices_stop_async_tx(device);
  252. } else {
  253. FURI_LOG_W(TAG, "Transmission on this frequency is restricted in your region");
  254. }
  255. if(!strcmp(furi_string_get_cstr(temp_str), "RAW")) {
  256. subghz_transmitter_stop(transmitter);
  257. repeat--;
  258. if(repeat) subghz_transmitter_deserialize(transmitter, fff_data_raw);
  259. }
  260. } while(repeat && !strcmp(furi_string_get_cstr(temp_str), "RAW"));
  261. subghz_devices_sleep(device);
  262. subghz_devices_end(device);
  263. // power off
  264. if(furi_hal_power_is_otg_enabled()) furi_hal_power_disable_otg();
  265. furi_hal_power_suppress_charge_exit();
  266. subghz_transmitter_free(transmitter);
  267. }
  268. FURI_LOG_I(TAG, "SUBGHZ: Action complete.");
  269. flipper_format_free(fff_data_raw);
  270. furi_string_free(temp_str);
  271. subghz_devices_deinit();
  272. subghz_environment_free(environment);
  273. }