diff --git a/ReadMe.md b/ReadMe.md index 9f3b4a252..0f4b96e53 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -11,11 +11,8 @@ - To avoid Application errors and duplicates, delete /ext/apps before doing the RM firmware update - Known Issues: `Chess` -- Last Synced/Checked [Unleashed/xMasterX](https://github.com/DarkFlippers/unleashed-firmware), changes in [changelog](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/CHANGELOG.md): `2022-10-14 16:52 GMT` -- Last Synced/Checked [OFW](https://github.com/flipperdevices/flipperzero-firmware), changes in [commits](https://github.com/flipperdevices/flipperzero-firmware/commits/dev): `2022-10-14 16:52 GMT` -- Added: [Tuning Fork (By besya)](https://github.com/besya/flipperzero-tuning-fork)[PR by skizzophrenic](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/360) -- Fixed Desktop issue [By skizzophrenic/Talking-Sasquach](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/363) -- Update from OFW PR to fix dolphion level issue, level may reset again +- Last Synced/Checked [Unleashed/xMasterX](https://github.com/DarkFlippers/unleashed-firmware), changes in [changelog](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/CHANGELOG.md): `2022-10-14 20:25 GMT` +- Last Synced/Checked [OFW](https://github.com/flipperdevices/flipperzero-firmware), changes in [commits](https://github.com/flipperdevices/flipperzero-firmware/commits/dev): `2022-10-14 20:25 GMT`
TO DO / REMOVED
diff --git a/applications/main/fap_loader/application.fam b/applications/main/fap_loader/application.fam index bd0403e0e..784ee9508 100644 --- a/applications/main/fap_loader/application.fam +++ b/applications/main/fap_loader/application.fam @@ -3,6 +3,7 @@ App( name="Applications", apptype=FlipperAppType.APP, entry_point="fap_loader_app", + cdefines=["APP_FAP_LOADER"], requires=[ "gui", "storage", diff --git a/applications/main/fap_loader/fap_loader_app.c b/applications/main/fap_loader/fap_loader_app.c index 6c909aeeb..faf8eefc8 100644 --- a/applications/main/fap_loader/fap_loader_app.c +++ b/applications/main/fap_loader/fap_loader_app.c @@ -101,7 +101,7 @@ static bool fap_loader_run_selected_app(FapLoader* loader) { } FURI_LOG_I(TAG, "Loaded in %ums", (size_t)(furi_get_tick() - start)); - FURI_LOG_I(TAG, "FAP Loader is staring app"); + FURI_LOG_I(TAG, "FAP Loader is starting app"); FuriThread* thread = flipper_application_spawn(loader->app, NULL); furi_thread_start(thread); diff --git a/applications/plugins/minesweeper/minesweeper.c b/applications/plugins/minesweeper/minesweeper.c index 6d29bab2d..d3a5207f9 100644 --- a/applications/plugins/minesweeper/minesweeper.c +++ b/applications/plugins/minesweeper/minesweeper.c @@ -42,10 +42,7 @@ typedef enum { TileTypeMine } TileType; -typedef enum { - FieldEmpty, // <-- same goes for this - FieldMine -} Field; +typedef enum { FieldEmpty, FieldMine } Field; typedef struct { Field minefield[PLAYFIELD_WIDTH][PLAYFIELD_HEIGHT]; @@ -99,6 +96,8 @@ static void render_callback(Canvas* const canvas, void* ctx) { furi_string_printf(timeStr, "%01d:%02d", minutes, seconds); canvas_draw_str_aligned(canvas, 128, 0, AlignRight, AlignTop, furi_string_get_cstr(timeStr)); + uint8_t* tile_to_draw; + for(int y = 0; y < PLAYFIELD_HEIGHT; y++) { for(int x = 0; x < PLAYFIELD_WIDTH; x++) { if(x == minesweeper_state->cursor_x && y == minesweeper_state->cursor_y) { @@ -106,114 +105,53 @@ static void render_callback(Canvas* const canvas, void* ctx) { } switch(minesweeper_state->playfield[x][y]) { case TileType0: - canvas_draw_xbm( - canvas, - x * TILE_HEIGHT, // x - 8 + (y * TILE_WIDTH), // y - TILE_WIDTH, - TILE_HEIGHT, - tile_0_bits); + tile_to_draw = tile_0_bits; break; case TileType1: - canvas_draw_xbm( - canvas, - x * TILE_HEIGHT, // x - 8 + (y * TILE_WIDTH), // y - TILE_WIDTH, - TILE_HEIGHT, - tile_1_bits); + tile_to_draw = tile_1_bits; break; case TileType2: - canvas_draw_xbm( - canvas, - x * TILE_HEIGHT, // x - 8 + (y * TILE_WIDTH), // y - TILE_WIDTH, - TILE_HEIGHT, - tile_2_bits); + tile_to_draw = tile_2_bits; break; case TileType3: - canvas_draw_xbm( - canvas, - x * TILE_HEIGHT, // x - 8 + (y * TILE_WIDTH), // y - TILE_WIDTH, - TILE_HEIGHT, - tile_3_bits); + tile_to_draw = tile_3_bits; break; case TileType4: - canvas_draw_xbm( - canvas, - x * TILE_HEIGHT, // x - 8 + (y * TILE_WIDTH), // y - TILE_WIDTH, - TILE_HEIGHT, - tile_4_bits); + tile_to_draw = tile_4_bits; break; case TileType5: - canvas_draw_xbm( - canvas, - x * TILE_HEIGHT, // x - 8 + (y * TILE_WIDTH), // y - TILE_WIDTH, - TILE_HEIGHT, - tile_5_bits); + tile_to_draw = tile_5_bits; break; case TileType6: - canvas_draw_xbm( - canvas, - x * TILE_HEIGHT, // x - 8 + (y * TILE_WIDTH), // y - TILE_WIDTH, - TILE_HEIGHT, - tile_6_bits); + tile_to_draw = tile_6_bits; break; case TileType7: - canvas_draw_xbm( - canvas, - x * TILE_HEIGHT, // x - 8 + (y * TILE_WIDTH), // y - TILE_WIDTH, - TILE_HEIGHT, - tile_7_bits); + tile_to_draw = tile_7_bits; break; case TileType8: - canvas_draw_xbm( - canvas, - x * TILE_HEIGHT, // x - 8 + (y * TILE_WIDTH), // y - TILE_WIDTH, - TILE_HEIGHT, - tile_8_bits); + tile_to_draw = tile_8_bits; break; case TileTypeFlag: - canvas_draw_xbm( - canvas, - x * TILE_HEIGHT, // x - 8 + (y * TILE_WIDTH), // y - TILE_WIDTH, - TILE_HEIGHT, - tile_flag_bits); + tile_to_draw = tile_flag_bits; break; case TileTypeUncleared: - canvas_draw_xbm( - canvas, - x * TILE_HEIGHT, // x - 8 + (y * TILE_WIDTH), // y - TILE_WIDTH, - TILE_HEIGHT, - tile_uncleared_bits); + tile_to_draw = tile_uncleared_bits; break; case TileTypeMine: - canvas_draw_xbm( - canvas, - x * TILE_HEIGHT, // x - 8 + (y * TILE_WIDTH), // y - TILE_WIDTH, - TILE_HEIGHT, - tile_mine_bits); + tile_to_draw = tile_mine_bits; + break; + default: + // this should never happen + tile_to_draw = tile_mine_bits; break; } + canvas_draw_xbm( + canvas, + x * TILE_HEIGHT, // x + 8 + (y * TILE_WIDTH), // y + TILE_WIDTH, + TILE_HEIGHT, + tile_to_draw); if(x == minesweeper_state->cursor_x && y == minesweeper_state->cursor_y) { canvas_invert_color(canvas); } @@ -479,25 +417,25 @@ int32_t minesweeper_app(void* p) { case InputKeyUp: minesweeper_state->cursor_y--; if(minesweeper_state->cursor_y < 0) { - minesweeper_state->cursor_y = 0; + minesweeper_state->cursor_y = PLAYFIELD_HEIGHT - 1; } break; case InputKeyDown: minesweeper_state->cursor_y++; if(minesweeper_state->cursor_y >= PLAYFIELD_HEIGHT) { - minesweeper_state->cursor_y = PLAYFIELD_HEIGHT - 1; + minesweeper_state->cursor_y = 0; } break; case InputKeyRight: minesweeper_state->cursor_x++; if(minesweeper_state->cursor_x >= PLAYFIELD_WIDTH) { - minesweeper_state->cursor_x = PLAYFIELD_WIDTH - 1; + minesweeper_state->cursor_x = 0; } break; case InputKeyLeft: minesweeper_state->cursor_x--; if(minesweeper_state->cursor_x < 0) { - minesweeper_state->cursor_x = 0; + minesweeper_state->cursor_x = PLAYFIELD_WIDTH - 1; } break; case InputKeyOk: diff --git a/applications/services/bt/bt_service/bt.c b/applications/services/bt/bt_service/bt.c index aeb2beec9..c003013e4 100644 --- a/applications/services/bt/bt_service/bt.c +++ b/applications/services/bt/bt_service/bt.c @@ -165,6 +165,11 @@ static uint16_t bt_serial_event_callback(SerialServiceEvent event, void* context ret = rpc_session_get_available_size(bt->rpc_session); } else if(event.event == SerialServiceEventTypeDataSent) { furi_event_flag_set(bt->rpc_event, BT_RPC_EVENT_BUFF_SENT); + } else if(event.event == SerialServiceEventTypesBleResetRequest) { + FURI_LOG_I(TAG, "BLE restart request received"); + BtMessage message = {.type = BtMessageTypeSetProfile, .data.profile = BtProfileSerial}; + furi_check( + furi_message_queue_put(bt->message_queue, &message, FuriWaitForever) == FuriStatusOk); } return ret; } @@ -226,6 +231,7 @@ static bool bt_on_gap_event_callback(GapEvent event, void* context) { rpc_session_set_context(bt->rpc_session, bt); furi_hal_bt_serial_set_event_callback( RPC_BUFFER_SIZE, bt_serial_event_callback, bt); + furi_hal_bt_serial_set_rpc_status(FuriHalBtSerialRpcStatusActive); } else { FURI_LOG_W(TAG, "RPC is busy, failed to open new session"); } @@ -241,6 +247,7 @@ static bool bt_on_gap_event_callback(GapEvent event, void* context) { } else if(event.type == GapEventTypeDisconnected) { if(bt->profile == BtProfileSerial && bt->rpc_session) { FURI_LOG_I(TAG, "Close RPC connection"); + furi_hal_bt_serial_set_rpc_status(FuriHalBtSerialRpcStatusNotActive); furi_event_flag_set(bt->rpc_event, BT_RPC_EVENT_DISCONNECTED); rpc_session_close(bt->rpc_session); furi_hal_bt_serial_set_event_callback(0, NULL, NULL); @@ -330,14 +337,20 @@ static void bt_change_profile(Bt* bt, BtMessage* message) { } furi_hal_bt_set_key_storage_change_callback(bt_on_key_storage_change_callback, bt); bt->profile = message->data.profile; - *message->result = true; + if(message->result) { + *message->result = true; + } } else { FURI_LOG_E(TAG, "Failed to start Bt App"); - *message->result = false; + if(message->result) { + *message->result = false; + } } } else { bt_show_warning(bt, "Radio stack doesn't support this app"); - *message->result = false; + if(message->result) { + *message->result = false; + } } furi_event_flag_set(bt->api_event, BT_API_UNLOCK_EVENT); } diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c index 07ba9925f..bdd9589ed 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c @@ -11,9 +11,16 @@ static bool favorite_fap_selector_item_callback( uint8_t** icon_ptr, FuriString* item_name) { UNUSED(context); +#ifdef APP_FAP_LOADER Storage* storage = furi_record_open(RECORD_STORAGE); bool success = fap_loader_load_name_and_icon(file_path, storage, icon_ptr, item_name); furi_record_close(RECORD_STORAGE); +#else + UNUSED(file_path); + UNUSED(icon_ptr); + UNUSED(item_name); + bool success = false; +#endif return success; } diff --git a/firmware/targets/f7/ble_glue/serial_service.c b/firmware/targets/f7/ble_glue/serial_service.c index 536557cce..c6421dc28 100644 --- a/firmware/targets/f7/ble_glue/serial_service.c +++ b/firmware/targets/f7/ble_glue/serial_service.c @@ -11,6 +11,7 @@ typedef struct { uint16_t rx_char_handle; uint16_t tx_char_handle; uint16_t flow_ctrl_char_handle; + uint16_t rpc_status_char_handle; FuriMutex* buff_size_mtx; uint32_t buff_size; uint16_t bytes_ready_to_receive; @@ -28,6 +29,8 @@ static const uint8_t char_rx_uuid[] = {0x00, 0x00, 0xfe, 0x62, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19}; static const uint8_t flow_ctrl_uuid[] = {0x00, 0x00, 0xfe, 0x63, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19}; +static const uint8_t rpc_status_uuid[] = + {0x00, 0x00, 0xfe, 0x64, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19}; static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void* event) { SVCCTL_EvtAckStatus_t ret = SVCCTL_EvtNotAck; @@ -67,6 +70,17 @@ static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void* event) { furi_check(furi_mutex_release(serial_svc->buff_size_mtx) == FuriStatusOk); } ret = SVCCTL_EvtAckFlowEnable; + } else if(attribute_modified->Attr_Handle == serial_svc->rpc_status_char_handle + 1) { + SerialServiceRpcStatus* rpc_status = + (SerialServiceRpcStatus*)attribute_modified->Attr_Data; + if(*rpc_status == SerialServiceRpcStatusNotActive) { + if(serial_svc->callback) { + SerialServiceEvent event = { + .event = SerialServiceEventTypesBleResetRequest, + }; + serial_svc->callback(event, serial_svc->context); + } + } } } else if(blecore_evt->ecode == ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE) { FURI_LOG_T(TAG, "Ack received"); @@ -82,6 +96,18 @@ static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void* event) { return ret; } +static void serial_svc_update_rpc_char(SerialServiceRpcStatus status) { + tBleStatus ble_status = aci_gatt_update_char_value( + serial_svc->svc_handle, + serial_svc->rpc_status_char_handle, + 0, + sizeof(SerialServiceRpcStatus), + (uint8_t*)&status); + if(ble_status) { + FURI_LOG_E(TAG, "Failed to update RPC status char: %d", ble_status); + } +} + void serial_svc_start() { tBleStatus status; serial_svc = malloc(sizeof(SerialSvc)); @@ -90,7 +116,7 @@ void serial_svc_start() { // Add service status = aci_gatt_add_service( - UUID_TYPE_128, (Service_UUID_t*)service_uuid, PRIMARY_SERVICE, 10, &serial_svc->svc_handle); + UUID_TYPE_128, (Service_UUID_t*)service_uuid, PRIMARY_SERVICE, 12, &serial_svc->svc_handle); if(status) { FURI_LOG_E(TAG, "Failed to add Serial service: %d", status); } @@ -141,6 +167,22 @@ void serial_svc_start() { if(status) { FURI_LOG_E(TAG, "Failed to add Flow Control characteristic: %d", status); } + // Add RPC status characteristic + status = aci_gatt_add_char( + serial_svc->svc_handle, + UUID_TYPE_128, + (const Char_UUID_t*)rpc_status_uuid, + sizeof(SerialServiceRpcStatus), + CHAR_PROP_READ | CHAR_PROP_WRITE | CHAR_PROP_NOTIFY, + ATTR_PERMISSION_AUTHEN_READ | ATTR_PERMISSION_AUTHEN_WRITE, + GATT_NOTIFY_ATTRIBUTE_WRITE, + 10, + CHAR_VALUE_LEN_CONSTANT, + &serial_svc->rpc_status_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to add RPC status characteristic: %d", status); + } + serial_svc_update_rpc_char(SerialServiceRpcStatusNotActive); // Allocate buffer size mutex serial_svc->buff_size_mtx = furi_mutex_alloc(FuriMutexTypeNormal); } @@ -198,6 +240,10 @@ void serial_svc_stop() { if(status) { FURI_LOG_E(TAG, "Failed to delete Flow Control characteristic: %d", status); } + status = aci_gatt_del_char(serial_svc->svc_handle, serial_svc->rpc_status_char_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to delete RPC Status characteristic: %d", status); + } // Delete service status = aci_gatt_del_service(serial_svc->svc_handle); if(status) { @@ -242,3 +288,8 @@ bool serial_svc_update_tx(uint8_t* data, uint16_t data_len) { return true; } + +void serial_svc_set_rpc_status(SerialServiceRpcStatus status) { + furi_assert(serial_svc); + serial_svc_update_rpc_char(status); +} diff --git a/firmware/targets/f7/ble_glue/serial_service.h b/firmware/targets/f7/ble_glue/serial_service.h index a1e5bc1cc..7d38066f4 100644 --- a/firmware/targets/f7/ble_glue/serial_service.h +++ b/firmware/targets/f7/ble_glue/serial_service.h @@ -10,9 +10,15 @@ extern "C" { #endif +typedef enum { + SerialServiceRpcStatusNotActive = 0UL, + SerialServiceRpcStatusActive = 1UL, +} SerialServiceRpcStatus; + typedef enum { SerialServiceEventTypeDataReceived, SerialServiceEventTypeDataSent, + SerialServiceEventTypesBleResetRequest, } SerialServiceEventType; typedef struct { @@ -34,6 +40,8 @@ void serial_svc_set_callbacks( SerialServiceEventCallback callback, void* context); +void serial_svc_set_rpc_status(SerialServiceRpcStatus status); + void serial_svc_notify_buffer_is_empty(); void serial_svc_stop(); diff --git a/firmware/targets/f7/furi_hal/furi_hal_bt_serial.c b/firmware/targets/f7/furi_hal/furi_hal_bt_serial.c index 9bdad5bf2..aa09dde52 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_bt_serial.c +++ b/firmware/targets/f7/furi_hal/furi_hal_bt_serial.c @@ -31,6 +31,16 @@ void furi_hal_bt_serial_notify_buffer_is_empty() { serial_svc_notify_buffer_is_empty(); } +void furi_hal_bt_serial_set_rpc_status(FuriHalBtSerialRpcStatus status) { + SerialServiceRpcStatus st; + if(status == FuriHalBtSerialRpcStatusActive) { + st = SerialServiceRpcStatusActive; + } else { + st = SerialServiceRpcStatusNotActive; + } + serial_svc_set_rpc_status(st); +} + bool furi_hal_bt_serial_tx(uint8_t* data, uint16_t size) { if(size > FURI_HAL_BT_SERIAL_PACKET_SIZE_MAX) { return false; diff --git a/firmware/targets/furi_hal_include/furi_hal_bt_serial.h b/firmware/targets/furi_hal_include/furi_hal_bt_serial.h index e1b7af224..1b6e79ab0 100644 --- a/firmware/targets/furi_hal_include/furi_hal_bt_serial.h +++ b/firmware/targets/furi_hal_include/furi_hal_bt_serial.h @@ -8,6 +8,11 @@ extern "C" { #define FURI_HAL_BT_SERIAL_PACKET_SIZE_MAX SERIAL_SVC_DATA_LEN_MAX +typedef enum { + FuriHalBtSerialRpcStatusNotActive, + FuriHalBtSerialRpcStatusActive, +} FuriHalBtSerialRpcStatus; + /** Serial service callback type */ typedef SerialServiceEventCallback FuriHalBtSerialCallback; @@ -30,6 +35,12 @@ void furi_hal_bt_serial_set_event_callback( FuriHalBtSerialCallback callback, void* context); +/** Set BLE RPC status + * + * @param status FuriHalBtSerialRpcStatus instance + */ +void furi_hal_bt_serial_set_rpc_status(FuriHalBtSerialRpcStatus status); + /** Notify that application buffer is empty */ void furi_hal_bt_serial_notify_buffer_is_empty(); diff --git a/scripts/update.py b/scripts/update.py index 1ff818c46..3259c5b09 100755 --- a/scripts/update.py +++ b/scripts/update.py @@ -78,9 +78,12 @@ class Main(App): def generate(self): stage_basename = "updater.bin" # used to be basename(self.args.stage) - dfu_basename = "firmware.dfu" # used to be basename(self.args.dfu) - radiobin_basename = "radio.bin" # used to be basename(self.args.radiobin) - radiobin_basename_arg = basename(self.args.radiobin) + dfu_basename = ( + "firmware.dfu" if self.args.dfu else "" + ) # used to be basename(self.args.dfu) + radiobin_basename = ( + "radio.bin" if self.args.radiobin else "" + ) # used to be basename(self.args.radiobin) resources_basename = "" radio_version = 0 @@ -116,7 +119,7 @@ class Main(App): if self.args.dfu: dfu_size = os.stat(self.args.dfu).st_size shutil.copyfile(self.args.dfu, join(self.args.directory, dfu_basename)) - if radiobin_basename_arg: + if radiobin_basename: shutil.copyfile( self.args.radiobin, join(self.args.directory, radiobin_basename) ) @@ -156,13 +159,10 @@ class Main(App): file.writeComment("little-endian hex!") file.writeKey("Loader CRC", self.int2ffhex(self.crc(self.args.stage))) file.writeKey("Firmware", dfu_basename) - if radiobin_basename_arg: - file.writeKey("Radio", radiobin_basename) - else: - file.writeKey("Radio", "") + file.writeKey("Radio", radiobin_basename or "") file.writeKey("Radio address", self.int2ffhex(radio_addr)) file.writeKey("Radio version", self.int2ffhex(radio_version, 12)) - if radiobin_basename_arg: + if radiobin_basename: file.writeKey("Radio CRC", self.int2ffhex(self.crc(self.args.radiobin))) else: file.writeKey("Radio CRC", self.int2ffhex(0))