diff options
-rw-r--r-- | bootloader_message/bootloader_message.cpp | 10 | ||||
-rw-r--r-- | bootloader_message/include/bootloader_message/bootloader_message.h | 20 | ||||
-rw-r--r-- | minui/events.cpp | 29 | ||||
-rw-r--r-- | minui/graphics.cpp | 4 | ||||
-rw-r--r-- | minui/graphics.h | 11 | ||||
-rw-r--r-- | minui/graphics_drm.cpp | 189 | ||||
-rw-r--r-- | minui/graphics_drm.h | 19 | ||||
-rw-r--r-- | minui/graphics_fbdev.cpp | 4 | ||||
-rw-r--r-- | minui/graphics_fbdev.h | 1 | ||||
-rw-r--r-- | minui/include/minui/minui.h | 3 |
10 files changed, 214 insertions, 76 deletions
diff --git a/bootloader_message/bootloader_message.cpp b/bootloader_message/bootloader_message.cpp index b70d54e5c..1ea56cd4e 100644 --- a/bootloader_message/bootloader_message.cpp +++ b/bootloader_message/bootloader_message.cpp @@ -304,6 +304,16 @@ bool WriteMiscVirtualAbMessage(const misc_virtual_ab_message& message, std::stri offsetof(misc_system_space_layout, virtual_ab_message), err); } +bool ReadMiscMemtagMessage(misc_memtag_message* message, std::string* err) { + return ReadMiscPartitionSystemSpace(message, sizeof(*message), + offsetof(misc_system_space_layout, memtag_message), err); +} + +bool WriteMiscMemtagMessage(const misc_memtag_message& message, std::string* err) { + return WriteMiscPartitionSystemSpace(&message, sizeof(message), + offsetof(misc_system_space_layout, memtag_message), err); +} + extern "C" bool write_reboot_bootloader(void) { std::string err; return write_reboot_bootloader(&err); diff --git a/bootloader_message/include/bootloader_message/bootloader_message.h b/bootloader_message/include/bootloader_message/bootloader_message.h index e4cf09b22..d58158dd6 100644 --- a/bootloader_message/include/bootloader_message/bootloader_message.h +++ b/bootloader_message/include/bootloader_message/bootloader_message.h @@ -93,18 +93,35 @@ struct misc_virtual_ab_message { uint8_t reserved[57]; } __attribute__((packed)); +struct misc_memtag_message { + uint8_t version; + uint32_t magic; // magic string for treble compat + uint32_t memtag_mode; + uint8_t reserved[55]; +} __attribute__((packed)); + #define MISC_VIRTUAL_AB_MESSAGE_VERSION 2 #define MISC_VIRTUAL_AB_MAGIC_HEADER 0x56740AB0 +#define MISC_MEMTAG_MESSAGE_VERSION 1 +#define MISC_MEMTAG_MAGIC_HEADER 0x5afefe5a +#define MISC_MEMTAG_MODE_MEMTAG 0x1 +#define MISC_MEMTAG_MODE_MEMTAG_ONCE 0x2 +#define MISC_MEMTAG_MODE_MEMTAG_KERNEL 0x4 +#define MISC_MEMTAG_MODE_MEMTAG_KERNEL_ONCE 0x8 + #if (__STDC_VERSION__ >= 201112L) || defined(__cplusplus) static_assert(sizeof(struct misc_virtual_ab_message) == 64, "struct misc_virtual_ab_message has wrong size"); +static_assert(sizeof(struct misc_memtag_message) == 64, + "struct misc_memtag_message has wrong size"); #endif // This struct is not meant to be used directly, rather, it is to make // computation of offsets easier. New fields must be added to the end. struct misc_system_space_layout { misc_virtual_ab_message virtual_ab_message; + misc_memtag_message memtag_message; } __attribute__((packed)); #ifdef __cplusplus @@ -172,6 +189,9 @@ bool write_wipe_package(const std::string& package_data, std::string* err); bool ReadMiscVirtualAbMessage(misc_virtual_ab_message* message, std::string* err); bool WriteMiscVirtualAbMessage(const misc_virtual_ab_message& message, std::string* err); +// Read or write the memtag message from system space in /misc. +bool ReadMiscMemtagMessage(misc_memtag_message* message, std::string* err); +bool WriteMiscMemtagMessage(const misc_memtag_message& message, std::string* err); #else #include <stdbool.h> diff --git a/minui/events.cpp b/minui/events.cpp index 863ac7474..b307a4977 100644 --- a/minui/events.cpp +++ b/minui/events.cpp @@ -267,6 +267,35 @@ int ev_get_input(int fd, uint32_t epevents, input_event* ev) { return -1; } +int ev_sync_sw_state(const ev_set_sw_callback& set_sw_cb) { + // Use unsigned long to match ioctl's parameter type. + unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)]; // NOLINT + unsigned long sw_bits[BITS_TO_LONGS(SW_MAX)]; // NOLINT + + for (size_t i = 0; i < g_ev_dev_count; ++i) { + memset(ev_bits, 0, sizeof(ev_bits)); + memset(sw_bits, 0, sizeof(sw_bits)); + + if (ioctl(ev_fdinfo[i].fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) == -1) { + continue; + } + if (!test_bit(EV_SW, ev_bits)) { + continue; + } + if (ioctl(ev_fdinfo[i].fd, EVIOCGSW(sizeof(sw_bits)), sw_bits) == -1) { + continue; + } + + for (int code = 0; code <= SW_MAX; code++) { + if (test_bit(code, sw_bits)) { + set_sw_cb(code, 1); + } + } + } + + return 0; +} + int ev_sync_key_state(const ev_set_key_callback& set_key_cb) { // Use unsigned long to match ioctl's parameter type. unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)]; // NOLINT diff --git a/minui/graphics.cpp b/minui/graphics.cpp index f25694ab5..597f2ceaf 100644 --- a/minui/graphics.cpp +++ b/minui/graphics.cpp @@ -450,6 +450,10 @@ void gr_fb_blank(bool blank) { gr_backend->Blank(blank); } +void gr_fb_blank(bool blank, int index) { + gr_backend->Blank(blank, static_cast<MinuiBackend::DrmConnector>(index)); +} + void gr_rotate(GRRotation rot) { rotation = rot; } diff --git a/minui/graphics.h b/minui/graphics.h index 3c45a406b..5408c93e9 100644 --- a/minui/graphics.h +++ b/minui/graphics.h @@ -21,6 +21,12 @@ class MinuiBackend { public: + enum DrmConnector { + DRM_MAIN = 0, + DRM_SEC, + DRM_MAX, + }; + // Initializes the backend and returns a GRSurface* to draw into. virtual GRSurface* Init() = 0; @@ -28,9 +34,12 @@ class MinuiBackend { // be displayed, and returns a new drawing surface. virtual GRSurface* Flip() = 0; - // Blank (or unblank) the screen. + // Blank (or unblank) the default screen. virtual void Blank(bool) = 0; + // Blank (or unblank) the specific screen. + virtual void Blank(bool blank, DrmConnector index) = 0; + // Device cleanup when drawing is done. virtual ~MinuiBackend() {}; }; diff --git a/minui/graphics_drm.cpp b/minui/graphics_drm.cpp index 9d31ff7a9..c55702276 100644 --- a/minui/graphics_drm.cpp +++ b/minui/graphics_drm.cpp @@ -153,22 +153,50 @@ void MinuiBackendDrm::DrmDisableCrtc(int drm_fd, drmModeCrtc* crtc) { } bool MinuiBackendDrm::DrmEnableCrtc(int drm_fd, drmModeCrtc* crtc, - const std::unique_ptr<GRSurfaceDrm>& surface) { + const std::unique_ptr<GRSurfaceDrm>& surface, + uint32_t* connector_id) { if (drmModeSetCrtc(drm_fd, crtc->crtc_id, surface->fb_id, 0, 0, // x,y - &main_monitor_connector->connector_id, - 1, // connector_count - &main_monitor_crtc->mode) != 0) { - perror("Failed to drmModeSetCrtc"); + connector_id, 1, // connector_count + &crtc->mode) != 0) { + fprintf(stderr, "Failed to drmModeSetCrtc(%d)\n", *connector_id); return false; } + return true; } void MinuiBackendDrm::Blank(bool blank) { + Blank(blank, DRM_MAIN); +} + +void MinuiBackendDrm::Blank(bool blank, DrmConnector index) { + const auto* drmInterface = &drm[DRM_MAIN]; + + switch (index) { + case DRM_MAIN: + drmInterface = &drm[DRM_MAIN]; + break; + case DRM_SEC: + drmInterface = &drm[DRM_SEC]; + break; + default: + fprintf(stderr, "Invalid index: %d\n", index); + return; + } + + if (!drmInterface->monitor_connector) { + fprintf(stderr, "Unsupported. index = %d\n", index); + return; + } + if (blank) { - DrmDisableCrtc(drm_fd, main_monitor_crtc); + DrmDisableCrtc(drm_fd, drmInterface->monitor_crtc); } else { - DrmEnableCrtc(drm_fd, main_monitor_crtc, GRSurfaceDrms[current_buffer]); + DrmEnableCrtc(drm_fd, drmInterface->monitor_crtc, + drmInterface->GRSurfaceDrms[drmInterface->current_buffer], + &drmInterface->monitor_connector->connector_id); + + active_display = index; } } @@ -210,18 +238,21 @@ static drmModeCrtc* find_crtc_for_connector(int fd, drmModeRes* resources, return nullptr; } -static drmModeConnector* find_used_connector_by_type(int fd, drmModeRes* resources, unsigned type) { +std::vector<drmModeConnector*> find_used_connector_by_type(int fd, drmModeRes* resources, + unsigned type) { + std::vector<drmModeConnector*> drmConnectors; for (int i = 0; i < resources->count_connectors; i++) { drmModeConnector* connector = drmModeGetConnector(fd, resources->connectors[i]); if (connector) { if ((connector->connector_type == type) && (connector->connection == DRM_MODE_CONNECTED) && (connector->count_modes > 0)) { - return connector; + drmConnectors.push_back(connector); + } else { + drmModeFreeConnector(connector); } - drmModeFreeConnector(connector); } } - return nullptr; + return drmConnectors; } static drmModeConnector* find_first_connected_connector(int fd, drmModeRes* resources) { @@ -239,8 +270,7 @@ static drmModeConnector* find_first_connected_connector(int fd, drmModeRes* reso return nullptr; } -drmModeConnector* MinuiBackendDrm::FindMainMonitor(int fd, drmModeRes* resources, - uint32_t* mode_index) { +bool MinuiBackendDrm::FindAndSetMonitor(int fd, drmModeRes* resources) { /* Look for LVDS/eDP/DSI connectors. Those are the main screens. */ static constexpr unsigned kConnectorPriority[] = { DRM_MODE_CONNECTOR_LVDS, @@ -248,37 +278,41 @@ drmModeConnector* MinuiBackendDrm::FindMainMonitor(int fd, drmModeRes* resources DRM_MODE_CONNECTOR_DSI, }; - drmModeConnector* main_monitor_connector = nullptr; - unsigned i = 0; - do { - main_monitor_connector = find_used_connector_by_type(fd, resources, kConnectorPriority[i]); - i++; - } while (!main_monitor_connector && i < arraysize(kConnectorPriority)); + std::vector<drmModeConnector*> drmConnectors; + for (int i = 0; i < arraysize(kConnectorPriority) && drmConnectors.size() < DRM_MAX; i++) { + auto connectors = find_used_connector_by_type(fd, resources, kConnectorPriority[i]); + for (auto connector : connectors) { + drmConnectors.push_back(connector); + if (drmConnectors.size() >= DRM_MAX) break; + } + } /* If we didn't find a connector, grab the first one that is connected. */ - if (!main_monitor_connector) { - main_monitor_connector = find_first_connected_connector(fd, resources); + if (drmConnectors.empty()) { + drmModeConnector* connector = find_first_connected_connector(fd, resources); + if (connector) { + drmConnectors.push_back(connector); + } } - /* If we still didn't find a connector, give up and return. */ - if (!main_monitor_connector) return nullptr; - - for (int modes = 0; modes < main_monitor_connector->count_modes; modes++) { - printf("Display Mode %d resolution: %d x %d @ %d FPS\n", modes, - main_monitor_connector->modes[modes].hdisplay, - main_monitor_connector->modes[modes].vdisplay, - main_monitor_connector->modes[modes].vrefresh); - } - *mode_index = 0; - for (int modes = 0; modes < main_monitor_connector->count_modes; modes++) { - if (main_monitor_connector->modes[modes].type & DRM_MODE_TYPE_PREFERRED) { - printf("Choosing display mode #%d\n", modes); - *mode_index = modes; - break; + for (int drm_index = 0; drm_index < drmConnectors.size(); drm_index++) { + drm[drm_index].monitor_connector = drmConnectors[drm_index]; + + drm[drm_index].selected_mode = 0; + for (int modes = 0; modes < drmConnectors[drm_index]->count_modes; modes++) { + printf("Display Mode %d resolution: %d x %d @ %d FPS\n", modes, + drmConnectors[drm_index]->modes[modes].hdisplay, + drmConnectors[drm_index]->modes[modes].vdisplay, + drmConnectors[drm_index]->modes[modes].vrefresh); + if (drmConnectors[drm_index]->modes[modes].type & DRM_MODE_TYPE_PREFERRED) { + printf("Choosing display mode #%d\n", modes); + drm[drm_index].selected_mode = modes; + break; + } } } - return main_monitor_connector; + return drmConnectors.size() > 0; } void MinuiBackendDrm::DisableNonMainCrtcs(int fd, drmModeRes* resources, drmModeCrtc* main_crtc) { @@ -329,46 +363,49 @@ GRSurface* MinuiBackendDrm::Init() { return nullptr; } - uint32_t selected_mode; - main_monitor_connector = FindMainMonitor(drm_fd, res, &selected_mode); - if (!main_monitor_connector) { - fprintf(stderr, "Failed to find main_monitor_connector\n"); + if (!FindAndSetMonitor(drm_fd, res)) { + fprintf(stderr, "Failed to find main monitor_connector\n"); drmModeFreeResources(res); - close(drm_fd); return nullptr; } - main_monitor_crtc = find_crtc_for_connector(drm_fd, res, main_monitor_connector); - if (!main_monitor_crtc) { - fprintf(stderr, "Failed to find main_monitor_crtc\n"); - drmModeFreeResources(res); - close(drm_fd); - return nullptr; - } - - DisableNonMainCrtcs(drm_fd, res, main_monitor_crtc); + for (int i = 0; i < DRM_MAX; i++) { + if (drm[i].monitor_connector) { + drm[i].monitor_crtc = find_crtc_for_connector(drm_fd, res, drm[i].monitor_connector); + if (!drm[i].monitor_crtc) { + fprintf(stderr, "Failed to find monitor_crtc, drm index=%d\n", i); + drmModeFreeResources(res); + return nullptr; + } - main_monitor_crtc->mode = main_monitor_connector->modes[selected_mode]; + drm[i].monitor_crtc->mode = drm[i].monitor_connector->modes[drm[i].selected_mode]; - int width = main_monitor_crtc->mode.hdisplay; - int height = main_monitor_crtc->mode.vdisplay; + int width = drm[i].monitor_crtc->mode.hdisplay; + int height = drm[i].monitor_crtc->mode.vdisplay; - drmModeFreeResources(res); + drm[i].GRSurfaceDrms[0] = GRSurfaceDrm::Create(drm_fd, width, height); + drm[i].GRSurfaceDrms[1] = GRSurfaceDrm::Create(drm_fd, width, height); + if (!drm[i].GRSurfaceDrms[0] || !drm[i].GRSurfaceDrms[1]) { + fprintf(stderr, "Failed to create GRSurfaceDrm, drm index=%d\n", i); + drmModeFreeResources(res); + return nullptr; + } - GRSurfaceDrms[0] = GRSurfaceDrm::Create(drm_fd, width, height); - GRSurfaceDrms[1] = GRSurfaceDrm::Create(drm_fd, width, height); - if (!GRSurfaceDrms[0] || !GRSurfaceDrms[1]) { - return nullptr; + drm[i].current_buffer = 0; + } } - current_buffer = 0; + DisableNonMainCrtcs(drm_fd, res, drm[DRM_MAIN].monitor_crtc); + + drmModeFreeResources(res); // We will likely encounter errors in the backend functions (i.e. Flip) if EnableCrtc fails. - if (!DrmEnableCrtc(drm_fd, main_monitor_crtc, GRSurfaceDrms[1])) { + if (!DrmEnableCrtc(drm_fd, drm[DRM_MAIN].monitor_crtc, drm[DRM_MAIN].GRSurfaceDrms[1], + &drm[DRM_MAIN].monitor_connector->connector_id)) { return nullptr; } - return GRSurfaceDrms[0].get(); + return drm[DRM_MAIN].GRSurfaceDrms[0].get(); } static void page_flip_complete(__unused int fd, @@ -380,10 +417,19 @@ static void page_flip_complete(__unused int fd, } GRSurface* MinuiBackendDrm::Flip() { + GRSurface* surface = NULL; + DrmInterface* current_drm = &drm[active_display]; bool ongoing_flip = true; - if (drmModePageFlip(drm_fd, main_monitor_crtc->crtc_id, GRSurfaceDrms[current_buffer]->fb_id, + + if (!current_drm->monitor_connector) { + fprintf(stderr, "Unsupported. active_display = %d\n", active_display); + return nullptr; + } + + if (drmModePageFlip(drm_fd, current_drm->monitor_crtc->crtc_id, + current_drm->GRSurfaceDrms[current_drm->current_buffer]->fb_id, DRM_MODE_PAGE_FLIP_EVENT, &ongoing_flip) != 0) { - perror("Failed to drmModePageFlip"); + fprintf(stderr, "Failed to drmModePageFlip, active_display=%d", active_display); return nullptr; } @@ -409,14 +455,19 @@ GRSurface* MinuiBackendDrm::Flip() { } } - current_buffer = 1 - current_buffer; - return GRSurfaceDrms[current_buffer].get(); + current_drm->current_buffer = 1 - current_drm->current_buffer; + surface = current_drm->GRSurfaceDrms[current_drm->current_buffer].get(); + return surface; } MinuiBackendDrm::~MinuiBackendDrm() { - DrmDisableCrtc(drm_fd, main_monitor_crtc); - drmModeFreeCrtc(main_monitor_crtc); - drmModeFreeConnector(main_monitor_connector); + for (int i = 0; i < DRM_MAX; i++) { + if (drm[i].monitor_connector) { + DrmDisableCrtc(drm_fd, drm[i].monitor_crtc); + drmModeFreeCrtc(drm[i].monitor_crtc); + drmModeFreeConnector(drm[i].monitor_connector); + } + } close(drm_fd); drm_fd = -1; } diff --git a/minui/graphics_drm.h b/minui/graphics_drm.h index 57ba39b83..fe3beaff9 100644 --- a/minui/graphics_drm.h +++ b/minui/graphics_drm.h @@ -59,16 +59,23 @@ class MinuiBackendDrm : public MinuiBackend { GRSurface* Init() override; GRSurface* Flip() override; void Blank(bool) override; + void Blank(bool blank, DrmConnector index) override; private: void DrmDisableCrtc(int drm_fd, drmModeCrtc* crtc); - bool DrmEnableCrtc(int drm_fd, drmModeCrtc* crtc, const std::unique_ptr<GRSurfaceDrm>& surface); + bool DrmEnableCrtc(int drm_fd, drmModeCrtc* crtc, const std::unique_ptr<GRSurfaceDrm>& surface, + uint32_t* conntcors); void DisableNonMainCrtcs(int fd, drmModeRes* resources, drmModeCrtc* main_crtc); - drmModeConnector* FindMainMonitor(int fd, drmModeRes* resources, uint32_t* mode_index); + bool FindAndSetMonitor(int fd, drmModeRes* resources); + + struct DrmInterface { + std::unique_ptr<GRSurfaceDrm> GRSurfaceDrms[2]; + int current_buffer{ 0 }; + drmModeCrtc* monitor_crtc{ nullptr }; + drmModeConnector* monitor_connector{ nullptr }; + uint32_t selected_mode{ 0 }; + } drm[DRM_MAX]; - std::unique_ptr<GRSurfaceDrm> GRSurfaceDrms[2]; - int current_buffer{ 0 }; - drmModeCrtc* main_monitor_crtc{ nullptr }; - drmModeConnector* main_monitor_connector{ nullptr }; int drm_fd{ -1 }; + DrmConnector active_display = DRM_MAIN; }; diff --git a/minui/graphics_fbdev.cpp b/minui/graphics_fbdev.cpp index 0d0fabce6..1cb0c0ab8 100644 --- a/minui/graphics_fbdev.cpp +++ b/minui/graphics_fbdev.cpp @@ -43,6 +43,10 @@ void MinuiBackendFbdev::Blank(bool blank) { if (ret < 0) perror("ioctl(): blank"); } +void MinuiBackendFbdev::Blank(bool blank, DrmConnector index) { + fprintf(stderr, "Unsupported multiple connectors, blank = %d, index = %d\n", blank, index); +} + void MinuiBackendFbdev::SetDisplayedFramebuffer(size_t n) { if (n > 1 || !double_buffered) return; diff --git a/minui/graphics_fbdev.h b/minui/graphics_fbdev.h index 596ba74ea..7e193c4ff 100644 --- a/minui/graphics_fbdev.h +++ b/minui/graphics_fbdev.h @@ -56,6 +56,7 @@ class MinuiBackendFbdev : public MinuiBackend { GRSurface* Init() override; GRSurface* Flip() override; void Blank(bool) override; + void Blank(bool blank, DrmConnector index) override; private: void SetDisplayedFramebuffer(size_t n); diff --git a/minui/include/minui/minui.h b/minui/include/minui/minui.h index 5470457e7..a2f62f0a6 100644 --- a/minui/include/minui/minui.h +++ b/minui/include/minui/minui.h @@ -127,6 +127,7 @@ int gr_fb_height(); void gr_flip(); void gr_fb_blank(bool blank); +void gr_fb_blank(bool blank, int index); // Clears entire surface to current color. void gr_clear(); @@ -161,6 +162,7 @@ struct input_event; using ev_callback = std::function<int(int fd, uint32_t epevents)>; using ev_set_key_callback = std::function<int(int code, int value)>; +using ev_set_sw_callback = std::function<int(int code, int value)>; int ev_init(ev_callback input_cb, bool allow_touch_inputs = false); void ev_exit(); @@ -168,6 +170,7 @@ int ev_add_fd(android::base::unique_fd&& fd, ev_callback cb); void ev_iterate_available_keys(const std::function<void(int)>& f); void ev_iterate_touch_inputs(const std::function<void(int)>& action); int ev_sync_key_state(const ev_set_key_callback& set_key_cb); +int ev_sync_sw_state(const ev_set_sw_callback& set_sw_cb); // 'timeout' has the same semantics as poll(2). // 0 : don't block |