rolling_flaws_send_keeloq.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #include "rolling_flaws_send_keeloq.h"
  2. #include <lib/subghz/transmitter.h>
  3. #include <lib/subghz/devices/cc1101_int/cc1101_int_interconnect.h>
  4. #include <lib/subghz/protocols/protocol_items.h>
  5. #include <lib/subghz/devices/devices.h>
  6. #ifdef TAG
  7. #undef TAG
  8. #endif
  9. #define TAG "RollingFlawsSendKeeloq"
  10. static SubGhzEnvironment* load_environment() {
  11. SubGhzEnvironment* environment = subghz_environment_alloc();
  12. subghz_environment_load_keystore(environment, SUBGHZ_KEYSTORE_DIR_NAME);
  13. subghz_environment_load_keystore(environment, SUBGHZ_KEYSTORE_DIR_USER_NAME);
  14. subghz_environment_set_came_atomo_rainbow_table_file_name(
  15. environment, SUBGHZ_CAME_ATOMO_DIR_NAME);
  16. subghz_environment_set_alutech_at_4n_rainbow_table_file_name(
  17. environment, SUBGHZ_ALUTECH_AT_4N_DIR_NAME);
  18. subghz_environment_set_nice_flor_s_rainbow_table_file_name(
  19. environment, SUBGHZ_NICE_FLOR_S_DIR_NAME);
  20. subghz_environment_set_protocol_registry(environment, (void*)&subghz_protocol_registry);
  21. return environment;
  22. }
  23. static void send_keeloq(
  24. uint32_t frequency,
  25. uint32_t serial,
  26. uint8_t btn,
  27. uint16_t cnt,
  28. const char* name_sysmem) {
  29. if(!furi_hal_region_is_frequency_allowed(frequency)) {
  30. // TODO: Show friendly UI message if frequency is not allowed.
  31. FURI_LOG_E(TAG, "Frequency %lu is not allowed in this region.", frequency);
  32. return;
  33. }
  34. FURI_LOG_I(TAG, "Sending signal on frequency %lu", frequency);
  35. // Populate the CC101 device list.
  36. subghz_devices_init();
  37. // Get the internal radio device.
  38. const SubGhzDevice* device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME);
  39. // Get the Princeton SubGhzTransmitter (for decoding our file format).
  40. SubGhzEnvironment* environment = load_environment();
  41. subghz_environment_set_protocol_registry(environment, (void*)&subghz_protocol_registry);
  42. SubGhzTransmitter* transmitter =
  43. subghz_transmitter_alloc_init(environment, SUBGHZ_PROTOCOL_KEELOQ_NAME);
  44. // Load the payload we want to send into flipper_format.
  45. FlipperFormat* flipper_format = flipper_format_string_alloc();
  46. SubGhzRadioPreset* preset = malloc(sizeof(SubGhzRadioPreset));
  47. preset->frequency = frequency;
  48. preset->name = furi_string_alloc();
  49. furi_string_set(preset->name, "AM650");
  50. preset->data = NULL;
  51. preset->data_size = 0;
  52. SubGhzProtocolEncoderBase* encoder = subghz_transmitter_get_protocol_instance(transmitter);
  53. // sadly, in some firmware this has a Repeat of 100, which is too much for our purposes.
  54. subghz_protocol_keeloq_create_data(
  55. encoder, flipper_format, serial, btn, cnt, name_sysmem, preset);
  56. // Fill out the SubGhzProtocolDecoderPrinceton (which includes SubGhzBlockGeneric data) in our transmitter based on parsing flipper_format.
  57. // initance->encoder.upload[] gets filled out with duration and level information (You can think of this as the RAW data).
  58. SubGhzProtocolStatus status = subghz_transmitter_deserialize(transmitter, flipper_format);
  59. furi_assert(status == SubGhzProtocolStatusOk);
  60. // Currently unused for internal radio, but good idea to still invoke it.
  61. subghz_devices_begin(device);
  62. // Initializes the CC1101 SPI bus
  63. subghz_devices_reset(device);
  64. // Use one of the presets in subghz_device_cc1101_int_interconnect_load_preset. If the first argument is FuriHalSubGhzPresetCustom, then the second argument is
  65. // a custom register table (Reg, value, reg, value, ...,0, 0, PATable [0..7] entries).
  66. subghz_devices_load_preset(device, FuriHalSubGhzPresetOok650Async, NULL);
  67. // Set the frequency, RF switch path (band), calibrates the oscillator on the CC1101.
  68. frequency = subghz_devices_set_frequency(device, frequency);
  69. // Stop charging the battery while transmitting.
  70. furi_hal_power_suppress_charge_enter();
  71. // Start transmitting (keeps the DMA buffer filled with the encoder.upload[] data)
  72. if(subghz_devices_start_async_tx(device, subghz_transmitter_yield, transmitter)) {
  73. int max_counter = 10;
  74. // Wait for the transmission to complete, or counter to expire (about 1 second).
  75. while(max_counter-- && !(subghz_devices_is_async_complete_tx(device))) {
  76. furi_delay_ms(100);
  77. }
  78. // Stop transmitting, debug log (tag="FuriHalSubGhz") the duty cycle information.
  79. subghz_devices_stop_async_tx(device);
  80. }
  81. // clean up and shutdown cc1101
  82. subghz_devices_sleep(device);
  83. // also does a shutdown of cc1101
  84. subghz_devices_end(device);
  85. // remove the devices from the registry
  86. subghz_devices_deinit();
  87. // Allow the battery to charge again.
  88. furi_hal_power_suppress_charge_exit();
  89. // Free resources we allocated.
  90. flipper_format_free(flipper_format);
  91. subghz_transmitter_free(transmitter);
  92. subghz_environment_free(environment);
  93. }
  94. void send_keeloq_count(uint32_t fix, uint32_t count, const char* name, uint32_t frequency) {
  95. uint32_t serial = fix & 0x0FFFFFFF;
  96. uint8_t btn = fix >> 28;
  97. send_keeloq(frequency, serial, btn, count, name);
  98. }