diff --git a/targets/f7/ble_glue/gap.c b/targets/f7/ble_glue/gap.c index f0533567e..0ada37048 100644 --- a/targets/f7/ble_glue/gap.c +++ b/targets/f7/ble_glue/gap.c @@ -28,6 +28,8 @@ typedef struct { GapConfig* config; GapConnectionParams connection_params; GapState state; + int8_t conn_rssi; + uint32_t time_rssi_sample; FuriMutex* state_mutex; GapEventCallback on_event_cb; void* context; @@ -56,6 +58,19 @@ static Gap* gap = NULL; static void gap_advertise_start(GapState new_state); static int32_t gap_app(void* context); +/** function for updating rssi informations in global Gap object + * +*/ +static inline void fetch_rssi() { + uint8_t ret_rssi = 127; + if(hci_read_rssi(gap->service.connection_handle, &ret_rssi) == BLE_STATUS_SUCCESS) { + gap->conn_rssi = (int8_t)ret_rssi; + gap->time_rssi_sample = furi_get_tick(); + return; + } + FURI_LOG_D(TAG, "Failed to read RSSI"); +} + static void gap_verify_connection_parameters(Gap* gap) { furi_assert(gap); @@ -128,6 +143,9 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) { gap->connection_params.supervisor_timeout = event->Supervision_Timeout; FURI_LOG_I(TAG, "Connection parameters event complete"); gap_verify_connection_parameters(gap); + + // Save rssi for current connection + fetch_rssi(); break; } @@ -162,6 +180,9 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) { gap->service.connection_handle = event->Connection_Handle; gap_verify_connection_parameters(gap); + + // Save rssi for current connection + fetch_rssi(); // Start pairing by sending security request aci_gap_slave_security_req(event->Connection_Handle); } break; @@ -242,6 +263,9 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) { pairing_complete->Status); aci_gap_terminate(gap->service.connection_handle, 5); } else { + // Save RSSI + fetch_rssi(); + FURI_LOG_I(TAG, "Pairing complete"); GapEvent event = {.type = GapEventTypeConnected}; gap->on_event_cb(event, gap->context); //-V595 @@ -310,7 +334,7 @@ static void gap_init_svc(Gap* gap) { // Initialize GATT interface aci_gatt_init(); // Initialize GAP interface - // Skip fist symbol AD_TYPE_COMPLETE_LOCAL_NAME + // Skip first symbol AD_TYPE_COMPLETE_LOCAL_NAME char* name = gap->service.adv_name + 1; aci_gap_init( GAP_PERIPHERAL_ROLE, @@ -346,21 +370,34 @@ static void gap_init_svc(Gap* gap) { hci_le_set_default_phy(ALL_PHYS_PREFERENCE, TX_2M_PREFERRED, RX_2M_PREFERRED); // Set I/O capability bool keypress_supported = false; + // New things below + uint8_t conf_mitm = CFG_MITM_PROTECTION; + uint8_t conf_used_fixed_pin = CFG_USED_FIXED_PIN; + bool conf_bonding = gap->config->bonding_mode; + if(gap->config->pairing_method == GapPairingPinCodeShow) { aci_gap_set_io_capability(IO_CAP_DISPLAY_ONLY); } else if(gap->config->pairing_method == GapPairingPinCodeVerifyYesNo) { aci_gap_set_io_capability(IO_CAP_DISPLAY_YES_NO); keypress_supported = true; + } else if(gap->config->pairing_method == GapPairingNone) { + // Just works pairing method (IOS accept it, it seems android and linux doesn't) + conf_mitm = 0; + conf_used_fixed_pin = 0; + conf_bonding = false; + // if just works isn't supported, we want the numeric comparaison method + aci_gap_set_io_capability(IO_CAP_DISPLAY_YES_NO); + keypress_supported = true; } // Setup authentication aci_gap_set_authentication_requirement( - gap->config->bonding_mode, - CFG_MITM_PROTECTION, + conf_bonding, + conf_mitm, CFG_SC_SUPPORT, keypress_supported, CFG_ENCRYPTION_KEY_SIZE_MIN, CFG_ENCRYPTION_KEY_SIZE_MAX, - CFG_USED_FIXED_PIN, + conf_used_fixed_pin, // 0x0 for no pin 0, CFG_IDENTITY_ADDRESS); // Configure whitelist @@ -463,7 +500,7 @@ void gap_stop_advertising() { furi_mutex_release(gap->state_mutex); } -static void gap_advetise_timer_callback(void* context) { +static void gap_advertise_timer_callback(void* context) { UNUSED(context); GapCommand command = GapCommandAdvLowPower; furi_check(furi_message_queue_put(gap->command_queue, &command, 0) == FuriStatusOk); @@ -477,7 +514,7 @@ bool gap_init(GapConfig* config, GapEventCallback on_event_cb, void* context) { gap = malloc(sizeof(Gap)); gap->config = config; // Create advertising timer - gap->advertise_timer = furi_timer_alloc(gap_advetise_timer_callback, FuriTimerTypeOnce, NULL); + gap->advertise_timer = furi_timer_alloc(gap_advertise_timer_callback, FuriTimerTypeOnce, NULL); // Initialization of GATT & GAP layer gap->service.adv_name = config->adv_name; gap_init_svc(gap); @@ -489,6 +526,9 @@ bool gap_init(GapConfig* config, GapEventCallback on_event_cb, void* context) { gap->service.connection_handle = 0xFFFF; gap->enable_adv = true; + gap->conn_rssi = 127; + gap->time_rssi_sample = 0; + // Thread configuration gap->thread = furi_thread_alloc_ex("BleGapDriver", 1024, gap_app, gap); furi_thread_start(gap->thread); @@ -508,6 +548,17 @@ bool gap_init(GapConfig* config, GapEventCallback on_event_cb, void* context) { return true; } +// Get RSSI +uint32_t gap_get_remote_conn_rssi(int8_t* rssi) { + if(gap && gap->state == GapStateConnected) { + fetch_rssi(); + *rssi = gap->conn_rssi; + + if(gap->time_rssi_sample) return furi_get_tick() - gap->time_rssi_sample; + } + return 0; +} + GapState gap_get_state() { GapState state; if(gap) { diff --git a/targets/f7/furi_hal/furi_hal_infrared.c b/targets/f7/furi_hal/furi_hal_infrared.c index 3b20b6bc3..9c0d84c55 100644 --- a/targets/f7/furi_hal/furi_hal_infrared.c +++ b/targets/f7/furi_hal/furi_hal_infrared.c @@ -9,12 +9,6 @@ #include #include -// #define INFRARED_TX_DEBUG - -#if defined INFRARED_TX_DEBUG -#define gpio_infrared_tx gpio_ext_pa7 -#endif - #define INFRARED_TIM_TX_DMA_BUFFER_SIZE 200 #define INFRARED_POLARITY_SHIFT 1 @@ -84,6 +78,7 @@ typedef enum { static volatile InfraredState furi_hal_infrared_state = InfraredStateIdle; static InfraredTimTx infrared_tim_tx; static InfraredTimRx infrared_tim_rx; +static bool infrared_external_output; static void furi_hal_infrared_tx_fill_buffer(uint8_t buf_num, uint8_t polarity_shift); static void furi_hal_infrared_async_tx_free_resources(void); @@ -94,6 +89,14 @@ static uint8_t furi_hal_infrared_get_current_dma_tx_buffer(void); static void furi_hal_infrared_tx_dma_polarity_isr(); static void furi_hal_infrared_tx_dma_isr(); +void furi_hal_infrared_set_debug_out(bool enable) { + infrared_external_output = enable; +} + +bool furi_hal_infrared_get_debug_out_status(void) { + return infrared_external_output; +} + static void furi_hal_infrared_tim_rx_isr() { static uint32_t previous_captured_ch2 = 0; @@ -348,27 +351,29 @@ static void furi_hal_infrared_configure_tim_pwm_tx(uint32_t freq, float duty_cyc LL_TIM_SetAutoReload( INFRARED_DMA_TIMER, __LL_TIM_CALC_ARR(SystemCoreClock, LL_TIM_GetPrescaler(INFRARED_DMA_TIMER), freq)); -#if defined INFRARED_TX_DEBUG - LL_TIM_OC_SetCompareCH1( - INFRARED_DMA_TIMER, ((LL_TIM_GetAutoReload(INFRARED_DMA_TIMER) + 1) * (1 - duty_cycle))); - LL_TIM_OC_EnablePreload(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1); - /* LL_TIM_OCMODE_PWM2 set by DMA */ - LL_TIM_OC_SetMode(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1, LL_TIM_OCMODE_FORCED_INACTIVE); - LL_TIM_OC_SetPolarity(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1N, LL_TIM_OCPOLARITY_HIGH); - LL_TIM_OC_DisableFast(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1); - LL_TIM_CC_EnableChannel(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1N); - LL_TIM_DisableIT_CC1(INFRARED_DMA_TIMER); -#else - LL_TIM_OC_SetCompareCH3( - INFRARED_DMA_TIMER, ((LL_TIM_GetAutoReload(INFRARED_DMA_TIMER) + 1) * (1 - duty_cycle))); - LL_TIM_OC_EnablePreload(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH3); - /* LL_TIM_OCMODE_PWM2 set by DMA */ - LL_TIM_OC_SetMode(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH3, LL_TIM_OCMODE_FORCED_INACTIVE); - LL_TIM_OC_SetPolarity(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH3N, LL_TIM_OCPOLARITY_HIGH); - LL_TIM_OC_DisableFast(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH3); - LL_TIM_CC_EnableChannel(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH3N); - LL_TIM_DisableIT_CC3(INFRARED_DMA_TIMER); -#endif + if(infrared_external_output) { + LL_TIM_OC_SetCompareCH1( + INFRARED_DMA_TIMER, + ((LL_TIM_GetAutoReload(INFRARED_DMA_TIMER) + 1) * (1 - duty_cycle))); + LL_TIM_OC_EnablePreload(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1); + /* LL_TIM_OCMODE_PWM2 set by DMA */ + LL_TIM_OC_SetMode(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1, LL_TIM_OCMODE_FORCED_INACTIVE); + LL_TIM_OC_SetPolarity(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1N, LL_TIM_OCPOLARITY_HIGH); + LL_TIM_OC_DisableFast(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1); + LL_TIM_CC_EnableChannel(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1N); + LL_TIM_DisableIT_CC1(INFRARED_DMA_TIMER); + } else { + LL_TIM_OC_SetCompareCH3( + INFRARED_DMA_TIMER, + ((LL_TIM_GetAutoReload(INFRARED_DMA_TIMER) + 1) * (1 - duty_cycle))); + LL_TIM_OC_EnablePreload(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH3); + /* LL_TIM_OCMODE_PWM2 set by DMA */ + LL_TIM_OC_SetMode(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH3, LL_TIM_OCMODE_FORCED_INACTIVE); + LL_TIM_OC_SetPolarity(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH3N, LL_TIM_OCPOLARITY_HIGH); + LL_TIM_OC_DisableFast(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH3); + LL_TIM_CC_EnableChannel(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH3N); + LL_TIM_DisableIT_CC3(INFRARED_DMA_TIMER); + } LL_TIM_DisableMasterSlaveMode(INFRARED_DMA_TIMER); LL_TIM_EnableAllOutputs(INFRARED_DMA_TIMER); LL_TIM_DisableIT_UPDATE(INFRARED_DMA_TIMER); @@ -377,11 +382,11 @@ static void furi_hal_infrared_configure_tim_pwm_tx(uint32_t freq, float duty_cyc static void furi_hal_infrared_configure_tim_cmgr2_dma_tx(void) { LL_DMA_InitTypeDef dma_config = {0}; -#if defined INFRARED_TX_DEBUG - dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (INFRARED_DMA_TIMER->CCMR1); -#else - dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (INFRARED_DMA_TIMER->CCMR2); -#endif + if(infrared_external_output) { + dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (INFRARED_DMA_TIMER->CCMR1); + } else { + dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (INFRARED_DMA_TIMER->CCMR2); + } dma_config.MemoryOrM2MDstAddress = (uint32_t)NULL; dma_config.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH; dma_config.Mode = LL_DMA_MODE_NORMAL; @@ -575,7 +580,11 @@ static void furi_hal_infrared_async_tx_free_resources(void) { (furi_hal_infrared_state == InfraredStateIdle) || (furi_hal_infrared_state == InfraredStateAsyncTxStopped)); - furi_hal_gpio_init(&gpio_infrared_tx, GpioModeAnalog, GpioPullDown, GpioSpeedLow); + if(infrared_external_output) { + furi_hal_gpio_init(&gpio_ext_pa7, GpioModeAnalog, GpioPullDown, GpioSpeedLow); + } else { + furi_hal_gpio_init(&gpio_infrared_tx, GpioModeAnalog, GpioPullDown, GpioSpeedLow); + } furi_hal_interrupt_set_isr(INFRARED_DMA_CH1_IRQ, NULL, NULL); furi_hal_interrupt_set_isr(INFRARED_DMA_CH2_IRQ, NULL, NULL); @@ -636,10 +645,22 @@ void furi_hal_infrared_async_tx_start(uint32_t freq, float duty_cycle) { furi_delay_us(5); LL_TIM_GenerateEvent_UPDATE(INFRARED_DMA_TIMER); /* DMA -> TIMx_RCR */ furi_delay_us(5); - LL_GPIO_ResetOutputPin( - gpio_infrared_tx.port, gpio_infrared_tx.pin); /* when disable it prevents false pulse */ - furi_hal_gpio_init_ex( - &gpio_infrared_tx, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedHigh, GpioAltFn1TIM1); + if(infrared_external_output) { + LL_GPIO_ResetOutputPin( + gpio_ext_pa7.port, gpio_ext_pa7.pin); /* when disable it prevents false pulse */ + furi_hal_gpio_init_ex( + &gpio_ext_pa7, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedHigh, GpioAltFn1TIM1); + } else { + LL_GPIO_ResetOutputPin( + gpio_infrared_tx.port, + gpio_infrared_tx.pin); /* when disable it prevents false pulse */ + furi_hal_gpio_init_ex( + &gpio_infrared_tx, + GpioModeAltFunctionPushPull, + GpioPullUp, + GpioSpeedHigh, + GpioAltFn1TIM1); + } FURI_CRITICAL_ENTER(); LL_TIM_GenerateEvent_UPDATE(INFRARED_DMA_TIMER); /* TIMx_RCR -> Repetition counter */ diff --git a/targets/f7/furi_hal/furi_hal_subghz.c b/targets/f7/furi_hal/furi_hal_subghz.c index f75146353..7db0329c7 100644 --- a/targets/f7/furi_hal/furi_hal_subghz.c +++ b/targets/f7/furi_hal/furi_hal_subghz.c @@ -1,6 +1,6 @@ #include #include -#include + #include #include #include @@ -51,14 +51,41 @@ typedef struct { volatile SubGhzState state; volatile SubGhzRegulation regulation; const GpioPin* async_mirror_pin; + + int8_t rolling_counter_mult; + bool ext_power_amp : 1; + bool dangerous_frequency_i : 1; } FuriHalSubGhz; volatile FuriHalSubGhz furi_hal_subghz = { .state = SubGhzStateInit, .regulation = SubGhzRegulationTxRx, .async_mirror_pin = NULL, + .rolling_counter_mult = 1, + .ext_power_amp = false, + .dangerous_frequency_i = false, }; +int8_t furi_hal_subghz_get_rolling_counter_mult(void) { + return furi_hal_subghz.rolling_counter_mult; +} + +void furi_hal_subghz_set_rolling_counter_mult(int8_t mult) { + furi_hal_subghz.rolling_counter_mult = mult; +} + +void furi_hal_subghz_set_dangerous_frequency(bool state_i) { + furi_hal_subghz.dangerous_frequency_i = state_i; +} + +void furi_hal_subghz_set_ext_power_amp(bool enabled) { + furi_hal_subghz.ext_power_amp = enabled; +} + +bool furi_hal_subghz_get_ext_power_amp() { + return furi_hal_subghz.ext_power_amp; +} + void furi_hal_subghz_set_async_mirror_pin(const GpioPin* pin) { furi_hal_subghz.async_mirror_pin = pin; } @@ -207,6 +234,7 @@ bool furi_hal_subghz_rx_pipe_not_empty() { cc1101_read_reg( &furi_hal_spi_bus_handle_subghz, (CC1101_STATUS_RXBYTES) | CC1101_BURST, (uint8_t*)status); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); + // TODO: Find reason why RXFIFO_OVERFLOW doesnt work correctly if(status->NUM_RXBYTES > 0) { return true; } else { @@ -291,10 +319,15 @@ uint8_t furi_hal_subghz_get_lqi() { return data[0] & 0x7F; } +/* + Modified by @tkerby & MX to the full YARD Stick One extended range of 281-361 MHz, 378-481 MHz, and 749-962 MHz. + These changes are at your own risk. The PLL may not lock and FZ devs have warned of possible damage! + */ + bool furi_hal_subghz_is_frequency_valid(uint32_t value) { - if(!(value >= 299999755 && value <= 348000335) && - !(value >= 386999938 && value <= 464000000) && - !(value >= 778999847 && value <= 928000000)) { + if(!(value >= 281000000 && value <= 361000000) && + !(value >= 378000000 && value <= 481000000) && + !(value >= 749000000 && value <= 962000000)) { return false; } @@ -302,12 +335,13 @@ bool furi_hal_subghz_is_frequency_valid(uint32_t value) { } uint32_t furi_hal_subghz_set_frequency_and_path(uint32_t value) { + // Set these values to the extended frequency range only. They dont define if you can transmit but do select the correct RF path value = furi_hal_subghz_set_frequency(value); - if(value >= 299999755 && value <= 348000335) { + if(value >= 281000000 && value <= 361000000) { furi_hal_subghz_set_path(FuriHalSubGhzPath315); - } else if(value >= 386999938 && value <= 464000000) { + } else if(value >= 378000000 && value <= 481000000) { furi_hal_subghz_set_path(FuriHalSubGhzPath433); - } else if(value >= 778999847 && value <= 928000000) { + } else if(value >= 749000000 && value <= 962000000) { furi_hal_subghz_set_path(FuriHalSubGhzPath868); } else { furi_crash("SubGhz: Incorrect frequency during set."); @@ -315,8 +349,27 @@ uint32_t furi_hal_subghz_set_frequency_and_path(uint32_t value) { return value; } +bool furi_hal_subghz_is_tx_allowed(uint32_t value) { + bool allow_extended_for_int = furi_hal_subghz.dangerous_frequency_i; + + if(!(allow_extended_for_int) && + !(value >= 299999755 && value <= 350000335) && // was increased from 348 to 350 + !(value >= 386999938 && value <= 467750000) && // was increased from 464 to 467.75 + !(value >= 778999847 && value <= 928000000)) { + FURI_LOG_I(TAG, "Frequency blocked - outside default range"); + return false; + } else if( + (allow_extended_for_int) && // + !furi_hal_subghz_is_frequency_valid(value)) { + FURI_LOG_I(TAG, "Frequency blocked - outside dangerous range"); + return false; + } + + return true; +} + uint32_t furi_hal_subghz_set_frequency(uint32_t value) { - if(furi_hal_region_is_frequency_allowed(value)) { + if(furi_hal_subghz_is_tx_allowed(value)) { furi_hal_subghz.regulation = SubGhzRegulationTxRx; } else { furi_hal_subghz.regulation = SubGhzRegulationOnlyRx; @@ -431,7 +484,8 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void* TIM_InitStruct.Prescaler = 64 - 1; TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP; TIM_InitStruct.Autoreload = 0x7FFFFFFE; - TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV4; // Clock division for capture filter + // Clock division for capture filter + TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV4; LL_TIM_Init(TIM2, &TIM_InitStruct); // Timer: advanced @@ -477,7 +531,7 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void* // Switch to RX furi_hal_subghz_rx(); - //Clear the variable after the end of the session + // Clear the variable after the end of the session furi_hal_subghz_capture_delta_duration = 0; } @@ -695,6 +749,11 @@ bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void* // Start debug if(furi_hal_subghz_start_debug()) { const GpioPin* gpio = furi_hal_subghz.async_mirror_pin; + // //Preparing bit mask + // //Debug pin is may be only PORTB! (PB0, PB1, .., PB15) + // furi_hal_subghz_debug_gpio_buff[0] = 0; + // furi_hal_subghz_debug_gpio_buff[1] = 0; + furi_hal_subghz_debug_gpio_buff[0] = (uint32_t)gpio->pin << GPIO_NUMBER; furi_hal_subghz_debug_gpio_buff[1] = gpio->pin; diff --git a/targets/f7/furi_hal/furi_hal_subghz_i.h b/targets/f7/furi_hal/furi_hal_subghz_i.h new file mode 100644 index 000000000..e7fe2602f --- /dev/null +++ b/targets/f7/furi_hal/furi_hal_subghz_i.h @@ -0,0 +1,3 @@ +#pragma once + +void furi_hal_subghz_set_dangerous_frequency(bool state_i); \ No newline at end of file diff --git a/targets/f7/furi_hal/furi_hal_version.c b/targets/f7/furi_hal/furi_hal_version.c index e4364a518..46a15bde8 100644 --- a/targets/f7/furi_hal/furi_hal_version.c +++ b/targets/f7/furi_hal/furi_hal_version.c @@ -90,7 +90,7 @@ typedef struct { static FuriHalVersion furi_hal_version = {0}; -static void furi_hal_version_set_name(const char* name) { +void furi_hal_version_set_name(const char* name) { if(name != NULL) { strlcpy(furi_hal_version.name, name, FURI_HAL_VERSION_ARRAY_NAME_LENGTH); snprintf( @@ -106,8 +106,16 @@ static void furi_hal_version_set_name(const char* name) { // BLE Mac address uint32_t udn = LL_FLASH_GetUDN(); + if(version_get_custom_name(NULL) != NULL) { + udn = *((uint32_t*)version_get_custom_name(NULL)); + } + uint32_t company_id = LL_FLASH_GetSTCompanyID(); - uint32_t device_id = LL_FLASH_GetDeviceID(); + // uint32_t device_id = LL_FLASH_GetDeviceID(); + // Some flippers return 0x27 (flippers with chip revision 2003 6495) instead of 0x26 (flippers with chip revision 2001 6495) + // Mobile apps expects it to return 0x26 + // Hardcoded here temporarily until mobile apps is updated to handle 0x27 + uint32_t device_id = 0x26; furi_hal_version.ble_mac[0] = (uint8_t)(udn & 0x000000FF); furi_hal_version.ble_mac[1] = (uint8_t)((udn & 0x0000FF00) >> 8); furi_hal_version.ble_mac[2] = (uint8_t)((udn & 0x00FF0000) >> 16); @@ -129,7 +137,11 @@ static void furi_hal_version_load_otp_v0() { furi_hal_version.board_body = otp->board_body; furi_hal_version.board_connect = otp->board_connect; - furi_hal_version_set_name(otp->name); + if(version_get_custom_name(NULL) != NULL) { + furi_hal_version_set_name(version_get_custom_name(NULL)); + } else { + furi_hal_version_set_name(otp->name); + } } static void furi_hal_version_load_otp_v1() { @@ -143,7 +155,11 @@ static void furi_hal_version_load_otp_v1() { furi_hal_version.board_color = otp->board_color; furi_hal_version.board_region = otp->board_region; - furi_hal_version_set_name(otp->name); + if(version_get_custom_name(NULL) != NULL) { + furi_hal_version_set_name(version_get_custom_name(NULL)); + } else { + furi_hal_version_set_name(otp->name); + } } static void furi_hal_version_load_otp_v2() { @@ -163,7 +179,11 @@ static void furi_hal_version_load_otp_v2() { if(otp->board_color != 0xFF) { furi_hal_version.board_color = otp->board_color; furi_hal_version.board_region = otp->board_region; - furi_hal_version_set_name(otp->name); + if(version_get_custom_name(NULL) != NULL) { + furi_hal_version_set_name(version_get_custom_name(NULL)); + } else { + furi_hal_version_set_name(otp->name); + } } else { furi_hal_version.board_color = 0; furi_hal_version.board_region = 0; @@ -239,11 +259,19 @@ uint8_t furi_hal_version_get_hw_connect() { } FuriHalVersionRegion furi_hal_version_get_hw_region() { + return FuriHalVersionRegionUnknown; +} + +FuriHalVersionRegion furi_hal_version_get_hw_region_otp() { return furi_hal_version.board_region; } const char* furi_hal_version_get_hw_region_name() { - switch(furi_hal_version_get_hw_region()) { + return "R00"; +} + +const char* furi_hal_version_get_hw_region_name_otp() { + switch(furi_hal_version_get_hw_region_otp()) { case FuriHalVersionRegionUnknown: return "R00"; case FuriHalVersionRegionEuRu: @@ -290,6 +318,13 @@ size_t furi_hal_version_uid_size() { return 64 / 8; } -const uint8_t* furi_hal_version_uid() { +const uint8_t* furi_hal_version_uid_default() { + return (const uint8_t*)UID64_BASE; +} + +const uint8_t* furi_hal_version_uid() { + if(version_get_custom_name(NULL) != NULL) { + return (const uint8_t*)&(*((uint32_t*)version_get_custom_name(NULL))); + } return (const uint8_t*)UID64_BASE; }