action_subghz.c 11 KB

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