 c209ec56fc
			
		
	
	
		c209ec56fc
		
			
		
	
	
	
	
		
			
			* Notification: use all input for backlight, otherwise it is causing issues on repeat. Dolphin: rework debug tools. * Notification: remove unused variable * Applications: fix incorrect count in system apps list * SubGhz: fix memory leak in settings * SubGhz: fix incorrect frequency in newly created keys * Loader: make cli command parallel safe
		
			
				
	
	
		
			368 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			368 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include "subghz_setting.h"
 | |
| #include "subghz_i.h"
 | |
| 
 | |
| #include <furi.h>
 | |
| #include <m-list.h>
 | |
| #include <lib/flipper_format/flipper_format.h>
 | |
| 
 | |
| #define TAG "SubGhzSetting"
 | |
| 
 | |
| #define SUBGHZ_SETTING_FILE_VERSION 1
 | |
| #define SUBGHZ_SETTING_FILE_TYPE "Flipper SubGhz Setting File"
 | |
| 
 | |
| typedef enum {
 | |
|     SubGhzSettingStateNoLoad = 0,
 | |
|     SubGhzSettingStateLoadFrequencyDefault,
 | |
|     SubGhzSettingStateOkLoad,
 | |
| } SubGhzSettingState;
 | |
| 
 | |
| static const uint32_t subghz_frequencies[] = {
 | |
|     /* 300 - 348 */
 | |
|     300000000,
 | |
|     303875000,
 | |
|     304250000,
 | |
|     315000000,
 | |
|     318000000,
 | |
| 
 | |
|     /* 387 - 464 */
 | |
|     390000000,
 | |
|     418000000,
 | |
|     433075000, /* LPD433 first */
 | |
|     433420000,
 | |
|     433920000, /* LPD433 mid */
 | |
|     434420000,
 | |
|     434775000, /* LPD433 last channels */
 | |
|     438900000,
 | |
| 
 | |
|     /* 779 - 928 */
 | |
|     868350000,
 | |
|     915000000,
 | |
|     925000000,
 | |
|     0,
 | |
| };
 | |
| static const uint32_t subghz_hopper_frequencies[] = {
 | |
|     315000000,
 | |
|     318000000,
 | |
|     390000000,
 | |
|     433920000,
 | |
|     868350000,
 | |
|     0,
 | |
| };
 | |
| static const uint32_t subghz_frequency_default_index = 9;
 | |
| 
 | |
| static const uint32_t subghz_frequencies_region_eu_ru[] = {
 | |
|     /* 300 - 348 */
 | |
|     300000000,
 | |
|     303875000,
 | |
|     304250000,
 | |
|     315000000,
 | |
|     318000000,
 | |
| 
 | |
|     /* 387 - 464 */
 | |
|     390000000,
 | |
|     418000000,
 | |
|     433075000, /* LPD433 first */
 | |
|     433420000,
 | |
|     433920000, /* LPD433 mid */
 | |
|     434420000,
 | |
|     434775000, /* LPD433 last channels */
 | |
|     438900000,
 | |
| 
 | |
|     /* 779 - 928 */
 | |
|     868350000,
 | |
|     915000000,
 | |
|     925000000,
 | |
|     0,
 | |
| };
 | |
| static const uint32_t subghz_hopper_frequencies_region_eu_ru[] = {
 | |
|     315000000,
 | |
|     318000000,
 | |
|     390000000,
 | |
|     433920000,
 | |
|     868350000,
 | |
|     0,
 | |
| };
 | |
| static const uint32_t subghz_frequency_default_index_region_eu_ru = 9;
 | |
| 
 | |
| static const uint32_t subghz_frequencies_region_us_ca_au[] = {
 | |
|     /* 300 - 348 */
 | |
|     300000000,
 | |
|     303875000,
 | |
|     304250000,
 | |
|     315000000,
 | |
|     318000000,
 | |
| 
 | |
|     /* 387 - 464 */
 | |
|     390000000,
 | |
|     418000000,
 | |
|     433075000, /* LPD433 first */
 | |
|     433420000,
 | |
|     433920000, /* LPD433 mid */
 | |
|     434420000,
 | |
|     434775000, /* LPD433 last channels */
 | |
|     438900000,
 | |
| 
 | |
|     /* 779 - 928 */
 | |
|     868350000,
 | |
|     915000000,
 | |
|     925000000,
 | |
|     0,
 | |
| };
 | |
| static const uint32_t subghz_hopper_frequencies_region_us_ca_au[] = {
 | |
|     315000000,
 | |
|     318000000,
 | |
|     390000000,
 | |
|     433920000,
 | |
|     868350000,
 | |
|     0,
 | |
| };
 | |
| static const uint32_t subghz_frequency_default_index_region_us_ca_au = 9;
 | |
| 
 | |
| static const uint32_t subghz_frequencies_region_jp[] = {
 | |
|     /* 300 - 348 */
 | |
|     300000000,
 | |
|     303875000,
 | |
|     304250000,
 | |
|     315000000,
 | |
|     318000000,
 | |
| 
 | |
|     /* 387 - 464 */
 | |
|     390000000,
 | |
|     418000000,
 | |
|     433075000, /* LPD433 first */
 | |
|     433420000,
 | |
|     433920000, /* LPD433 mid */
 | |
|     434420000,
 | |
|     434775000, /* LPD433 last channels */
 | |
|     438900000,
 | |
| 
 | |
|     /* 779 - 928 */
 | |
|     868350000,
 | |
|     915000000,
 | |
|     925000000,
 | |
|     0,
 | |
| };
 | |
| static const uint32_t subghz_hopper_frequencies_region_jp[] = {
 | |
|     315000000,
 | |
|     318000000,
 | |
|     390000000,
 | |
|     433920000,
 | |
|     868350000,
 | |
|     0,
 | |
| };
 | |
| static const uint32_t subghz_frequency_default_index_region_jp = 9;
 | |
| 
 | |
| LIST_DEF(FrequenciesList, uint32_t)
 | |
| 
 | |
| struct SubGhzSetting {
 | |
|     FrequenciesList_t frequencies;
 | |
|     FrequenciesList_t hopper_frequencies;
 | |
|     size_t frequencies_count;
 | |
|     size_t hopper_frequencies_count;
 | |
|     uint32_t frequency_default_index;
 | |
| };
 | |
| 
 | |
| SubGhzSetting* subghz_setting_alloc(void) {
 | |
|     SubGhzSetting* instance = malloc(sizeof(SubGhzSetting));
 | |
|     FrequenciesList_init(instance->frequencies);
 | |
|     FrequenciesList_init(instance->hopper_frequencies);
 | |
|     return instance;
 | |
| }
 | |
| 
 | |
| void subghz_setting_free(SubGhzSetting* instance) {
 | |
|     furi_assert(instance);
 | |
|     FrequenciesList_clear(instance->frequencies);
 | |
|     FrequenciesList_clear(instance->hopper_frequencies);
 | |
|     free(instance);
 | |
| }
 | |
| 
 | |
| void subghz_setting_load_default(
 | |
|     SubGhzSetting* instance,
 | |
|     const uint32_t frequencies[],
 | |
|     const uint32_t hopper_frequencies[],
 | |
|     const uint32_t frequency_default_index) {
 | |
|     furi_assert(instance);
 | |
|     size_t i = 0;
 | |
|     FrequenciesList_clear(instance->frequencies);
 | |
|     FrequenciesList_clear(instance->hopper_frequencies);
 | |
|     i = 0;
 | |
|     while(frequencies[i]) {
 | |
|         FrequenciesList_push_back(instance->frequencies, frequencies[i]);
 | |
|         i++;
 | |
|     }
 | |
|     instance->frequencies_count = i;
 | |
| 
 | |
|     i = 0;
 | |
|     while(hopper_frequencies[i]) {
 | |
|         FrequenciesList_push_back(instance->hopper_frequencies, hopper_frequencies[i]);
 | |
|         i++;
 | |
|     }
 | |
|     instance->hopper_frequencies_count = i;
 | |
| 
 | |
|     instance->frequency_default_index = frequency_default_index;
 | |
| }
 | |
| 
 | |
| void subghz_setting_load(SubGhzSetting* instance, const char* file_path) {
 | |
|     furi_assert(instance);
 | |
| 
 | |
|     FrequenciesList_clear(instance->frequencies);
 | |
|     FrequenciesList_clear(instance->hopper_frequencies);
 | |
| 
 | |
|     Storage* storage = furi_record_open("storage");
 | |
|     FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
 | |
| 
 | |
|     string_t temp_str;
 | |
|     string_init(temp_str);
 | |
|     uint32_t temp_data32;
 | |
|     SubGhzSettingState loading = SubGhzSettingStateNoLoad;
 | |
|     uint16_t i = 0;
 | |
| 
 | |
|     if(file_path) {
 | |
|         do {
 | |
|             if(!flipper_format_file_open_existing(fff_data_file, file_path)) {
 | |
|                 FURI_LOG_E(TAG, "Error open file %s", file_path);
 | |
|                 break;
 | |
|             }
 | |
| 
 | |
|             if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) {
 | |
|                 FURI_LOG_E(TAG, "Missing or incorrect header");
 | |
|                 break;
 | |
|             }
 | |
| 
 | |
|             if((!strcmp(string_get_cstr(temp_str), SUBGHZ_SETTING_FILE_TYPE)) &&
 | |
|                temp_data32 == SUBGHZ_SETTING_FILE_VERSION) {
 | |
|             } else {
 | |
|                 FURI_LOG_E(TAG, "Type or version mismatch");
 | |
|                 break;
 | |
|             }
 | |
| 
 | |
|             if(!flipper_format_rewind(fff_data_file)) {
 | |
|                 FURI_LOG_E(TAG, "Rewind error");
 | |
|                 break;
 | |
|             }
 | |
|             i = 0;
 | |
|             while(flipper_format_read_uint32(
 | |
|                 fff_data_file, "Frequency", (uint32_t*)&temp_data32, 1)) {
 | |
|                 if(furi_hal_subghz_is_frequency_valid(temp_data32)) {
 | |
|                     FURI_LOG_I(TAG, "Frequency loaded %lu", temp_data32);
 | |
|                     FrequenciesList_push_back(instance->frequencies, temp_data32);
 | |
|                     i++;
 | |
|                 } else {
 | |
|                     FURI_LOG_E(TAG, "Frequency not supported %lu", temp_data32);
 | |
|                 }
 | |
|             }
 | |
|             instance->frequencies_count = i;
 | |
| 
 | |
|             if(!flipper_format_rewind(fff_data_file)) {
 | |
|                 FURI_LOG_E(TAG, "Rewind error");
 | |
|                 break;
 | |
|             }
 | |
|             i = 0;
 | |
|             while(flipper_format_read_uint32(
 | |
|                 fff_data_file, "Hopper_frequency", (uint32_t*)&temp_data32, 1)) {
 | |
|                 if(furi_hal_subghz_is_frequency_valid(temp_data32)) {
 | |
|                     FURI_LOG_I(TAG, "Hopper frequency loaded %lu", temp_data32);
 | |
|                     FrequenciesList_push_back(instance->hopper_frequencies, temp_data32);
 | |
|                     i++;
 | |
|                 } else {
 | |
|                     FURI_LOG_E(TAG, "Hopper frequency not supported %lu", temp_data32);
 | |
|                 }
 | |
|             }
 | |
|             instance->hopper_frequencies_count = i;
 | |
| 
 | |
|             if(!flipper_format_rewind(fff_data_file)) {
 | |
|                 FURI_LOG_E(TAG, "Rewind error");
 | |
|                 break;
 | |
|             }
 | |
|             if(!flipper_format_read_uint32(
 | |
|                    fff_data_file, "Frequency_default", (uint32_t*)&temp_data32, 1)) {
 | |
|                 FURI_LOG_E(TAG, "Frequency default missing");
 | |
|                 break;
 | |
|             }
 | |
| 
 | |
|             for(i = 0; i < instance->frequencies_count; i++) {
 | |
|                 if(subghz_setting_get_frequency(instance, i) == temp_data32) {
 | |
|                     instance->frequency_default_index = i;
 | |
|                     FURI_LOG_I(TAG, "Frequency default index %lu", i);
 | |
|                     loading = SubGhzSettingStateLoadFrequencyDefault;
 | |
|                     break;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             if(loading == SubGhzSettingStateLoadFrequencyDefault) {
 | |
|                 loading = SubGhzSettingStateOkLoad;
 | |
|             } else {
 | |
|                 FURI_LOG_E(TAG, "Frequency default index missing");
 | |
|             }
 | |
|         } while(false);
 | |
|     }
 | |
| 
 | |
|     string_clear(temp_str);
 | |
|     flipper_format_free(fff_data_file);
 | |
|     furi_record_close("storage");
 | |
| 
 | |
|     if(loading != SubGhzSettingStateOkLoad) {
 | |
|         switch(furi_hal_version_get_hw_region()) {
 | |
|         case FuriHalVersionRegionEuRu:
 | |
|             subghz_setting_load_default(
 | |
|                 instance,
 | |
|                 subghz_frequencies_region_eu_ru,
 | |
|                 subghz_hopper_frequencies_region_eu_ru,
 | |
|                 subghz_frequency_default_index_region_eu_ru);
 | |
|             break;
 | |
|         case FuriHalVersionRegionUsCaAu:
 | |
|             subghz_setting_load_default(
 | |
|                 instance,
 | |
|                 subghz_frequencies_region_us_ca_au,
 | |
|                 subghz_hopper_frequencies_region_us_ca_au,
 | |
|                 subghz_frequency_default_index_region_us_ca_au);
 | |
|             break;
 | |
|         case FuriHalVersionRegionJp:
 | |
|             subghz_setting_load_default(
 | |
|                 instance,
 | |
|                 subghz_frequencies_region_jp,
 | |
|                 subghz_hopper_frequencies_region_jp,
 | |
|                 subghz_frequency_default_index_region_jp);
 | |
|             break;
 | |
| 
 | |
|         default:
 | |
|             subghz_setting_load_default(
 | |
|                 instance,
 | |
|                 subghz_frequencies,
 | |
|                 subghz_hopper_frequencies,
 | |
|                 subghz_frequency_default_index);
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| size_t subghz_setting_get_frequency_count(SubGhzSetting* instance) {
 | |
|     furi_assert(instance);
 | |
|     return instance->frequencies_count;
 | |
| }
 | |
| 
 | |
| size_t subghz_setting_get_hopper_frequency_count(SubGhzSetting* instance) {
 | |
|     furi_assert(instance);
 | |
|     return instance->hopper_frequencies_count;
 | |
| }
 | |
| 
 | |
| uint32_t subghz_setting_get_frequency(SubGhzSetting* instance, size_t idx) {
 | |
|     furi_assert(instance);
 | |
|     return *FrequenciesList_get(instance->frequencies, idx);
 | |
| }
 | |
| 
 | |
| uint32_t subghz_setting_get_hopper_frequency(SubGhzSetting* instance, size_t idx) {
 | |
|     furi_assert(instance);
 | |
|     return *FrequenciesList_get(instance->hopper_frequencies, idx);
 | |
| }
 | |
| 
 | |
| uint32_t subghz_setting_get_frequency_default_index(SubGhzSetting* instance) {
 | |
|     furi_assert(instance);
 | |
|     return instance->frequency_default_index;
 | |
| }
 | |
| 
 | |
| uint32_t subghz_setting_get_default_frequency(SubGhzSetting* instance) {
 | |
|     furi_assert(instance);
 | |
|     return *FrequenciesList_get(instance->frequencies, instance->frequency_default_index);
 | |
| }
 |