[FL-2297, FL-2289] Power info command, Validator fixes (#1097)
* Power info command, validator fixes * strdup in validator, fix memory leak * furi_hal_crypto fixed again * FuriHal: limit ARR and CC in speaker hal * FuriHal: LL_TIM_DisableAllOutputs in speaker stop * Rpc: fix memory leak in screen streaming * Get rid of crypto_enable/crypto_disable Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
		| @@ -15,13 +15,16 @@ | ||||
| #define CRYPTO_TIMEOUT (1000) | ||||
|  | ||||
| #define CRYPTO_MODE_ENCRYPT 0U | ||||
| #define CRYPTO_MODE_INIT (AES_CR_MODE_0) | ||||
| #define CRYPTO_MODE_DECRYPT (AES_CR_MODE_1) | ||||
| #define CRYPTO_MODE_DECRYPT_INIT (AES_CR_MODE_0 | AES_CR_MODE_1) | ||||
|  | ||||
| #define CRYPTO_DATATYPE_32B 0U | ||||
| #define CRYPTO_KEYSIZE_256B (AES_CR_KEYSIZE) | ||||
| #define CRYPTO_AES_CBC (AES_CR_CHMOD_0) | ||||
|  | ||||
| static osMutexId_t furi_hal_crypto_mutex = NULL; | ||||
| static bool furi_hal_crypto_mode_init_done = false; | ||||
|  | ||||
| static const uint8_t enclave_signature_iv[ENCLAVE_FACTORY_KEY_SLOTS][16] = { | ||||
|     {0xac, 0x5d, 0x68, 0xb8, 0x79, 0x74, 0xfc, 0x7f, 0x45, 0x02, 0x82, 0xf1, 0x48, 0x7e, 0x75, 0x8a}, | ||||
| @@ -177,20 +180,8 @@ bool furi_hal_crypto_store_add_key(FuriHalCryptoKey* key, uint8_t* slot) { | ||||
|     return (shci_state == SHCI_Success); | ||||
| } | ||||
|  | ||||
| static void crypto_enable() { | ||||
|     SET_BIT(AES1->CR, AES_CR_EN); | ||||
| } | ||||
|  | ||||
| static void crypto_disable() { | ||||
|     CLEAR_BIT(AES1->CR, AES_CR_EN); | ||||
|     FURI_CRITICAL_ENTER(); | ||||
|     LL_AHB2_GRP1_ForceReset(LL_AHB2_GRP1_PERIPH_AES1); | ||||
|     LL_AHB2_GRP1_ReleaseReset(LL_AHB2_GRP1_PERIPH_AES1); | ||||
|     FURI_CRITICAL_EXIT(); | ||||
| } | ||||
|  | ||||
| static void crypto_key_init(uint32_t* key, uint32_t* iv) { | ||||
|     crypto_disable(); | ||||
|     CLEAR_BIT(AES1->CR, AES_CR_EN); | ||||
|     MODIFY_REG( | ||||
|         AES1->CR, | ||||
|         AES_CR_DATATYPE | AES_CR_KEYSIZE | AES_CR_CHMOD, | ||||
| @@ -254,12 +245,13 @@ bool furi_hal_crypto_store_load_key(uint8_t slot, const uint8_t* iv) { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     furi_hal_crypto_mode_init_done = false; | ||||
|     crypto_key_init(NULL, (uint32_t*)iv); | ||||
|  | ||||
|     if(SHCI_C2_FUS_LoadUsrKey(slot) == SHCI_Success) { | ||||
|         return true; | ||||
|     } else { | ||||
|         crypto_disable(); | ||||
|         CLEAR_BIT(AES1->CR, AES_CR_EN); | ||||
|         furi_check(osMutexRelease(furi_hal_crypto_mutex) == osOK); | ||||
|         return false; | ||||
|     } | ||||
| @@ -270,9 +262,16 @@ bool furi_hal_crypto_store_unload_key(uint8_t slot) { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     crypto_disable(); | ||||
|     CLEAR_BIT(AES1->CR, AES_CR_EN); | ||||
|  | ||||
|     SHCI_CmdStatus_t shci_state = SHCI_C2_FUS_UnloadUsrKey(slot); | ||||
|     furi_assert(shci_state == SHCI_Success); | ||||
|  | ||||
|     FURI_CRITICAL_ENTER(); | ||||
|     LL_AHB2_GRP1_ForceReset(LL_AHB2_GRP1_PERIPH_AES1); | ||||
|     LL_AHB2_GRP1_ReleaseReset(LL_AHB2_GRP1_PERIPH_AES1); | ||||
|     FURI_CRITICAL_EXIT(); | ||||
|  | ||||
|     furi_check(osMutexRelease(furi_hal_crypto_mutex) == osOK); | ||||
|     return (shci_state == SHCI_Success); | ||||
| } | ||||
| @@ -280,7 +279,7 @@ bool furi_hal_crypto_store_unload_key(uint8_t slot) { | ||||
| bool furi_hal_crypto_encrypt(const uint8_t* input, uint8_t* output, size_t size) { | ||||
|     bool state = false; | ||||
|  | ||||
|     crypto_enable(); | ||||
|     SET_BIT(AES1->CR, AES_CR_EN); | ||||
|  | ||||
|     MODIFY_REG(AES1->CR, AES_CR_MODE, CRYPTO_MODE_ENCRYPT); | ||||
|  | ||||
| @@ -295,7 +294,7 @@ bool furi_hal_crypto_encrypt(const uint8_t* input, uint8_t* output, size_t size) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     crypto_disable(); | ||||
|     CLEAR_BIT(AES1->CR, AES_CR_EN); | ||||
|  | ||||
|     return state; | ||||
| } | ||||
| @@ -303,9 +302,28 @@ bool furi_hal_crypto_encrypt(const uint8_t* input, uint8_t* output, size_t size) | ||||
| bool furi_hal_crypto_decrypt(const uint8_t* input, uint8_t* output, size_t size) { | ||||
|     bool state = false; | ||||
|  | ||||
|     MODIFY_REG(AES1->CR, AES_CR_MODE, CRYPTO_MODE_DECRYPT_INIT); | ||||
|     if(!furi_hal_crypto_mode_init_done) { | ||||
|         MODIFY_REG(AES1->CR, AES_CR_MODE, CRYPTO_MODE_INIT); | ||||
|  | ||||
|     crypto_enable(); | ||||
|         SET_BIT(AES1->CR, AES_CR_EN); | ||||
|  | ||||
|         uint32_t countdown = CRYPTO_TIMEOUT; | ||||
|         while(!READ_BIT(AES1->SR, AES_SR_CCF)) { | ||||
|             if(LL_SYSTICK_IsActiveCounterFlag()) { | ||||
|                 countdown--; | ||||
|             } | ||||
|             if(countdown == 0) { | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         SET_BIT(AES1->CR, AES_CR_CCFC); | ||||
|  | ||||
|         furi_hal_crypto_mode_init_done = true; | ||||
|     } | ||||
|  | ||||
|     MODIFY_REG(AES1->CR, AES_CR_MODE, CRYPTO_MODE_DECRYPT); | ||||
|     SET_BIT(AES1->CR, AES_CR_EN); | ||||
|  | ||||
|     for(size_t i = 0; i < size; i += CRYPTO_BLK_LEN) { | ||||
|         size_t blk_len = size - i; | ||||
| @@ -318,7 +336,7 @@ bool furi_hal_crypto_decrypt(const uint8_t* input, uint8_t* output, size_t size) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     crypto_disable(); | ||||
|     CLEAR_BIT(AES1->CR, AES_CR_EN); | ||||
|  | ||||
|     return state; | ||||
| } | ||||
|   | ||||
| @@ -239,6 +239,13 @@ uint32_t furi_hal_power_get_battery_full_capacity() { | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| uint32_t furi_hal_power_get_battery_design_capacity() { | ||||
|     furi_hal_i2c_acquire(&furi_hal_i2c_handle_power); | ||||
|     uint32_t ret = bq27220_get_design_capacity(&furi_hal_i2c_handle_power); | ||||
|     furi_hal_i2c_release(&furi_hal_i2c_handle_power); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| float furi_hal_power_get_battery_voltage(FuriHalPowerIC ic) { | ||||
|     float ret = 0.0f; | ||||
|  | ||||
| @@ -399,3 +406,58 @@ void furi_hal_power_suppress_charge_exit() { | ||||
|         furi_hal_i2c_release(&furi_hal_i2c_handle_power); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void furi_hal_power_info_get(FuriHalPowerInfoCallback out, void* context) { | ||||
|     furi_assert(out); | ||||
|  | ||||
|     string_t value; | ||||
|     string_init(value); | ||||
|  | ||||
|     // Power Info version | ||||
|     out("power_info_major", "1", false, context); | ||||
|     out("power_info_minor", "0", false, context); | ||||
|  | ||||
|     uint8_t charge = furi_hal_power_get_pct(); | ||||
|  | ||||
|     string_printf(value, "%u", charge); | ||||
|     out("charge_level", string_get_cstr(value), false, context); | ||||
|  | ||||
|     if(furi_hal_power_is_charging()) { | ||||
|         if(charge < 100) { | ||||
|             string_printf(value, "charging"); | ||||
|         } else { | ||||
|             string_printf(value, "charged"); | ||||
|         } | ||||
|     } else { | ||||
|         string_printf(value, "discharging"); | ||||
|     } | ||||
|     out("charge_state", string_get_cstr(value), false, context); | ||||
|  | ||||
|     uint16_t voltage = | ||||
|         (uint16_t)(furi_hal_power_get_battery_voltage(FuriHalPowerICFuelGauge) * 1000.f); | ||||
|     string_printf(value, "%u", voltage); | ||||
|     out("battery_voltage", string_get_cstr(value), false, context); | ||||
|  | ||||
|     int16_t current = | ||||
|         (int16_t)(furi_hal_power_get_battery_current(FuriHalPowerICFuelGauge) * 1000.f); | ||||
|     string_printf(value, "%d", current); | ||||
|     out("battery_current", string_get_cstr(value), false, context); | ||||
|  | ||||
|     int16_t temperature = (int16_t)furi_hal_power_get_battery_temperature(FuriHalPowerICFuelGauge); | ||||
|     string_printf(value, "%d", temperature); | ||||
|     out("gauge_temp", string_get_cstr(value), false, context); | ||||
|  | ||||
|     string_printf(value, "%u", furi_hal_power_get_bat_health_pct()); | ||||
|     out("battery_health", string_get_cstr(value), false, context); | ||||
|  | ||||
|     string_printf(value, "%u", furi_hal_power_get_battery_remaining_capacity()); | ||||
|     out("capacity_remain", string_get_cstr(value), false, context); | ||||
|  | ||||
|     string_printf(value, "%u", furi_hal_power_get_battery_full_capacity()); | ||||
|     out("capacity_full", string_get_cstr(value), false, context); | ||||
|  | ||||
|     string_printf(value, "%u", furi_hal_power_get_battery_design_capacity()); | ||||
|     out("capacity_design", string_get_cstr(value), true, context); | ||||
|  | ||||
|     string_clear(value); | ||||
| } | ||||
|   | ||||
| @@ -25,21 +25,32 @@ void furi_hal_speaker_start(float frequency, float volume) { | ||||
|     if(volume > 1) volume = 1; | ||||
|     volume = volume * volume * volume; | ||||
|  | ||||
|     uint32_t autoreload = (SystemCoreClock / FURI_HAL_SPEAKER_PRESCALER / frequency) - 1; | ||||
|     if(autoreload < 2) { | ||||
|         autoreload = 2; | ||||
|     } else if(autoreload > UINT16_MAX) { | ||||
|         autoreload = UINT16_MAX; | ||||
|     } | ||||
|  | ||||
|     LL_TIM_InitTypeDef TIM_InitStruct = {0}; | ||||
|     TIM_InitStruct.Prescaler = FURI_HAL_SPEAKER_PRESCALER - 1; | ||||
|     TIM_InitStruct.Autoreload = ((SystemCoreClock / FURI_HAL_SPEAKER_PRESCALER) / frequency) - 1; | ||||
|     TIM_InitStruct.Autoreload = autoreload; | ||||
|     LL_TIM_Init(FURI_HAL_SPEAKER_TIMER, &TIM_InitStruct); | ||||
|  | ||||
| #ifdef FURI_HAL_SPEAKER_NEW_VOLUME | ||||
|     uint16_t compare_value = volume * FURI_HAL_SPEAKER_MAX_VOLUME; | ||||
|     uint16_t clip_value = volume * TIM_InitStruct.Autoreload / 2; | ||||
|     uint32_t compare_value = volume * FURI_HAL_SPEAKER_MAX_VOLUME; | ||||
|     uint32_t clip_value = volume * TIM_InitStruct.Autoreload / 2; | ||||
|     if(compare_value > clip_value) { | ||||
|         compare_value = clip_value; | ||||
|     } | ||||
| #else | ||||
|     uint16_t compare_value = volume * TIM_InitStruct.Autoreload / 2; | ||||
|     uint32_t compare_value = volume * autoreload / 2; | ||||
| #endif | ||||
|  | ||||
|     if(compare_value == 0) { | ||||
|         compare_value = 1; | ||||
|     } | ||||
|  | ||||
|     LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0}; | ||||
|     TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1; | ||||
|     TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE; | ||||
| @@ -51,6 +62,6 @@ void furi_hal_speaker_start(float frequency, float volume) { | ||||
| } | ||||
|  | ||||
| void furi_hal_speaker_stop() { | ||||
|     LL_TIM_CC_DisableChannel(FURI_HAL_SPEAKER_TIMER, FURI_HAL_SPEAKER_CHANNEL); | ||||
|     LL_TIM_DisableAllOutputs(FURI_HAL_SPEAKER_TIMER); | ||||
|     LL_TIM_DisableCounter(FURI_HAL_SPEAKER_TIMER); | ||||
| } | ||||
|   | ||||
| @@ -113,6 +113,12 @@ uint32_t furi_hal_power_get_battery_remaining_capacity(); | ||||
|  */ | ||||
| uint32_t furi_hal_power_get_battery_full_capacity(); | ||||
|  | ||||
| /** Get battery capacity in mAh from battery profile | ||||
|  * | ||||
|  * @return     capacity in mAh | ||||
|  */ | ||||
| uint32_t furi_hal_power_get_battery_design_capacity(); | ||||
|  | ||||
| /** Get battery voltage in V | ||||
|  * | ||||
|  * @param      ic    FuriHalPowerIc to get measurment | ||||
| @@ -171,6 +177,23 @@ void furi_hal_power_suppress_charge_enter(); | ||||
|  */ | ||||
| void furi_hal_power_suppress_charge_exit(); | ||||
|  | ||||
| /** Callback type called by furi_hal_power_info_get every time another key-value pair of information is ready | ||||
|  * | ||||
|  * @param      key[in]      power information type identifier | ||||
|  * @param      value[in]    power information value | ||||
|  * @param      last[in]     whether the passed key-value pair is the last one | ||||
|  * @param      context[in]  to pass to callback | ||||
|  */ | ||||
| typedef void ( | ||||
|     *FuriHalPowerInfoCallback)(const char* key, const char* value, bool last, void* context); | ||||
|  | ||||
| /** Get power information | ||||
|  * | ||||
|  * @param[in]  callback     callback to provide with new data | ||||
|  * @param[in]  context      context to pass to callback | ||||
|  */ | ||||
| void furi_hal_power_info_get(FuriHalPowerInfoCallback callback, void* context); | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|   | ||||
		Reference in New Issue
	
	Block a user