Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions include/pbl/drivers/flash.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ void flash_read_bytes(uint8_t* buffer, uint32_t start_addr, uint32_t buffer_size
*/
void flash_write_bytes(const uint8_t* buffer, uint32_t start_addr, uint32_t buffer_size);

/**
* The CPU-addressable pointer for a flash address. Only exists on platforms whose flash is
* permanently memory-mapped (region addresses include the XIP base, FLASH_REGION_BASE_ADDRESS),
* where flash bytes can be read directly instead of copied out with flash_read_bytes.
*/
const void *flash_memory_mapped_address(uint32_t flash_addr);

typedef void (*FlashOperationCompleteCb)(void *context, status_t result);

/**
Expand Down
16 changes: 14 additions & 2 deletions include/pbl/services/imaging.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,26 @@ typedef struct CommSession CommSession;

//! Generic image-fetch service. Consumers (album art, ...) ask the phone for an image and get the
//! reassembled bitmap back through a registered handler. Watch-pull only, capability-gated.
//! On boards with memory-mapped flash the decoded image is stored in one of a small fixed pool of
//! flash slots and rendered straight from there, so no pixel-sized heap buffer is held; two
//! consumers can each display an image at once.

//! Called on KernelMain when a requested image finishes transferring. `bitmap` is NULL when the
//! phone reported it has no image (ImagingResponseFlagNoImage). Ownership of a non-NULL `bitmap`
//! (and its pixel/palette buffers) passes to the handler. `token` echoes the request.
//! (and its palette) passes to the handler. The pixels are heap memory to free only when
//! `info.is_bitmap_heap_allocated` is set; otherwise they live in a memory-mapped flash slot owned
//! by the service, which stays valid until the same consumer requests again or calls
//! imaging_release. `token` echoes the request.
typedef void (*ImagingReceivedHandler)(uint8_t token, struct GBitmap *bitmap);

//! Register the handler for an image type. One handler per type; overwrites any previous.
void imaging_register_handler(ImagingImageType image_type, ImagingReceivedHandler handler);

//! Tell the service a consumer has stopped displaying its image and isn't replacing it (e.g. its
//! window closed), so the flash slot it held can be reused. Replacing an image needs no release —
//! a fresh request hands the slot over automatically. No-op where the slot pool isn't compiled in.
void imaging_release(ImagingImageType image_type);

//! True if the connected phone advertises image-fetch support and hasn't told us it can't serve
//! this image type (see ImagingResponseFlagUnsupported). Latched state resets on reconnect.
bool imaging_is_type_supported(ImagingImageType image_type);
Expand All @@ -35,7 +46,8 @@ bool imaging_request_album_art(uint8_t token, ImagingFormat format, uint16_t wid
const char *title, const char *artist);

//! Ask the phone for the image it holds for timeline item `item_id`, at the given size/format.
//! No-op (and returns false) if unsupported. The matching handler is invoked when the transfer
//! No-op (and returns false) if unsupported or if the request could not be sent, in which case
//! nothing will be delivered. Otherwise the matching handler is invoked when the transfer
//! completes.
bool imaging_request_notification_image(uint8_t token, ImagingFormat format, uint16_t width,
uint16_t height, const Uuid *item_id);
Expand Down
6 changes: 6 additions & 0 deletions src/fw/drivers/flash/flash_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,12 @@ void flash_read_bytes(uint8_t* buffer, uint32_t start_addr,
pbl_mutex_unlock(&s_flash_lock);
}

#ifdef FLASH_REGION_BASE_ADDRESS
const void *flash_memory_mapped_address(uint32_t flash_addr) {
return (const void *)(uintptr_t)flash_addr;
}
#endif

#ifdef TEST_FLASH_LOCK_PROTECTION
static bool s_assert_write_error = false;
void flash_expect_program_failure(bool expect_failure) {
Expand Down
14 changes: 12 additions & 2 deletions src/fw/flash_region/flash_region_gd25q256e.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@
MACRO(SAFE_FIRMWARE, 0x0090000 /* 576K */, arg) /* 0x12A20000 - 0x12AAFFFF */ \
MACRO(FILESYSTEM, 0x1490000 /* 21056K */, arg) /* 0x12AB0000 - 0x13F3FFFF */ \
MACRO(CD, 0x0080000 /* 512K */, arg) /* 0x12A40000 - 0x13FBFFFF */ \
MACRO(RSVD1, 0x000F000 /* 60K */, arg) /* 0x13FC0000 - 0x13FCEFFF */ \
MACRO(IMAGING_0, 0x000A000 /* 40K */, arg) /* 0x13FC0000 - 0x13FC9FFF */ \
MACRO(RSVD1, 0x0005000 /* 20K */, arg) /* 0x13FCA000 - 0x13FCEFFF */ \
MACRO(DEBUG_DB, 0x0020000 /* 128K */, arg) /* 0x13FCF000 - 0x13FEEFFF */ \
MACRO(RSVD2, 0x000C000 /* 48K */, arg) /* 0x13FEF000 - 0x13FFAFFF */ \
MACRO(IMAGING_1, 0x000A000 /* 40K */, arg) /* 0x13FEF000 - 0x13FF8FFF */ \
MACRO(RSVD2, 0x0002000 /* 8K */, arg) /* 0x13FF9000 - 0x13FFAFFF */ \
MACRO(MFG_RESULTS, 0x0001000 /* 4K */, arg) /* 0x13FFB000 - 0x13FFBFFF */ \
MACRO(MFG_BATTERY_STATE, 0x0001000 /* 4K */, arg) /* 0x13FFC000 - 0x13FFCFFF */ \
MACRO(TZINFO, 0x0001000 /* 4K */, arg) /* 0x13FFD000 - 0x13FFDFFF */ \
Expand Down Expand Up @@ -68,6 +70,14 @@
#define FLASH_REGION_CD_BEGIN FLASH_REGION_START_ADDR(CD)
#define FLASH_REGION_CD_END FLASH_REGION_END_ADDR(CD)

// Two fixed slots for phone-supplied images (see services/imaging): each holds one decoded
// bitmap, written as it streams in and rendered directly through the memory-mapped flash
// window. Two slots so any two image consumers can display at once.
#define FLASH_REGION_IMAGING_0_BEGIN FLASH_REGION_START_ADDR(IMAGING_0)
#define FLASH_REGION_IMAGING_0_END FLASH_REGION_END_ADDR(IMAGING_0)
#define FLASH_REGION_IMAGING_1_BEGIN FLASH_REGION_START_ADDR(IMAGING_1)
#define FLASH_REGION_IMAGING_1_END FLASH_REGION_END_ADDR(IMAGING_1)

#define FLASH_REGION_DEBUG_DB_BEGIN FLASH_REGION_START_ADDR(DEBUG_DB)
#define FLASH_REGION_DEBUG_DB_END FLASH_REGION_END_ADDR(DEBUG_DB)
#define FLASH_DEBUG_DB_BLOCK_SIZE SUBSECTOR_SIZE_BYTES
Expand Down
14 changes: 12 additions & 2 deletions src/fw/flash_region/flash_region_qemu.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@
MACRO(SAFE_FIRMWARE, 0x0090000 /* 576K */, arg) /* 0x10A20000 - 0x10AAFFFF */ \
MACRO(FILESYSTEM, 0x1490000 /* 21056K */, arg) /* 0x10AB0000 - 0x11F3FFFF */ \
MACRO(CD, 0x0080000 /* 512K */, arg) /* 0x11F40000 - 0x11FBFFFF */ \
MACRO(RSVD1, 0x000F000 /* 60K */, arg) /* 0x11FC0000 - 0x11FCEFFF */ \
MACRO(IMAGING_0, 0x000A000 /* 40K */, arg) /* 0x11FC0000 - 0x11FC9FFF */ \
MACRO(RSVD1, 0x0005000 /* 20K */, arg) /* 0x11FCA000 - 0x11FCEFFF */ \
MACRO(DEBUG_DB, 0x0020000 /* 128K */, arg) /* 0x11FCF000 - 0x11FEEFFF */ \
MACRO(RSVD2, 0x000C000 /* 48K */, arg) /* 0x11FEF000 - 0x11FFAFFF */ \
MACRO(IMAGING_1, 0x000A000 /* 40K */, arg) /* 0x11FEF000 - 0x11FF8FFF */ \
MACRO(RSVD2, 0x0002000 /* 8K */, arg) /* 0x11FF9000 - 0x11FFAFFF */ \
MACRO(MFG_RESULTS, 0x0001000 /* 4K */, arg) /* 0x11FFB000 - 0x11FFBFFF */ \
MACRO(MFG_BATTERY_STATE, 0x0001000 /* 4K */, arg) /* 0x11FFC000 - 0x11FFCFFF */ \
MACRO(TZINFO, 0x0001000 /* 4K */, arg) /* 0x11FFD000 - 0x11FFDFFF */ \
Expand Down Expand Up @@ -66,6 +68,14 @@

// CD region is defined by flash_region.h based on CONFIG_PBLBOOT

// Two fixed slots for phone-supplied images (see services/imaging): each holds one decoded
// bitmap, written as it streams in and rendered directly through the memory-mapped flash
// window. Two slots so any two image consumers can display at once.
#define FLASH_REGION_IMAGING_0_BEGIN FLASH_REGION_START_ADDR(IMAGING_0)
#define FLASH_REGION_IMAGING_0_END FLASH_REGION_END_ADDR(IMAGING_0)
#define FLASH_REGION_IMAGING_1_BEGIN FLASH_REGION_START_ADDR(IMAGING_1)
#define FLASH_REGION_IMAGING_1_END FLASH_REGION_END_ADDR(IMAGING_1)

#define FLASH_REGION_DEBUG_DB_BEGIN FLASH_REGION_START_ADDR(DEBUG_DB)
#define FLASH_REGION_DEBUG_DB_END FLASH_REGION_END_ADDR(DEBUG_DB)
#define FLASH_DEBUG_DB_BLOCK_SIZE SUBSECTOR_SIZE_BYTES
Expand Down
11 changes: 9 additions & 2 deletions src/fw/popups/notifications/notification_window.c
Original file line number Diff line number Diff line change
Expand Up @@ -1151,6 +1151,10 @@ static void prv_window_unload(Window *window) {

swap_layer_deinit(&data->swap_layer);
notification_image_clear();
#if NOTIFICATION_IMAGE_SUPPORTED
// The card is gone, so let the imaging service reuse the flash slot its image was in.
imaging_release(ImagingImageTypeNotification);
#endif
status_bar_layer_deinit(&data->status_layer);
notifications_presented_list_deinit(prv_handle_presented_notif_deinit, NULL);
gbitmap_deinit(&data->dnd_icon);
Expand Down Expand Up @@ -1195,8 +1199,11 @@ static void prv_maybe_request_notification_image(LayoutLayer *layout, TimelineIt
!notification_image_claim(&item->header.id, &token)) {
return;
}
imaging_request_notification_image(token, ImagingFormat4BitPalette, size.w, size.h,
&item->header.id);
if (!imaging_request_notification_image(token, ImagingFormat4BitPalette, size.w, size.h,
&item->header.id)) {
// Nothing is coming, so resolve the slot rather than leave the card on its placeholder.
notification_image_store(token, NULL);
}
}
#endif

Expand Down
Loading