From: Kichan Kwon Date: Mon, 14 May 2018 08:14:09 +0000 (+0900) Subject: Initial source X-Git-Tag: accepted/tizen/5.0/unified/20181102.021047~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=45f88636b4b260e2eebf7722615416f02df526b3;p=platform%2Fcore%2Fsystem%2Fsystem-recovery.git Initial source Change-Id: I22b9a4f8d1082d85290ddc51c50bd816e433d98e Signed-off-by: Kichan Kwon --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5cf9594 --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +*.cache +*.swp + +/build-aux +/m4 +/build_* + +aclocal.m4 +config.h +config.h.in +config.log +config.status +configure +debugfiles.list +debuglinks.list +debugsources.list +documentation.list +initrd-recovery.manifest +Makefile.in diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9fe66f6 --- /dev/null +++ b/LICENSE @@ -0,0 +1,203 @@ +Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..20f3675 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,195 @@ +ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} + +SUBDIRS = . + +initrd_recovery_libexecdir=$(INITRD_RECOVERY_LIBEXEC_DIR) +initrd_recovery_datadir=$(INITRD_RECOVERY_DATA_DIR) +initrd_recovery_install_dropindir=$(INITRD_RECOVERY_INSTALL_DROPIN_DIR) + +DEFAULT_CFLAGS = \ + $(LIBSYSTEM_CFLAGS) \ + $(OUR_CFLAGS) + +DEFAULT_LDFLAGS = \ + $(LIBSYSTEM_LDFLAGS) \ + $(OUR_LDFLAGS) + +DEFAULT_LIBS = \ + $(LIBSYSTEM_LIBS) \ + libinitrd-recovery-shared.la + +AM_CPPFLAGS = \ + -include $(top_builddir)/config.h \ + -I $(top_srcdir)/src \ + -I $(top_srcdir)/src/shared \ + $(DEFAULT_CFLAGS) + +AM_CFLAGS = $(DEFAULT_CFLAGS) +AM_LDFLAGS = $(DEFAULT_LDFLAGS) +AM_LIBS = $(DEFAULT_LIBS) + +CLEANFILES = +EXTRA_DIST = + +lib_LTLIBRARIES = +noinst_LTLIBRARIES = + +bin_PROGRAMS = + +initrd_recovery_install_dropin_DATA = + +# ------------------------------------------------------------------------------ +noinst_LTLIBRARIES += \ + libinitrd-recovery-shared.la + +libinitrd_recovery_shared_la_SOURCES = \ + src/shared/log.c \ + src/shared/log.h + +libinitrd_recovery_shared_la_CFLAGS = \ + $(AM_CFLAGS) + +libinitrd_recovery_shared_la_LIBADD = \ + $(LIBSYSTEM_LIBS) + +# ------------------------------------------------------------------------------ +if RECOVERY_GUI +noinst_LTLIBRARIES += \ + librui.la + +librui_la_SOURCES = \ + src/librui/graphics.c \ + src/librui/input-events.c \ + src/librui/resources.c \ + src/librui/rui-description.c \ + src/librui/rui-images.c \ + src/librui/rui-menu.c \ + src/librui/rui-progress-bar.c \ + src/librui/rui-rulers.c \ + src/librui/rui.c + +if HAVE_TDM +librui_la_SOURCES += \ + src/librui/graphics-tdm.c \ + src/librui/tdm-if.c +else +librui_la_SOURCES += \ + src/librui/graphics-fbdev-common.c \ + src/librui/graphics-fbdev.c +endif + +librui_la_CFLAGS = \ + $(LIBPNG_CFLAGS) \ + $(LIBTDM_CFLAGS) \ + $(VCONF_INTERNAL_KEYS) \ + $(AM_CFLAGS) \ + -I $(top_srcdir)/src/librui \ + -I $(top_srcdir)/src/fonts + +librui_la_LIBADD = \ + $(LIBPNG_LIBS) \ + $(LIBTDM_LIBS) \ + $(AM_LIBS) +endif + +# ------------------------------------------------------------------------------ +system_recovery_datadir = $(SYSTEM_RECOVERY_DATA_DIR) +system_recovery_imagedir = $(SYSTEM_RECOVERY_IMAGE_DIR) +system_recovery_libexecdir = $(SYSTEM_RECOVERY_LIBEXEC_DIR) + +system_recovery_SOURCES = \ + src/system-recovery/recovery-main.c + +system_recovery_CFLAGS = \ + $(AM_CFLAGS) \ + -DSYSTEM_RECOVERY_CONFIG_FILE=\""${system_recovery_datadir}/system-recovery.cfg"\" \ + $(LIBCONFIG_CFLAGS) \ + -I $(top_srcdir)/src/system-recovery + +system_recovery_LDADD = \ + $(AM_LIBS) \ + $(LIBCONFIG_LIBS) + +if RECOVERY_GUI +system_recovery_SOURCES += \ + src/system-recovery/process-util.c \ + src/system-recovery/recovery-rui.c + +system_recovery_CFLAGS += \ + -I $(librui_la_CFLAGS) \ + -I $(top_srcdir)/src/librui + +system_recovery_LDADD += \ + librui.la + +system_recovery_image_DATA = \ + src/system-recovery/res/images/font.png \ + src/system-recovery/res/images/menu-title.png \ + src/system-recovery/res/images/tizen-anim.png \ + src/system-recovery/res/images/warning.png + +initrd_recovery_install_dropin_DATA += \ + src/system-recovery/50-system-recovery-sprd.list + +else + +system_recovery_SOURCES += \ + src/system-recovery/recovery-headless.c +endif + +system_recovery_libexec_PROGRAMS = \ + system-recovery + +system_recovery_data_DATA = \ + src/system-recovery/system-recovery.cfg + +system_recovery_libexec_SCRIPTS = \ + src/system-recovery/recovery-init + +sbin_SCRIPTS = \ + src/system-recovery/recovery-action-set + +initrd_recovery_install_dropin_DATA += \ + src/system-recovery/50-system-recovery.list + +EXTRA_DIST += \ + src/system-recovery/50-system-recovery.list.m4 \ + src/system-recovery/recovery-init.in \ + src/system-recovery/recovery-action-set.in \ + src/system-recovery/system-recovery.cfg.m4.in + +CLEANFILES += \ + src/system-recovery/50-system-recovery.list \ + src/system-recovery/recovery-init \ + src/system-recovery/system-recovery.cfg.m4 \ + src/system-recovery/recovery-action-set + +# ------------------------------------------------------------------------------ +substitutions = \ + '|PACKAGE_VERSION=$(PACKAGE_VERSION)|' \ + '|PACKAGE_NAME=$(PACKAGE_NAME)|' \ + '|PACKAGE_URL=$(PACKAGE_URL)|' \ + '|includedir=$(includedir)|' \ + '|VERSION=$(VERSION)|' \ + '|MKDIR_P=$(MKDIR_P)|' \ + '|INITRD_RECOVERY_INSTALL_DROPIN_DIR=$(INITRD_RECOVERY_INSTALL_DROPIN_DIR)|' \ + '|INITRD_RECOVERY_LIBEXEC_DIR=$(INITRD_RECOVERY_LIBEXEC_DIR)|' \ + '|SYSTEM_RECOVERY_IMAGE_DIR=$(SYSTEM_RECOVERY_IMAGE_DIR)|' \ + '|SYSTEM_RECOVERY_LIBEXEC_DIR=$(SYSTEM_RECOVERY_LIBEXEC_DIR)|' \ + '|SYSTEM_RECOVERY_DATA_DIR=$(SYSTEM_RECOVERY_DATA_DIR)|' \ + '|SYSTEM_RECOVERY_ACTION_FILE=$(SYSTEM_RECOVERY_ACTION_FILE)|' \ + '|RECOVERY_GUI=$(RECOVERY_GUI)|' + +SED_PROCESS = \ + $(AM_V_GEN)$(MKDIR_P) $(dir $@) && \ + $(SED) $(subst '|,-e 's|@,$(subst =,\@|,$(subst |',|g',$(substitutions)))) \ + < $< > $@ + +src/%: src/%.in Makefile + $(SED_PROCESS) + +src/%: src/%.m4 + $(AM_V_at)$(MKDIR_P) $(dir $@) + $(AM_V_M4)$(M4) -P $(M4_DEFINES) < $< > $@ + +install-exec-hook: $(INSTALL_EXEC_HOOKS) diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..968bc8e --- /dev/null +++ b/autogen.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +set -e + +if [ -f .git/hooks/pre-commit.sample ] && [ ! -f .git/hooks/pre-commit ]; then + # This part is allowed to fail + cp -p .git/hooks/pre-commit.sample .git/hooks/pre-commit && \ + chmod +x .git/hooks/pre-commit && \ + echo "Activated pre-commit hook." || : +fi + +# README and INSTALL are required by automake, but may be deleted by +# clean up rules. to get automake to work, simply touch these here, +# they will be regenerated from their corresponding *.in files by +# ./configure anyway. +touch README INSTALL + +# Make sure m4 directory exist +mkdir -p m4 + +autoreconf --force --install --verbose || exit $? diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..23f1b2c --- /dev/null +++ b/configure.ac @@ -0,0 +1,153 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ([2.69]) +AC_INIT([initrd-recovery], [2.1.1], [walyong.cho@samsung.com]) + +AC_CONFIG_MACRO_DIR([m4]) +AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_AUX_DIR([build-aux]) + +AC_USE_SYSTEM_EXTENSIONS +AC_SYS_LARGEFILE +AC_PREFIX_DEFAULT([/usr]) +AM_INIT_AUTOMAKE([foreign subdir-objects]) + +LT_PREREQ(2.2) +LT_INIT([disable-static]) + +# Checks for programs. +AC_PROG_CC +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_MAKE_SET +AC_PROG_MKDIR_P +AC_PATH_PROG([M4], [m4]) + +# Checks for libraries. + +# Checks for header files. +AC_CHECK_HEADERS([fcntl.h limits.h mntent.h stdint.h stdlib.h string.h sys/ioctl.h sys/mount.h unistd.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_CHECK_HEADER_STDBOOL +AC_C_INLINE +AC_TYPE_PID_T +AC_TYPE_SIZE_T +AC_TYPE_UINT32_T + +# Checks for library functions. +AC_FUNC_FORK +AC_FUNC_GETMNTENT +AC_FUNC_MALLOC +AC_FUNC_MMAP +AC_CHECK_FUNCS([dup2 getmntent memset munmap strcasecmp strchr strdup strerror strrchr strstr]) + +# ------------------------------------------------------------------------------ +our_cflags=" \ + -g -O2 \ + -Werror \ + -fpie" + +our_ldflags=" \ + -Wl,--as-needed \ + -Wl,--no-undefined \ + -Wl,--gc-sections \ + -Wl,-z,relro \ + -Wl,-z,now \ + -pie" + +AC_SUBST([OUR_CFLAGS], "$our_cflags") +AC_SUBST([OUR_LDFLAGS], "$our_ldflags") + +M4_DEFINES= +# ------------------------------------------------------------------------------ +AC_ARG_WITH([tdm], + AS_HELP_STRING([--without-tdm], [disable TDM/TBM graphical backend (default: test)])) +PKG_CHECK_MODULES([LIBCONFIG], + [libconfig >= 1.6], + have_libconfig=yes, + have_libconfig=no) + +if test "x$have_libconfig" = "xno"; then + AC_MSG_ERROR([libconfig not found]) +fi + +AC_ARG_ENABLE([recovery-gui], + AS_HELP_STRING([--disable-recovery-gui], [disable recovery gui mode]), + [case "${enableval}" in + yes) enable_recovery_gui=yes ;; + no) enable_recovery_gui=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-recovery-gui) ;; + esac], + enable_recovery_gui=yes) + +have_libtdm=no +if test "x$enable_recovery_gui" == "xyes"; then + M4_DEFINES="$M4_DEFINES -DRECOVERY_GUI" + AC_SUBST([OUR_CFLAGS], "$OUR_CFLAGS -DRECOVERY_GUI") + PKG_CHECK_MODULES(LIBPNG, [libpng]) + if test "x$with_tdm" != "xno"; then + PKG_CHECK_MODULES(LIBTDM, + [libtdm >= 1.7.0], + [AC_DEFINE(HAVE_TDM, 1, [Define if using TDM/TBM graphical backend]) + have_libtdm=yes]) + if test "x$with_tdm" = "xyes" -a "x$have_libtdm" = "xno"; then + AC_MSG_ERROR([--with-tdm has been specified but libtdm is not available.]) + fi + fi + RECOVERY_GUI="GUI" +else + RECOVERY_GUI="NO" +fi + +AC_SUBST([RECOVERY_GUI]) +AM_CONDITIONAL([RECOVERY_GUI], [test "x$enable_recovery_gui" != "xno"]) +AM_CONDITIONAL([HAVE_TDM], [test "x$have_libtdm" = "xyes"]) + +SYSTEM_RECOVERY_DATA_DIR="${datadir}/system-recovery" +AC_DEFINE_UNQUOTED([SYSTEM_RECOVERY_DATA_DIR], ["$SYSTEM_RECOVERY_DATA_DIR"], "Directory where data for system-recovery UI are stored") +AC_SUBST([SYSTEM_RECOVERY_DATA_DIR]) + +SYSTEM_RECOVERY_IMAGE_DIR="${datadir}/system-recovery/res/images" +AC_DEFINE_UNQUOTED([SYSTEM_RECOVERY_IMAGE_DIR], ["$SYSTEM_RECOVERY_IMAGE_DIR"], "Directory where images for system-recovery UI are stored") +AC_SUBST([SYSTEM_RECOVERY_IMAGE_DIR]) + +RUI_IMAGES_DIR="${SYSTEM_RECOVERY_IMAGE_DIR}" +AC_DEFINE_UNQUOTED([RUI_IMAGES_DIR], ["$RUI_IMAGES_DIR"], "Directory where images for system-recovery UI are stored") + +SYSTEM_RECOVERY_LIBEXEC_DIR="${libexecdir}/system-recovery" +AC_DEFINE_UNQUOTED([SYSTEM_RECOVERY_LIBEXEC_DIR], ["$SYSTEM_RECOVERY_LIBEXEC_DIR"], "Directory where sub-programmes for system-recovery UI are stored") +AC_SUBST([SYSTEM_RECOVERY_LIBEXEC_DIR]) + +SYSTEM_RECOVERY_ACTION_FILE="/opt/.recovery.action" +AC_DEFINE_UNQUOTED([SYSTEM_RECOVERY_ACTION_FILE], ["$SYSTEM_RECOVERY_ACTION_FILE"], "File where recovery action is stored") +AC_SUBST([SYSTEM_RECOVERY_ACTION_FILE]) + +INITRD_RECOVERY_DATA_DIR="${datadir}/initrd-recovery" +AC_DEFINE_UNQUOTED([INITRD_RECOVERY_DATA_DIR], ["$INITRD_RECOVERY_DATA_DIR"], "Directory where data for recovery initrd are stored") +AC_SUBST([INITRD_RECOVERY_DATA_DIR]) + +INITRD_RECOVERY_INSTALL_DROPIN_DIR="${INITRD_RECOVERY_DATA_DIR}/initrd.list.d" +AC_DEFINE_UNQUOTED([INITRD_RECOVERY_INSTALL_DROPIN_DIR], ["$INITRD_RECOVERY_INSTALL_DROPIN_DIR"], "Directory where configuration drop-in files for recovery initrd are stored") +AC_SUBST([INITRD_RECOVERY_INSTALL_DROPIN_DIR]) + +INITRD_RECOVERY_LIBEXEC_DIR="${libexecdir}/initrd-recovery" +AC_DEFINE_UNQUOTED([INITRD_RECOVERY_LIBEXEC_DIR], ["$INITRD_RECOVERY_LIBEXEC_DIR"], "Directory where sub-progremmes for recovery initrd are stored") +AC_SUBST([INITRD_RECOVERY_LIBEXEC_DIR]) + +# ------------------------------------------------------------------------------ +AC_SUBST(M4_DEFINES) + +# ------------------------------------------------------------------------------ +AC_CONFIG_FILES([Makefile]) + +AC_OUTPUT +AC_MSG_RESULT([ + $PACKAGE_NAME $VERSION + ===================== + prefix: ${prefix} + recovery gui mode: ${enable_recovery_gui} + with TDM: ${have_libtdm} + OUR CFLAGS: ${OUR_CFLAGS} ${CFLAGS} +]) diff --git a/packaging/system-recovery.manifest b/packaging/system-recovery.manifest new file mode 100644 index 0000000..2a0cec5 --- /dev/null +++ b/packaging/system-recovery.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/packaging/system-recovery.spec b/packaging/system-recovery.spec new file mode 100644 index 0000000..4742d1e --- /dev/null +++ b/packaging/system-recovery.spec @@ -0,0 +1,116 @@ +Name: system-recovery +Summary: System recovery +Version: 0.2.0 +Release: 0 +Group: System/Utilities +License: Apache-2.0 +ExclusiveArch: %{arm} + +Source0: %{name}-%{version}.tar.gz +Source1001: system-recovery.manifest + +BuildRequires: autoconf +BuildRequires: automake +BuildRequires: libtool +BuildRequires: pkgconfig(libconfig) +BuildRequires: pkgconfig(libtdm) +BuildRequires: pkgconfig(libpng) + +Requires: initrd-recovery +Requires: system-recovery-compat = %{version}-%{release} +Recommends: system-recovery-non_gui = %{version}-%{release} + +%description +A simple initrd menu for system recovery. + +# non_gui profile: common, wearable +%package non_gui +Summary: system-recovery without gui +Provides: system-recovery-compat = %{version}-%{release} +Conflicts: system-recovery-gui +%description non_gui +system-recovery package without gui + +# gui profile: mobile +%package gui +Summary: system-recovery with gui +Provides: system-recovery-compat = %{version}-%{release} +Conflicts: system-recovery-non_gui +%description gui +system-recovery package with gui + +# Configuration for mkinitrd-recovery, one package per target +%package sprd +Summary: mkinitrd-recovery configuration file for spreadtrum platform +Group: System/Utilities +License: Apache-2.0 +Requires: system-recovery-gui +%description sprd +mkinitrd-recovery configuration file for spreadtrum platform + +%prep +%setup -q + +%build +cp %{SOURCE1001} . +%autogen + +# common, wearalbe: without gui +mkdir -p build_non_gui +ln -nfs ../%{_configure} build_non_gui +pushd build_non_gui +%configure \ + --disable-recovery-gui \ + --srcdir=../ +make %{?_smp_mflags} +popd + +# mobile: with gui +mkdir -p build_gui +ln -nfs ../%{_configure} build_gui +pushd build_gui +%configure \ + --srcdir=../ +make %{?_smp_mflags} +popd + +%install +# common, wearable +pushd build_non_gui +%make_install +mv %{buildroot}%{_libexecdir}/system-recovery/system-recovery \ + %{buildroot}%{_libexecdir}/system-recovery/system-recovery.non_gui \ + +mv %{buildroot}%{_datadir}/initrd-recovery/initrd.list.d/50-system-recovery.list \ + %{buildroot}%{_datadir}/initrd-recovery/initrd.list.d/50-system-recovery-non_gui.list +popd + +# mobile +pushd build_gui +%make_install +mv %{buildroot}%{_libexecdir}/system-recovery/system-recovery \ + %{buildroot}%{_libexecdir}/system-recovery/system-recovery.gui \ + +mv %{buildroot}%{_datadir}/initrd-recovery/initrd.list.d/50-system-recovery.list \ + %{buildroot}%{_datadir}/initrd-recovery/initrd.list.d/50-system-recovery-gui.list +popd + +%files +%defattr(-,root,root,-) +%manifest system-recovery.manifest +%license LICENSE +%{_datadir}/system-recovery/system-recovery.cfg +%{_libexecdir}/system-recovery/recovery-init +%{_sbindir}/recovery-action-set + +%files non_gui +%{_datadir}/initrd-recovery/initrd.list.d/50-system-recovery-non_gui.list +%{_libexecdir}/system-recovery/system-recovery.non_gui + +%files gui +%{_datadir}/initrd-recovery/initrd.list.d/50-system-recovery-gui.list +%{_datadir}/system-recovery/res/images/*.png +%{_libexecdir}/system-recovery/system-recovery.gui + +%files sprd +%{_datadir}/initrd-recovery/initrd.list.d/50-system-recovery-sprd.list diff --git a/src/fonts/font-10x18.h b/src/fonts/font-10x18.h new file mode 100644 index 0000000..1b3d86f --- /dev/null +++ b/src/fonts/font-10x18.h @@ -0,0 +1,216 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +struct { + unsigned width; + unsigned height; + unsigned cwidth; + unsigned cheight; + unsigned char rundata[2973]; +} font = { + .width = 960, + .height = 18, + .cwidth = 10, + .cheight = 18, + .rundata = { + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x55, 0x82, 0x06, 0x82, 0x02, 0x82, 0x10, 0x82, + 0x11, 0x83, 0x08, 0x82, 0x0a, 0x82, 0x04, 0x82, 0x46, 0x82, 0x08, 0x82, 0x07, 0x84, 0x06, + 0x84, 0x0a, 0x81, 0x03, 0x88, 0x04, 0x84, 0x04, 0x88, 0x04, 0x84, 0x06, 0x84, 0x1e, 0x81, + 0x0e, 0x81, 0x0a, 0x84, 0x06, 0x84, 0x07, 0x82, 0x05, 0x85, 0x07, 0x84, 0x04, 0x86, 0x04, + 0x88, 0x02, 0x88, 0x04, 0x84, 0x04, 0x82, 0x04, 0x82, 0x02, 0x88, 0x05, 0x86, 0x01, 0x82, + 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x04, 0x84, 0x04, + 0x86, 0x06, 0x84, 0x04, 0x86, 0x06, 0x84, 0x04, 0x88, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, + 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, + 0x88, 0x03, 0x86, 0x0e, 0x86, 0x06, 0x82, 0x11, 0x82, 0x10, 0x82, 0x18, 0x82, 0x0f, 0x84, + 0x0d, 0x82, 0x1c, 0x82, 0x09, 0x84, 0x7f, 0x16, 0x84, 0x05, 0x82, 0x05, 0x84, 0x07, 0x83, + 0x02, 0x82, 0x19, 0x82, 0x06, 0x82, 0x02, 0x82, 0x06, 0x82, 0x01, 0x82, 0x03, 0x86, 0x04, + 0x83, 0x02, 0x82, 0x03, 0x82, 0x01, 0x82, 0x07, 0x82, 0x09, 0x82, 0x06, 0x82, 0x3e, 0x82, + 0x04, 0x84, 0x06, 0x83, 0x06, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x03, + 0x82, 0x09, 0x82, 0x02, 0x82, 0x09, 0x82, 0x03, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, + 0x1c, 0x82, 0x0e, 0x82, 0x08, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x05, 0x84, 0x04, + 0x82, 0x02, 0x82, 0x05, 0x82, 0x02, 0x82, 0x03, 0x82, 0x03, 0x82, 0x03, 0x82, 0x08, 0x82, + 0x09, 0x82, 0x02, 0x82, 0x03, 0x82, 0x04, 0x82, 0x05, 0x82, 0x0a, 0x82, 0x03, 0x82, 0x04, + 0x82, 0x02, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x83, 0x03, 0x82, 0x03, 0x82, 0x02, 0x82, + 0x03, 0x82, 0x03, 0x82, 0x04, 0x82, 0x02, 0x82, 0x03, 0x82, 0x03, 0x82, 0x04, 0x82, 0x02, + 0x82, 0x06, 0x82, 0x05, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, + 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x08, 0x82, 0x03, 0x82, 0x08, 0x82, 0x0c, + 0x82, 0x05, 0x84, 0x11, 0x82, 0x0f, 0x82, 0x18, 0x82, 0x0e, 0x82, 0x02, 0x82, 0x0c, 0x82, + 0x1c, 0x82, 0x0b, 0x82, 0x7f, 0x15, 0x82, 0x08, 0x82, 0x08, 0x82, 0x05, 0x82, 0x01, 0x82, + 0x01, 0x82, 0x19, 0x82, 0x06, 0x82, 0x02, 0x82, 0x06, 0x82, 0x01, 0x82, 0x02, 0x82, 0x01, + 0x82, 0x01, 0x82, 0x02, 0x82, 0x01, 0x82, 0x01, 0x82, 0x03, 0x82, 0x01, 0x82, 0x07, 0x82, + 0x08, 0x82, 0x08, 0x82, 0x3d, 0x82, 0x03, 0x82, 0x02, 0x82, 0x04, 0x84, 0x05, 0x82, 0x04, + 0x82, 0x02, 0x82, 0x04, 0x82, 0x06, 0x83, 0x03, 0x82, 0x08, 0x82, 0x04, 0x81, 0x09, 0x82, + 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x1a, 0x82, 0x10, 0x82, 0x06, 0x82, 0x04, + 0x82, 0x02, 0x82, 0x04, 0x82, 0x03, 0x82, 0x02, 0x82, 0x03, 0x82, 0x03, 0x82, 0x03, 0x82, + 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, + 0x82, 0x04, 0x82, 0x05, 0x82, 0x0a, 0x82, 0x03, 0x82, 0x03, 0x82, 0x03, 0x82, 0x08, 0x83, + 0x02, 0x83, 0x02, 0x83, 0x03, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, + 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x05, 0x82, 0x05, 0x82, + 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x03, 0x82, 0x02, 0x82, 0x04, + 0x82, 0x02, 0x82, 0x09, 0x82, 0x03, 0x82, 0x08, 0x82, 0x0c, 0x82, 0x04, 0x82, 0x02, 0x82, + 0x11, 0x82, 0x0e, 0x82, 0x18, 0x82, 0x0e, 0x82, 0x02, 0x82, 0x0c, 0x82, 0x0b, 0x82, 0x0b, + 0x82, 0x02, 0x82, 0x0b, 0x82, 0x4d, 0x82, 0x45, 0x82, 0x08, 0x82, 0x08, 0x82, 0x05, 0x82, + 0x02, 0x83, 0x1a, 0x82, 0x07, 0x81, 0x02, 0x81, 0x07, 0x82, 0x01, 0x82, 0x02, 0x82, 0x01, + 0x82, 0x05, 0x82, 0x01, 0x84, 0x04, 0x82, 0x01, 0x82, 0x07, 0x82, 0x08, 0x82, 0x08, 0x82, + 0x06, 0x82, 0x02, 0x82, 0x06, 0x82, 0x28, 0x82, 0x04, 0x82, 0x02, 0x82, 0x03, 0x82, 0x01, + 0x82, 0x05, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x05, 0x84, 0x03, 0x82, 0x08, 0x82, + 0x0d, 0x82, 0x03, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x19, 0x82, 0x12, 0x82, 0x05, + 0x82, 0x04, 0x82, 0x02, 0x82, 0x02, 0x84, 0x03, 0x82, 0x02, 0x82, 0x03, 0x82, 0x03, 0x82, + 0x03, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x08, 0x82, 0x08, 0x82, 0x04, + 0x82, 0x05, 0x82, 0x0a, 0x82, 0x03, 0x82, 0x03, 0x82, 0x03, 0x82, 0x08, 0x83, 0x02, 0x83, + 0x02, 0x84, 0x02, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, + 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x0b, 0x82, 0x05, 0x82, 0x04, 0x82, 0x02, 0x82, + 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x03, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x08, + 0x82, 0x04, 0x82, 0x09, 0x82, 0x0b, 0x82, 0x03, 0x82, 0x04, 0x82, 0x20, 0x82, 0x18, 0x82, + 0x0e, 0x82, 0x10, 0x82, 0x0b, 0x82, 0x0b, 0x82, 0x02, 0x82, 0x0b, 0x82, 0x4d, 0x82, 0x45, + 0x82, 0x08, 0x82, 0x08, 0x82, 0x26, 0x82, 0x10, 0x88, 0x01, 0x82, 0x01, 0x82, 0x06, 0x83, + 0x01, 0x82, 0x04, 0x84, 0x08, 0x81, 0x08, 0x82, 0x0a, 0x82, 0x05, 0x82, 0x02, 0x82, 0x06, + 0x82, 0x28, 0x82, 0x03, 0x82, 0x04, 0x82, 0x05, 0x82, 0x0b, 0x82, 0x08, 0x82, 0x04, 0x82, + 0x01, 0x82, 0x03, 0x82, 0x08, 0x82, 0x0d, 0x82, 0x03, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, + 0x82, 0x18, 0x82, 0x06, 0x88, 0x06, 0x82, 0x04, 0x82, 0x04, 0x82, 0x02, 0x82, 0x01, 0x85, + 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x03, 0x82, 0x03, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, + 0x82, 0x08, 0x82, 0x08, 0x82, 0x08, 0x82, 0x04, 0x82, 0x05, 0x82, 0x0a, 0x82, 0x03, 0x82, + 0x02, 0x82, 0x04, 0x82, 0x08, 0x88, 0x02, 0x84, 0x02, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, + 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x0b, 0x82, + 0x05, 0x82, 0x04, 0x82, 0x03, 0x82, 0x02, 0x82, 0x03, 0x82, 0x04, 0x82, 0x04, 0x84, 0x06, + 0x84, 0x08, 0x82, 0x05, 0x82, 0x09, 0x82, 0x0b, 0x82, 0x2b, 0x82, 0x18, 0x82, 0x0e, 0x82, + 0x10, 0x82, 0x1c, 0x82, 0x0b, 0x82, 0x4d, 0x82, 0x45, 0x82, 0x08, 0x82, 0x08, 0x82, 0x26, + 0x82, 0x11, 0x82, 0x01, 0x82, 0x03, 0x82, 0x01, 0x82, 0x09, 0x82, 0x06, 0x82, 0x12, 0x82, + 0x0a, 0x82, 0x06, 0x84, 0x07, 0x82, 0x27, 0x82, 0x04, 0x82, 0x04, 0x82, 0x05, 0x82, 0x0b, + 0x82, 0x07, 0x82, 0x04, 0x82, 0x02, 0x82, 0x03, 0x82, 0x01, 0x83, 0x04, 0x82, 0x01, 0x83, + 0x08, 0x82, 0x05, 0x82, 0x02, 0x82, 0x03, 0x82, 0x04, 0x82, 0x05, 0x83, 0x07, 0x83, 0x05, + 0x82, 0x16, 0x82, 0x08, 0x82, 0x03, 0x82, 0x01, 0x82, 0x01, 0x82, 0x02, 0x82, 0x04, 0x82, + 0x02, 0x82, 0x02, 0x82, 0x04, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x08, + 0x82, 0x08, 0x82, 0x04, 0x82, 0x05, 0x82, 0x0a, 0x82, 0x03, 0x82, 0x02, 0x82, 0x04, 0x82, + 0x08, 0x82, 0x01, 0x82, 0x01, 0x82, 0x02, 0x82, 0x01, 0x82, 0x01, 0x82, 0x02, 0x82, 0x04, + 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x03, 0x82, + 0x0a, 0x82, 0x05, 0x82, 0x04, 0x82, 0x03, 0x82, 0x02, 0x82, 0x03, 0x82, 0x01, 0x82, 0x01, + 0x82, 0x04, 0x84, 0x06, 0x84, 0x08, 0x82, 0x05, 0x82, 0x0a, 0x82, 0x0a, 0x82, 0x23, 0x85, + 0x03, 0x82, 0x01, 0x83, 0x06, 0x85, 0x05, 0x83, 0x01, 0x82, 0x04, 0x84, 0x04, 0x86, 0x05, + 0x85, 0x01, 0x81, 0x02, 0x82, 0x01, 0x83, 0x05, 0x84, 0x09, 0x84, 0x02, 0x82, 0x03, 0x82, + 0x06, 0x82, 0x05, 0x81, 0x01, 0x82, 0x01, 0x82, 0x03, 0x82, 0x01, 0x83, 0x06, 0x84, 0x04, + 0x82, 0x01, 0x83, 0x06, 0x83, 0x01, 0x82, 0x02, 0x82, 0x01, 0x84, 0x04, 0x86, 0x03, 0x86, + 0x04, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, + 0x82, 0x02, 0x82, 0x04, 0x82, 0x03, 0x87, 0x05, 0x82, 0x08, 0x82, 0x08, 0x82, 0x26, 0x82, + 0x11, 0x82, 0x01, 0x82, 0x04, 0x86, 0x07, 0x82, 0x05, 0x83, 0x12, 0x82, 0x0a, 0x82, 0x04, + 0x88, 0x02, 0x88, 0x0c, 0x88, 0x10, 0x82, 0x04, 0x82, 0x04, 0x82, 0x05, 0x82, 0x0a, 0x82, + 0x06, 0x83, 0x04, 0x82, 0x03, 0x82, 0x03, 0x83, 0x02, 0x82, 0x03, 0x83, 0x02, 0x82, 0x07, + 0x82, 0x06, 0x84, 0x05, 0x82, 0x02, 0x83, 0x05, 0x83, 0x07, 0x83, 0x04, 0x82, 0x18, 0x82, + 0x06, 0x82, 0x04, 0x82, 0x01, 0x82, 0x01, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x86, 0x04, + 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x86, 0x04, 0x86, 0x04, 0x82, 0x02, 0x84, 0x02, 0x88, + 0x05, 0x82, 0x0a, 0x82, 0x03, 0x85, 0x05, 0x82, 0x08, 0x82, 0x01, 0x82, 0x01, 0x82, 0x02, + 0x82, 0x01, 0x82, 0x01, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x03, 0x82, 0x03, 0x82, + 0x04, 0x82, 0x02, 0x82, 0x03, 0x82, 0x05, 0x84, 0x07, 0x82, 0x05, 0x82, 0x04, 0x82, 0x03, + 0x82, 0x02, 0x82, 0x03, 0x82, 0x01, 0x82, 0x01, 0x82, 0x05, 0x82, 0x08, 0x82, 0x08, 0x82, + 0x06, 0x82, 0x0a, 0x82, 0x0a, 0x82, 0x22, 0x82, 0x03, 0x82, 0x02, 0x83, 0x02, 0x82, 0x04, + 0x82, 0x03, 0x82, 0x03, 0x82, 0x02, 0x83, 0x03, 0x82, 0x02, 0x82, 0x05, 0x82, 0x06, 0x82, + 0x03, 0x83, 0x02, 0x83, 0x02, 0x82, 0x06, 0x82, 0x0b, 0x82, 0x02, 0x82, 0x02, 0x82, 0x07, + 0x82, 0x05, 0x88, 0x02, 0x83, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x03, 0x83, 0x02, 0x82, + 0x04, 0x82, 0x02, 0x83, 0x03, 0x83, 0x02, 0x82, 0x02, 0x82, 0x04, 0x82, 0x04, 0x82, 0x06, + 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x03, 0x82, 0x02, 0x82, + 0x03, 0x82, 0x04, 0x82, 0x08, 0x82, 0x02, 0x84, 0x09, 0x82, 0x09, 0x84, 0x23, 0x82, 0x11, + 0x82, 0x01, 0x82, 0x06, 0x82, 0x01, 0x82, 0x05, 0x82, 0x05, 0x82, 0x01, 0x82, 0x11, 0x82, + 0x0a, 0x82, 0x06, 0x84, 0x07, 0x82, 0x26, 0x82, 0x05, 0x82, 0x04, 0x82, 0x05, 0x82, 0x08, + 0x83, 0x09, 0x82, 0x03, 0x82, 0x03, 0x82, 0x09, 0x82, 0x02, 0x82, 0x04, 0x82, 0x05, 0x82, + 0x06, 0x82, 0x02, 0x82, 0x05, 0x83, 0x01, 0x82, 0x17, 0x82, 0x16, 0x82, 0x06, 0x82, 0x05, + 0x82, 0x01, 0x82, 0x01, 0x82, 0x02, 0x88, 0x02, 0x82, 0x03, 0x82, 0x03, 0x82, 0x08, 0x82, + 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x05, + 0x82, 0x0a, 0x82, 0x03, 0x82, 0x02, 0x82, 0x04, 0x82, 0x08, 0x82, 0x01, 0x82, 0x01, 0x82, + 0x02, 0x82, 0x02, 0x84, 0x02, 0x82, 0x04, 0x82, 0x02, 0x86, 0x04, 0x82, 0x04, 0x82, 0x02, + 0x86, 0x09, 0x82, 0x06, 0x82, 0x05, 0x82, 0x04, 0x82, 0x04, 0x84, 0x04, 0x82, 0x01, 0x82, + 0x01, 0x82, 0x04, 0x84, 0x07, 0x82, 0x07, 0x82, 0x07, 0x82, 0x0b, 0x82, 0x09, 0x82, 0x27, + 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, + 0x04, 0x82, 0x06, 0x82, 0x03, 0x82, 0x03, 0x82, 0x04, 0x82, 0x05, 0x82, 0x0b, 0x82, 0x02, + 0x82, 0x01, 0x82, 0x08, 0x82, 0x05, 0x82, 0x01, 0x82, 0x01, 0x82, 0x02, 0x82, 0x04, 0x82, + 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x03, 0x82, 0x07, + 0x82, 0x0a, 0x82, 0x06, 0x82, 0x04, 0x82, 0x03, 0x82, 0x02, 0x82, 0x03, 0x82, 0x04, 0x82, + 0x04, 0x84, 0x04, 0x82, 0x04, 0x82, 0x07, 0x82, 0x06, 0x82, 0x08, 0x82, 0x08, 0x82, 0x26, + 0x82, 0x0f, 0x88, 0x05, 0x82, 0x01, 0x82, 0x05, 0x82, 0x05, 0x82, 0x02, 0x82, 0x01, 0x82, + 0x0d, 0x82, 0x0a, 0x82, 0x05, 0x82, 0x02, 0x82, 0x06, 0x82, 0x26, 0x82, 0x05, 0x82, 0x04, + 0x82, 0x05, 0x82, 0x07, 0x82, 0x0c, 0x82, 0x02, 0x88, 0x08, 0x82, 0x02, 0x82, 0x04, 0x82, + 0x05, 0x82, 0x05, 0x82, 0x04, 0x82, 0x08, 0x82, 0x18, 0x82, 0x14, 0x82, 0x07, 0x82, 0x05, + 0x82, 0x01, 0x84, 0x03, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, + 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x05, + 0x82, 0x0a, 0x82, 0x03, 0x82, 0x02, 0x82, 0x04, 0x82, 0x08, 0x82, 0x01, 0x82, 0x01, 0x82, + 0x02, 0x82, 0x02, 0x84, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, + 0x82, 0x02, 0x82, 0x0a, 0x82, 0x05, 0x82, 0x05, 0x82, 0x04, 0x82, 0x04, 0x84, 0x04, 0x82, + 0x01, 0x82, 0x01, 0x82, 0x04, 0x84, 0x07, 0x82, 0x07, 0x82, 0x07, 0x82, 0x0b, 0x82, 0x09, + 0x82, 0x22, 0x87, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x88, + 0x04, 0x82, 0x06, 0x82, 0x03, 0x82, 0x03, 0x82, 0x04, 0x82, 0x05, 0x82, 0x0b, 0x82, 0x02, + 0x84, 0x09, 0x82, 0x05, 0x82, 0x01, 0x82, 0x01, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, + 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x03, 0x82, 0x08, 0x86, 0x05, + 0x82, 0x06, 0x82, 0x04, 0x82, 0x03, 0x82, 0x02, 0x82, 0x03, 0x82, 0x01, 0x82, 0x01, 0x82, + 0x05, 0x82, 0x05, 0x82, 0x04, 0x82, 0x06, 0x82, 0x07, 0x82, 0x08, 0x82, 0x08, 0x82, 0x26, + 0x82, 0x10, 0x82, 0x01, 0x82, 0x07, 0x82, 0x01, 0x82, 0x04, 0x82, 0x01, 0x83, 0x02, 0x82, + 0x03, 0x83, 0x0f, 0x82, 0x08, 0x82, 0x06, 0x82, 0x02, 0x82, 0x06, 0x82, 0x25, 0x82, 0x07, + 0x82, 0x02, 0x82, 0x06, 0x82, 0x06, 0x82, 0x07, 0x82, 0x04, 0x82, 0x07, 0x82, 0x09, 0x82, + 0x02, 0x82, 0x04, 0x82, 0x04, 0x82, 0x06, 0x82, 0x04, 0x82, 0x08, 0x82, 0x19, 0x82, 0x05, + 0x88, 0x05, 0x82, 0x08, 0x82, 0x05, 0x82, 0x02, 0x82, 0x04, 0x82, 0x04, 0x82, 0x02, 0x82, + 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x08, 0x82, 0x04, + 0x82, 0x02, 0x82, 0x04, 0x82, 0x05, 0x82, 0x05, 0x82, 0x03, 0x82, 0x03, 0x82, 0x03, 0x82, + 0x03, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x82, 0x03, 0x83, 0x02, 0x82, 0x04, 0x82, 0x02, + 0x82, 0x08, 0x82, 0x01, 0x82, 0x01, 0x82, 0x02, 0x82, 0x03, 0x82, 0x09, 0x82, 0x05, 0x82, + 0x05, 0x82, 0x04, 0x82, 0x04, 0x84, 0x04, 0x83, 0x02, 0x83, 0x03, 0x82, 0x02, 0x82, 0x06, + 0x82, 0x06, 0x82, 0x08, 0x82, 0x0c, 0x82, 0x08, 0x82, 0x21, 0x82, 0x04, 0x82, 0x02, 0x82, + 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x82, 0x0a, 0x82, 0x06, 0x82, 0x03, + 0x82, 0x03, 0x82, 0x04, 0x82, 0x05, 0x82, 0x0b, 0x82, 0x02, 0x85, 0x08, 0x82, 0x05, 0x82, + 0x01, 0x82, 0x01, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, + 0x82, 0x02, 0x82, 0x04, 0x82, 0x03, 0x82, 0x0d, 0x82, 0x04, 0x82, 0x06, 0x82, 0x04, 0x82, + 0x04, 0x84, 0x04, 0x82, 0x01, 0x82, 0x01, 0x82, 0x05, 0x82, 0x05, 0x82, 0x04, 0x82, 0x05, + 0x82, 0x08, 0x82, 0x08, 0x82, 0x08, 0x82, 0x38, 0x82, 0x01, 0x82, 0x04, 0x82, 0x01, 0x82, + 0x01, 0x82, 0x04, 0x84, 0x01, 0x82, 0x01, 0x82, 0x03, 0x82, 0x10, 0x82, 0x08, 0x82, 0x30, + 0x83, 0x06, 0x82, 0x07, 0x82, 0x02, 0x82, 0x06, 0x82, 0x05, 0x82, 0x08, 0x82, 0x04, 0x82, + 0x07, 0x82, 0x03, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x04, 0x82, 0x06, 0x82, 0x04, + 0x82, 0x03, 0x81, 0x04, 0x82, 0x1a, 0x82, 0x10, 0x82, 0x10, 0x82, 0x08, 0x82, 0x04, 0x82, + 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x08, + 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x05, 0x82, 0x05, 0x82, 0x03, 0x82, + 0x03, 0x82, 0x03, 0x82, 0x03, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x82, 0x03, 0x83, 0x02, + 0x82, 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x02, 0x84, 0x02, 0x82, 0x03, 0x82, 0x03, 0x82, + 0x04, 0x82, 0x05, 0x82, 0x05, 0x82, 0x04, 0x82, 0x05, 0x82, 0x05, 0x83, 0x02, 0x83, 0x03, + 0x82, 0x02, 0x82, 0x06, 0x82, 0x05, 0x82, 0x09, 0x82, 0x0c, 0x82, 0x08, 0x82, 0x21, 0x82, + 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x82, 0x0a, + 0x82, 0x07, 0x85, 0x04, 0x82, 0x04, 0x82, 0x05, 0x82, 0x0b, 0x82, 0x02, 0x82, 0x02, 0x82, + 0x07, 0x82, 0x05, 0x82, 0x01, 0x82, 0x01, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, + 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x03, 0x82, 0x0d, 0x82, 0x04, 0x82, + 0x06, 0x82, 0x04, 0x82, 0x04, 0x84, 0x04, 0x82, 0x01, 0x82, 0x01, 0x82, 0x04, 0x84, 0x04, + 0x82, 0x04, 0x82, 0x04, 0x82, 0x09, 0x82, 0x08, 0x82, 0x08, 0x82, 0x26, 0x82, 0x10, 0x82, + 0x01, 0x82, 0x05, 0x86, 0x04, 0x82, 0x01, 0x82, 0x01, 0x82, 0x01, 0x83, 0x01, 0x84, 0x10, + 0x82, 0x06, 0x82, 0x1d, 0x83, 0x11, 0x83, 0x05, 0x82, 0x09, 0x84, 0x07, 0x82, 0x05, 0x82, + 0x09, 0x82, 0x02, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, + 0x82, 0x08, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x06, 0x83, 0x07, 0x83, 0x09, 0x82, + 0x0e, 0x82, 0x0a, 0x82, 0x06, 0x82, 0x03, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x82, 0x03, + 0x82, 0x04, 0x82, 0x02, 0x82, 0x03, 0x82, 0x03, 0x82, 0x03, 0x82, 0x08, 0x82, 0x09, 0x82, + 0x02, 0x83, 0x02, 0x82, 0x04, 0x82, 0x05, 0x82, 0x06, 0x82, 0x01, 0x82, 0x04, 0x82, 0x04, + 0x82, 0x02, 0x82, 0x08, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x03, 0x82, 0x02, 0x82, + 0x03, 0x82, 0x09, 0x82, 0x02, 0x82, 0x03, 0x82, 0x04, 0x82, 0x03, 0x82, 0x02, 0x82, 0x06, + 0x82, 0x06, 0x82, 0x02, 0x82, 0x06, 0x82, 0x05, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, + 0x05, 0x82, 0x05, 0x82, 0x09, 0x82, 0x0d, 0x82, 0x07, 0x82, 0x21, 0x82, 0x04, 0x82, 0x02, + 0x83, 0x02, 0x82, 0x04, 0x82, 0x03, 0x82, 0x03, 0x82, 0x02, 0x83, 0x03, 0x82, 0x03, 0x82, + 0x04, 0x82, 0x06, 0x82, 0x08, 0x82, 0x04, 0x82, 0x05, 0x82, 0x0b, 0x82, 0x02, 0x82, 0x03, + 0x82, 0x06, 0x82, 0x05, 0x82, 0x01, 0x82, 0x01, 0x82, 0x02, 0x82, 0x04, 0x82, 0x03, 0x82, + 0x02, 0x82, 0x03, 0x83, 0x02, 0x82, 0x04, 0x82, 0x02, 0x83, 0x03, 0x82, 0x07, 0x82, 0x04, + 0x82, 0x04, 0x82, 0x02, 0x82, 0x03, 0x82, 0x02, 0x83, 0x05, 0x82, 0x05, 0x88, 0x03, 0x82, + 0x02, 0x82, 0x04, 0x82, 0x02, 0x83, 0x03, 0x82, 0x0a, 0x82, 0x08, 0x82, 0x08, 0x82, 0x26, + 0x82, 0x1c, 0x82, 0x06, 0x82, 0x02, 0x83, 0x03, 0x84, 0x02, 0x82, 0x10, 0x82, 0x04, 0x82, + 0x1e, 0x83, 0x11, 0x83, 0x05, 0x82, 0x0a, 0x82, 0x05, 0x88, 0x02, 0x88, 0x04, 0x84, 0x09, + 0x82, 0x05, 0x84, 0x06, 0x84, 0x05, 0x82, 0x09, 0x84, 0x06, 0x84, 0x07, 0x83, 0x07, 0x83, + 0x0a, 0x81, 0x0e, 0x81, 0x0b, 0x82, 0x07, 0x85, 0x03, 0x82, 0x04, 0x82, 0x02, 0x86, 0x06, + 0x84, 0x04, 0x86, 0x04, 0x88, 0x02, 0x82, 0x0a, 0x84, 0x01, 0x81, 0x02, 0x82, 0x04, 0x82, + 0x02, 0x88, 0x04, 0x83, 0x05, 0x82, 0x04, 0x82, 0x02, 0x88, 0x02, 0x82, 0x04, 0x82, 0x02, + 0x82, 0x04, 0x82, 0x04, 0x84, 0x04, 0x82, 0x0a, 0x85, 0x03, 0x82, 0x04, 0x82, 0x04, 0x84, + 0x07, 0x82, 0x07, 0x84, 0x07, 0x82, 0x05, 0x82, 0x04, 0x82, 0x02, 0x82, 0x04, 0x82, 0x05, + 0x82, 0x05, 0x88, 0x03, 0x86, 0x09, 0x82, 0x03, 0x86, 0x22, 0x85, 0x01, 0x81, 0x02, 0x82, + 0x01, 0x83, 0x06, 0x85, 0x05, 0x83, 0x01, 0x82, 0x04, 0x85, 0x05, 0x82, 0x07, 0x86, 0x03, + 0x82, 0x04, 0x82, 0x02, 0x88, 0x08, 0x82, 0x02, 0x82, 0x04, 0x82, 0x02, 0x88, 0x02, 0x82, + 0x01, 0x82, 0x01, 0x82, 0x02, 0x82, 0x04, 0x82, 0x04, 0x84, 0x04, 0x82, 0x01, 0x83, 0x06, + 0x83, 0x01, 0x82, 0x03, 0x82, 0x08, 0x86, 0x06, 0x84, 0x05, 0x83, 0x01, 0x82, 0x05, 0x82, + 0x06, 0x82, 0x02, 0x82, 0x03, 0x82, 0x04, 0x82, 0x04, 0x83, 0x01, 0x82, 0x03, 0x87, 0x06, + 0x84, 0x05, 0x82, 0x05, 0x84, 0x7f, 0x15, 0x83, 0x7f, 0x14, 0x83, 0x7f, 0x5e, 0x82, 0x7f, + 0x05, 0x89, 0x47, 0x82, 0x04, 0x82, 0x17, 0x82, 0x03, 0x82, 0x34, 0x82, 0x0e, 0x82, 0x4e, + 0x82, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x0a, 0x82, 0x04, 0x82, 0x17, 0x82, 0x03, 0x82, + 0x34, 0x82, 0x0e, 0x82, 0x48, 0x82, 0x04, 0x82, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x0a, + 0x82, 0x04, 0x82, 0x17, 0x82, 0x03, 0x82, 0x34, 0x82, 0x0e, 0x82, 0x49, 0x82, 0x02, 0x82, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x0c, 0x86, 0x19, 0x85, 0x35, 0x82, 0x0e, 0x82, 0x4a, + 0x84, 0x3f, + 0x00, + } +}; diff --git a/src/librui/common.h b/src/librui/common.h new file mode 100644 index 0000000..72ce978 --- /dev/null +++ b/src/librui/common.h @@ -0,0 +1,49 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef UNUSED +#define UNUSED __attribute__((unused)) +#endif /* UNUSED */ + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#endif /* ARRAY_SIZE */ + +#if __STDC_VERSION__ < 199901L +#if __GNUC__ >= 2 +#define __func__ __FUNCTION__ +#else +#define __func__ "" +#endif +#endif + +#define ASSERT_ARRAYS_EQUAL_LENGTH(a1, a2) \ + _Static_assert(ARRAY_SIZE(a1) == ARRAY_SIZE(a2), \ + "Arrays " #a1 " and " #a2 " must have equal length."); + +#ifdef __cplusplus +} +#endif diff --git a/src/librui/fbdev.h b/src/librui/fbdev.h new file mode 100644 index 0000000..2949820 --- /dev/null +++ b/src/librui/fbdev.h @@ -0,0 +1,46 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * Copyright (c) 2007 The Android Open Source Project + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include + +#include "graphics.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + int fd, + displayed_buffer; + gr_surface gr_draw; + GRSurface gr_framebuffer[2]; + struct fb_var_screeninfo vi; + struct fb_fix_screeninfo fi; +} fbdev_common; + +bool fbdev_init_common(gr_backend *backend); +bool fbdev_exit_common(gr_backend *backend); + +#ifdef __cplusplus +} +#endif diff --git a/src/librui/graphics-fbdev-common.c b/src/librui/graphics-fbdev-common.c new file mode 100644 index 0000000..4e23054 --- /dev/null +++ b/src/librui/graphics-fbdev-common.c @@ -0,0 +1,87 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "fbdev.h" +#include "common.h" +#include "graphics.h" + +bool fbdev_init_common(gr_backend *backend) +{ + fbdev_common *fb = (fbdev_common *)backend->data; + + memset(fb->gr_framebuffer, 0, sizeof(fb->gr_framebuffer)); + + fb->fd = open("/dev/fb0", O_RDWR); + if (fb->fd < 0) { + perror("Cannot open fb0"); + return false; + } + + if (ioctl(fb->fd, FBIOGET_VSCREENINFO, &fb->vi) < 0) { + perror("Failed to get fb0 info"); + backend->exit(backend); + return false; + } + + if (ioctl(fb->fd, FBIOGET_FSCREENINFO, &fb->fi) < 0) { + printf("Failed to get fb0 fix info"); + return false; + } + + /* If you have a device that has other BPP patches welcome... */ + if (fb->vi.bits_per_pixel != 32) { + printf("Non-32-bit framebuffers not supported yet. Sorry.\n"); + backend->exit(backend); + return false; + } + + fb->gr_framebuffer[0].width = fb->vi.xres; + fb->gr_framebuffer[0].height = fb->vi.yres; + fb->gr_framebuffer[0].pixel_bytes = fb->vi.bits_per_pixel / 8; + fb->gr_framebuffer[0].row_bytes = fb->gr_framebuffer[0].width * fb->gr_framebuffer[0].pixel_bytes; + memcpy(fb->gr_framebuffer + 1, fb->gr_framebuffer, sizeof(GRSurface)); + fb->gr_draw = fb->gr_framebuffer + 1; + return true; +} + +bool fbdev_exit_common(gr_backend *backend) +{ + fbdev_common *fb = (fbdev_common *)backend->data; + + fb->gr_framebuffer[0].data = NULL; + fb->gr_framebuffer[1].data = NULL; + fb->gr_draw = NULL; + + if (fb->fd != -1 && close(fb->fd) < 0) { + perror("Can't close framebuffer descriptor"); + return false; + } + + fb->fd = -1; + return true; +} diff --git a/src/librui/graphics-fbdev.c b/src/librui/graphics-fbdev.c new file mode 100644 index 0000000..c0211c9 --- /dev/null +++ b/src/librui/graphics-fbdev.c @@ -0,0 +1,157 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * Copyright (c) 2014 The Android Open Source Project + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "fbdev.h" +#include "common.h" +#include "graphics.h" + +static gr_surface fbdev_init(gr_backend *); +static gr_surface fbdev_flip(gr_backend *); +static bool fbdev_exit(gr_backend *); + +fbdev_common fb_data = { + .fd = -1, + .displayed_buffer = 0, + .gr_draw = NULL +}; + +static gr_backend fbdev_backend = { + .init = fbdev_init, + .flip = fbdev_flip, + .exit = fbdev_exit, + .data = (void *)&fb_data +}; + +gr_backend *open_fbdev(void) +{ + return &fbdev_backend; +} + +static void fbdev_blank(gr_backend *backend, bool blank) +{ + int ret; + fbdev_common *fb = (fbdev_common *)backend->data; + + ret = ioctl(fb->fd, FBIOBLANK, blank ? FB_BLANK_POWERDOWN : + FB_BLANK_UNBLANK); + if (ret < 0) + perror("ioctl(): blank"); +} + +static void set_displayed_framebuffer(fbdev_common *fb, unsigned int n) +{ + if (n > 1) + return; + + if (n == 0) + fb->vi.yoffset = 0; + else + fb->vi.yoffset = fb->vi.yres; + + if (ioctl(fb->fd, FBIOPUT_VSCREENINFO, &fb->vi) < 0) + perror("Active fb swap failed"); + + fb->displayed_buffer = n; +} + +static gr_surface fbdev_init(gr_backend *backend) +{ + size_t bufsize; + size_t bufsize_for_mmap; + int nr_buffer; + + fbdev_common *fb = (fbdev_common *)backend->data; + + if (!fbdev_init_common(backend)) + return NULL; + + nr_buffer = fb->vi.yres_virtual / fb->vi.yres; + printf("Frame buffer nr = %d\n", nr_buffer); + + bufsize = fb->fi.line_length * fb->vi.yres; + //TODO : Based on Kernel code, following code is right. + // : However, it is strange because of bufsize > bufsize_for_mmap + // : It should be re-checked later with other kernel's framebuffer. + bufsize_for_mmap = fb->vi.xres * fb->vi.yres * fb->vi.bits_per_pixel / 8; + + fb->gr_framebuffer[0].data = mmap(0, bufsize_for_mmap * nr_buffer, + PROT_READ | PROT_WRITE, MAP_SHARED, + fb->fd, 0); + + if (fb->gr_framebuffer[0].data == MAP_FAILED) { + perror("Failed to mmap video memory"); + fbdev_exit(backend); + return NULL; + } + + fb->gr_framebuffer[1].data = fb->gr_framebuffer[0].data + bufsize; + gr_fill_alpha(&fb->gr_framebuffer[0]); + memcpy(fb->gr_framebuffer[1].data, fb->gr_framebuffer[0].data, + bufsize); + set_displayed_framebuffer(fb, 0); + + printf("Framebuffer: %dx%d, %d BPP\n", fb->gr_draw->width, + fb->gr_draw->height, fb->vi.bits_per_pixel); + + fbdev_blank(backend, true); + fbdev_blank(backend, false); + return fb->gr_draw; +} + +static gr_surface fbdev_flip(gr_backend *backend) +{ + fbdev_common *fb = (fbdev_common *)backend->data; + + /* Change gr_draw to point to the buffer currently displayed, + * then flip the driver so we're displaying the other buffer + * instead. */ + fb->gr_draw = fb->gr_framebuffer + fb->displayed_buffer; + set_displayed_framebuffer(fb, 1 - fb->displayed_buffer); + return fb->gr_draw; +} + +static bool fbdev_exit(gr_backend *backend) +{ + fbdev_common *fb = (fbdev_common *)backend->data; + size_t bufsize = fb->vi.xres * fb->vi.yres * fb->vi.bits_per_pixel / 8; + + /* Unmap double buffer */ + if (fb->gr_framebuffer[0].data && + munmap(fb->gr_framebuffer[0].data, bufsize * 2) < 0) { + perror("Failed to unmmap video memory"); + return false; + } + + return fbdev_exit_common(backend); +} diff --git a/src/librui/graphics-tdm.c b/src/librui/graphics-tdm.c new file mode 100644 index 0000000..0cbe536 --- /dev/null +++ b/src/librui/graphics-tdm.c @@ -0,0 +1,101 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil -*- + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "graphics.h" +#include "tdm-if.h" + +static gr_surface tdm_init(gr_backend *); +static gr_surface tdm_flip(gr_backend *); +static bool tdm_exit(gr_backend *); + +struct _tdm_data { + GRSurface gr_framebuffer; +}; + +static struct _tdm_data tdm_data; + +static gr_backend tdm_backend = { + .init = tdm_init, + .flip = tdm_flip, + .exit = tdm_exit, + .data = (void*)&tdm_data, +}; + +gr_backend *open_tdm(void) +{ + return &tdm_backend; +} + +gr_surface tdm_init(gr_backend *backend) +{ + struct _tdm_data *data = (struct _tdm_data*)backend->data; + gr_surface gr_draw = (gr_surface)&data->gr_framebuffer; + + if (tdm_if_display_init() < 0) + return NULL; + + tdm_if_lcd_off(); + + gr_draw->width = tdm_if_display_width(); + gr_draw->height = tdm_if_display_height(); + gr_draw->pixel_bytes = 4; /* XXX */ + gr_draw->row_bytes = tdm_if_display_stride(); + gr_draw->data = malloc(tdm_if_display_bufsize()); + if (gr_draw->data == NULL) + return NULL; + + tdm_if_lcd_on(); + return gr_draw; +} + +gr_surface tdm_flip(gr_backend *backend) +{ + struct _tdm_data *data = (struct _tdm_data*)backend->data; + gr_surface gr_draw = (gr_surface)&data->gr_framebuffer; + + tdm_if_buffer_update(gr_draw->data); + tdm_if_display_update(); + + return gr_draw; +} + +bool tdm_exit(gr_backend *backend) +{ + struct _tdm_data *data = (struct _tdm_data*)backend->data; + gr_surface gr_draw = (gr_surface)&data->gr_framebuffer; + + tdm_if_display_deinit(); + + if (gr_draw->data != NULL) + free(gr_draw->data); + + return true; +} diff --git a/src/librui/graphics.c b/src/librui/graphics.c new file mode 100644 index 0000000..f564ab5 --- /dev/null +++ b/src/librui/graphics.c @@ -0,0 +1,495 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * Copyright (c) 2007 The Android Open Source Project + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "graphics.h" +#include "rui-image.h" +#include "font-10x18.h" + +#include "config.h" + +typedef struct { + gr_surface texture; + int cwidth; + int cheight; +} GRFont; + +static GRFont *gr_font = NULL; +static gr_backend *g_backend = NULL; + +static color gr_current_color = WHITE; +static gr_surface gr_draw = NULL; + +static bool outside(int x, int y) +{ + return x < 0 || x >= gr_draw->width || y < 0 || y >= gr_draw->height; +} + +int gr_get_font_cwidth(void) +{ + return gr_font->cwidth; +} + +int gr_get_font_cheight(void) +{ + return gr_font->cheight; +} + +void gr_set_color(color c) +{ + gr_current_color = c; +} + +void gr_draw_rectangle(int x, int y, int width, int height) +{ + int i, j; + unsigned char *dst_p, *first_line; + color *px; + + if (outside(x, y) || outside(x + width - 1, y + height - 1)) + return; + + dst_p = gr_draw->data + y * gr_draw->row_bytes + + x * gr_draw->pixel_bytes; + + for (i = 0, px = (color *)dst_p; i < width; i++) + *px++ = gr_current_color; + + first_line = dst_p; + dst_p += gr_draw->row_bytes; + for (j = 1; j < height; j++, dst_p += gr_draw->row_bytes) + memcpy(dst_p, first_line, width * gr_draw->pixel_bytes); +} + +void gr_clear(void) +{ + gr_draw_rectangle(0, 0, gr_draw->width, gr_draw->height); +} + +/* Set Alpha component of pixels to 255 to make overlay visible. */ +void gr_fill_alpha(gr_surface gr) +{ + int i, j; + unsigned char *dst_p, *first_line; + color *px; + + dst_p = gr->data; + for (i = 0, px = (color *)dst_p; i < gr->width; i++) + *px++ = BLACK; + + first_line = dst_p; + dst_p += gr->row_bytes; + for (j = 1; j < gr->height; j++, dst_p += gr->row_bytes) + memcpy(dst_p, first_line, gr->width * gr->pixel_bytes); +} + +static void gr_blit(gr_surface source, int sx, int sy, int w, int h, int dx, int dy) +{ + int i; + unsigned char *src_p, *dst_p; + + if (!source) + return; + + if (gr_draw->pixel_bytes != source->pixel_bytes) { + printf("%s: source has wrong format: %d bytes per pixel\n", + __func__, source->pixel_bytes); + return; + } + + if (outside(dx, dy) || outside(dx + w - 1, dy + h - 1)) + return; + + src_p = source->data + sy * source->row_bytes + + sx * source->pixel_bytes; + dst_p = gr_draw->data + dy * gr_draw->row_bytes + + dx * gr_draw->pixel_bytes; + + for (i = 0; i < h; ++i) { + memcpy(dst_p, src_p, w * source->pixel_bytes); + src_p += source->row_bytes; + dst_p += gr_draw->row_bytes; + } +} + +/* RGB + Alpha */ +static void gr_blend_rgba(gr_surface source, int w, int h, unsigned char *src_p, + unsigned char *dst_p) +{ + int i, j; + + for (j = 0; j < h; j++) { + color *sx = (color *)src_p; + color *px = (color *)dst_p; + + for (i = 0; i < w; i++) { + unsigned char r = sx->r, g = sx->g, b = sx->b, + a = sx->a; + + if (a == 255) { + *px++ = *sx; + } else { + px->r = (px->r * (255 - a) + r * a) / 255; + px->g = (px->g * (255 - a) + g * a) / 255; + px->b = (px->b * (255 - a) + b * a) / 255; + px->a = 255; + } + } + + src_p += source->row_bytes; + dst_p += gr_draw->row_bytes; + } +} + +/* RGB: Using current color's Alpha as alpha */ +static void gr_blend_rgb(gr_surface source, int w, int h, unsigned char *src_p, + unsigned char *dst_p) +{ + int i, j; + + for (j = 0; j < h; j++) { + color *sx = (color *)src_p; + color *px = (color *)dst_p; + + for (i = 0; i < w; i++) { + unsigned char r = sx->r, g = sx->g, b = sx->b; + + if (gr_current_color.a == 255) { + *px = *sx; + px->a = 255; + px++; + } else { + px->r = (px->r * (255 - gr_current_color.a) + + r * gr_current_color.a) / 255; + px->g = (px->g * (255 - gr_current_color.a) + + g * gr_current_color.a) / 255; + px->b = (px->b * (255 - gr_current_color.a) + + b * gr_current_color.a) / 255; + px->a = 255; + px++; + } + } + + src_p += source->row_bytes; + dst_p += gr_draw->row_bytes; + } +} + +/* Grayscale + Alpha */ +static void gr_blend_ga(gr_surface source, int w, int h, unsigned char *src_p, + unsigned char *dst_p) +{ + int i, j; + + for (j = 0; j < h; j++) { + unsigned char *sx = src_p; + color *px = (color *)dst_p; + + for (i = 0; i < w; i++) { + unsigned char gr = *sx++, a = *sx++; + + if (a == 255) { + px->r = gr; + px->g = gr; + px->b = gr; + px->a = 255; + px++; + } else { + px->r = (px->r * (255 - a) + gr * a) / 255; + px->g = (px->g * (255 - a) + gr * a) / 255; + px->b = (px->b * (255 - a) + gr * a) / 255; + px->a = 255; + ++px; + } + } + + src_p += source->row_bytes; + dst_p += gr_draw->row_bytes; + } +} + +/* Grayscale. + * Using image as Alpha channel and current color for foreground. */ +static void gr_blend_g(gr_surface source, int w, int h, unsigned char *src_p, + unsigned char *dst_p) +{ + int i, j; + + for (j = 0; j < h; j++) { + unsigned char *sx = src_p; + color *px = (color *)dst_p; + + for (i = 0; i < w; i++) { + unsigned char a = *sx++; + + if (gr_current_color.a < 255) + a = ((int)a * gr_current_color.a) / 255; + + if (a == 255) { + *px = gr_current_color; + px++; + } else { + px->r = (px->r * (255 - a) + + gr_current_color.r * a) / 255; + px->g = (px->g * (255 - a) + + gr_current_color.g * a) / 255; + px->b = (px->b * (255 - a) + + gr_current_color.b * a) / 255; + px->a = 255; + ++px; + } + } + + src_p += source->row_bytes; + dst_p += gr_draw->row_bytes; + } +} + +static void gr_blend(gr_surface source, int sx, int sy, int w, int h, int dx, int dy) +{ + unsigned char *src_p, *dst_p; + + if (!source) + return; + + if (outside(dx, dy) || outside(dx + w - 1, dy + h - 1)) + return; + + src_p = source->data + sy * source->row_bytes + + sx * source->pixel_bytes; + dst_p = gr_draw->data + dy * gr_draw->row_bytes + + dx * gr_draw->pixel_bytes; + + if (source->pixel_bytes == 4) + gr_blend_rgba(source, w, h, src_p, dst_p); + else if (source->pixel_bytes == 3) + gr_blend_rgb(source, w, h, src_p, dst_p); + else if (source->pixel_bytes == 2) + gr_blend_ga(source, w, h, src_p, dst_p); + else if (source->pixel_bytes == 1) + gr_blend_g(source, w, h, src_p, dst_p); + else + printf("%s: source has wrong format: %d bytes per pixel\n", + __func__, source->pixel_bytes); +} + +void gr_text(int x, int y, const char *s, gr_font_style style) +{ + GRFont *font = gr_font; + unsigned int off; + int start_x = x; + + if (!font->texture || !s) + return; + + if (gr_current_color.a == 0) + return; + + if (style == GR_FONT_BOLD && font->texture->height == font->cheight) + style = GR_FONT_REGULAR; /* No bold font in image */ + + while ((off = *s++)) { + unsigned char *src_p, *dst_p; + + if (off == '\n') { + x = start_x; + y += font->cheight; + continue; + } + + if (outside(x, y) || + outside(x + font->cwidth - 1, y + font->cheight - 1)) + continue; + + off -= 32; + if (off >= 96) + off = '_' - 32; /* Replacement for unknown symbols */ + + src_p = font->texture->data + off * font->cwidth + + (style == GR_FONT_BOLD ? + font->cheight * font->texture->row_bytes : 0); + dst_p = gr_draw->data + y * gr_draw->row_bytes + + x * gr_draw->pixel_bytes; + gr_blend_g(font->texture, font->cwidth, font->cheight, src_p, + dst_p); + + x += font->cwidth; + } +} + +static void gr_align_surface(gr_surface surface, int *posX, int *posY, + gr_align_horizontal xalign, gr_align_vertical yalign, + int offset_x, int offset_y) +{ + if (xalign == GR_ALIGN_LEFT) + *posX = 0; + else if (xalign == GR_ALIGN_CENTER) + *posX = (gr_fb_width() - gr_get_width(surface)) / 2; + else + *posX = gr_fb_width() - gr_get_width(surface); + + if (yalign == GR_ALIGN_TOP) + *posY = 0; + else if (yalign == GR_ALIGN_MIDDLE) + *posY = (gr_fb_height() - gr_get_height(surface)) / 2; + else + *posY = gr_fb_height() - gr_get_height(surface); + + *posX += offset_x; + *posY += offset_y; +} + +void gr_blend_image_aligned(gr_surface source, gr_align_horizontal xalign, + gr_align_vertical yalign, int offset_x, int offset_y) +{ + int posX, posY; + + gr_align_surface(source, &posX, &posY, xalign, yalign, offset_x, + offset_y); + gr_blend(source, 0, 0, gr_get_width(source), gr_get_height(source), + posX, posY); +} + +void gr_blit_image_aligned(gr_surface source, gr_align_horizontal xalign, + gr_align_vertical yalign, int offset_x, int offset_y) +{ + int posX, posY; + + gr_align_surface(source, &posX, &posY, xalign, yalign, offset_x, + offset_y); + gr_blit(source, 0, 0, gr_get_width(source), gr_get_height(source), + posX, posY); +} + +unsigned int gr_get_width(gr_surface surface) +{ + if (!surface) + return 0; + + return surface->width; +} + +unsigned int gr_get_height(gr_surface surface) +{ + if (!surface) + return 0; + + return surface->height; +} + +static void gr_init_font(void) +{ + int res; + + gr_font = calloc(sizeof(*gr_font), 1); + if (gr_font == NULL) { + printf("%s:%d: Memory allocation has failed.", __FILE__, __LINE__); + return; + } + + res = res_create_image_surface(RUI_IMAGES_DIR "/font.png", + &(gr_font->texture), GR_WITH_ALPHA); + if (res == 0) { + /* The font image should be a 96x2 array of character images. + * The columns are the printable ASCII characters 0x20 - 0x7f. + * The top row is regular text; the bottom row is bold. */ + gr_font->cwidth = gr_font->texture->width / 96; + gr_font->cheight = gr_font->texture->height / 2; + } else { + unsigned char *bits, *in, data; + + printf("Failed to read font: res=%d\n", res); + + /* fall back to the compiled-in font. */ + gr_font->texture = malloc(sizeof(*gr_font->texture)); + if (gr_font->texture == NULL) { + printf("%s:%d: Memory allocation has failed.", __FILE__, __LINE__); + free(gr_font); + return; + } + gr_font->texture->width = font.width; + gr_font->texture->height = font.height; + gr_font->texture->row_bytes = font.width; + gr_font->texture->pixel_bytes = 1; + + bits = malloc(font.width * font.height); + gr_font->texture->data = (void *)bits; + + in = font.rundata; + while ((data = *in++)) { + memset(bits, (data & 0x80) ? 255 : 0, data & 0x7f); + bits += (data & 0x7f); + } + + gr_font->cwidth = font.cwidth; + gr_font->cheight = font.cheight; + } +} + +void gr_flip(void) +{ + gr_draw = g_backend->flip(g_backend); +} + +bool gr_init(void) +{ + gr_init_font(); + +#ifdef HAVE_TDM + g_backend = open_tdm(); +#else + g_backend = open_fbdev(); +#endif + gr_draw = g_backend->init(g_backend); + if (gr_draw == NULL) + return false; + + gr_flip(); + gr_flip(); + + return true; +} + +void gr_exit(void) +{ + g_backend->exit(g_backend); +} + +int gr_fb_width(void) +{ + return gr_draw->width; +} + +int gr_fb_height(void) +{ + return gr_draw->height; +} diff --git a/src/librui/graphics.h b/src/librui/graphics.h new file mode 100644 index 0000000..a768462 --- /dev/null +++ b/src/librui/graphics.h @@ -0,0 +1,155 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * Copyright (c) 2007 The Android Open Source Project + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include + +#include "config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + int width; + int height; + int row_bytes; + int pixel_bytes; + unsigned char *data; +} GRSurface; + +typedef GRSurface *gr_surface; + +typedef struct gr_backend { + /* Initializes the backend and returns a gr_surface to draw into. */ + gr_surface(*init)(struct gr_backend *); + + /* Causes the current drawing surface (returned by the most recent + * call to flip() or init()) to be displayed, and returns a new + * drawing surface. */ + gr_surface(*flip)(struct gr_backend *); + + /* Device cleanup when drawing is done. */ + bool (*exit)(struct gr_backend *); + + void *data; /* Private data for graphics backend */ +} gr_backend; + +#ifdef HAVE_TDM /* BGRA */ +typedef struct { + unsigned char b, g, r, a; +} color; + +gr_backend *open_tdm(void); + +#else /* RGBA */ +typedef struct { + unsigned char r, g, b, a; +} color; + +gr_backend *open_fbdev(void); +#endif + +#define BLACK (color) { .r = 0, .g = 0, .b = 0, .a = 255 } +#define RED (color) { .r = 255, .g = 0, .b = 0, .a = 255 } +#define GREEN (color) { .r = 0, .g = 255, .b = 0, .a = 255 } +#define YELLOW (color) { .r = 255, .g = 255, .b = 0, .a = 255 } +#define BLUE (color) { .r = 0, .g = 0, .b = 255, .a = 255 } +#define MAGENTA (color) { .r = 255, .g = 0, .b = 255, .a = 255 } +#define CYAN (color) { .r = 0, .g = 255, .b = 255, .a = 255 } +#define WHITE (color) { .r = 255, .g = 255, .b = 255, .a = 255 } + +bool gr_init(void); +void gr_exit(void); + +int gr_fb_width(void); +int gr_fb_height(void); + +void gr_flip(void); + +void gr_fill_alpha(gr_surface gr); +void gr_clear(); /* Clear entire surface to current color */ +void gr_set_color(color c); /* Set current color */ +void gr_draw_rectangle(int x, int y, int width, int height); + +typedef enum { + GR_FONT_REGULAR, + GR_FONT_BOLD +} gr_font_style; + +void gr_text(int x, int y, const char *s, gr_font_style style); +int gr_get_font_cwidth(void); +int gr_get_font_cheight(void); + +typedef enum { + GR_ALIGN_LEFT, + GR_ALIGN_CENTER, + GR_ALIGN_RIGHT +} gr_align_horizontal; + +typedef enum { + GR_ALIGN_TOP, + GR_ALIGN_MIDDLE, + GR_ALIGN_BOTTOM +} gr_align_vertical; + +void gr_blit_image_aligned(gr_surface source, gr_align_horizontal xalign, + gr_align_vertical yalign, int offset_x, + int offset_y); +void gr_blend_image_aligned(gr_surface source, gr_align_horizontal xalign, + gr_align_vertical yalign, int offset_x, + int offset_y); + +unsigned int gr_get_width(gr_surface surface); +unsigned int gr_get_height(gr_surface surface); + +typedef enum { + GR_WITHOUT_ALPHA, + GR_WITH_ALPHA +} gr_img_type; + +/* Load a single display surface from a PNG image. */ +int res_create_image_surface(const char *name, gr_surface *pSurface, + gr_img_type img_type); + +/* Load an array of display surfaces from a single PNG image. The PNG + * should have a "Frames" text chunk whose value is the number of + * frames this image represents. The pixel data itself is interlaced + * by row. */ +int res_create_anim_image_surfaces(const char *name, int *frames, + gr_surface **pSurface, + gr_img_type img_type); + +/* Load part of a grayscale PNG image that is the first match for the + * given locale. The image is expected to be a composite of multiple + * translations of the same text, with special added rows that encode + * the subimages' size and intended locale in the pixel data. */ +int res_create_localized_alpha_surface(const char *name, const char *locale, + gr_surface *pSurface); + +/* Free a surface allocated by any of the res_create_*_surface() + * functions. */ +void res_free_surface(gr_surface surface); + +#ifdef __cplusplus +} +#endif diff --git a/src/librui/input-events.c b/src/librui/input-events.c new file mode 100644 index 0000000..325391c --- /dev/null +++ b/src/librui/input-events.c @@ -0,0 +1,309 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * Copyright (c) 2007 The Android Open Source Project + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define _POSIX_C_SOURCE 200809L + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "input-events.h" + +#define MAX_INPUTS 32 + +#define BITS_PER_LONG (sizeof(unsigned long) * 8) +#define BITS_TO_LONGS(x) (((x) + BITS_PER_LONG - 1) / BITS_PER_LONG) + +#define test_bit(bit, array) \ + ((array)[(bit) / BITS_PER_LONG] & (1 << ((bit) % BITS_PER_LONG))) + +static struct pollfd ev_fds[MAX_INPUTS]; + +static unsigned ev_count = 0; + +static unsigned signalfd_idx = -1; +static unsigned timerfd_idx = -1; + +#define IS_SIGNAL_EVENT(x) (x == signalfd_idx) +#define IS_TIMER_EVENT(x) (x == timerfd_idx) + +static bool ev_signal_init(void) +{ + sigset_t mask; + + if (ev_count >= MAX_INPUTS) + return false; + + sigemptyset(&mask); + sigaddset(&mask, SIGINT); + if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) { + perror("sigprocmask"); + return false; + } + + ev_fds[ev_count].fd = signalfd(-1, &mask, 0); + ev_fds[ev_count].events = POLLIN; + if (ev_fds[ev_count].fd == -1) { + perror("signalfd"); + return false; + } + signalfd_idx = ev_count++; + + return true; +} + +static bool ev_timer_init(void) +{ + int fd; + struct itimerspec timer_spec = { + .it_interval = {TIMER_INTERVAL, 0}, + .it_value = {0, 1}, + }; + + if (ev_count >= MAX_INPUTS) + return false; + + fd = timerfd_create(CLOCK_REALTIME, 0); + if (fd < 0) { + perror("timerfd_create"); + return false; + } + + timerfd_settime(fd, 0, &timer_spec, NULL); + ev_fds[ev_count].fd = fd; + ev_fds[ev_count].events = POLLIN; + timerfd_idx = ev_count++; + + return true; +} + +static bool ev_input_init(void) +{ + DIR *dir; + struct dirent *de; + int fd; + int t = ev_count; + + dir = opendir("/dev/input"); + if (!dir) { + printf("Can't open directory \"/dev/input\".\n"); + return false; + } + + while ((de = readdir(dir))) { + unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)]; + + /* fprintf(stderr,"/dev/input/%s\n", de->d_name);*/ + if (strncmp(de->d_name, "event", 5)) + continue; + + fd = openat(dirfd(dir), de->d_name, O_RDONLY); + if (fd < 0) + continue; + + /* read the evbits of the input device */ + if (ioctl(fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) < 0) { + close(fd); + continue; + } + + /* TODO: add ability to specify event masks. For now, just + * assume that only EV_KEY and EV_REL event types are ever + * needed. */ + if (!test_bit(EV_KEY, ev_bits) && !test_bit(EV_REL, ev_bits)) { + close(fd); + continue; + } + + ev_fds[ev_count].fd = fd; + ev_fds[ev_count].events = POLLIN; + ev_count++; + if (ev_count == MAX_INPUTS) + break; + } + + closedir(dir); + if (ev_count == t) { + printf("No input devices found.\n"); + return false; + } + + return true; +} + +bool ev_init(void) +{ + return ev_input_init() && ev_signal_init() && ev_timer_init(); +} + +void ev_exit(void) +{ + while (ev_count > 0) + close(ev_fds[--ev_count].fd); +} + +static user_action last_action = ACTION_NONE; +static time_t event_start = 0; + +static void ev_input_longpress_check(input_callback callback) +{ + if (event_start && time(NULL) - event_start >= LONGPRESS_TIME) { + callback(last_action, ACTION_TYPE_LONGPRESS); + event_start = time(NULL); /* Restarting the event */ + } +} + +static bool ev_input_process(struct input_event *ev, input_callback callback) +{ + user_action action = ACTION_NONE; + + ev_input_longpress_check(callback); + + if (!ev) { /* Timeout */ + callback(ACTION_NONE, ACTION_TYPE_IDLE); + return true; + } + + if (ev->type == EV_SYN) + return true; + else if (ev->type == EV_KEY && ev->code <= KEY_MAX) { + switch (ev->code) { + case KEY_DOWN: + case KEY_VOLUMEDOWN: + action = ACTION_DOWN; + break; + case KEY_UP: + case KEY_VOLUMEUP: + action = ACTION_UP; + break; + case KEY_ENTER: + case KEY_POWER: + action = ACTION_CONFIRM; + break; + case KEY_MENU: + action = ACTION_HOME; + break; + case KEY_PHONE: + action = ACTION_MENU; + break; + case KEY_BACK: + action = ACTION_BACK; + break; + default: + /* printf("Unknown key %d.\n", ev->code);*/ + break; + } + + if (action != ACTION_NONE) { + if (ev->value == 1) { + last_action = action; + event_start = time(NULL); + } else if (action == last_action) { + last_action = ACTION_NONE; + event_start = 0; + } + + if (callback) + callback(action, ev->value == 1 ? + ACTION_TYPE_BEGIN : + ACTION_TYPE_END); + } + } else if (ev->type == EV_REL) { /* Relative event */ + + } else if (ev->type == EV_ABS) { /* Absolute event */ + + } + + return true; +} + +static int ev_wait(int timeout) +{ + int ret; + + if ((ret = poll(ev_fds, ev_count, timeout)) < 0) + perror("poll()"); + + return ret; +} + +bool ev_dispatch(input_callback callback) +{ + int r; + unsigned n; + + r = ev_wait(DISPATCH_TIMEOUT); + if (r < 0) + return false; + else if (r == 0) /* Timeout */ + return ev_input_process(NULL, callback); + + for (n = 0; n < ev_count; n++) + if (ev_fds[n].revents & POLLIN) { + int r; + struct input_event ev; + + if (IS_SIGNAL_EVENT(n)) { /* signalfd */ + struct signalfd_siginfo fdsi; + r = read(ev_fds[n].fd, &fdsi, sizeof(fdsi)); + if (r != sizeof(fdsi)) { + perror("read"); + return false; + } + if (fdsi.ssi_signo == SIGINT) + return false; + continue; + } + + if (IS_TIMER_EVENT(n)) { + uint64_t exp; + + r = read(ev_fds[n].fd, &exp, sizeof(exp)); + if (r != sizeof(exp)) { + perror("read"); + return false; + } + + callback(ACTION_TIMEOUT, ACTION_TYPE_TIMER); + continue; + } + + r = read(ev_fds[n].fd, &ev, sizeof(ev)); + if (r != sizeof(ev)) + continue; + + if (!ev_input_process(&ev, callback)) + return false; + } + + return true; +} diff --git a/src/librui/input-events.h b/src/librui/input-events.h new file mode 100644 index 0000000..b07f996 --- /dev/null +++ b/src/librui/input-events.h @@ -0,0 +1,59 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define DISPATCH_TIMEOUT (1 * 1000) /* One second */ +#define LONGPRESS_TIME 3 /* Seconds */ +#define TIMER_INTERVAL 1 /* Seconds */ + +typedef enum { + ACTION_NONE, + ACTION_DOWN, + ACTION_UP, + ACTION_CONFIRM, + ACTION_HOME, + ACTION_MENU, + ACTION_BACK, + ACTION_TIMEOUT, +} user_action; + +typedef enum { + ACTION_TYPE_IDLE, + ACTION_TYPE_BEGIN, + ACTION_TYPE_END, + ACTION_TYPE_LONGPRESS, + ACTION_TYPE_TIMER, +} user_action_type; + +typedef void (*input_callback)(user_action action, + user_action_type action_type); + +bool ev_init(void); +bool ev_dispatch(input_callback callback); +void ev_exit(void); + +#ifdef __cplusplus +} +#endif diff --git a/src/librui/resources.c b/src/librui/resources.c new file mode 100644 index 0000000..cd579f4 --- /dev/null +++ b/src/librui/resources.c @@ -0,0 +1,534 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * Copyright (c) 2007 The Android Open Source Project + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "graphics.h" + +extern char *locale; + +#define SURFACE_DATA_ALIGNMENT 8 + +static gr_surface malloc_surface(size_t data_size) +{ + gr_surface surface; + unsigned char *temp; + + temp = malloc(sizeof(GRSurface) + data_size + SURFACE_DATA_ALIGNMENT); + if (!temp) + return NULL; + + surface = (gr_surface)temp; + surface->data = temp + sizeof(GRSurface) + (SURFACE_DATA_ALIGNMENT - + (sizeof(GRSurface) % SURFACE_DATA_ALIGNMENT)); + return surface; +} + +static int open_png(const char *name, + png_structp *png_ptr, + png_infop *info_ptr, + png_uint_32 *width, + png_uint_32 *height, + png_byte *channels) +{ + unsigned char header[8]; + int result = 0, color_type, bit_depth; + size_t bytesRead; + FILE *fp; + + fp = fopen(name, "rb"); + if (fp == NULL) { + result = -1; + goto exit2; + } + + bytesRead = fread(header, 1, sizeof(header), fp); + if (bytesRead != sizeof(header)) { + result = -2; + goto exit2; + } + + if (png_sig_cmp(header, 0, sizeof(header))) { + result = -3; + goto exit2; + } + + *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, + NULL); + if (!*png_ptr) { + result = -4; + goto exit1; + } + + *info_ptr = png_create_info_struct(*png_ptr); + if (!*info_ptr) { + png_destroy_read_struct(png_ptr, NULL, NULL); + result = -5; + goto exit2; + } + + if (setjmp(png_jmpbuf(*png_ptr))) { + result = -6; + goto exit1; + } + + png_init_io(*png_ptr, fp); + png_set_sig_bytes(*png_ptr, sizeof(header)); + png_read_info(*png_ptr, *info_ptr); + + png_get_IHDR(*png_ptr, *info_ptr, width, height, &bit_depth, + &color_type, NULL, NULL, NULL); + + *channels = png_get_channels(*png_ptr, *info_ptr); + + if (bit_depth == 8 && *channels == 3 && + color_type == PNG_COLOR_TYPE_RGB) { + /* 8-bit RGB: great, nothing to do. */ + } else if (bit_depth == 8 && *channels == 4 && + color_type == PNG_COLOR_TYPE_RGB_ALPHA) { + /* 8-bit RGB with alpha: great, nothing to do. */ + } else if (bit_depth == 8 && *channels == 2 && + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { + /* 8-bit gray with alpha: great, nothing to do. */ + } else if (bit_depth == 8 && *channels == 1 && + color_type == PNG_COLOR_TYPE_GRAY) { + /* 8-bit gray with: great, nothing to do. */ + } else if (bit_depth < 8 && *channels == 2 && + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { + /* 1-, 2- or 4-bit gray with alpha: expand to 8-bit gray. */ + png_set_expand_gray_1_2_4_to_8(*png_ptr); + } else if (bit_depth < 8 && *channels == 1 && + color_type == PNG_COLOR_TYPE_GRAY) { + /* 1-, 2- or 4-bit gray: expand to 8-bit gray. */ + png_set_expand_gray_1_2_4_to_8(*png_ptr); + } else if (bit_depth <= 8 && *channels == 1 && + color_type == PNG_COLOR_TYPE_PALETTE) { + int color_num; + png_colorp palette; + + if (png_get_PLTE(*png_ptr, *info_ptr, &palette, + &color_num)) { + int i, rgb = 0; + + for (i = 0; i < color_num; i++) + if (palette[i].red != palette[i].green || + palette[i].red != palette[i].blue) { + rgb = 1; + break; + } + + if (!rgb) { + png_set_rgb_to_gray_fixed(*png_ptr, 1, -1, -1); + *channels = 1; + } else + *channels = 3; + + /* paletted images: expand to 8-bit RGB. */ + png_set_palette_to_rgb(*png_ptr); + + /* Expand paletted or RGB images with transparency to full + * alpha channels so the data will be available as RGBA + * quartets. */ + if (*channels == 3 && + png_get_valid(*png_ptr, *info_ptr, PNG_INFO_tRNS)) { + png_set_tRNS_to_alpha(*png_ptr); + *channels = 4; + } + } + } else { + fprintf(stderr, + "RUI doesn't support PNG depth %d channels %d " + "color_type %d of image \"%s\"\n", + bit_depth, *channels, color_type, name); + result = -7; + goto exit1; + } + + return result; + +exit1: + if (result < 0) + png_destroy_read_struct(png_ptr, info_ptr, NULL); + +exit2: + if (fp != NULL) + fclose(fp); + + return result; +} + +/* "display" surfaces are transformed into the framebuffer's required + * pixel format (currently only RGBX is supported) at load time, so + * gr_blit() can be nothing more than a memcpy() for each row. The + * next two functions are the only ones that know anything about the + * framebuffer pixel format; they need to be modified if the + * framebuffer format changes (but nothing else should). */ + +/* Allocate and return a gr_surface sufficient for storing an image of + * the indicated size in the framebuffer pixel format. */ +static gr_surface init_display_surface(png_uint_32 width, png_uint_32 height, int channels) +{ + gr_surface surface; + + if (!(surface = malloc_surface(width * height * channels))) + return NULL; + + surface->width = width; + surface->height = height; + surface->row_bytes = width * channels; + surface->pixel_bytes = channels; + + return surface; +} + +/* Copy 'input_row' to 'output_row', transforming it to the + * framebuffer pixel format. The input format depends on the value of + * 'channels': + * + * 1 - input is 8-bit grayscale + * 2 - input is 8-bit grayscale + 8-bit alpha + * 3 - input is 24-bit RGB + * 4 - input is 32-bit RGBA/RGBX + * + * 'width' is the number of pixels in the row. */ +static void transform_rgb_to_draw(unsigned char *input_row, + unsigned char *output_row, + int channels, + int width) +{ + int x; + unsigned char *ip = input_row, *op = output_row; + + switch (channels) { + case 1: /* expand gray level to RGBX */ + for (x = 0; x < width; x++) { + *op++ = *ip; + *op++ = *ip; + *op++ = *ip++; + *op++ = 0xff; + } + + break; + case 2: /* expand gray level plus alpha to RGBX */ + for (x = 0; x < width; ++x) { + *op++ = *ip; + *op++ = *ip; + *op++ = *ip++; + *op++ = *ip++; + } + + break; + case 3: /* expand RGBA to RGBX */ + for (x = 0; x < width; ++x) { + *op++ = *ip++; + *op++ = *ip++; + *op++ = *ip++; + *op++ = 0xff; + } + + break; + case 4: /* copy RGBA to RGBX */ + memcpy(output_row, input_row, width * 4); + break; + } +} + +int res_create_anim_image_surfaces(const char *name, int *frames, + gr_surface **pSurface, gr_img_type img_type) +{ + int result = 0, i, num_text; + unsigned char *p_row = NULL; + unsigned int y; + gr_surface *surface = NULL; + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + png_uint_32 width, height; + png_byte channels; + png_textp text; + + *pSurface = NULL; + *frames = -1; + + result = open_png(name, &png_ptr, &info_ptr, &width, &height, + &channels); + if (result < 0) { + printf("Can't load image \"%s\": %d.\n", name, result); + return result; + } + + *frames = 1; + + if (png_get_text(png_ptr, info_ptr, &text, &num_text)) + for (i = 0; i < num_text; i++) + if (text[i].key && !strcmp(text[i].key, "Frames") && + text[i].text) { + *frames = atoi(text[i].text); + break; + } + + if (*frames <= 0) { + printf("Bad frame count (%d)\n", *frames); + result = -9; + goto exit; + } + + if (height % *frames || height < *frames) { + printf("Bad image height (%d) for frame count (%d)\n", + (int)height, *frames); + result = -9; + goto exit; + } + + if (!(surface = malloc(*frames * sizeof(gr_surface)))) { + result = -8; + goto exit; + } + + for (i = 0; i < *frames; i++) + if (!(surface[i] = init_display_surface(width, + height / *frames, + (img_type == GR_WITH_ALPHA ? + channels : 4)))) { + result = -8; + goto exit; + } + + if (img_type == GR_WITHOUT_ALPHA) + p_row = malloc(width * channels); + + for (y = 0; y < height; y++) { + int frame = y % *frames; + unsigned char *p_dst = surface[frame]->data + (y / *frames) * + surface[frame]->row_bytes; + + if (img_type == GR_WITH_ALPHA) + png_read_row(png_ptr, p_dst, NULL); + else { + png_read_row(png_ptr, p_row, NULL); + transform_rgb_to_draw(p_row, p_dst, channels, width); + } + } + + if (img_type == GR_WITHOUT_ALPHA) + free(p_row); + + *pSurface = (gr_surface *)surface; + +exit: + if (png_get_io_ptr(png_ptr)) + fclose((FILE *)png_get_io_ptr(png_ptr)); + + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + + if (result < 0 && surface) { + for (i = 0; i < *frames; i++) + if (surface[i]) + free(surface[i]); + + free(surface); + } + + return result; +} + +int res_create_image_surface(const char *name, gr_surface *pSurface, + gr_img_type img_type) +{ + gr_surface surface = NULL; + int result = 0; + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + png_uint_32 width, height; + png_byte channels; + unsigned char *p_row = NULL; + unsigned int y; + + *pSurface = NULL; + + result = open_png(name, &png_ptr, &info_ptr, &width, &height, + &channels); + if (result < 0) { + printf("Can't load image \"%s\": %d.\n", name, result); + return result; + } + + if (!(surface = init_display_surface(width, height, + (img_type == GR_WITH_ALPHA ? + channels : 4)))) { + result = -8; + goto exit; + } + + if (img_type == GR_WITHOUT_ALPHA) + p_row = malloc(width * channels); + + for (y = 0; y < height; y++) { + unsigned char *p_dst = surface->data + y * surface->row_bytes; + + if (img_type == GR_WITH_ALPHA) + png_read_row(png_ptr, p_dst, NULL); + else { + png_read_row(png_ptr, p_row, NULL); + transform_rgb_to_draw(p_row, p_dst, channels, width); + } + } + + if (img_type == GR_WITHOUT_ALPHA) + free(p_row); + + *pSurface = surface; +exit: + if (png_get_io_ptr(png_ptr)) + fclose((FILE *)png_get_io_ptr(png_ptr)); + + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + + return result; +} + +#if 0 /* Currently unneeded */ +static int matches_locale(const char *loc, const char *locale) +{ + int i; + + if (locale == NULL) + return 0; + + if (!strcmp(loc, locale)) + return 1; + + /* if loc does *not* have an underscore, and it matches the start + * of locale, and the next character in locale *is* an underscore, + * that's a match. For instance, loc == "en" matches locale == + * "en_US". */ + + for (i = 0; loc[i] != 0 && loc[i] != '_'; ++i) + ; + + if (loc[i] == '_') + return 0; + + return (!strncmp(locale, loc, i) && locale[i] == '_'); +} + +int res_create_localized_alpha_surface(const char *name, const char *locale, + gr_surface *pSurface) +{ + gr_surface surface = NULL; + int result = 0; + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + png_uint_32 width, height; + png_byte channels; + unsigned char *row; + png_uint_32 y; + + *pSurface = NULL; + + if (locale == NULL) { + surface = malloc_surface(0); + surface->width = 0; + surface->height = 0; + surface->row_bytes = 0; + surface->pixel_bytes = 1; + goto exit; + } + + result = open_png(name, &png_ptr, &info_ptr, &width, &height, + &channels); + if (result < 0) { + printf("Can't load image \"%s\": %d.\n", name, result); + return result; + } + + if (channels != 1) { + result = -7; + goto exit; + } + + row = malloc(width); + for (y = 0; y < height; ++y) { + int w, h; + char *loc; + + png_read_row(png_ptr, row, NULL); + w = (row[1] << 8) | row[0]; + h = (row[3] << 8) | row[2]; + loc = (char *)row + 5; + + if (y + 1 + h >= height || matches_locale(loc, locale)) { + int i; + + printf(" %20s: %s (%d x %d @ %d)\n", name, loc, w, h, + (int)y); + + surface = malloc_surface(w * h); + if (surface == NULL) { + result = -8; + goto exit; + } + + surface->width = w; + surface->height = h; + surface->row_bytes = w; + surface->pixel_bytes = 1; + + for (i = 0; i < h; i++, y++) { + png_read_row(png_ptr, row, NULL); + memcpy(surface->data + i * w, row, w); + } + + *pSurface = (gr_surface)surface; + break; + } else { + int i; + + for (i = 0; i < h; i++, y++) + png_read_row(png_ptr, row, NULL); + } + } + +exit: + if (png_get_io_ptr(png_ptr)) + fclose((FILE *)png_get_io_ptr(png_ptr)); + + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + if (result < 0 && surface != NULL) + free(surface); + + return result; +} +#endif /* 0 Currently unneeded */ + +void res_free_surface(gr_surface surface) +{ + free(surface); +} diff --git a/src/librui/rui-description.c b/src/librui/rui-description.c new file mode 100644 index 0000000..c906499 --- /dev/null +++ b/src/librui/rui-description.c @@ -0,0 +1,32 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "graphics.h" +#include "rui-description.h" + +void rui_description_draw(rui_description *d) +{ + if (!d) + return; + + gr_set_color(d->style->c_title); + gr_text(d->pos_x, d->pos_y, d->title, GR_FONT_BOLD); + gr_set_color(d->style->c_text); + gr_text(d->pos_x, d->pos_y + gr_get_font_cheight(), d->text, + GR_FONT_BOLD); +} diff --git a/src/librui/rui-description.h b/src/librui/rui-description.h new file mode 100644 index 0000000..293ac3c --- /dev/null +++ b/src/librui/rui-description.h @@ -0,0 +1,44 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "graphics.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + color c_title; + color c_text; +} rui_description_style; + +typedef struct { + int pos_x; + int pos_y; + rui_description_style *style; + const char *title; + const char *text; +} rui_description; + +void rui_description_draw(rui_description *d); + +#ifdef __cplusplus +} +#endif diff --git a/src/librui/rui-image.h b/src/librui/rui-image.h new file mode 100644 index 0000000..bd7408f --- /dev/null +++ b/src/librui/rui-image.h @@ -0,0 +1,67 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "graphics.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + RUI_IMAGE_NONE = -1 +} rui_image_id; + +typedef enum { + RUI_ANIMATION_NONE = -1 +} rui_animation_id; + +typedef struct { + const char *fname; + color c_bg; + gr_align_horizontal align_hor; + gr_align_vertical align_ver; + int offset_x, + offset_y; + gr_img_type img_type; + gr_surface surface; +} rui_image; + +typedef struct { + const char *fname; + color c_bg; + gr_align_horizontal align_hor; + gr_align_vertical align_ver; + int frames_num, + current_frame; + int offset_x, + offset_y; + gr_img_type img_type; + gr_surface *surfaces; +} rui_animation; + +void rui_images_init(rui_image *images, int images_num, + rui_animation *animations, int animations_num); +void rui_images_exit(void); +void rui_images_draw(void); +void rui_animations_draw(void); + +#ifdef __cplusplus +} +#endif diff --git a/src/librui/rui-images.c b/src/librui/rui-images.c new file mode 100644 index 0000000..b5b0998 --- /dev/null +++ b/src/librui/rui-images.c @@ -0,0 +1,153 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "rui.h" +#include "common.h" +#include "graphics.h" +#include "rui-image.h" + +static rui_image *rui_images = NULL; +static rui_animation *rui_animations = NULL; +static int rui_images_num = 0, rui_animations_num = 0; + +void rui_images_draw(void) +{ + size_t i = 0; + rui_screen *cs; + rui_image_id img_id; + + cs = get_current_screen(); + if (!cs->images) + return; + + while ((img_id = cs->images[i]) != RUI_IMAGE_NONE) { + rui_image *img = &rui_images[img_id]; + + if (!img->surface) { + i++; + continue; + } + + if (img->img_type == GR_WITH_ALPHA) { + gr_set_color(img->c_bg); + gr_blend_image_aligned(img->surface, img->align_hor, + img->align_ver, img->offset_x, + img->offset_y); + } else + gr_blit_image_aligned(img->surface, img->align_hor, + img->align_ver, img->offset_x, + img->offset_y); + + i++; + } +} + +void rui_animations_draw(void) +{ + int i = 0; + rui_screen *cs; + rui_animation_id anim_id; + + cs = get_current_screen(); + if (!cs->animations) + return; + + while ((anim_id = cs->animations[i]) != RUI_ANIMATION_NONE) { + rui_animation *anim = &rui_animations[anim_id]; + + if (!anim->surfaces) { + i++; + continue; + } + + if (anim->img_type == GR_WITH_ALPHA) { + gr_set_color(anim->c_bg); + gr_blend_image_aligned(anim->surfaces[anim->current_frame], + anim->align_hor, + anim->align_ver, + anim->offset_x, + anim->offset_y); + } else + gr_blit_image_aligned(anim->surfaces[anim->current_frame], + anim->align_hor, + anim->align_ver, + anim->offset_x, + anim->offset_y); + + i++; + if (++anim->current_frame >= anim->frames_num) + anim->current_frame = 0; + } +} + +void rui_images_init(rui_image *images, + int images_num, + rui_animation *animations, + int animations_num) +{ + int i; + + rui_images = images; + rui_images_num = images_num; + rui_animations = animations; + rui_animations_num = animations_num; + + for (i = 0; i < rui_images_num; i++) + if (res_create_image_surface(rui_images[i].fname, + &rui_images[i].surface, + rui_images[i].img_type) < 0) + rui_images[i].surface = NULL; + + for (i = 0; i < rui_animations_num; i++) + if (res_create_anim_image_surfaces(rui_animations[i].fname, + &rui_animations[i].frames_num, + &rui_animations[i].surfaces, + rui_animations[i].img_type) < 0) + rui_animations[i].surfaces = NULL; +} + +void rui_images_exit(void) +{ + int i; + + for (i = 0; i < rui_images_num; i++) + if (rui_images[i].surface) { + res_free_surface(rui_images[i].surface); + rui_images[i].surface = NULL; + } + + rui_images = NULL; + rui_images_num = 0; + + for (i = 0; i < rui_animations_num; i++) + if (rui_animations[i].surfaces) { + int j; + + for (j = 0; j < rui_animations[i].frames_num; j++) + res_free_surface(rui_animations[i].surfaces[j]); + + free(rui_animations[i].surfaces); + rui_animations[i].surfaces = NULL; + } + + rui_animations = NULL; + rui_animations_num = 0; +} diff --git a/src/librui/rui-menu.c b/src/librui/rui-menu.c new file mode 100644 index 0000000..fb7698f --- /dev/null +++ b/src/librui/rui-menu.c @@ -0,0 +1,106 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "rui.h" +#include "graphics.h" +#include "rui-menu.h" + +static void rui_menu_draw_item(int i, rui_menu *m) +{ + gr_set_color((i == m->item_selected) ? m->style->c_bg_selected : + m->style->c_bg_unselected); + gr_draw_rectangle(m->pos_x, + m->pos_y + i * (m->style->item_height + + m->style->item_spacing), + gr_fb_width() - m->pos_x, m->style->item_height); + + gr_set_color((i == m->item_selected) ? m->style->c_text_selected : + m->style->c_text_unselected); + gr_text(m->style->text_pos_x, + m->pos_y + + i * (m->style->item_height + m->style->item_spacing) + + (m->style->item_height - gr_get_font_cheight()) / 2, + m->items[i], + (i == m->item_selected) ? GR_FONT_BOLD : GR_FONT_REGULAR); +} + +void rui_menu_draw(rui_menu *menu) +{ + int i; + + if (!menu) + return; + + for (i = 0; i < menu->items_num; i++) + rui_menu_draw_item(i, menu); +} + +int rui_menu_cursor_up(rui_menu *menu) +{ + if (!menu) + return 0; /* Don't need to repaint */ + + if (--menu->item_selected < 0) + menu->item_selected = menu->items_num - 1; + + return 1; /* Need repaint */ +} + +int rui_menu_cursor_down(rui_menu *menu) +{ + if (!menu) + return 0; /* Don't need to repaint */ + + if (++menu->item_selected >= menu->items_num) + menu->item_selected = 0; + + return 1; /* Need repaint */ +} + +int rui_menu_action_run(rui_menu *menu) +{ + int item_selected; + int ret; + + if (!menu || !menu->actions) + return 0; /* Don't need to repaint */ + + item_selected = menu->item_selected; + rui_screen_switch(menu->actions[item_selected].screen_switch_to); + if (menu->actions[item_selected].action_handler) { + ret = system(menu->actions[item_selected].action_handler); + if (ret < 0) + return ret; + + if (menu->actions[item_selected].exit_after_action) + exit(0); + } + + return 1; /* Repaint unconditionally. Just in case. */ +} + +void rui_menu_init(rui_menu *menu) +{ + if (!menu) + return; + + if (menu->item_default != RUI_MENU_ITEM_DO_NOT_CHANGE) + menu->item_selected = menu->item_default; +} diff --git a/src/librui/rui-menu.h b/src/librui/rui-menu.h new file mode 100644 index 0000000..1bb051a --- /dev/null +++ b/src/librui/rui-menu.h @@ -0,0 +1,68 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "graphics.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + int item_height, + item_spacing, + text_pos_x; + color c_bg_selected, + c_bg_unselected, + c_text_selected, + c_text_unselected; +} rui_menu_style; + +typedef enum { + RUI_MENU_ITEM_DO_NOT_CHANGE = -1 +} rui_menu_item_id; + +struct rui_menu_t; + +typedef struct { + int screen_switch_to; + const char *action_handler; + int exit_after_action; +} rui_menu_action; + +typedef struct rui_menu_t { + rui_menu_style *style; + int pos_x, + pos_y, + items_num, + item_selected, + item_default; + const char **items; + rui_menu_action *actions; +} rui_menu; + +void rui_menu_draw(rui_menu *menu); +int rui_menu_cursor_up(rui_menu *menu); +int rui_menu_cursor_down(rui_menu *menu); +int rui_menu_action_run(rui_menu *menu); +void rui_menu_init(rui_menu *menu); + +#ifdef __cplusplus +} +#endif diff --git a/src/librui/rui-progress-bar.c b/src/librui/rui-progress-bar.c new file mode 100644 index 0000000..80fbfdb --- /dev/null +++ b/src/librui/rui-progress-bar.c @@ -0,0 +1,68 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "rui.h" +#include "graphics.h" +#include "rui-progress-bar.h" + +void rui_progress_bar_draw(rui_progress_bar *b) +{ + int width, progress_width; + + if (!b) + return; + + gr_set_color(b->style->c_border); + width = gr_fb_width() - 2 * b->pos_x; + /* Draw progress bar symmetrically to center. */ + gr_draw_rectangle(b->pos_x, b->pos_y, width, b->height); + progress_width = b->progress * + (width - 2 * b->style->border_width) / 100; + + if (b->progress != 0) { /* Draw bar. */ + gr_set_color(b->style->c_bar); + gr_draw_rectangle(b->pos_x + b->style->border_width, + b->pos_y + b->style->border_width, + progress_width, + b->height - 2 * b->style->border_width); + } + + if (b->progress != 100) { /* Draw background. */ + gr_set_color(b->style->c_background); + gr_draw_rectangle(b->pos_x + b->style->border_width + + progress_width, + b->pos_y + b->style->border_width, + width - 2 * b->style->border_width - + progress_width, + b->height - 2 * b->style->border_width); + } +} + +int rui_progress_bar_get_progress(rui_progress_bar *b) +{ + return b->progress; +} + +/* Set progress value for progress bar on the current screen. */ +void rui_progress_bar_set_progress(rui_progress_bar *b, int progress) +{ + if (!b || progress < 0 || progress > 100) + return; + + b->progress = progress; +} diff --git a/src/librui/rui-progress-bar.h b/src/librui/rui-progress-bar.h new file mode 100644 index 0000000..def59f8 --- /dev/null +++ b/src/librui/rui-progress-bar.h @@ -0,0 +1,48 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "graphics.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + color c_background, + c_border, + c_bar; + int border_width; +} rui_progress_bar_style; + +typedef struct { + int pos_x, + pos_y, + height, + progress; /* 0 - 100 */ + rui_progress_bar_style *style; +} rui_progress_bar; + +void rui_progress_bar_draw(rui_progress_bar *b); +int rui_progress_bar_get_progress(rui_progress_bar *b); +void rui_progress_bar_set_progress(rui_progress_bar *b, int progress); + +#ifdef __cplusplus +} +#endif diff --git a/src/librui/rui-ruler.h b/src/librui/rui-ruler.h new file mode 100644 index 0000000..1c4aa09 --- /dev/null +++ b/src/librui/rui-ruler.h @@ -0,0 +1,42 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "graphics.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + color c_ruler; +} rui_ruler_style; + +typedef struct { + int pos_x, + pos_y, + height; + rui_ruler_style *style; +} rui_ruler; + +void rui_rulers_draw(rui_ruler *rulers); + +#ifdef __cplusplus +} +#endif diff --git a/src/librui/rui-rulers.c b/src/librui/rui-rulers.c new file mode 100644 index 0000000..2f67995 --- /dev/null +++ b/src/librui/rui-rulers.c @@ -0,0 +1,36 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "graphics.h" +#include "rui-ruler.h" + +void rui_rulers_draw(rui_ruler *rulers) +{ + rui_ruler *r = rulers; + + while (r) { + if (!r->style) + break; + + gr_set_color(r->style->c_ruler); + /* Draw ruler symmetrically to center. */ + gr_draw_rectangle(r->pos_x, r->pos_y, + gr_fb_width() - 2 * r->pos_x, r->height); + r++; + } +} diff --git a/src/librui/rui.c b/src/librui/rui.c new file mode 100644 index 0000000..0954853 --- /dev/null +++ b/src/librui/rui.c @@ -0,0 +1,119 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "rui.h" +#include "common.h" +#include "rui-menu.h" +#include "graphics.h" +#include "rui-image.h" +#include "rui-ruler.h" +#include "input-events.h" +#include "rui-description.h" + +static rui_screen *rui_screens = NULL; +static int rui_screens_num = 0, rui_current_screen = 0; + +rui_screen * get_current_screen(void) +{ + return &rui_screens[rui_current_screen]; +} + +int get_current_screen_id(void) +{ + return rui_current_screen; +} + +void rui_draw(void) +{ + rui_screen *cs; + + cs = get_current_screen(); + if (cs->style) + gr_set_color(cs->style->c_background); + gr_clear(); + rui_images_draw(); + rui_animations_draw(); + + if (cs->rulers) + rui_rulers_draw(cs->rulers); + + if (cs->menu) + rui_menu_draw(cs->menu); + + if (cs->description) + rui_description_draw(cs->description); + + if (cs->progress_bar) + rui_progress_bar_draw(cs->progress_bar); + + if (cs->draw) + cs->draw(); + + gr_flip(); +} + +/* Returns need_repaint */ +bool rui_screen_switch(int screen) +{ + if (screen == RUI_SCREEN_CURRENT || screen == get_current_screen_id()) + return false; /* Don't need to repaint */ + + if (screen == RUI_SCREEN_BACK) { + rui_screen *cs; + + cs = get_current_screen(); + return rui_screen_switch(cs->screen_back); + } + + rui_current_screen = screen; + if (rui_screens[screen].menu) + rui_menu_init(rui_screens[screen].menu); + + if (rui_screens[screen].progress_bar) + rui_progress_bar_set_progress( + rui_screens[screen].progress_bar, 0); + + if (rui_screens[screen].on_enter) + rui_screens[screen].on_enter(); + + return true; /* Need to repaint */ +} + +bool rui_init(rui_screen *screens, int screens_num, int current_screen, + rui_image *images, int images_num, + rui_animation *animations, int animations_num) +{ + if (!gr_init()) + return false; + + rui_screens = screens; + rui_screens_num = screens_num; + rui_current_screen = current_screen; + rui_images_init(images, images_num, animations, animations_num); + return true; +} + +void rui_exit(void) +{ + rui_images_exit(); + gr_exit(); +} diff --git a/src/librui/rui.h b/src/librui/rui.h new file mode 100644 index 0000000..765092b --- /dev/null +++ b/src/librui/rui.h @@ -0,0 +1,72 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include "graphics.h" +#include "rui-menu.h" +#include "rui-image.h" +#include "rui-ruler.h" +#include "rui-description.h" +#include "rui-progress-bar.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*rui_screen_on_enter)(void); +typedef void (*rui_screen_draw)(void); + +typedef struct { + color c_background; +} rui_screen_style; + +typedef enum { + RUI_SCREEN_BACK = -2, + RUI_SCREEN_CURRENT = -1 +} rui_screen_id; + +typedef struct { + rui_screen_style *style; + rui_menu *menu; + rui_description *description; + rui_ruler *rulers; + rui_progress_bar *progress_bar; + int *images; + rui_animation_id *animations; + int rulers_num; + rui_screen_on_enter on_enter; + rui_screen_draw draw; + int screen_back; + int allow_force_reboot; +} rui_screen; + +bool rui_init(rui_screen *screens, int screens_num, int current_screen, + rui_image *images, int images_num, + rui_animation *animations, int animations_num); +void rui_exit(void); +void rui_draw(void); +bool rui_screen_switch(int screen); /* Returns need_repaint */ +rui_screen *get_current_screen(void); +int get_current_screen_id(void); + +#ifdef __cplusplus +} +#endif diff --git a/src/librui/tdm-if.c b/src/librui/tdm-if.c new file mode 100755 index 0000000..7f2371b --- /dev/null +++ b/src/librui/tdm-if.c @@ -0,0 +1,360 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil -*- + * + * system-recovery + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Based on tdm-if.c from tota-ua. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tdm-if.h" + +#define LOGD(format, ...) printf("[TDM-IF] " format "\n", ##__VA_ARGS__) + +#define C(b, m) (((b) >> (m)) & 0xFF) +#define B(c, s) ((((unsigned int)(c)) & 0xff) << (s)) +#define FOURCC(a, b, c, d) (B(d, 24) | B(c, 16) | B(b, 8) | B(a, 0)) +#define FOURCC_STR(id) C(id, 0), C(id, 8), C(id, 16), C(id, 24) +#define FOURCC_ID(str) FOURCC(((char*)str)[0], ((char*)str)[1], ((char*)str)[2], ((char*)str)[3]) + +static tdm_if_disp s_st_disp; + +static void tdm_if_display_commit_handler_cb(tdm_output *output, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, + void *user_data) +{ + LOGD("commit_handle_cb!!"); + + return ; +} + +int tdm_if_display_init(void) +{ + const tdm_output_mode *output_modes, *preferred_mode; + tdm_info_layer layer_info; + tdm_layer_capability layer_caps; + tdm_output_conn_status conn_status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED; + tdm_output_type output_type = TDM_OUTPUT_TYPE_Unknown; + tdm_output *output = NULL; + int buf_cnt; + tdm_error err = TDM_ERROR_NONE; + tdm_if_disp *st_disp = &s_st_disp; + int i, j; + int layer_count = 0; + int output_count = 0; + + LOGD("START"); + + st_disp->disp = tdm_display_init(&err); + if (!st_disp->disp) { + LOGD("failed to init tdm_display. error num = %d", err); + goto exit; + } + + err = tdm_display_get_fd(st_disp->disp, &st_disp->tdm_fd); + if (err != TDM_ERROR_NONE) { + LOGD("failed to get tdm fd. error num = %d", err); + goto exit; + } + + st_disp->drm_fd = tdm_helper_get_fd("TDM_DRM_MASTER_FD"); + if (st_disp->drm_fd == -1) { + LOGD("failed to get tdm fd. error num = %d", err); + goto exit; + } + + err = tdm_display_get_output_count(st_disp->disp, &output_count); + if (err != TDM_ERROR_NONE) { + LOGD("failed to get output count. error num = %d", err); + goto exit; + } + + if (output_count < 1) { + LOGD("insufficient number of outputs"); + goto exit; + } + + for (i = 0; i < output_count; i++) { + output = tdm_display_get_output(st_disp->disp, i, &err); + if (err != TDM_ERROR_NONE) { + LOGD("failed to get outout. error num = %d", err); + goto exit; + } + + err = tdm_output_get_output_type(output, &output_type); + if (err != TDM_ERROR_NONE) { + LOGD("failed to get output type. error num = %d", err); + goto exit; + } + + err = tdm_output_get_conn_status(output, &conn_status); + if (err != TDM_ERROR_NONE) { + LOGD("failed to get output connection status. error num = %d", err); + goto exit; + } + + LOGD("output_type=%d conn_status=%d", output_type, conn_status); + if ((output_type == TDM_OUTPUT_TYPE_LVDS) || + (output_type == TDM_OUTPUT_TYPE_DSI)) { + int cnt = 0; + err = tdm_output_get_available_modes(output, &output_modes, &cnt); + if (err != TDM_ERROR_NONE) { + LOGD("failed to get output available modes. error num = %d", err); + goto exit; + } + LOGD("%d output modes available", cnt); + + preferred_mode = output_modes; + for (j = 0; j < cnt; j++) { + if (output_modes[i].type & TDM_OUTPUT_MODE_TYPE_PREFERRED) { + preferred_mode = &output_modes[i]; + break; + } + } + + /* GET MODE INFO */ + st_disp->output = output; + st_disp->width = preferred_mode->hdisplay; + st_disp->height = preferred_mode->vdisplay; + + err = tdm_output_set_mode(st_disp->output, preferred_mode); + if (err != TDM_ERROR_NONE) { + LOGD("unable to set mode: \"%s\"", preferred_mode->name); + goto exit; + } + + /* informational */ + unsigned int width_mm = 0; + unsigned int height_mm = 0; + err = tdm_output_get_physical_size(output, &width_mm, &height_mm); + LOGD("TDM_OUTPUT_MODE:name[%s] mode:wh[%d %d] mm[%d %d]", + preferred_mode->name, st_disp->width, st_disp->height, width_mm, height_mm); + + break; + } + } + + /* SET LAYER */ + err = tdm_output_get_layer_count(st_disp->output, &layer_count); + if (err != TDM_ERROR_NONE) { + LOGD("failed to get number of layers"); + goto exit; + } + if (layer_count < 1) { + LOGD("insufficient number of layers: %d", layer_count); + goto exit; + } + + for (i = 0; i < layer_count; i++) { + st_disp->layer = tdm_output_get_layer(st_disp->output, i, &err); + if (err != TDM_ERROR_NONE) { + LOGD("failed to get layer: %d", i); + goto exit; + } + + err = tdm_layer_get_capabilities(st_disp->layer, &layer_caps); + if (err != TDM_ERROR_NONE) { + LOGD("failed to get layer capabilities: %d", i); + goto exit; + } + + if ((layer_caps & TDM_LAYER_CAPABILITY_PRIMARY) && + (layer_caps & TDM_LAYER_CAPABILITY_GRAPHIC)) + break; + } + + layer_info.src_config.size.h = st_disp->width; + layer_info.src_config.size.v = st_disp->height; + layer_info.src_config.pos.x = 0; + layer_info.src_config.pos.y = 0; + layer_info.src_config.pos.w = st_disp->width; + layer_info.src_config.pos.h = st_disp->height; + layer_info.src_config.format = TBM_FORMAT_ARGB8888; + layer_info.dst_pos.x = 0; + layer_info.dst_pos.y = 0; + layer_info.dst_pos.w = st_disp->width; + layer_info.dst_pos.h = st_disp->height; + layer_info.transform = TDM_TRANSFORM_NORMAL; + + err = tdm_layer_set_info(st_disp->layer, &layer_info); + if (err != TDM_ERROR_NONE) { + LOGD("failed to get output layer. error num = %d", err); + goto exit; + } + + for (buf_cnt = 0; buf_cnt < MAX_BUF; buf_cnt++) { + tbm_surface_error_e e; + tbm_surface_info_s si; + + st_disp->surf[buf_cnt] = tbm_surface_internal_create_with_flags(st_disp->width, + st_disp->height, + TBM_FORMAT_ARGB8888, + TBM_BO_SCANOUT); + e = get_last_result(); + if (e != TBM_SURFACE_ERROR_NONE || + !st_disp->surf[buf_cnt]){ + LOGD("failed to create tbm_surface!"); + goto exit; + } + + e = tbm_surface_get_info(st_disp->surf[buf_cnt], &si); + if (e != TBM_SURFACE_ERROR_NONE) { + LOGD("failed to get info for tbm_surface!"); + goto exit; + } + + LOGD("surface created: %dx%d %c%c%c%c bpp:%d size:%d planes:%d stride:%d", + si.width, si.height, + FOURCC_STR(si.format), + si.bpp, si.size, si.num_planes, + si.planes[0].stride); + + if (si.num_planes != 1) { + LOGD("unsupported number of planes: %d", si.num_planes); + goto exit; + } + st_disp->buffer_size = si.planes[0].size; + st_disp->stride = si.planes[0].stride; + } + + + st_disp->current_buf_id = 0; + + for (i = 0; i < MAX_BUF; i++) { + tdm_if_buffer_update(NULL); + tdm_if_display_update(); + } + + LOGD("DONE"); + return 0; +exit: + tdm_if_display_deinit(); + return -1; +} + +void tdm_if_display_deinit(void) +{ + int buf_cnt = 0; + tdm_if_disp *st_disp = &s_st_disp; + + tdm_if_lcd_off(); + + if (st_disp->disp != NULL) { + /* RELEASE RESOURCE */ + for (buf_cnt = 0; buf_cnt < MAX_BUF; buf_cnt++) { + if (st_disp->surf[buf_cnt] != NULL) + tbm_surface_destroy(st_disp->surf[buf_cnt]); + } + + tdm_display_deinit(st_disp->disp); + st_disp->disp = NULL; + } +} + +int tdm_if_display_width(void) +{ + tdm_if_disp *st_disp = &s_st_disp; + return st_disp->width; +} + +int tdm_if_display_height(void) +{ + tdm_if_disp *st_disp = &s_st_disp; + return st_disp->height; +} + +int tdm_if_display_bufsize(void) +{ + tdm_if_disp *st_disp = &s_st_disp; + return st_disp->buffer_size; +} + +int tdm_if_display_stride(void) +{ + tdm_if_disp *st_disp = &s_st_disp; + return st_disp->stride; +} + +void tdm_if_buffer_update(unsigned char *buffer) +{ + tdm_if_disp *st_disp = &s_st_disp; + int buf_cnt = st_disp->current_buf_id; + tbm_surface_info_s tbm_surface_info; + tbm_surface_error_e err; + uint32_t *surface; + + err = tbm_surface_map(st_disp->surf[buf_cnt], TBM_SURF_OPTION_WRITE, &tbm_surface_info); + if (err != TBM_SURFACE_ERROR_NONE) { + LOGD("tbm_surface_map failed!"); + return; + } + + surface = (uint32_t*)tbm_surface_info.planes[0].ptr; + + if (buffer == NULL) + memset(surface, 0, st_disp->buffer_size); + else + memcpy(surface, buffer, st_disp->buffer_size); + + tbm_surface_unmap(st_disp->surf[buf_cnt]); +} + +void tdm_if_display_update(void) +{ + /* DISPLAY UPDATE */ + int buf_cnt = 0; + tdm_if_disp *st_disp = &s_st_disp; + + buf_cnt = st_disp->current_buf_id; + st_disp->current_buf_id = (st_disp->current_buf_id + 1)%MAX_BUF; + + tdm_layer_set_buffer(st_disp->layer, st_disp->surf[buf_cnt]); + + // TODO: sync or async?? + tdm_output_commit(st_disp->output, 1, tdm_if_display_commit_handler_cb, st_disp); +} + +void tdm_if_lcd_on(void) +{ + tdm_if_disp *st_disp = &s_st_disp; + + LOGD("DPMS ON!"); + tdm_output_set_dpms(st_disp->output, TDM_OUTPUT_DPMS_ON); +} + +void tdm_if_lcd_off(void) +{ + tdm_if_disp *st_disp = &s_st_disp; + + LOGD("DPMS OFF!"); + tdm_output_set_dpms(st_disp->output, TDM_OUTPUT_DPMS_OFF); +} diff --git a/src/librui/tdm-if.h b/src/librui/tdm-if.h new file mode 100755 index 0000000..9c92e7d --- /dev/null +++ b/src/librui/tdm-if.h @@ -0,0 +1,69 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil -*- + * + * system-recovery + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Based on tdm-if.h from tota-ua. + */ + +#ifndef __TDM_IF_H__ +#define __TDM_IF_H__ + +#include +#include +#include +#include +#include + +#define MAX_BUF 2 +#define RGB32_BPP 32 +#define RGB32_PITCH 4 + +typedef struct _tdm_if_disp { + tdm_display *disp; + tdm_output *output; + tdm_layer *layer; + int tdm_fd; + int drm_fd; + tbm_surface_h surf[MAX_BUF]; + int buffer_size; + int width; + int height; + int stride; + int current_buf_id; +} tdm_if_disp; + +typedef enum { + FRONT_BUFFER = 0, + BACK_BUFFER +} BUFFER_TYPE; + +extern tdm_if_disp s_disp; + +int tdm_if_display_init(void); +void tdm_if_display_deinit(void); +void tdm_if_display_update(void); +int tdm_if_display_width(void); +int tdm_if_display_height(void); +int tdm_if_display_bufsize(void); +int tdm_if_display_stride(void); + +void tdm_if_buffer_update(unsigned char *buffer); + +void tdm_if_lcd_on(void); +void tdm_if_lcd_off(void); + +#endif /* __TDM_IF_H__ */ diff --git a/src/shared/log.c b/src/shared/log.c new file mode 100644 index 0000000..fd08409 --- /dev/null +++ b/src/shared/log.c @@ -0,0 +1,414 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * libsystem + * + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "log.h" + +#define FILEBUF 1024 + +static inline void __cleanup_free_func(void *p) +{ + free(*(void**) p); +} + +static inline bool isempty(const char *p) +{ + return !p || !p[0]; +} + +#define _cleanup_(x) __attribute__((cleanup(x))) + +#define _cleanup_free_ _cleanup_(__cleanup_free_func) + +#define new(t, n) ((t*) malloc(sizeof(t) * (n))) + +#define FOREACH_WORD_SEPARATOR(word, length, s, separator, state) \ + for ((state) = NULL, (word) = split((s), &(length), (separator), &(state)); (word); (word) = split((s), &(length), (separator), &(state))) + +#define strncaseeq(a, b, n) (strncasecmp((a), (b), (n)) == 0) + +static FILE *log_f[LOG_TYPE_MAX]; +static int stdout_bak = -1; +static int stderr_bak = -1; + +static int log_level = LOG_DEBUG; + +static const char const *log_priority_name[] = { + [LOG_ALERT] = "alert", + [LOG_CRIT] = "crit", + [LOG_DEBUG] = "debug", + [LOG_EMERG] = "emerg", + [LOG_ERR] = "err", + [LOG_INFO] = "info", + [LOG_NOTICE] = "notice", + [LOG_WARNING] = "warning" +}; + +void set_log_level(int level) +{ + log_level = level; +} + +int get_log_level(void) +{ + return log_level; +} + +static bool __quote_complete(char *str, size_t l, char q) +{ + char *s, *s2; + + assert(str); + + if (!l) + return true; + + s = strchr(str, q); + if (!s || (s - str) > l) + return true; + + s = strchr(s + 1, q); + if (!s || (s - str) > l) + return false; + + s2 = strchr(s + 1, q); + if (!s2 || (s2 - str) > l) + return true; + + return __quote_complete(s + 1, l - (s + 1 - str), q); +} + +#define QUOTES "\"\'" +static bool quote_complete(char *str, size_t l) +{ + char quotes[] = QUOTES; + int i; + + assert(str); + + if (!l) + return true; + + for (i = 0; quotes[i]; i++) { + if (!__quote_complete(str, l, quotes[i])) + return false; + } + + return true; +} + +static char *split(const char *c, size_t *l, const char *separator, char **state) +{ + bool separator_include_quotes; + char *current; + size_t s; + + assert(c); + assert(l); + assert(separator); + assert(state); + + current = *state ? *state : (char *) c; + if (!*current || *c == 0) + return NULL; + + *l = 0; + separator_include_quotes = !!strspn(separator, QUOTES); + current += strspn(current, separator); + + while ((s = strcspn(current + *l, separator))) { + *l += s; + if (separator_include_quotes || + quote_complete(current, *l)) + break; + (*l)++; + } + + *state = current + *l; + + return (char *) current; +} + +static int stdpath_dup_and_backup(FILE *f) +{ + int r, fd; + + stdout_bak = dup(STDOUT_FILENO); + stderr_bak = dup(STDERR_FILENO); + + fd = fileno(f); + r = dup2(fd, STDOUT_FILENO); + if (r < 0) + return -errno; + + r = dup2(fd, STDERR_FILENO); + if (r < 0) + return -errno; + + return 0; +} + +static int stdpath_restore(void) +{ + int r; + + if (stdout_bak >= 0) { + r = dup2(stdout_bak, STDOUT_FILENO); + if (r < 0) + return -errno; + + close(stdout_bak); + stdout_bak = -1; + } + + if (stderr_bak >= 0) { + r = dup2(stderr_bak, STDERR_FILENO); + if (r < 0) + return -errno; + + close(stderr_bak); + stderr_bak = -1; + } + + return 0; +} + +int log_open(enum log_mask log_set, const char *path) +{ + int r; + + if (log_set & LOG_MASK_FILE) { + assert(path); + + log_f[LOG_TYPE_FILE] = fopen(path, "w+"); + if (!log_f[LOG_TYPE_FILE]) + return -errno; + + /* If standard output/error were not set, redirect + * standard output/error to log file */ + if (!(log_set & LOG_MASK_STANDARD)) { + r = stdpath_dup_and_backup(log_f[LOG_TYPE_FILE]); + if (r < 0) + return r; + } + } + + if (log_set & LOG_MASK_KMSG) { + log_f[LOG_TYPE_KMSG] = fopen("/dev/kmsg", "we"); + if (!log_f[LOG_TYPE_KMSG]) + return -errno; + + /* If standard output/error or log file were not set, + * redirect standard output/error to kmsg */ + if (!(log_set & LOG_MASK_STANDARD) && + !(log_set & LOG_MASK_FILE)) { + r = stdpath_dup_and_backup(log_f[LOG_TYPE_KMSG]); + if (r < 0) + return r; + } + } + + return 0; +} + +int log_close(void) +{ + enum log_type type; + + for (type = 0; type < LOG_TYPE_MAX; type++) { + if (type == LOG_TYPE_STANDARD || !log_f[type]) + continue; + + fclose(log_f[type]); + log_f[type] = NULL; + } + + return stdpath_restore(); +} + +static int _log_write( + int level, + const char *file, + int line, + const char *func, + const char *format, + va_list ap) +{ + char buff[LINE_MAX]; + enum log_type type; + + vsnprintf(buff, LINE_MAX, format, ap); + + for (type = 0; type < LOG_TYPE_MAX; type++) { + if (type != LOG_TYPE_STANDARD && !log_f[type]) + continue; + + switch (type) { + case LOG_TYPE_STANDARD: + fprintf(level <= LOG_ERR ? stderr : stdout, + "%s\n", buff); + break; + case LOG_TYPE_FILE: + fprintf(log_f[LOG_TYPE_FILE], + "%-8s: %s\n", log_priority_name[level], buff); + fflush(log_f[LOG_TYPE_FILE]); + break; + case LOG_TYPE_KMSG: + fprintf(log_f[LOG_TYPE_KMSG], + "initrd: %s\n", buff); + break; + default: + break; + } + } + + return 0; +} + +int log_write( + int level, + const char*file, + int line, + const char *func, + const char *format, ...) +{ + va_list ap; + int r; + + va_start(ap, format); + r = _log_write(level, file, line, func, format, ap); + va_end(ap); + + return r; +} + +int log_move(const char *to) +{ + _cleanup_free_ char *buf = NULL; + FILE *w = NULL; + size_t len; + int r; + + assert(to); + + if (!log_f[LOG_TYPE_FILE]) + return 0; + + buf = new(char, FILEBUF); + if (!buf) { + r = -ENOMEM; + goto error; + } + + w = fopen(to, "a+"); + if (!w) { + r = -errno; + goto error; + } + + r = fseek(log_f[LOG_TYPE_FILE], 0, SEEK_SET); + if (r < 0) { + r = -errno; + goto error; + } + + r = fflush(log_f[LOG_TYPE_FILE]); + if (r < 0) { + r = -errno; + goto error; + } + + while ((len = fread(buf, sizeof(char), FILEBUF, log_f[LOG_TYPE_FILE])) > 0) { + if (fwrite(buf, sizeof(char), len, w) != len) { + r = -errno; + goto error; + } + } + + fclose(log_f[LOG_TYPE_FILE]); + log_f[LOG_TYPE_FILE] = w; + + r = stdpath_dup_and_backup(log_f[LOG_TYPE_FILE]); + if (r < 0) + goto error; + + return 0; + +error: + if (w) + fclose(w); + + log_dbg("Failed to move log: %d\n", errno); + + return r; +} + +enum log_mask parse_log_type(const char *type) +{ + char *word, *state; + enum log_mask mask = 0; + size_t l; + + if (!type) + return LOG_MASK_INVALID; + + FOREACH_WORD_SEPARATOR(word, l, type, "+", state) { + + if (strncaseeq(word, "standard", l)) + mask |= LOG_MASK_STANDARD; + else if (strncaseeq(word, "file", l)) + mask |= LOG_MASK_FILE; + else if (strncaseeq(word, "kmsg", l)) + mask |= LOG_MASK_KMSG; + else + return LOG_MASK_INVALID; + } + + return mask; +} + +int config_parse_log_type( + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data) +{ + + enum log_mask *mask = data; + + if (isempty(rvalue)) + return 0; + + *mask = parse_log_type(rvalue); + + return *mask == LOG_MASK_INVALID ? -EINVAL : 0; +} diff --git a/src/shared/log.h b/src/shared/log.h new file mode 100644 index 0000000..ce26b1e --- /dev/null +++ b/src/shared/log.h @@ -0,0 +1,71 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * libsystem + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +enum log_type { + LOG_TYPE_INVALID = -1, + LOG_TYPE_STANDARD = 0, + LOG_TYPE_FILE, + LOG_TYPE_KMSG, + LOG_TYPE_MAX +}; + +enum log_mask { + LOG_MASK_INVALID = -1, + LOG_MASK_STANDARD = 1 << LOG_TYPE_STANDARD, + LOG_MASK_FILE = 1 << LOG_TYPE_FILE, + LOG_MASK_KMSG = 1 << LOG_TYPE_KMSG, +}; + +#define log_full(level, ...) \ + do { \ + log_write((level), __FILE__, __LINE__, __func__, __VA_ARGS__); \ + } while (0) + +void set_log_level(int level); +int get_log_level(void); +int log_open(enum log_mask log_set, const char *path); +int log_close(void); +int log_write(int level, const char*file, int line, const char *func, const char *format, ...); +int log_move(const char *to); +enum log_mask parse_log_type(const char *type); +int config_parse_log_type(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data); + +#define log_dbg(format, ...) \ + do { \ + if (get_log_level() >= LOG_DEBUG) \ + log_full(LOG_DEBUG, format, ##__VA_ARGS__); \ + } while (0) + +#define log_err(format, ...) \ + do { \ + if (get_log_level() >= LOG_ERR) \ + log_full(LOG_ERR, format, ##__VA_ARGS__); \ + } while (0) + +#define log_info(format, ...) \ + do { \ + if (get_log_level() >= LOG_INFO) \ + log_full(LOG_INFO, format, ##__VA_ARGS__); \ + } while (0) diff --git a/src/system-recovery/.gitignore b/src/system-recovery/.gitignore new file mode 100644 index 0000000..9cda7ea --- /dev/null +++ b/src/system-recovery/.gitignore @@ -0,0 +1,2 @@ +/50-system-recovery.list +/recovery-init \ No newline at end of file diff --git a/src/system-recovery/50-system-recovery-sprd.list b/src/system-recovery/50-system-recovery-sprd.list new file mode 100644 index 0000000..6b30709 --- /dev/null +++ b/src/system-recovery/50-system-recovery-sprd.list @@ -0,0 +1,24 @@ +# ---- Target contents ----------------------------------------------------- # +DIRECTORIES=" +/usr/lib/bufmgr +/usr/lib/tdm +" + +DIR_SYMLINKS=" +" + +MVWITHLIBS=" +" + +WITHLIBS=" +/usr/lib/bufmgr/libtbm_sprd.so.0.0.0 +/usr/lib/tdm/libtdm-sprd.so +" + +# LinkFileName:Target +SYMLINKS=" +/usr/lib/bufmgr/libtbm_default.so:libtbm_sprd.so +/usr/lib/bufmgr/libtbm_sprd.so.0:libtbm_sprd.so.0.0.0 +/usr/lib/bufmgr/libtbm_sprd.so:libtbm_sprd.so.0.0.0 +/usr/lib/tdm/libtdm-default.so:libtdm-sprd.so +" diff --git a/src/system-recovery/50-system-recovery.list.m4.in b/src/system-recovery/50-system-recovery.list.m4.in new file mode 100644 index 0000000..a8e3344 --- /dev/null +++ b/src/system-recovery/50-system-recovery.list.m4.in @@ -0,0 +1,44 @@ +# ---- Target contents ----------------------------------------------------- # +DIRECTORIES=" +/dev +/etc +/proc +/smack +/sys +/system +/tmp +/usr/bin +/usr/lib +/usr/sbin +" + +MVWITHLIBS=" +@SYSTEM_RECOVERY_LIBEXEC_DIR@/recovery-init +@INITRD_RECOVERY_LIBEXEC_DIR@/minireboot +m4_ifdef(`RECOVERY_GUI', +`@SYSTEM_RECOVERY_IMAGE_DIR@/font.png +@SYSTEM_RECOVERY_IMAGE_DIR@/menu-title.png +@SYSTEM_RECOVERY_IMAGE_DIR@/tizen-anim.png +@SYSTEM_RECOVERY_IMAGE_DIR@/warning.png') +m4_ifdef(`RECOVERY_GUI', `@SYSTEM_RECOVERY_LIBEXEC_DIR@/system-recovery.gui', `@SYSTEM_RECOVERY_LIBEXEC_DIR@/system-recovery.non_gui') +" + +WITHLIBS=" +/usr/bin/bash +/usr/bin/mount +/usr/bin/sync +/usr/bin/touch +/usr/bin/umount +/usr/sbin/blkid +/usr/bin/ls +/usr/sbin/agetty +" + +VERBATIMS=" +@SYSTEM_RECOVERY_DATA_DIR@/system-recovery.cfg +" + +# LinkFileName:Target +SYMLINKS=" +/sbin/recovery-init:@SYSTEM_RECOVERY_LIBEXEC_DIR@/recovery-init +" diff --git a/src/system-recovery/process-util.c b/src/system-recovery/process-util.c new file mode 100644 index 0000000..a5a34b9 --- /dev/null +++ b/src/system-recovery/process-util.c @@ -0,0 +1,90 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define _POSIX_SOURCE + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "process-util.h" +#include "system-recovery.h" /* For LOGD */ + +int process_exec(process_exec_type sync, char *argv[]) +{ + pid_t pid; + struct sigaction act, oldact; + int r = 0; + + if (!argv) + return -EINVAL; + + /* Use default signal handler */ + act.sa_handler = SIG_DFL; + act.sa_flags = 0; + sigemptyset(&act.sa_mask); + + if (sigaction(SIGCHLD, &act, &oldact) < 0) + return -errno; + + pid = fork(); + if (pid < 0) { /* Error */ + LOGD("Failed to fork\n"); + r = -errno; + } else if (!pid) { /* Child */ + int i; + + for (i = 0; i < _NSIG; i++) + signal(i, SIG_DFL); + + r = execv(argv[0], (char **)argv); + if (r < 0) + exit(EXIT_FAILURE); + } else { /* Parent */ + int status; + + if (sync == PROCESS_NON_WAIT) + return pid; + + /* Wait for child */ + if (waitpid(pid, &status, 0) != -1) { + if (WIFEXITED(status)) { /* Terminated normally */ + LOGD("%d terminated by exit(%d)\n", pid, + WEXITSTATUS(status)); + return WEXITSTATUS(status); + } else if (WIFSIGNALED(status)) + LOGD("%d terminated by signal %d\n", pid, + WTERMSIG(status)); + else if (WIFSTOPPED(status)) + LOGD("%d stopped by signal %d\n", pid, + WSTOPSIG(status)); + } else + LOGD("%d waitpid() failed - %d\n", pid, errno); + } + + if (sigaction(SIGCHLD, &oldact, NULL) < 0) + LOGD("failed to restore sigaction\n"); + + return r; +} diff --git a/src/system-recovery/process-util.h b/src/system-recovery/process-util.h new file mode 100644 index 0000000..016c51a --- /dev/null +++ b/src/system-recovery/process-util.h @@ -0,0 +1,34 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + PROCESS_NON_WAIT, + PROCESS_WAIT_CHILD +} process_exec_type; + +int process_exec(process_exec_type sync, char *argv[]); + +#ifdef __cplusplus +} +#endif diff --git a/src/system-recovery/recovery-action-set.in b/src/system-recovery/recovery-action-set.in new file mode 100755 index 0000000..a6ddf8c --- /dev/null +++ b/src/system-recovery/recovery-action-set.in @@ -0,0 +1,18 @@ +#!/bin/sh + +CONFIG_FILE="@SYSTEM_RECOVERY_DATA_DIR@/system-recovery.cfg" +ACTION_FILE="@SYSTEM_RECOVERY_ACTION_FILE@" + +actions=`cat $CONFIG_FILE | sed -ne '/^action_handlers[[:space:]]*=[[:space:]]*{/,/}/ p' | sed -ne 's/[[:space:]]*\(.*\)[[:space:]]*=[[:space:]]*\".*/\1/ p'` + +for a in ${actions} +do + if [ "$a" = "${1}" ] + then + echo "${1}" > $ACTION_FILE + echo "Action changed to ${1}" + exit + fi +done + +echo "Action ${1} is not specified in configuration." diff --git a/src/system-recovery/recovery-headless.c b/src/system-recovery/recovery-headless.c new file mode 100644 index 0000000..e07035c --- /dev/null +++ b/src/system-recovery/recovery-headless.c @@ -0,0 +1,68 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "log.h" +#include "system-recovery.h" + +static char *get_action_from_config(config_t *cfg) +{ + config_setting_t *node; + const char *action; + + node = config_lookup(cfg, "headless_action"); + if (!node) + return NULL; + + action = config_setting_get_string(node); + + return strdup(action); +} + +int recovery_headless(config_t *cfg) +{ + config_setting_t *node; + + node = config_lookup(cfg, "action_handlers"); + if (!node) + return -ENOENT; + + char *action = get_action_from_cmdline(); + if (!action) + action = get_action_from_file(); + if (!action) + action = get_action_from_config(cfg); + if (!action) + return -ENOENT; + + const char *handler; + int r = config_setting_lookup_string(node, action, &handler); + free(action); + + if (r == CONFIG_FALSE) + return -ENOENT; + + return system(handler); +} diff --git a/src/system-recovery/recovery-init.in b/src/system-recovery/recovery-init.in new file mode 100644 index 0000000..bdf5338 --- /dev/null +++ b/src/system-recovery/recovery-init.in @@ -0,0 +1,79 @@ +#!/bin/sh + +SYSTEM_RECOVERY_GUI="@SYSTEM_RECOVERY_LIBEXEC_DIR@/system-recovery.gui" +SYSTEM_RECOVERY_NON_GUI="@SYSTEM_RECOVERY_LIBEXEC_DIR@/system-recovery.non_gui" +FAKE_ROOT=/system + +MOUNT="/usr/bin/mount" +BLKID="/usr/sbin/blkid" +REBOOT="@INITRD_RECOVERY_LIBEXEC_DIR@/minireboot" +SYNC="/usr/bin/sync" +UMOUNT="/usr/bin/umount" + +#------------------------------------------------ +# get partition id +#------------------------------------------------ +get_partition_id() { + PART_ROOTFS=$("$BLKID" --match-token PARTLABEL=ROOTFS -o device || "$BLKID" --match-token LABEL=rootfs -o device) + PART_SYSTEM_DATA=$("$BLKID" --match-token PARTLABEL=SYSTEM-DATA -o device || "$BLKID" --match-token LABEL=system-data -o device) + PART_USER=$("$BLKID" --match-token PARTLABEL=USER -o device || "$BLKID" --match-token LABEL=user -o device) +} + +#------------------------------------------------ +# mount_partitions +#------------------------------------------------ +mount_partitions() { + echo "mount partitions" + get_partition_id + + "$MOUNT" -t ext4 ${PART_ROOTFS} ${FAKE_ROOT} -o ro + "$MOUNT" -t ext4 ${PART_SYSTEM_DATA} ${FAKE_ROOT}/opt + "$MOUNT" -t ext4 ${PART_USER} ${FAKE_ROOT}/opt/usr + + "$MOUNT" -t proc none ${FAKE_ROOT}/proc + "$MOUNT" -t sysfs none ${FAKE_ROOT}/sys + "$MOUNT" -t smackfs smackfs ${FAKE_ROOT}/sys/fs/smackfs + "$MOUNT" -t devtmpfs devtmpfs ${FAKE_ROOT}/dev + "$MOUNT" -t devpts devpts ${FAKE_ROOT}/dev/pts + "$MOUNT" -t tmpfs tmpfs ${FAKE_ROOT}/tmp -o mode=1777,smackfsroot=* +} + +#------------------------------------------------ +# umount_partitions +#------------------------------------------------ +umount_partitions() { + echo "umount partitions" + "$SYNC" + + "$UMOUNT" ${FAKE_ROOT}/opt/usr + "$UMOUNT" ${FAKE_ROOT}/opt + "$UMOUNT" ${FAKE_ROOT} +} + +#------------------------------------------------ +# do_reboot +#------------------------------------------------ +do_reboot() { + echo "Reboot" + "$SYNC" + "$REBOOT" + while [ 1 ] + do + sleep 1 + echo "." + done +} + +#------------------------------------------------ +# system-recovery initrc +#------------------------------------------------ +echo "Starting system recovery." +mount_partitions + +# For debugging - It should be deleted on Release +/sbin/agetty -l /bin/sh -n --keep-baud 115200,38400,9600 ttyS1 linux & + +[ -x "${SYSTEM_RECOVERY_GUI}" ] && "${SYSTEM_RECOVERY_GUI}" || "${SYSTEM_RECOVERY_NON_GUI}" + +umount_partitions +do_reboot diff --git a/src/system-recovery/recovery-main.c b/src/system-recovery/recovery-main.c new file mode 100644 index 0000000..dd30ce9 --- /dev/null +++ b/src/system-recovery/recovery-main.c @@ -0,0 +1,125 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define _POSIX_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include // for COMMAND_LINE_SIZE + +#include "system-recovery.h" + +void sys_power_reboot(void) +{ + reboot(RB_AUTOBOOT); +} + +#define KERNEL_CMDLINE_KEY "tizen.recovery" +#define ACTION_BUFFER_SIZE 256 +#define _STR(x) #x +#define STR(x) _STR(x) + +// looks for tizen.recovery= key in kernel command line +char *get_action_from_cmdline(void) +{ + FILE *fp; + char cmdline[COMMAND_LINE_SIZE]; + int len; + + fp = fopen("/proc/cmdline", "r"); + if (!fp) + return NULL; + + char *p = fgets(cmdline, sizeof cmdline, fp); + fclose(fp); + if (!p) + return NULL; + + const char *prefix = KERNEL_CMDLINE_KEY "="; + p = strstr(cmdline, prefix); + if (!p) + return NULL; + p += strlen(prefix); + + for (len = 0; *(p + len) != 0 && !isspace(*(p + len)); ++len) + ; /* skip */ + + return strndup(p, len); +} + +char *get_action_from_file(void) +{ + FILE *fp; + char buf[ACTION_BUFFER_SIZE]; + int ret; + + fp = fopen(SYSTEM_RECOVERY_ACTION_FILE, "r"); + if (!fp) { + LOGD("Could not open recovery action file\n"); + return NULL; + } + + ret = fscanf(fp, "%" STR(ACTION_BUFFER_SIZE) "s", buf); + fclose(fp); + if (unlink(SYSTEM_RECOVERY_ACTION_FILE) < 0) + LOGD("Could not unlink recovery action file: %m\n"); + + if (ret != 1) + return NULL; + + return strndup(buf, ACTION_BUFFER_SIZE); +} + +int main(void) +{ + config_t cfg; + int ret; + + LOGD("[main] recovery started.\n"); + + config_init(&cfg); + ret = config_read_file(&cfg, SYSTEM_RECOVERY_CONFIG_FILE); + if (ret == CONFIG_FALSE) { + LOGD("Can't read config file"); + return 1; + } + +#ifdef RECOVERY_GUI + ret = recovery_gui(&cfg); +#else + ret = recovery_headless(&cfg); +#endif + + LOGD("[main] recovery finished.\n"); + config_destroy(&cfg); + + return ret; +} diff --git a/src/system-recovery/recovery-rui-skin.h b/src/system-recovery/recovery-rui-skin.h new file mode 100644 index 0000000..fe2df56 --- /dev/null +++ b/src/system-recovery/recovery-rui-skin.h @@ -0,0 +1,136 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "graphics.h" + +#define RUI_COLOR_BACKGROUND BLACK +#define RUI_COLOR_TITLE (color) { .r = 27, .g = 199, .b = 204, .a = 255 } +#define RUI_COLOR_RULER RUI_COLOR_TITLE + +#define RUI_COLOR_MENU_BG_SELECTED RUI_COLOR_TITLE +#define RUI_COLOR_MENU_BG_UNSELECTED BLACK +#define RUI_COLOR_MENU_TEXT_SELECTED WHITE +#define RUI_COLOR_MENU_TEXT_UNSELECTED WHITE + +#define RUI_COLOR_DESCRIPTION_TITLE RUI_COLOR_TITLE +#define RUI_COLOR_DESCRIPTION_TEXT WHITE + +#define RUI_COLOR_PROGRESS_BAR_BAR YELLOW +#define RUI_COLOR_PROGRESS_BAR_BORDER RUI_COLOR_TITLE +#define RUI_COLOR_PROGRESS_BAR_BACKGROUND BLACK + +#ifdef FEATURE_DISPLAY_720X1280 +#define RUI_MENU_ITEM_HEIGHT 60 +#define RUI_MENU_ITEM_SPACING 8 +#define RUI_MENU_TEXT_POS_X 15 + +#define RUI_COMMON_MENU_POS_X 0 + +#define RUI_MAIN_MENU_POS_X RUI_COMMON_MENU_POS_X +#define RUI_MAIN_MENU_POS_Y 100 + +#define RUI_REBOOT_MENU_POS_X RUI_COMMON_MENU_POS_X +#define RUI_REBOOT_MENU_POS_Y 480 + +#define RUI_SAFE_MENU_POS_X RUI_COMMON_MENU_POS_X +#define RUI_SAFE_MENU_POS_Y 480 + +#define RUI_FACTORY_MENU_POS_X RUI_COMMON_MENU_POS_X +#define RUI_FACTORY_MENU_POS_Y 480 + +#define RUI_SD_RESTORE_MENU_POS_X RUI_COMMON_MENU_POS_X +#define RUI_SD_RESTORE_MENU_POS_Y 480 + +#define RUI_MAIN_SCREEN_DESCRIPTION_POS_X 15 +#define RUI_MAIN_SCREEN_DESCRIPTION_POS_Y 480 + +#define RUI_COMMON_SCREEN_DESCRIPTION_POS_X 15 +#define RUI_COMMON_SCREEN_DESCRIPTION_POS_Y 100 + +#define RUI_RULER_HEIGHT 2 + +#define RUI_RULER_TOP_POS_X 0 +#define RUI_RULER_TOP_POS_Y 80 +#define RUI_MAIN_SCREEN_RULER_POS_Y 420 + +#define RUI_PROGRESS_BAR_BORDER_WIDTH 1 +#define RUI_PROGRESS_BAR_HEIGHT 20 + +#define RUI_SD_RESTORE_RUN_SCREEN_PROGRESS_BAR_POS_X 5 +#define RUI_SD_RESTORE_RUN_SCREEN_PROGRESS_BAR_POS_Y 600 + +#else +#define RUI_MENU_ITEM_HEIGHT 50 +#define RUI_MENU_ITEM_SPACING 5 +#define RUI_MENU_TEXT_POS_X 5 + +#define RUI_COMMON_MENU_POS_X 0 + +#define RUI_MAIN_MENU_POS_X RUI_COMMON_MENU_POS_X +#define RUI_MAIN_MENU_POS_Y 100 + +#define RUI_REBOOT_MENU_POS_X RUI_COMMON_MENU_POS_X +#define RUI_REBOOT_MENU_POS_Y 160 + +#define RUI_SAFE_MENU_POS_X RUI_COMMON_MENU_POS_X +#define RUI_SAFE_MENU_POS_Y 240 + +#define RUI_FACTORY_MENU_POS_X RUI_COMMON_MENU_POS_X +#define RUI_FACTORY_MENU_POS_Y 240 + +#define RUI_SD_RESTORE_MENU_POS_X RUI_COMMON_MENU_POS_X +#define RUI_SD_RESTORE_MENU_POS_Y 240 + +#define RUI_MAIN_SCREEN_DESCRIPTION_POS_X 5 +#define RUI_MAIN_SCREEN_DESCRIPTION_POS_Y 372 + +#define RUI_COMMON_SCREEN_DESCRIPTION_POS_X 5 +#define RUI_COMMON_SCREEN_DESCRIPTION_POS_Y 100 + +#define RUI_RULER_HEIGHT 2 + +#define RUI_RULER_TOP_POS_X 0 +#define RUI_RULER_TOP_POS_Y 60 +#define RUI_MAIN_SCREEN_RULER_POS_Y 347 + +#define RUI_PROGRESS_BAR_BORDER_WIDTH 1 +#define RUI_PROGRESS_BAR_HEIGHT 20 + +#define RUI_SD_RESTORE_RUN_SCREEN_PROGRESS_BAR_POS_X 5 +#define RUI_SD_RESTORE_RUN_SCREEN_PROGRESS_BAR_POS_Y 600 +#endif + +#define RUI_REBOOT_SCREEN_DESCRIPTION_POS_X RUI_COMMON_SCREEN_DESCRIPTION_POS_X +#define RUI_REBOOT_SCREEN_DESCRIPTION_POS_Y RUI_COMMON_SCREEN_DESCRIPTION_POS_Y + +#define RUI_SAFE_SCREEN_DESCRIPTION_POS_X RUI_COMMON_SCREEN_DESCRIPTION_POS_X +#define RUI_SAFE_SCREEN_DESCRIPTION_POS_Y RUI_COMMON_SCREEN_DESCRIPTION_POS_Y + +#define RUI_FACTORY_SCREEN_DESCRIPTION_POS_X RUI_COMMON_SCREEN_DESCRIPTION_POS_X +#define RUI_FACTORY_SCREEN_DESCRIPTION_POS_Y RUI_COMMON_SCREEN_DESCRIPTION_POS_Y + +#define RUI_FACTORY_RUN_SCREEN_DESCRIPTION_POS_X RUI_COMMON_SCREEN_DESCRIPTION_POS_X +#define RUI_FACTORY_RUN_SCREEN_DESCRIPTION_POS_Y RUI_COMMON_SCREEN_DESCRIPTION_POS_Y + +#define RUI_SD_RESTORE_SCREEN_DESCRIPTION_POS_X RUI_COMMON_SCREEN_DESCRIPTION_POS_X +#define RUI_SD_RESTORE_SCREEN_DESCRIPTION_POS_Y RUI_COMMON_SCREEN_DESCRIPTION_POS_Y + +#define RUI_SD_RESTORE_RUN_SCREEN_DESCRIPTION_POS_X RUI_COMMON_SCREEN_DESCRIPTION_POS_X +#define RUI_SD_RESTORE_RUN_SCREEN_DESCRIPTION_POS_Y RUI_COMMON_SCREEN_DESCRIPTION_POS_Y diff --git a/src/system-recovery/recovery-rui.c b/src/system-recovery/recovery-rui.c new file mode 100644 index 0000000..0deefad --- /dev/null +++ b/src/system-recovery/recovery-rui.c @@ -0,0 +1,854 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include "rui.h" +#include "common.h" +#include "config.h" +#include "rui-menu.h" +#include "graphics.h" +#include "log.h" +#include "rui-image.h" +#include "rui-ruler.h" +#include "input-events.h" +#include "rui-description.h" +#include "system-recovery.h" +#include "rui-progress-bar.h" +#include "recovery-rui-skin.h" +#include "process-util.h" + +/* if user does not do anything, default action will be taken after this timeout*/ +#define DEFAULT_ACTION_TIMEOUT 4 + +#define BUFFER_SIZE 512 + +bool volatile running = true; +static const char *original_description = NULL; +static char description_buffer[BUFFER_SIZE]; +static char *rui_default_action = NULL; +static const char *rui_default_handler = NULL; + +static int timer_count = 0; +static bool user_idle = true; + +static void timeout_handler(rui_screen *cs) +{ + int ret; + + if (rui_default_action && user_idle) { + if (!original_description) { + original_description = cs->description->text; + cs->description->text = description_buffer; + } + + snprintf(description_buffer, BUFFER_SIZE, + "%s\nDefault action (%s) will be taken after %d seconds", + original_description, rui_default_action, + DEFAULT_ACTION_TIMEOUT - timer_count/TIMER_INTERVAL); + + if (timer_count/TIMER_INTERVAL == DEFAULT_ACTION_TIMEOUT) { + ret = system(rui_default_handler); + if (ret < 0) + LOGD("Could not run action: %s\n", rui_default_handler); + } + } + + if (original_description && !user_idle) { + cs->description->text = original_description; + original_description = NULL; + } + + timer_count++; +} + +void recovery_rui_input_callback(user_action action, user_action_type action_type) +{ + int need_repaint = 1; + rui_screen *cs; + + /* We interested only in button downs, long presses and idle events */ + if (action_type != ACTION_TYPE_BEGIN && + action_type != ACTION_TYPE_LONGPRESS && + action_type != ACTION_TYPE_IDLE && + action_type != ACTION_TYPE_TIMER) + return; + + cs = get_current_screen(); + if (action_type != ACTION_TYPE_TIMER && + action_type != ACTION_TYPE_IDLE && + user_idle) { + user_idle = false; + timeout_handler(cs); + } + + if (action == ACTION_DOWN && cs->menu) + rui_menu_cursor_down(cs->menu); + else if (action == ACTION_UP && cs->menu) + rui_menu_cursor_up(cs->menu); + else if (cs->allow_force_reboot && + action == ACTION_CONFIRM && + action_type == ACTION_TYPE_LONGPRESS) + sys_power_reboot(); + else if ((action == ACTION_CONFIRM || action == ACTION_HOME) && + cs->menu) + rui_menu_action_run(cs->menu); + else if (action == ACTION_BACK) + rui_screen_switch(RUI_SCREEN_BACK); + else if (action == ACTION_TIMEOUT) + timeout_handler(cs); + else if (action != ACTION_NONE || action_type != ACTION_TYPE_IDLE || + !cs->animations) + need_repaint = 0; + + if (need_repaint) + rui_draw(); +} + +static struct { + const char **rui_screens; + const char **rui_menus; + const char **rui_animations; + const char **rui_images; + const char **rui_colors; + const char **rui_screen_styles; + const char **rui_menu_styles; + const char **rui_ruler_styles; + const char **rui_rulers; + const char **rui_description_styles; + const char **rui_descriptions; + const char **rui_action_handlers; +} rui_config_labels; + +static rui_screen *rui_screens = NULL; +static rui_menu *rui_menus = NULL; +static rui_screen_style *rui_screen_styles = NULL; +static rui_menu_style *rui_menu_styles = NULL; +static rui_ruler_style *rui_ruler_styles = NULL; +static rui_animation *rui_animations = NULL; +static rui_image *rui_images = NULL; +static color *rui_colors = NULL; +static rui_ruler **rui_rulers = NULL; +static rui_description_style *rui_description_styles = NULL; +static rui_description *rui_descriptions = NULL; +static const char **rui_action_handlers = NULL; + +/* naive search */ +int find_string(const char **list, const char *s) +{ + int i; + + if (!list) + return -EINVAL; + + for (i = 0; list[i]; ++i) + if (strcmp(list[i], s) == 0) + return i; + + return -ENOENT; +} + +static inline int _rui_lookup_setting(config_setting_t *root, const char **labels, const char *name) +{ + const char *value; + int ret; + + ret = config_setting_lookup_string(root, name, &value); + if (ret == CONFIG_FALSE) + return -1; + + return find_string(labels, value); +} + +#define rui_lookup_setting(root, list, out, field) do { \ + int _idx = _rui_lookup_setting(root, rui_config_labels.list, #field); \ + if (_idx < 0 || !list) { \ + (out)->field = NULL; \ + log_dbg("Could not find setting %s.%s", #out, #field); \ + } else \ + (out)->field = &list[_idx]; \ + } while (0) + +#define rui_lookup_setting_value(root, list, out, field) do { \ + int _idx = _rui_lookup_setting(root, rui_config_labels.list, #field); \ + if (_idx < 0 || !list) \ + log_dbg("Could not find setting %s.%s", #out, #field); \ + else \ + out->field = list[_idx]; \ + } while (0) + +static inline int ascii_hex(char c) +{ + switch (c) { + case '0' ... '9': + return c - '0'; + case 'A' ... 'F': + return c - 'A' + 10; + case 'a' ... 'f': + return c - 'a' + 10; + } + + return 0; +} + +static inline char get_hex_byte(const char *s) +{ + return 16 * ascii_hex(s[0]) + ascii_hex(s[1]); +} + +static int color_entry_parse(config_setting_t *root, void *data) +{ + color *c = data; + const char *str; + + str = config_setting_get_string(root); + if (!str) + return -ENOENT; + + if (strlen(str) == 9 && str[0] == '#') { + c->r = get_hex_byte(str + 1); + c->g = get_hex_byte(str + 3); + c->b = get_hex_byte(str + 5); + c->a = get_hex_byte(str + 7); + + return 0; + } + + return -ENOTSUP; +} + +struct str2int_map { + const char *key; + int value; +}; + +static int map_find(const char *key, struct str2int_map *map) +{ + int i; + + for (i = 0; map[i].key; ++i) + if (strcmp(key, map[i].key) == 0) + return map[i].value; + + return -1; +} + +static struct str2int_map align_hor_map[] = { + {"left", GR_ALIGN_LEFT}, + {"center", GR_ALIGN_CENTER}, + {"right", GR_ALIGN_RIGHT}, + {NULL, 0} +}; + +static struct str2int_map align_ver_map[] = { + {"top", GR_ALIGN_TOP}, + {"middle", GR_ALIGN_MIDDLE}, + {"bottom", GR_ALIGN_BOTTOM}, + {NULL, 0} +}; + +static struct str2int_map img_type_map[] = { + {"no-alpha", GR_WITHOUT_ALPHA}, + {"alpha", GR_WITH_ALPHA}, + {NULL, 0} +}; + +static int image_entry_parse(config_setting_t *root, void *data) +{ + rui_image *image = data; + const char *value; + int ret; + + ret = config_setting_lookup_string(root, "fname", &image->fname); + if (ret == CONFIG_FALSE) + return -1; + + rui_lookup_setting_value(root, rui_colors, image, c_bg); + + ret = config_setting_lookup_string(root, "align_hor", &value); + image->align_hor = map_find(value, align_hor_map); + + ret = config_setting_lookup_string(root, "align_ver", &value); + image->align_ver = map_find(value, align_ver_map); + + config_setting_lookup_int(root, "offset_x", &image->offset_x); + config_setting_lookup_int(root, "offset_y", &image->offset_y); + + ret = config_setting_lookup_string(root, "img_type", &value); + image->img_type = map_find(value, img_type_map); + + image->surface = NULL; + + return 0; +} + +static int animation_entry_parse(config_setting_t *root, void *data) +{ + rui_animation *animation = data; + const char *value; + int ret; + + ret = config_setting_lookup_string(root, "fname", &animation->fname); + if (ret == CONFIG_FALSE) + return -1; + + rui_lookup_setting_value(root, rui_colors, animation, c_bg); + + ret = config_setting_lookup_string(root, "align_hor", &value); + animation->align_hor = map_find(value, align_hor_map); + + ret = config_setting_lookup_string(root, "align_ver", &value); + animation->align_ver = map_find(value, align_ver_map); + + config_setting_lookup_int(root, "offset_x", &animation->offset_x); + config_setting_lookup_int(root, "offset_y", &animation->offset_y); + config_setting_lookup_int(root, "frames_num", &animation->frames_num); + config_setting_lookup_int(root, "icurrent_frame", &animation->frames_num); + + ret = config_setting_lookup_string(root, "img_type", &value); + animation->img_type = map_find(value, img_type_map); + + animation->surfaces = NULL; + + return 0; +} + +static int get_screen_id(config_setting_t *root, const char *key) +{ + int ret; + static const char *special_labels[] = { + "", + "CURRENT", + "BACK", + }; + + ret = _rui_lookup_setting(root, + rui_config_labels.rui_screens, key); + if (ret != -ENOENT) + return ret; + + ret = _rui_lookup_setting(root, special_labels, key); + if (ret < 0) { + log_err("Could not get screen id"); + return RUI_SCREEN_CURRENT; + } else { + return -ret; + } +} + +static int menu_entry_parse(config_setting_t *root, void *data) +{ + config_setting_t *actions, *node; + rui_menu *menu = data; + int i; + int ret; + + rui_lookup_setting(root, rui_menu_styles, menu, style); + + config_setting_lookup_int(root, "pos_x", &menu->pos_x); + config_setting_lookup_int(root, "pos_y", &menu->pos_y); + config_setting_lookup_int(root, "item_selected", &menu->item_selected); + config_setting_lookup_int(root, "item_default", &menu->item_default); + + actions = config_setting_get_member(root, "actions"); + if (!actions) + return 0; + + menu->items_num = config_setting_length(actions); + menu->items = calloc(menu->items_num, sizeof(*menu->items)); + menu->actions = calloc(menu->items_num, sizeof(*menu->actions)); + if (!menu->items || !menu->actions) { + ret = -ENOMEM; + goto err; + } + + for (i = 0; i < menu->items_num; ++i) { + node = config_setting_get_elem(actions, i); + if (!node) { + log_err("Could not get next setting"); + ret = -ENOMEM; + goto err; + } + + config_setting_lookup_string(node, "label", &menu->items[i]); + menu->actions[i].screen_switch_to = get_screen_id(node, "screen_switch_to"); + config_setting_lookup_int(node, "exit_after_action", &menu->actions[i].exit_after_action); + rui_lookup_setting_value(node, rui_action_handlers, (&menu->actions[i]), action_handler); + } + + return 0; + +err: + free(menu->items); + free(menu->actions); + return ret; +} + +static int description_style_entry_parse(config_setting_t *root, void *data) +{ + rui_description_style *style = data; + rui_lookup_setting_value(root, rui_colors, style, c_title); + rui_lookup_setting_value(root, rui_colors, style, c_text); + + return 0; +} + +static int description_entry_parse(config_setting_t *root, void *data) +{ + rui_description *desc = data; + + config_setting_lookup_int(root, "pos_x", &desc->pos_x); + config_setting_lookup_int(root, "pos_y", &desc->pos_y); + rui_lookup_setting(root, rui_description_styles, desc, style); + config_setting_lookup_string(root, "title", &desc->title); + config_setting_lookup_string(root, "text", &desc->text); + + return 0; +} + +static int labels_list_parse(config_setting_t *root, int **out, + const char *name, const char **labels) +{ + int i; + int num; + int *list; + config_setting_t *elem, *node; + const char *value; + + node = config_setting_get_member(root, name); + if (!node) + return 0; + + num = config_setting_length(node); + if (num < 0) + return -EINVAL; + + list = calloc(num + 1, sizeof(*list)); + if (!list) + return -ENOMEM; + + for (i = 0; i < num; ++i) { + elem = config_setting_get_elem(node, i); + if (!elem) + goto err_nomem; + + value = config_setting_get_string(elem); + if (!value) + goto err_nomem; + + list[i] = find_string(labels, value); + } + + list[num] = -1; + + *out = list; + return 0; + +err_nomem: + free(list); + return -ENOMEM; +} + +static int screen_entry_parse(config_setting_t *root, void *data) +{ + rui_screen *screen = data; + + rui_lookup_setting(root, rui_screen_styles, screen, style); + rui_lookup_setting(root, rui_menus, screen, menu); + rui_lookup_setting_value(root, rui_rulers, screen, rulers); + rui_lookup_setting(root, rui_descriptions, screen, description); + + labels_list_parse(root, &screen->images, "images", + rui_config_labels.rui_images); + labels_list_parse(root, &screen->animations, "animations", + rui_config_labels.rui_animations); + + screen->screen_back = get_screen_id(root, "screen_back"); + config_setting_lookup_int(root, "allow_force_reboot", &screen->allow_force_reboot); + + /* + screen->progress_bar = NULL; + screen->on_enter = NULL; + screen->draw = NULL; + */ + + return 0; +} + +static int ruler_entry_parse(config_setting_t *root, void *data) +{ + rui_ruler *ruler = *(rui_ruler **)data; + config_setting_t *node; + int num; + int i; + + num = config_setting_length(root); + if (num < 0) + return -EINVAL; + + for (i = 0; i < num; ++i) { + node = config_setting_get_elem(root, i); + if (!node) + return -ENOMEM; + + config_setting_lookup_int(node, "pos_x", &ruler[i].pos_x); + config_setting_lookup_int(node, "pos_y", &ruler[i].pos_y); + config_setting_lookup_int(node, "height", &ruler[i].height); + rui_lookup_setting(node, rui_ruler_styles, &ruler[i], style); + } + + return 0; +} + +static int ruler_entry_init(config_setting_t *root, void *data) +{ + rui_ruler **out = data; + rui_ruler *ruler; + int num; + + num = config_setting_length(root); + if (num < 0) + return -EINVAL; + + ruler = calloc(num + 1, sizeof(*ruler)); + if (!ruler) + return -ENOMEM; + + *out = ruler; + return 0; +} + +static int screen_style_entry_parse(config_setting_t *root, void *data) +{ + rui_screen_style *style = data; + + rui_lookup_setting_value(root, rui_colors, style, c_background); + + return 0; +} + +static int menu_style_entry_parse(config_setting_t *root, void *data) +{ + rui_menu_style *style = data; + + config_setting_lookup_int(root, "item_height", &style->item_height); + config_setting_lookup_int(root, "item_spacing", &style->item_spacing); + config_setting_lookup_int(root, "text_pos_x", &style->text_pos_x); + rui_lookup_setting_value(root, rui_colors, style, c_bg_selected); + rui_lookup_setting_value(root, rui_colors, style, c_bg_unselected); + rui_lookup_setting_value(root, rui_colors, style, c_text_selected); + rui_lookup_setting_value(root, rui_colors, style, c_text_unselected); + + return 0; +} + +static int ruler_style_entry_parse(config_setting_t *root, void *data) +{ + rui_ruler_style *style = data; + + rui_lookup_setting_value(root, rui_colors, style, c_ruler); + + return 0; +} + +static int action_handler_entry_parse(config_setting_t *root, void *data) +{ + const char **handler = data; + + *handler = config_setting_get_string(root); + return 0; +} + +static int rui_config_group_init(config_t *cfg, const char *group_name, + int (*entry_init)(config_setting_t *root, void *out), + void **out, size_t entry_size, const char ***labels) +{ + int num, i; + config_setting_t *root, *node; + char *data; + const char **labels_data; + int ret; + + root = config_lookup(cfg, group_name); + if (!root) { + log_err("Could not find %s group in config", group_name); + return -ENOENT; + } + + num = config_setting_length(root); + if (num <= 0) + return 0; + + data = calloc(num, entry_size); + labels_data = calloc(num + 1, sizeof(*labels_data)); + if (!data || !labels_data) { + log_err("Could not allocate memory"); + ret = -ENOMEM; + goto err; + } + + for (i = 0; i < num; ++i) { + node = config_setting_get_elem(root, i); + if (!node) { + log_err("Could not get next setting"); + ret = -ENOMEM; + goto err; + } + + labels_data[i] = config_setting_name(node); + + if (entry_init) { + ret = entry_init(node, data + i * entry_size); + if (ret < 0) + goto err; + } + } + + *out = data; + *labels = labels_data; + return num; + +err: + free(data); + free(labels_data); + return ret; +} + +static int rui_config_group_parse(config_t *cfg, const char *group_name, + int (*entry_parse)(config_setting_t *root, void *out), + char *data, size_t entry_size) +{ + int num, i; + config_setting_t *root, *node; + int ret; + + root = config_lookup(cfg, group_name); + if (!root) { + log_err("Could not find %s group in config", group_name); + return -ENOENT; + } + + num = config_setting_length(root); + if (num <= 0) + return 0; + + for (i = 0; i < num; ++i) { + node = config_setting_get_elem(root, i); + if (!node) { + log_err("Could not get next setting"); + ret = -ENOMEM; + goto err; + } + + ret = entry_parse(node, data + i * entry_size); + if (ret < 0) + goto err; + } + + return num; + +err: + return ret; +} + +bool recovery_rui_init(config_t *cfg) +{ + int main_screen_n = 0; + int i; + +#define DECLARE_GROUP(n, g, h) { \ + .name = n, \ + .out = (void **)&g, \ + .entry_size = sizeof(*g), \ + .entry_init = NULL, \ + .entry_parse = h, \ + .labels = &rui_config_labels.g \ +} + +#define DECLARE_GROUP_INIT(n, g, i, h) { \ + .name = n, \ + .out = (void **)&g, \ + .entry_size = sizeof(*g), \ + .entry_init = i, \ + .entry_parse = h, \ + .labels = &rui_config_labels.g \ +} + + static struct { + const char *name; + void **out; + size_t entry_size; + int (*entry_init)(config_setting_t *root, void *out); + int (*entry_parse)(config_setting_t *root, void *out); + const char ***labels; + + int num; + } groups[] = { + DECLARE_GROUP("screens", rui_screens, screen_entry_parse), + DECLARE_GROUP("images", rui_images, image_entry_parse), + DECLARE_GROUP("animations", rui_animations, animation_entry_parse), + DECLARE_GROUP("action_handlers", rui_action_handlers, action_handler_entry_parse), + DECLARE_GROUP("menus", rui_menus, menu_entry_parse), + DECLARE_GROUP("colors", rui_colors, color_entry_parse), + DECLARE_GROUP("menu_styles", rui_menu_styles, menu_style_entry_parse), + DECLARE_GROUP("screen_styles", rui_screen_styles, screen_style_entry_parse), + DECLARE_GROUP("ruler_styles", rui_ruler_styles, ruler_style_entry_parse), + DECLARE_GROUP_INIT("rulers", rui_rulers, ruler_entry_init, ruler_entry_parse), + DECLARE_GROUP("description_styles", rui_description_styles, description_style_entry_parse), + DECLARE_GROUP("descriptions", rui_descriptions, description_entry_parse), + {NULL} + + }; +#undef DECLARE_GROUP +#undef DECLARE_GROUP_INIT + + for (i = 0; groups[i].name; ++i) + groups[i].num = rui_config_group_init(cfg, groups[i].name, groups[i].entry_init, + groups[i].out, groups[i].entry_size, groups[i].labels); + + for (i = 0; groups[i].name; ++i) + groups[i].num = rui_config_group_parse(cfg, groups[i].name, groups[i].entry_parse, + *(char **)groups[i].out, groups[i].entry_size); + + return rui_init(rui_screens, groups[0].num, + main_screen_n, + rui_images, groups[1].num, + rui_animations, groups[2].num); +} + +void cleanup_menus() +{ + int i; + if (!rui_menus) + return; + + for (i = 0; rui_config_labels.rui_menus[i]; ++i) { + free(rui_menus[i].items); + free(rui_menus[i].actions); + } +} + +void cleanup_rulers() +{ + int i; + if (!rui_rulers) + return; + + for (i = 0; rui_config_labels.rui_rulers[i]; ++i) + free(rui_rulers[i]); +} + +void cleanup_screens() +{ + int i; + if (!rui_screens) + return; + + for (i = 0; rui_config_labels.rui_screens[i]; ++i) + free(rui_screens[i].images); +} + +void recovery_rui_exit(void) +{ + rui_exit(); + + cleanup_screens(); + free(rui_screens); + cleanup_menus(); + free(rui_menus); + free(rui_screen_styles); + free(rui_menu_styles); + free(rui_ruler_styles); + free(rui_animations); + free(rui_images); + free(rui_colors); + cleanup_rulers(); + free(rui_rulers); + free(rui_descriptions); + + free(rui_config_labels.rui_screens); + free(rui_config_labels.rui_menus); + free(rui_config_labels.rui_screen_styles); + free(rui_config_labels.rui_menu_styles); + free(rui_config_labels.rui_ruler_styles); + free(rui_config_labels.rui_animations); + free(rui_config_labels.rui_images); + free(rui_config_labels.rui_colors); + free(rui_config_labels.rui_rulers); + free(rui_config_labels.rui_descriptions); + + free(rui_default_action); +} + + +int recovery_gui(config_t *cfg) +{ +#ifdef HAVE_TDM + /* These should be set externally */ + + /* + * Under normal circumstances XDG_RUNTIME_DIR is set during + * session setup (login). On initrd there is no session. This + * is used in libwayland-server and there is no default value. + */ + setenv("XDG_RUNTIME_DIR", "/run", 1); + + /* Tell TBM to work without an external wayland display manager. */ + setenv("TBM_DISPLAY_SERVER", "1", 1); +#endif + + if (!recovery_rui_init(cfg)) { + LOGD("Can't initialize GUI.\n"); + return 1; + } + + rui_default_action = get_action_from_cmdline(); + if (!rui_default_action) + rui_default_action = get_action_from_file(); + + if (rui_default_action) { + int idx = find_string(rui_config_labels.rui_action_handlers, rui_default_action); + if (idx < 0) { + LOGD("Invalid action: %s\n", rui_default_action); + free(rui_default_action); + rui_default_action = NULL; + } else + rui_default_handler = rui_action_handlers[idx]; + } + + if (!ev_init()) { + LOGD("Can't initialize input subsystem.\n"); + recovery_rui_exit(); + return 1; + } + + rui_draw(); + + while (running) + if (!ev_dispatch(recovery_rui_input_callback)) + break; + + ev_exit(); + recovery_rui_exit(); + + return 0; +} diff --git a/src/system-recovery/res-util/README.txt b/src/system-recovery/res-util/README.txt new file mode 100644 index 0000000..e79d127 --- /dev/null +++ b/src/system-recovery/res-util/README.txt @@ -0,0 +1,13 @@ +This directory contains some source files for images used by system-recovery +framebuffer GUI. + +The menu title image can be generated by ./make-menu-title.sh shell-script. +The required font SamsungSans_Md.ttf can be found +in magnolia/framework/graphics/all-fonts-slp project. + +It is possible to draw menu title by using fixed-width font but +label typed with TrueType font looks better. + +To draw progress animation system-recovery uses interlaced PNG-image +with all frames combined. For making tizen-anim.png you can use ./make-anim.sh +shell-script which uses ./interlace-frames.py python-script. diff --git a/src/system-recovery/res-util/interlace-frames.py b/src/system-recovery/res-util/interlace-frames.py new file mode 100755 index 0000000..d8b11df --- /dev/null +++ b/src/system-recovery/res-util/interlace-frames.py @@ -0,0 +1,56 @@ +#!/usr/bin/python +# +# Copyright (C) 2014 The Android Open Source Project +# Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Script to take a set of frames (PNG files) for a recovery animation +and turn it into a single output image which contains the input frames +interlaced by row. Run with the names of all the input frames on the +command line, in order, followed by the name of the output file.""" + +import sys +try: + import Image + import PngImagePlugin +except ImportError: + print "This script requires the Python Imaging Library to be installed." + sys.exit(1) + +frames = [Image.open(fn).convert("RGBA") for fn in sys.argv[1:-1]] +assert len(frames) > 0, "Must have at least one input frame." +sizes = set() +for fr in frames: + sizes.add(fr.size) + +assert len(sizes) == 1, "All input images must have the same size." +w, h = sizes.pop() +N = len(frames) + +out = Image.new("RGBA", (w, h * N)) +for j in range(h): + for i in range(w): + for fn, f in enumerate(frames): + out.putpixel((i, j * N + fn), f.getpixel((i, j))) + +# When loading this image, the graphics library expects to find a text +# chunk that specifies how many frames this animation represents. If +# you post-process the output of this script with some kind of +# optimizer tool (eg pngcrush or zopflipng) make sure that your +# optimizer preserves this text chunk. + +meta = PngImagePlugin.PngInfo() +meta.add_text("Frames", str(N)) + +out.save(sys.argv[-1], pnginfo=meta) diff --git a/src/system-recovery/res-util/make-anim.sh b/src/system-recovery/res-util/make-anim.sh new file mode 100755 index 0000000..a169dbe --- /dev/null +++ b/src/system-recovery/res-util/make-anim.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +FNAME="../res/system-recovery/images/tizen-anim.png" +SRCIMG="./tizen-anim?src.png" + +./interlace-frames.py $SRCIMG "$FNAME" +optipng -o 7 "$FNAME" diff --git a/src/system-recovery/res-util/make-menu-title.sh b/src/system-recovery/res-util/make-menu-title.sh new file mode 100755 index 0000000..5c194cb --- /dev/null +++ b/src/system-recovery/res-util/make-menu-title.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +FNAME="../res/system-recovery/images/menu-title.png" +TEXT="Tizen system recovery" +FONTSIZE=46 +FONT="./SamsungSans_Md.ttf" + +convert -background black -fill white -font "$FONT" -pointsize $FONTSIZE label:"$TEXT" "$FNAME" + +optipng -o 7 "$FNAME" diff --git a/src/system-recovery/res-util/tizen-anim1src.png b/src/system-recovery/res-util/tizen-anim1src.png new file mode 100644 index 0000000..54995eb Binary files /dev/null and b/src/system-recovery/res-util/tizen-anim1src.png differ diff --git a/src/system-recovery/res-util/tizen-anim2src.png b/src/system-recovery/res-util/tizen-anim2src.png new file mode 100644 index 0000000..43533a3 Binary files /dev/null and b/src/system-recovery/res-util/tizen-anim2src.png differ diff --git a/src/system-recovery/res-util/tizen-anim3src.png b/src/system-recovery/res-util/tizen-anim3src.png new file mode 100644 index 0000000..e949873 Binary files /dev/null and b/src/system-recovery/res-util/tizen-anim3src.png differ diff --git a/src/system-recovery/res-util/tizen-anim4src.png b/src/system-recovery/res-util/tizen-anim4src.png new file mode 100644 index 0000000..bcd8c35 Binary files /dev/null and b/src/system-recovery/res-util/tizen-anim4src.png differ diff --git a/src/system-recovery/res-util/tizen-anim5src.png b/src/system-recovery/res-util/tizen-anim5src.png new file mode 100644 index 0000000..cb07923 Binary files /dev/null and b/src/system-recovery/res-util/tizen-anim5src.png differ diff --git a/src/system-recovery/res/images/12x22.png b/src/system-recovery/res/images/12x22.png new file mode 100644 index 0000000..f63dc89 Binary files /dev/null and b/src/system-recovery/res/images/12x22.png differ diff --git a/src/system-recovery/res/images/18x32.png b/src/system-recovery/res/images/18x32.png new file mode 100644 index 0000000..aa7064e Binary files /dev/null and b/src/system-recovery/res/images/18x32.png differ diff --git a/src/system-recovery/res/images/font.png b/src/system-recovery/res/images/font.png new file mode 100644 index 0000000..f63dc89 Binary files /dev/null and b/src/system-recovery/res/images/font.png differ diff --git a/src/system-recovery/res/images/menu-title-480x800.png b/src/system-recovery/res/images/menu-title-480x800.png new file mode 100644 index 0000000..213c766 Binary files /dev/null and b/src/system-recovery/res/images/menu-title-480x800.png differ diff --git a/src/system-recovery/res/images/menu-title-720x1280.png b/src/system-recovery/res/images/menu-title-720x1280.png new file mode 100644 index 0000000..ef8aaff Binary files /dev/null and b/src/system-recovery/res/images/menu-title-720x1280.png differ diff --git a/src/system-recovery/res/images/menu-title.png b/src/system-recovery/res/images/menu-title.png new file mode 100644 index 0000000..213c766 Binary files /dev/null and b/src/system-recovery/res/images/menu-title.png differ diff --git a/src/system-recovery/res/images/tizen-anim.png b/src/system-recovery/res/images/tizen-anim.png new file mode 100644 index 0000000..a2e8f0b Binary files /dev/null and b/src/system-recovery/res/images/tizen-anim.png differ diff --git a/src/system-recovery/res/images/warning.png b/src/system-recovery/res/images/warning.png new file mode 100644 index 0000000..d591696 Binary files /dev/null and b/src/system-recovery/res/images/warning.png differ diff --git a/src/system-recovery/system-recovery.cfg.m4.in b/src/system-recovery/system-recovery.cfg.m4.in new file mode 100644 index 0000000..664c272 --- /dev/null +++ b/src/system-recovery/system-recovery.cfg.m4.in @@ -0,0 +1,285 @@ +// -*- mode: conf; indent-tabs-mode: nil -*- + +m4_define(`confirm_action',`({ + label = "Yes"; + action_handler = "$1"; + exit_after_action = $2; + },{ + label = "No"; + screen_switch_to = "BACK"; + })')m4_dnl + +action_handlers = { + reboot = "reboot -f"; + factory-reset = "touch -f /opt/.factoryreset"; + safeboot = "touch -f /opt/etc/.safeboot"; +} + +headless_action = "factory-reset"; + +colors = { + background = "#000000ff"; + title = "#1bc7ccff"; + ruler = "#1bc7ccff"; + white = "#ffffffff"; +}; + +ruler_styles = { + common = { + c_ruler = "ruler"; + }; +}; + +menu_styles = { + common = { + item_height = 80; + item_spacing = 8; + text_pos_x = 15; + c_bg_selected = "title"; + c_bg_unselected = "background"; + c_text_selected = "white"; + c_text_unselected = "white"; + }; +}; + +screen_styles = { + common = { + c_background = "background"; + }; +}; + +description_styles = { + common = { + c_title = "title"; + c_text = "white"; + }; +}; + +rulers = { + main = ( + { + pos_x = 0; + pos_y = 80; + height = 2; + style = "common"; + }, { + pos_x = 0; + pos_y = 420; + height = 2; + style = "common"; + }); + + confirm = ( + { + pos_x = 0; + pos_y = 80; + height = 2; + style = "common"; + }); +}; + +images = { + background_default = { + fname = "@SYSTEM_RECOVERY_IMAGE_DIR@/warning.png"; + c_bg = "background"; // reference to colors + align_hor = "center"; + align_ver = "bottom"; + offset_x = 0; + offset_y = 0; + img_type = "alpha"; // alt: "no-alpha"; + // surface = ; + }; + menu_title = { + fname = "@SYSTEM_RECOVERY_IMAGE_DIR@/menu-title.png"; + c_bg = "title"; + align_hor = "center"; + align_ver = "top"; + offset_x = 0; + offset_y = 20; + img_type = "no-alpha"; // alt: "no-alpha"; + // surface = ; + }; +}; + +animations = { + working = { + fname = "@SYSTEM_RECOVERY_IMAGE_DIR@/tizen-anim.png"; + c_bg = "background"; + align_hor = "center"; + align_ver = "middle"; + offset_x = 0; + offset_y = 0; + frames_num = 0; + current_frame = 0; + img_type = "no-alpha"; // alt: "no-alpha"; + // surface = ; + }; +}; + +menus = { + main = { + pos_x = 0; // use M4 macros + pos_y = 100; // use M4 macros + style = "common"; + // item_selected = ; + // item_default = ; + actions = ({ + label = "Reboot system now"; + screen_switch_to = "reboot"; + // action_handler = ; + },{ + label = "Safe mode"; + screen_switch_to = "safe"; + // action_handler = ; + },{ + label = "Phone reinitialisation"; + screen_switch_to = "factory"; + // action_handler = ; + }); + }; + reboot = { + pos_x = 0; // use M4 macros + pos_y = 480; // use M4 macros + style = "common"; + item_selected = 1; + item_default = 1; + actions = confirm_action(`reboot', 0); + }; + safe = { + pos_x = 0; // use M4 macros + pos_y = 480; // use M4 macros + style = "common"; + item_selected = 1; + item_default = 1; + actions = confirm_action(`safeboot', 1); + }; + factory = { + pos_x = 0; // use M4 macros + pos_y = 480; // use M4 macros + style = "common"; + item_selected = 1; + item_default = 1; + actions = ({ + label = "Yes"; + screen_switch_to = "factory-run"; + action_handler = "factory-reset"; + exit_after_action = 1; + },{ + label = "No"; + screen_switch_to = "BACK"; + }); + }; +}; + +descriptions = { + main = { + pos_x = 15; + pos_y = 480; + style = "common"; + title = "Controls:"; + text = "Volume Up/Down to move menu cursor\n" + "Power button to select"; + }; + + reboot = { + pos_x = 15; + pos_y = 100; + title = "The phone will be restarted."; + text = "Continue?"; + style = "common"; + }; + + safe = { + pos_x = 15; + pos_y = 100; + title = "Safe mode:", + text = "The phone will be started in safe mode.\n" + "Home screen will be changed to default\n" + "setting and just allow a user to use\n" + "only preloaded applications.\n" + "Continue?"; + style = "common"; + }; + + factory = { + pos_x = 15; + pos_y = 100; + title = "Factory reset (except SD-card)"; + text = "This will erase all data from your\n" + "phone's internal storage, including\n" + "settings of downloaded and preloaded\n" + "applications and system configuration.\n" + "Continue?"; + style = "common"; + }; + + factory-run = { + pos_x = 15; + pos_y = 100; + style = "common"; + title = "Restoring settings to factory default."; + text = "Please wait. Do not turn off.\n" + "(Hold power button for 3 seconds\n" + "to reboot the device. Not recommended.)"; + } +}; + +screens = { + main = { + style = "common"; + menu = "main"; + rulers = "main"; + description = "main"; + // progress_bar = ; + images = ("background_default", "menu_title"); + // animations = ; + // on_enter = ; + // draw = ; + screen_back = "CURRENT"; + }; + reboot = { + style = "common"; + menu = "reboot"; + description = "reboot" + rulers = "confirm" ; + // progress_bar = ; + images = ("background_default", "menu_title"); + // animations = ; + // on_enter = ; + // draw = ; + screen_back = "main"; + }; + safe = { + style = "common"; + menu = "safe"; + description = "safe"; + rulers = "confirm"; + // progress_bar = ; + images = ("background_default", "menu_title"); + // animations = ; + // on_enter = ; + // draw = ; + screen_back = "main"; + }; + factory = { + style = "common"; + menu = "factory"; + description = "factory"; + rulers = "confirm"; + // progress_bar = ; + images = ("background_default", "menu_title"); + // animations = ; + // on_enter = ; + // draw = ; + screen_back = "main"; + }; + factory-run = { + style = "common"; + description = "factory-run"; + rulers = "confirm"; + images = ("background_default", "menu_title"); + animations = ("working"); + screen_back = "main"; + allow_force_reboot = 1; + }; +}; diff --git a/src/system-recovery/system-recovery.h b/src/system-recovery/system-recovery.h new file mode 100644 index 0000000..b75ade8 --- /dev/null +++ b/src/system-recovery/system-recovery.h @@ -0,0 +1,46 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define LOGD printf +#define FILE_IO_BUF_SIZE 128 + +#define ROOT_MOUNT_DIR "/system" +#define INITRD_MOUNT_DIR "/system/mnt/initrd-recovery" + +int pivot_root(const char *new_root, const char *put_old); + +void sys_power_reboot(void); + +int recovery_gui(config_t *cfg); +int recovery_headless(config_t *cfg); +char *get_action_from_cmdline(void); +char *get_action_from_file(void); + +#ifdef __cplusplus +} +#endif