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 = 1; // This is set to 10 in the cli - why?
  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_E(TAG, "Load_keystore keeloq_mfcodes ERROR");
  87. }
  88. if(!subghz_environment_load_keystore(environment, SUBGHZ_KEYSTORE_DIR_USER_NAME)) {
  89. FURI_LOG_E(TAG, "Load_keystore keeloq_mfcodes_user ERROR");
  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. if(action_subghz_get_preset_name(furi_string_get_cstr(temp_str)) ==
  139. FuriHalSubGhzPresetIDLE) {
  140. ACTION_SET_ERROR("SUBGHZ: Unknown preset");
  141. break;
  142. }
  143. subghz_devices_begin(device);
  144. subghz_devices_reset(device);
  145. if(!strcmp(furi_string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) {
  146. uint8_t* custom_preset_data;
  147. uint32_t custom_preset_data_size;
  148. if(!flipper_format_get_value_count(fff_data_file, "Custom_preset_data", &temp_data32))
  149. break;
  150. if(!temp_data32 || (temp_data32 % 2)) {
  151. FURI_LOG_E(TAG, "Custom_preset_data size error");
  152. ACTION_SET_ERROR("SUBGHZ: Custom_preset_data size error");
  153. break;
  154. }
  155. custom_preset_data_size = sizeof(uint8_t) * temp_data32;
  156. custom_preset_data = malloc(custom_preset_data_size);
  157. if(!flipper_format_read_hex(
  158. fff_data_file,
  159. "Custom_preset_data",
  160. custom_preset_data,
  161. custom_preset_data_size)) {
  162. FURI_LOG_E(TAG, "Custom_preset_data read error");
  163. ACTION_SET_ERROR("SUBGHZ: Custom_preset_data read error");
  164. break;
  165. }
  166. subghz_devices_load_preset(
  167. device,
  168. action_subghz_get_preset_name(furi_string_get_cstr(temp_str)),
  169. custom_preset_data);
  170. free(custom_preset_data);
  171. } else {
  172. subghz_devices_load_preset(
  173. device, action_subghz_get_preset_name(furi_string_get_cstr(temp_str)), NULL);
  174. }
  175. subghz_devices_set_frequency(device, frequency);
  176. // Load Protocol
  177. if(!flipper_format_read_string(fff_data_file, "Protocol", temp_str)) {
  178. FURI_LOG_E(TAG, "Missing protocol");
  179. ACTION_SET_ERROR("SUBGHZ: Missing protocol");
  180. break;
  181. }
  182. SubGhzProtocolStatus status;
  183. bool is_init_protocol = true;
  184. if(!strcmp(furi_string_get_cstr(temp_str), "RAW")) {
  185. FURI_LOG_I(TAG, "Protocol = RAW");
  186. subghz_protocol_raw_gen_fff_data(
  187. fff_data_raw, file_name, subghz_devices_get_name(device));
  188. transmitter =
  189. subghz_transmitter_alloc_init(environment, furi_string_get_cstr(temp_str));
  190. if(transmitter == NULL) {
  191. FURI_LOG_E(TAG, "Error transmitter");
  192. is_init_protocol = false;
  193. }
  194. if(is_init_protocol) {
  195. status = subghz_transmitter_deserialize(transmitter, fff_data_raw);
  196. if(status != SubGhzProtocolStatusOk) {
  197. FURI_LOG_E(TAG, "Error deserialize protocol");
  198. is_init_protocol = false;
  199. }
  200. }
  201. } else { // if not RAW protocol
  202. FURI_LOG_I(TAG, "Protocol != RAW");
  203. flipper_format_insert_or_update_uint32(fff_data_file, "Repeat", &repeat, 1);
  204. transmitter =
  205. subghz_transmitter_alloc_init(environment, furi_string_get_cstr(temp_str));
  206. if(transmitter == NULL) {
  207. FURI_LOG_E(TAG, "Error transmitter");
  208. is_init_protocol = false;
  209. }
  210. if(is_init_protocol) {
  211. status = subghz_transmitter_deserialize(transmitter, fff_data_file);
  212. if(status != SubGhzProtocolStatusOk) {
  213. FURI_LOG_E(TAG, "Error deserialize protocol");
  214. ACTION_SET_ERROR("SUBGHZ: Protocol error");
  215. is_init_protocol = false;
  216. }
  217. }
  218. flipper_format_delete_key(fff_data_file, "Repeat");
  219. }
  220. if(is_init_protocol) {
  221. check_file = true;
  222. } else {
  223. subghz_devices_sleep(device);
  224. subghz_devices_end(device);
  225. subghz_transmitter_free(transmitter);
  226. }
  227. } while(false);
  228. flipper_format_free(fff_data_file);
  229. if(check_file) {
  230. furi_hal_power_suppress_charge_enter();
  231. FURI_LOG_I(
  232. TAG,
  233. "Transmitting at %s. Frequency=%lu, Protocol=%s",
  234. file_name,
  235. frequency,
  236. furi_string_get_cstr(temp_str));
  237. do {
  238. // delay in downloading files and other preparatory processes
  239. furi_delay_ms(200);
  240. if(subghz_devices_start_async_tx(device, subghz_transmitter_yield, transmitter)) {
  241. while(!(subghz_devices_is_async_complete_tx(
  242. device))) { // || cli_cmd_interrupt_received
  243. furi_delay_ms(333);
  244. }
  245. subghz_devices_stop_async_tx(device);
  246. } else {
  247. FURI_LOG_W(TAG, "Transmission on this frequency is restricted in your region");
  248. }
  249. if(!strcmp(furi_string_get_cstr(temp_str), "RAW")) {
  250. subghz_transmitter_stop(transmitter);
  251. repeat--;
  252. if(repeat) subghz_transmitter_deserialize(transmitter, fff_data_raw);
  253. }
  254. } while(repeat && !strcmp(furi_string_get_cstr(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. }