Merge pull request #15 from hkfuertes/mifi_smb1360
Add Device MF68E With Display
This commit is contained in:
25 files changed
+1466
-20
No files matched your search
@@ -0,0 +1,97 @@
|
||||
name: OpenWrt Builder (MF68E)
|
||||
on:
|
||||
repository_dispatch:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
UPLOAD_BIN_DIR: true
|
||||
UPLOAD_FIRMWARE: true
|
||||
UPLOAD_RELEASE: false
|
||||
TZ: Europe/Madrid
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Initialization environment
|
||||
env:
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
run: |
|
||||
sudo rm -rf /etc/apt/sources.list.d/* /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL
|
||||
sudo docker image prune --all --force
|
||||
sudo -E apt-get -qq update
|
||||
sudo -E ./devenv/dependencies.sh
|
||||
sudo -E apt-get -qq autoremove --purge
|
||||
sudo -E apt-get -qq clean
|
||||
sudo timedatectl set-timezone "$TZ"
|
||||
|
||||
- name: "Clone OpenWrt source code"
|
||||
run: |
|
||||
df -hT $PWD
|
||||
git clone --depth=1 --branch "main" https://git.openwrt.org/openwrt/openwrt.git openwrt
|
||||
|
||||
- name: Load msm89xx target and uz801 packages
|
||||
run: |
|
||||
git apply --unsafe-paths enable_wcn36xx_mac80211.patch
|
||||
mv msm89xx openwrt/target/linux/msm89xx
|
||||
mv packages openwrt/package/uz801
|
||||
if [ "${{ inputs.openwrt_version }}" == "openwrt-24.10" ]; then
|
||||
sed -i '/^KERNEL_PATCHVER/c\KERNEL_PATCHVER:=6.6' openwrt/target/linux/msm89xx/Makefile
|
||||
fi
|
||||
|
||||
- name: Update and install feeds
|
||||
run: |
|
||||
cd openwrt
|
||||
rm -rf tmp
|
||||
./scripts/feeds update -a
|
||||
./scripts/feeds install -a
|
||||
|
||||
- name: "Load diffconfig"
|
||||
run: |
|
||||
[ -f mf68e_diffconfig ] && mv mf68e_diffconfig openwrt/.config
|
||||
|
||||
- name: Download package
|
||||
id: package
|
||||
run: |
|
||||
cd openwrt
|
||||
make defconfig
|
||||
make download -j8
|
||||
find dl -size -1024c -exec ls -l {} \; || true
|
||||
find dl -size -1024c -exec rm -f {} \; || true
|
||||
|
||||
- name: Compile the firmware
|
||||
id: compile
|
||||
run: |
|
||||
cd openwrt
|
||||
echo -e "$(nproc) thread compile"
|
||||
make -j$(nproc) || make -j1 || make -j1 V=s
|
||||
echo "status=success" >> $GITHUB_OUTPUT
|
||||
grep '^CONFIG_TARGET.*DEVICE.*=y' .config | sed -r 's/.*DEVICE_(.*)=y/\1/' > DEVICE_NAME
|
||||
[ -s DEVICE_NAME ] && echo "DEVICE_NAME=$(cat DEVICE_NAME)" >> $GITHUB_ENV
|
||||
echo "FILE_DATE=$(date +"%Y%m%d%H%M")" >> $GITHUB_ENV
|
||||
|
||||
- name: Organize files
|
||||
id: organize
|
||||
if: env.UPLOAD_FIRMWARE == 'true' && !cancelled()
|
||||
run: |
|
||||
cd openwrt/bin/targets/*/*
|
||||
rm -rf packages
|
||||
echo "FIRMWARE=$PWD" >> $GITHUB_ENV
|
||||
echo "status=success" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Upload firmware
|
||||
uses: actions/upload-artifact@v4
|
||||
if: steps.organize.outputs.status == 'success' && !cancelled()
|
||||
with:
|
||||
name: openwrt_firmware_${{ env.DEVICE_NAME }}_${{ env.FILE_DATE }}
|
||||
path: |
|
||||
${{ env.FIRMWARE }}/openwrt-msm89xx-msm8916-yiming-uz801v3-squashfs-gpt_both0.bin
|
||||
${{ env.FIRMWARE }}/openwrt-msm89xx-msm8916-yiming-uz801v3-squashfs-boot.img
|
||||
${{ env.FIRMWARE }}/openwrt-msm89xx-msm8916-yiming-uz801v3-squashfs-system.img
|
||||
${{ env.FIRMWARE }}/openwrt-msm89xx-msm8916-yiming-uz801v3.manifest
|
||||
${{ env.FIRMWARE }}/openwrt-msm89xx-msm8916-yiming-uz801v3-flash.sh
|
||||
${{ env.FIRMWARE }}/openwrt-msm89xx-msm8916-yiming-uz801v3-firmware.zip
|
||||
@@ -1,4 +1,4 @@
|
||||
name: OpenWrt Builder
|
||||
name: OpenWrt Builder (UZ801)
|
||||
on:
|
||||
repository_dispatch:
|
||||
workflow_dispatch:
|
||||
@@ -22,7 +22,6 @@ CONFIG_PACKAGE_kmod-tun=y
|
||||
CONFIG_PACKAGE_kmod-udptunnel4=y
|
||||
CONFIG_PACKAGE_kmod-udptunnel6=y
|
||||
CONFIG_PACKAGE_kmod-wireguard=y
|
||||
CONFIG_PACKAGE_ledcontrol=y
|
||||
CONFIG_PACKAGE_libattr=y
|
||||
CONFIG_PACKAGE_libdbus=y
|
||||
CONFIG_PACKAGE_libexpat=y
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
CONFIG_TARGET_msm89xx=y
|
||||
CONFIG_TARGET_msm89xx_msm8916=y
|
||||
CONFIG_TARGET_msm89xx_msm8916_DEVICE_generic-mf68e=y
|
||||
CONFIG_BUSYBOX_CUSTOM=y
|
||||
CONFIG_BUSYBOX_CONFIG_FBSET=y
|
||||
CONFIG_BUSYBOX_CONFIG_USLEEP=y
|
||||
CONFIG_LIBQMI_COLLECTION_BASIC=y
|
||||
CONFIG_LIBQMI_WITH_MBIM_QMUX=y
|
||||
CONFIG_LIBQMI_WITH_QRTR_GLIB=y
|
||||
CONFIG_MODEMMANAGER_WITH_MBIM=y
|
||||
CONFIG_MODEMMANAGER_WITH_NETIFD=y
|
||||
CONFIG_MODEMMANAGER_WITH_QMI=y
|
||||
CONFIG_MODEMMANAGER_WITH_QRTR=y
|
||||
CONFIG_PACKAGE_bash=y
|
||||
CONFIG_PACKAGE_cgi-io=y
|
||||
CONFIG_PACKAGE_dbus=y
|
||||
CONFIG_PACKAGE_glib2=y
|
||||
CONFIG_PACKAGE_ip-tiny=y
|
||||
CONFIG_PACKAGE_kmod-crypto-kpp=y
|
||||
CONFIG_PACKAGE_kmod-crypto-lib-chacha20=y
|
||||
CONFIG_PACKAGE_kmod-crypto-lib-chacha20poly1305=y
|
||||
CONFIG_PACKAGE_kmod-crypto-lib-curve25519=y
|
||||
CONFIG_PACKAGE_kmod-crypto-lib-poly1305=y
|
||||
CONFIG_PACKAGE_kmod-tun=y
|
||||
CONFIG_PACKAGE_kmod-udptunnel4=y
|
||||
CONFIG_PACKAGE_kmod-udptunnel6=y
|
||||
CONFIG_PACKAGE_kmod-wireguard=y
|
||||
CONFIG_PACKAGE_libattr=y
|
||||
CONFIG_PACKAGE_libdbus=y
|
||||
CONFIG_PACKAGE_libexpat=y
|
||||
CONFIG_PACKAGE_libfdisk=y
|
||||
CONFIG_PACKAGE_libffi=y
|
||||
CONFIG_PACKAGE_libiwinfo=y
|
||||
CONFIG_PACKAGE_libiwinfo-data=y
|
||||
CONFIG_PACKAGE_liblua=y
|
||||
CONFIG_PACKAGE_liblucihttp=y
|
||||
CONFIG_PACKAGE_liblucihttp-lua=y
|
||||
CONFIG_PACKAGE_liblucihttp-ucode=y
|
||||
CONFIG_PACKAGE_libmbim=y
|
||||
CONFIG_PACKAGE_libmount=y
|
||||
CONFIG_PACKAGE_libncurses=y
|
||||
CONFIG_PACKAGE_libpcre2=y
|
||||
CONFIG_PACKAGE_libqmi=y
|
||||
CONFIG_PACKAGE_libqrtr-glib=y
|
||||
CONFIG_PACKAGE_libreadline=y
|
||||
CONFIG_PACKAGE_libubus-lua=y
|
||||
CONFIG_PACKAGE_lsblk=y
|
||||
CONFIG_PACKAGE_lua=y
|
||||
CONFIG_PACKAGE_luci=y
|
||||
CONFIG_PACKAGE_luci-app-firewall=y
|
||||
CONFIG_PACKAGE_luci-app-package-manager=y
|
||||
CONFIG_PACKAGE_luci-app-usb-gadget=y
|
||||
CONFIG_PACKAGE_luci-base=y
|
||||
CONFIG_PACKAGE_luci-lib-base=y
|
||||
CONFIG_PACKAGE_luci-lib-ip=y
|
||||
CONFIG_PACKAGE_luci-lib-json=y
|
||||
CONFIG_PACKAGE_luci-lib-jsonc=y
|
||||
CONFIG_PACKAGE_luci-lib-nixio=y
|
||||
CONFIG_PACKAGE_luci-lib-uqr=y
|
||||
CONFIG_PACKAGE_luci-light=y
|
||||
CONFIG_PACKAGE_luci-lua-runtime=y
|
||||
CONFIG_PACKAGE_luci-mod-admin-full=y
|
||||
CONFIG_PACKAGE_luci-mod-network=y
|
||||
CONFIG_PACKAGE_luci-mod-rpc=y
|
||||
CONFIG_PACKAGE_luci-mod-status=y
|
||||
CONFIG_PACKAGE_luci-mod-system=y
|
||||
CONFIG_PACKAGE_luci-proto-ipv6=y
|
||||
CONFIG_PACKAGE_luci-proto-modemmanager=y
|
||||
CONFIG_PACKAGE_luci-proto-ppp=y
|
||||
CONFIG_PACKAGE_luci-proto-wireguard=y
|
||||
CONFIG_PACKAGE_luci-theme-bootstrap=y
|
||||
CONFIG_PACKAGE_modemmanager=y
|
||||
CONFIG_PACKAGE_mount-utils=y
|
||||
CONFIG_PACKAGE_mtools=y
|
||||
CONFIG_PACKAGE_nano=y
|
||||
CONFIG_PACKAGE_resize2fs=y
|
||||
CONFIG_PACKAGE_resolveip=y
|
||||
CONFIG_PACKAGE_rpcd=y
|
||||
CONFIG_PACKAGE_rpcd-mod-file=y
|
||||
CONFIG_PACKAGE_rpcd-mod-iwinfo=y
|
||||
CONFIG_PACKAGE_rpcd-mod-luci=y
|
||||
CONFIG_PACKAGE_rpcd-mod-rrdns=y
|
||||
CONFIG_PACKAGE_rpcd-mod-ucode=y
|
||||
CONFIG_PACKAGE_sfdisk=y
|
||||
CONFIG_PACKAGE_terminfo=y
|
||||
CONFIG_PACKAGE_tune2fs=y
|
||||
CONFIG_PACKAGE_ucode-mod-html=y
|
||||
CONFIG_PACKAGE_ucode-mod-log=y
|
||||
CONFIG_PACKAGE_ucode-mod-lua=y
|
||||
CONFIG_PACKAGE_ucode-mod-math=y
|
||||
CONFIG_PACKAGE_uhttpd=y
|
||||
CONFIG_PACKAGE_uhttpd-mod-ubus=y
|
||||
CONFIG_PACKAGE_wireguard-tools=y
|
||||
# CONFIG_TARGET_ROOTFS_EXT4FS is not set
|
||||
+20
-12
@@ -1,4 +1,5 @@
|
||||
|
||||
|
||||
# CONFIG_ARM_MHU_V2 is not set
|
||||
# CONFIG_ARM_MHU_V3 is not set
|
||||
# CONFIG_ARM_QCOM_CPUFREQ_HW is not set
|
||||
@@ -22,6 +23,7 @@
|
||||
# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set
|
||||
# CONFIG_CMA_SYSFS is not set
|
||||
# CONFIG_COMPAT_ALIGNMENT_FIXUPS is not set
|
||||
# CONFIG_CONSOLE_TRANSLATIONS is not set
|
||||
# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
|
||||
# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
|
||||
# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
|
||||
@@ -35,9 +37,13 @@
|
||||
# CONFIG_DEVFREQ_GOV_POWERSAVE is not set
|
||||
# CONFIG_DEVFREQ_GOV_USERSPACE is not set
|
||||
# CONFIG_DEVFREQ_THERMAL is not set
|
||||
# CONFIG_DRM_MSM is not set
|
||||
# CONFIG_DUMMY_CONSOLE is not set
|
||||
# CONFIG_EC_ACER_ASPIRE1 is not set
|
||||
# CONFIG_EXPERT is not set
|
||||
# CONFIG_FIPS_SIGNATURE_SELFTEST is not set
|
||||
# CONFIG_FORTIFY_SOURCE is not set
|
||||
# CONFIG_FRAMEBUFFER_CONSOLE is not set
|
||||
# CONFIG_FW_LOADER_USER_HELPER is not set
|
||||
# CONFIG_GCC_PLUGIN_LATENT_ENTROPY is not set
|
||||
# CONFIG_GCC_PLUGIN_STACKLEAK is not set
|
||||
@@ -69,6 +75,7 @@
|
||||
# CONFIG_KPSS_XCC is not set
|
||||
# CONFIG_LEDS_BRIGHTNESS_HW_CHANGED is not set
|
||||
# CONFIG_LEDS_TRIGGER_NETDEV is not set
|
||||
# CONFIG_LOGO is not set
|
||||
# CONFIG_LWTUNNEL_BPF is not set
|
||||
# CONFIG_MAILBOX_TEST is not set
|
||||
# CONFIG_MFD_HI6421_SPMI is not set
|
||||
@@ -260,6 +267,9 @@
|
||||
# CONFIG_VIRTIO_IOMMU is not set
|
||||
# CONFIG_VIRTIO_MENU is not set
|
||||
# CONFIG_VIRTIO_NET is not set
|
||||
# CONFIG_VT is not set
|
||||
# CONFIG_VT_CONSOLE is not set
|
||||
# CONFIG_VT_HW_CONSOLE_BINDING is not set
|
||||
CONFIG_64BIT=y
|
||||
CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y
|
||||
CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y
|
||||
@@ -323,7 +333,10 @@ CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
|
||||
CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y
|
||||
CONFIG_AUTOFS_FS=y
|
||||
CONFIG_BACKLIGHT_CLASS_DEVICE=y
|
||||
CONFIG_BACKLIGHT_GPIO=y
|
||||
CONFIG_BACKLIGHT_PWM=y
|
||||
CONFIG_BATTERY_PM8916_BMS_VM=y
|
||||
CONFIG_BATTERY_PM8916_BMS=y
|
||||
CONFIG_BLK_DEBUG_FS=y
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
@@ -342,6 +355,7 @@ CONFIG_BUILTIN_RETURN_ADDRESS_STRIPS_PAC=y
|
||||
CONFIG_CACHESTAT_SYSCALL=y
|
||||
CONFIG_CC_HAVE_SHADOW_CALL_STACK=y
|
||||
CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y
|
||||
CONFIG_CHARGER_PM8916_LBC=y
|
||||
CONFIG_CLONE_BACKWARDS=y
|
||||
CONFIG_CLZ_TAB=y
|
||||
CONFIG_CMA_ALIGNMENT=8
|
||||
@@ -357,7 +371,6 @@ CONFIG_COMPAT_BINFMT_ELF=y
|
||||
CONFIG_COMPAT_OLD_SIGACTION=y
|
||||
CONFIG_COMPAT=y
|
||||
CONFIG_CONFIGFS_FS=y
|
||||
CONFIG_CONSOLE_TRANSLATIONS=y
|
||||
CONFIG_CONTEXT_TRACKING_IDLE=y
|
||||
CONFIG_CONTEXT_TRACKING=y
|
||||
CONFIG_CONTIG_ALLOC=y
|
||||
@@ -468,7 +481,6 @@ CONFIG_DST_CACHE=y
|
||||
CONFIG_DT_IDLE_GENPD=y
|
||||
CONFIG_DT_IDLE_STATES=y
|
||||
CONFIG_DTC=y
|
||||
CONFIG_DUMMY_CONSOLE=y
|
||||
CONFIG_EDAC_SUPPORT=y
|
||||
CONFIG_ELF_CORE=y
|
||||
CONFIG_EXCLUSIVE_SYSTEM_RAM=y
|
||||
@@ -481,8 +493,12 @@ CONFIG_EXTCON_USB_GPIO=y
|
||||
CONFIG_EXTCON=y
|
||||
CONFIG_FANOTIFY=y
|
||||
CONFIG_FAT_FS=y
|
||||
CONFIG_FB_CFB_COPYAREA=y
|
||||
CONFIG_FB_CFB_FILLRECT=y
|
||||
CONFIG_FB_CFB_IMAGEBLIT=y
|
||||
CONFIG_FB_CORE=y
|
||||
CONFIG_FB=y
|
||||
CONFIG_FB=y
|
||||
CONFIG_FHANDLE=y
|
||||
CONFIG_FIX_EARLYCON_MEM=y
|
||||
CONFIG_FIXED_PHY=y
|
||||
@@ -490,9 +506,6 @@ CONFIG_FONT_8x16=y
|
||||
CONFIG_FONT_8x8=y
|
||||
CONFIG_FONT_SUPPORT=y
|
||||
CONFIG_FRAME_POINTER=y
|
||||
CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
|
||||
CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
|
||||
CONFIG_FRAMEBUFFER_CONSOLE=y
|
||||
CONFIG_FS_IOMAP=y
|
||||
CONFIG_FS_MBCACHE=y
|
||||
CONFIG_FS_POSIX_ACL=y
|
||||
@@ -632,10 +645,6 @@ CONFIG_LOCALVERSION_AUTO=y
|
||||
CONFIG_LOCALVERSION="-msm8916"
|
||||
CONFIG_LOCK_DEBUGGING_SUPPORT=y
|
||||
CONFIG_LOCK_SPIN_ON_OWNER=y
|
||||
CONFIG_LOGO_LINUX_CLUT224=y
|
||||
CONFIG_LOGO_LINUX_MONO=y
|
||||
CONFIG_LOGO_LINUX_VGA16=y
|
||||
CONFIG_LOGO=y
|
||||
CONFIG_LRU_GEN_WALKS_MMU=y
|
||||
CONFIG_LSM="landlock,lockdown,yama,loadpin,safesetid,integrity,bpf"
|
||||
CONFIG_LWTUNNEL=y
|
||||
@@ -710,6 +719,7 @@ CONFIG_OF_DYNAMIC=y
|
||||
CONFIG_OF_EARLY_FLATTREE=y
|
||||
CONFIG_OF_FLATTREE=y
|
||||
CONFIG_OF_GPIO=y
|
||||
CONFIG_OF_GRAPH=y
|
||||
CONFIG_OF_IOMMU=y
|
||||
CONFIG_OF_IRQ=y
|
||||
CONFIG_OF_KOBJ=y
|
||||
@@ -959,15 +969,13 @@ CONFIG_UTS_NS=y
|
||||
CONFIG_VDSO_GETRANDOM=y
|
||||
CONFIG_VFAT_FS=y
|
||||
CONFIG_VIDEO=y
|
||||
CONFIG_VIDEOMODE_HELPERS=y
|
||||
CONFIG_VIRTIO_ANCHOR=y
|
||||
CONFIG_VIRTIO=y
|
||||
CONFIG_VLAN_8021Q_GVRP=y
|
||||
CONFIG_VLAN_8021Q_MVRP=y
|
||||
CONFIG_VM_EVENT_COUNTERS=y
|
||||
CONFIG_VMAP_STACK=y
|
||||
CONFIG_VT_CONSOLE=y
|
||||
CONFIG_VT_HW_CONSOLE_BINDING=y
|
||||
CONFIG_VT=y
|
||||
CONFIG_WANT_DEV_COREDUMP=y
|
||||
CONFIG_WATCHDOG_CORE=y
|
||||
CONFIG_WATCHDOG_SYSFS=y
|
||||
|
||||
@@ -35,8 +35,20 @@ define Device/yiming-uz801v3
|
||||
FILESYSTEMS := squashfs
|
||||
DEVICE_PACKAGES := configs-uz801 wpad-basic-wolfssl rmtfs uci-usb-gadget \
|
||||
block-mount f2fs-tools prepare-rootfs-data \
|
||||
msm-firmware-dumper
|
||||
msm-firmware-dumper ledcontrol
|
||||
endef
|
||||
TARGET_DEVICES += yiming-uz801v3
|
||||
|
||||
define Device/generic-mf68e
|
||||
$(Device/msm8916)
|
||||
DEVICE_VENDOR := Generic
|
||||
DEVICE_MODEL := MF68E
|
||||
FILESYSTEMS := squashfs
|
||||
CMDLINE := "earlycon console=ttyMSM0,115200 quiet loglevel=0 vt.global_cursor_default=0 vt.cur_default=0 root=/dev/mmcblk0p14 rootfstype=squashfs rootwait"
|
||||
DEVICE_PACKAGES := configs-mf68e wpad-basic-wolfssl rmtfs uci-usb-gadget \
|
||||
block-mount f2fs-tools prepare-rootfs-data \
|
||||
msm-firmware-dumper kmod-fbtft-gc9107 router-display
|
||||
endef
|
||||
TARGET_DEVICES += generic-mf68e
|
||||
|
||||
endif
|
||||
@@ -0,0 +1,21 @@
|
||||
From: hkfuertes <hkfuertes@example.com>
|
||||
Date: Sat, 11 Oct 2025 11:49:00 +0200
|
||||
Subject: [PATCH] arm64: dts: qcom: Add MF68E to Makefile
|
||||
|
||||
Add msm8916-generic-mf68e.dtb to Makefile.
|
||||
|
||||
Signed-off-by: hkfuertes <hkfuertes@example.com>
|
||||
---
|
||||
arch/arm64/boot/dts/qcom/Makefile | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/arch/arm64/boot/dts/qcom/Makefile
|
||||
+++ b/arch/arm64/boot/dts/qcom/Makefile
|
||||
@@ -23,6 +23,7 @@ dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsu
|
||||
dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-gt58.dtb
|
||||
dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-j3ltetw.dtb
|
||||
dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-j5.dtb
|
||||
+dtb-$(CONFIG_ARCH_QCOM) += msm8916-generic-mf68e.dtb
|
||||
dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-j5x.dtb
|
||||
dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-rossa.dtb
|
||||
dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-serranove.dtb
|
||||
@@ -0,0 +1,168 @@
|
||||
--- /dev/null
|
||||
+++ b/arch/arm64/boot/dts/qcom/msm8916-generic-mf68e.dts
|
||||
@@ -0,0 +1,165 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+
|
||||
+/dts-v1/;
|
||||
+
|
||||
+#include "msm8916-ufi.dtsi"
|
||||
+#include <dt-bindings/gpio/gpio.h>
|
||||
+#include <dt-bindings/pinctrl/qcom,pmic-mpp.h>
|
||||
+#include <dt-bindings/pwm/pwm.h>
|
||||
+
|
||||
+/ {
|
||||
+ model = "MF68E 4G LTE Mobile WiFi Router";
|
||||
+ compatible = "generic,mf68e", "qcom,msm8916";
|
||||
+
|
||||
+ bat: battery {
|
||||
+ compatible = "simple-battery";
|
||||
+ voltage-min-design-microvolt = <3400000>;
|
||||
+ voltage-max-design-microvolt = <4350000>;
|
||||
+ energy-full-design-microwatt-hours = <11100000>;
|
||||
+ charge-full-design-microamp-hours = <3000000>;
|
||||
+
|
||||
+ ocv-capacity-celsius = <25>;
|
||||
+ ocv-capacity-table-0 = <4330000 100>, <4265000 95>,
|
||||
+ <4208000 90>, <4154000 85>, <4102000 80>,
|
||||
+ <4063000 75>, <4006000 70>, <3972000 65>,
|
||||
+ <3931000 60>, <3880000 55>, <3841000 50>,
|
||||
+ <3817000 45>, <3798000 40>, <3783000 35>,
|
||||
+ <3767000 30>, <3747000 25>, <3729000 20>,
|
||||
+ <3700000 16>, <3687000 13>, <3683000 11>,
|
||||
+ <3681000 10>, <3680000 9>, <3678000 8>,
|
||||
+ <3674000 7>, <3666000 6>, <3641000 5>,
|
||||
+ <3597000 4>, <3537000 3>, <3457000 2>,
|
||||
+ <3336000 1>, <3000000 0>;
|
||||
+ };
|
||||
+
|
||||
+ usb_id: usb-id {
|
||||
+ compatible = "linux,extcon-usb-gpio";
|
||||
+ id-gpios = <&tlmm 110 GPIO_ACTIVE_HIGH>;
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&usb_id_default>;
|
||||
+ };
|
||||
+
|
||||
+ backlight: backlight {
|
||||
+ compatible = "pwm-backlight";
|
||||
+ pwms = <&pm8916_pwm 0 100000>;
|
||||
+ brightness-levels = <255 128 64 32 16 8 4 0>;
|
||||
+ num-interpolated-steps = <255>;
|
||||
+ default-brightness-level = <6>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
+/* GC9107 Panel on SPI5 (0x78b9000) */
|
||||
+&blsp_spi5 {
|
||||
+ status = "okay";
|
||||
+
|
||||
+ pinctrl-names = "default", "sleep";
|
||||
+ pinctrl-0 = <&spi5_default>;
|
||||
+ pinctrl-1 = <&spi5_sleep>;
|
||||
+
|
||||
+ panel@0 {
|
||||
+ compatible = "galaxycore,gc9107";
|
||||
+ reg = <0>;
|
||||
+ spi-max-frequency = <16000000>;
|
||||
+
|
||||
+ reset-gpios = <&tlmm 11 GPIO_ACTIVE_LOW>;
|
||||
+ dc-gpios = <&tlmm 30 GPIO_ACTIVE_HIGH>;
|
||||
+ backlight = <&backlight>;
|
||||
+
|
||||
+ vdd-supply = <&pm8916_l17>;
|
||||
+ vddio-supply = <&pm8916_l6>;
|
||||
+
|
||||
+ width-mm = <23>;
|
||||
+ height-mm = <23>;
|
||||
+
|
||||
+ buswidth = <8>;
|
||||
+ width = <128>;
|
||||
+ height = <128>;
|
||||
+ rotate = <0>;
|
||||
+ bgr;
|
||||
+ fps = <27>;
|
||||
+ debug = <1>;
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
+&pm8916_l6 {
|
||||
+ regulator-always-on;
|
||||
+};
|
||||
+
|
||||
+&pm8916_l13 {
|
||||
+ regulator-boot-on;
|
||||
+ regulator-allow-set-load;
|
||||
+};
|
||||
+
|
||||
+&pm8916_rpm_regulators {
|
||||
+ pm8916_l17: l17 {
|
||||
+ regulator-min-microvolt = <2850000>;
|
||||
+ regulator-max-microvolt = <2850000>;
|
||||
+ regulator-always-on;
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
+&pm8916_pwm {
|
||||
+ status = "okay";
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&pwm_out>;
|
||||
+};
|
||||
+
|
||||
+&pm8916_mpps {
|
||||
+ pwm_out: mpp4-state {
|
||||
+ pins = "mpp4";
|
||||
+ function = "digital";
|
||||
+ output-low;
|
||||
+ qcom,dtest = <1>;
|
||||
+ power-source = <PM8916_MPP_VPH>;
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
+&pm8916_bms {
|
||||
+ status = "okay";
|
||||
+ monitored-battery = <&bat>;
|
||||
+ power-supplies = <&pm8916_charger>;
|
||||
+};
|
||||
+
|
||||
+&pm8916_charger {
|
||||
+ status = "okay";
|
||||
+ monitored-battery = <&bat>;
|
||||
+ qcom,fast-charge-safe-current = <900000>;
|
||||
+ qcom,fast-charge-safe-voltage = <4350000>;
|
||||
+};
|
||||
+
|
||||
+&usb {
|
||||
+ status = "okay";
|
||||
+ extcon = <&usb_id>, <&usb_id>;
|
||||
+};
|
||||
+
|
||||
+&usb_hs_phy {
|
||||
+ extcon = <&usb_id>;
|
||||
+};
|
||||
+
|
||||
+&sdhc_1 {
|
||||
+ status = "okay";
|
||||
+};
|
||||
+
|
||||
+&tlmm {
|
||||
+ spi5_default: spi5-default-state {
|
||||
+ pins = "gpio16", "gpio17", "gpio19";
|
||||
+ function = "blsp_spi5";
|
||||
+ drive-strength = <12>;
|
||||
+ bias-disable;
|
||||
+ };
|
||||
+
|
||||
+ spi5_sleep: spi5-sleep-state {
|
||||
+ pins = "gpio16", "gpio17", "gpio19";
|
||||
+ function = "gpio";
|
||||
+ drive-strength = <2>;
|
||||
+ bias-pull-down;
|
||||
+ };
|
||||
+
|
||||
+ usb_id_default: usb-id-default-state {
|
||||
+ pins = "gpio110";
|
||||
+ function = "gpio";
|
||||
+ drive-strength = <8>;
|
||||
+ bias-pull-up;
|
||||
+ };
|
||||
+};
|
||||
@@ -0,0 +1,218 @@
|
||||
--- /dev/null
|
||||
+++ b/drivers/staging/fbtft/fb_gc9107.c
|
||||
@@ -0,0 +1,191 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0+
|
||||
+/*
|
||||
+ * FB driver for the GC9107 LCD Controller
|
||||
+ *
|
||||
+ * Copyright (C) 2025
|
||||
+ * Based on:
|
||||
+ * - Espressif ESP-IDF GC9107 driver (esp_lcd_gc9107.c)
|
||||
+ * - Craig Bishop init sequence
|
||||
+ * - Android MSM8916 MF68E device
|
||||
+ */
|
||||
+
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/delay.h>
|
||||
+
|
||||
+#include "fbtft.h"
|
||||
+
|
||||
+#define DRVNAME "fb_gc9107"
|
||||
+#define WIDTH 128
|
||||
+#define HEIGHT 128
|
||||
+#define BPP 16
|
||||
+
|
||||
+/* GC9107 Commands */
|
||||
+#define GC9107_SWRESET 0x01
|
||||
+#define GC9107_SLPOUT 0x11
|
||||
+#define GC9107_INVON 0x21
|
||||
+#define GC9107_INVOFF 0x20
|
||||
+#define GC9107_DISPOFF 0x28
|
||||
+#define GC9107_DISPON 0x29
|
||||
+#define GC9107_CASET 0x2A
|
||||
+#define GC9107_RASET 0x2B
|
||||
+#define GC9107_RAMWR 0x2C
|
||||
+#define GC9107_MADCTL 0x36
|
||||
+#define GC9107_COLMOD 0x3A
|
||||
+
|
||||
+/*
|
||||
+ * Init sequence from Espressif ESP-IDF driver
|
||||
+ * Includes proper gamma, power control, and timing
|
||||
+ */
|
||||
+static int init_display(struct fbtft_par *par)
|
||||
+{
|
||||
+ par->fbtftops.reset(par);
|
||||
+ mdelay(120);
|
||||
+
|
||||
+ /* Frame Rate Control */
|
||||
+ write_reg(par, 0xB0, 0xC0);
|
||||
+
|
||||
+ /* Porch Control */
|
||||
+ write_reg(par, 0xB2, 0x2F);
|
||||
+ write_reg(par, 0xB3, 0x03);
|
||||
+
|
||||
+ /* Display Function Control */
|
||||
+ write_reg(par, 0xB6, 0x19);
|
||||
+ write_reg(par, 0xB7, 0x01);
|
||||
+
|
||||
+ /* Power Control Settings */
|
||||
+ write_reg(par, 0xAC, 0xCB);
|
||||
+ write_reg(par, 0xAB, 0x0E);
|
||||
+ write_reg(par, 0xB4, 0x04);
|
||||
+
|
||||
+ /* Internal Register */
|
||||
+ write_reg(par, 0xA8, 0x19);
|
||||
+ write_reg(par, 0xB8, 0x08);
|
||||
+
|
||||
+ /* Tesla Control */
|
||||
+ write_reg(par, 0xE8, 0x24);
|
||||
+ write_reg(par, 0xE9, 0x48);
|
||||
+ write_reg(par, 0xEA, 0x22);
|
||||
+
|
||||
+ /* Interface Control */
|
||||
+ write_reg(par, 0xC6, 0x30);
|
||||
+ write_reg(par, 0xC7, 0x18);
|
||||
+
|
||||
+ /* Positive Gamma Control */
|
||||
+ write_reg(par, 0xF0,
|
||||
+ 0x1F, 0x28, 0x04, 0x3E, 0x2A, 0x2E, 0x20,
|
||||
+ 0x00, 0x0C, 0x06, 0x00, 0x1C, 0x1F, 0x0F);
|
||||
+
|
||||
+ /* Negative Gamma Control */
|
||||
+ write_reg(par, 0xF1,
|
||||
+ 0x00, 0x2D, 0x2F, 0x3C, 0x6F, 0x1C, 0x0B,
|
||||
+ 0x00, 0x00, 0x00, 0x07, 0x0D, 0x11, 0x0F);
|
||||
+
|
||||
+ /* Tearing Effect Line ON */
|
||||
+ write_reg(par, 0x35, 0x00);
|
||||
+
|
||||
+ /* Pixel Format: RGB565 (16 bits/pixel) */
|
||||
+ write_reg(par, GC9107_COLMOD, 0x55);
|
||||
+
|
||||
+ /* Display Inversion OFF - looks bad with INVON */
|
||||
+ write_reg(par, GC9107_INVOFF);
|
||||
+
|
||||
+ /* Sleep Out */
|
||||
+ write_reg(par, GC9107_SLPOUT);
|
||||
+ mdelay(120);
|
||||
+
|
||||
+ /* Display ON */
|
||||
+ write_reg(par, GC9107_DISPON);
|
||||
+ mdelay(20);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Set address window with proper offsets for GC9107
|
||||
+ * GC9107 GRAM is 132x130, but display is 128x128
|
||||
+ * Requires COL_OFFSET=2, ROW_OFFSET=1
|
||||
+ */
|
||||
+static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
|
||||
+{
|
||||
+ /* GC9107 specific offsets */
|
||||
+ const int col_offset = 2;
|
||||
+ const int row_offset = 1;
|
||||
+
|
||||
+ /* Column Address Set */
|
||||
+ write_reg(par, GC9107_CASET,
|
||||
+ (xs + col_offset) >> 8,
|
||||
+ (xs + col_offset) & 0xFF,
|
||||
+ (xe + col_offset) >> 8,
|
||||
+ (xe + col_offset) & 0xFF);
|
||||
+
|
||||
+ /* Row Address Set */
|
||||
+ write_reg(par, GC9107_RASET,
|
||||
+ (ys + row_offset) >> 8,
|
||||
+ (ys + row_offset) & 0xFF,
|
||||
+ (ye + row_offset) >> 8,
|
||||
+ (ye + row_offset) & 0xFF);
|
||||
+
|
||||
+ /* Memory Write */
|
||||
+ write_reg(par, GC9107_RAMWR);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Memory Data Access Control (MADCTL)
|
||||
+ * Controls rotation and BGR mode
|
||||
+ */
|
||||
+static int set_var(struct fbtft_par *par)
|
||||
+{
|
||||
+ u8 madctl = 0;
|
||||
+
|
||||
+ /* Rotation */
|
||||
+ switch (par->info->var.rotate) {
|
||||
+ case 0:
|
||||
+ madctl = 0x00;
|
||||
+ break;
|
||||
+ case 90:
|
||||
+ madctl = 0x60; /* MV | MX */
|
||||
+ break;
|
||||
+ case 180:
|
||||
+ madctl = 0xC0; /* MY | MX */
|
||||
+ break;
|
||||
+ case 270:
|
||||
+ madctl = 0xA0; /* MV | MY */
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ /* BGR mode from DTS */
|
||||
+ if (par->bgr)
|
||||
+ madctl |= 0x08;
|
||||
+
|
||||
+ write_reg(par, GC9107_MADCTL, madctl);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct fbtft_display display = {
|
||||
+ .regwidth = 8,
|
||||
+ .width = WIDTH,
|
||||
+ .height = HEIGHT,
|
||||
+ .bpp = BPP,
|
||||
+ .fps = 30,
|
||||
+ .fbtftops = {
|
||||
+ .init_display = init_display,
|
||||
+ .set_addr_win = set_addr_win,
|
||||
+ .set_var = set_var,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+FBTFT_REGISTER_DRIVER(DRVNAME, "galaxycore,gc9107", &display);
|
||||
+
|
||||
+MODULE_ALIAS("spi:" DRVNAME);
|
||||
+MODULE_ALIAS("platform:" DRVNAME);
|
||||
+MODULE_ALIAS("spi:gc9107");
|
||||
+MODULE_ALIAS("platform:gc9107");
|
||||
+
|
||||
+MODULE_DESCRIPTION("FB driver for GC9107 LCD Controller");
|
||||
+MODULE_AUTHOR("Based on Espressif ESP-IDF driver");
|
||||
+MODULE_LICENSE("GPL");
|
||||
--- a/drivers/staging/fbtft/Kconfig
|
||||
+++ b/drivers/staging/fbtft/Kconfig
|
||||
@@ -39,6 +39,12 @@ config FB_TFT_AGM1264K_FL
|
||||
help
|
||||
Generic Framebuffer support for AGM1264K-FL LCD display
|
||||
|
||||
+config FB_TFT_GC9107
|
||||
+ tristate "FB driver for the GC9107 LCD Controller"
|
||||
+ depends on FB_TFT
|
||||
+ help
|
||||
+ Framebuffer support for GalaxyCore GC9107 128x128 LCD
|
||||
+
|
||||
config FB_TFT_BD663474
|
||||
tristate "FB driver for the BD663474 LCD Controller"
|
||||
depends on FB_TFT
|
||||
--- a/drivers/staging/fbtft/Makefile
|
||||
+++ b/drivers/staging/fbtft/Makefile
|
||||
@@ -6,6 +6,7 @@ obj-$(CONFIG_FB_TFT) += fbtft.o
|
||||
fbtft-y += fbtft-core.o fbtft-sysfs.o fbtft-bus.o fbtft-io.o
|
||||
|
||||
obj-$(CONFIG_FB_TFT_AGM1264K_FL) += fb_agm1264k-fl.o
|
||||
+obj-$(CONFIG_FB_TFT_GC9107) += fb_gc9107.o
|
||||
obj-$(CONFIG_FB_TFT_BD663474) += fb_bd663474.o
|
||||
obj-$(CONFIG_FB_TFT_HX8340BN) += fb_hx8340bn.o
|
||||
@@ -0,0 +1,55 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=configs-mf68e
|
||||
PKG_VERSION:=1.0
|
||||
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/$(PKG_NAME)
|
||||
SECTION:=Utilities
|
||||
CATEGORY:=Utilities
|
||||
TITLE:=Default Settings For mf68e
|
||||
DEPENDS:=+PACKAGE_luci:luci-proto-modemmanager
|
||||
endef
|
||||
|
||||
# Optional description
|
||||
define Package/$(PKG_NAME)/description
|
||||
Tweaks and defaults for mf68e, including cleanup of problematic APK feeds and LuCI battery widget.
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
# Install configuration files and payload you already had
|
||||
define Package/$(PKG_NAME)/install
|
||||
$(INSTALL_DIR) $(1)/etc/uci-defaults
|
||||
$(INSTALL_BIN) ./files/uci_defaults $(1)/etc/uci-defaults/99-default-config
|
||||
|
||||
$(INSTALL_DIR) $(1)/root/
|
||||
$(INSTALL_BIN) ./files/luci-app-tailscale*.apk $(1)/root/
|
||||
|
||||
# Battery widget for LuCI
|
||||
$(INSTALL_DIR) $(1)/usr/lib/lua/luci/view/admin_status/index
|
||||
$(INSTALL_DATA) ./files/battery.htm $(1)/usr/lib/lua/luci/view/admin_status/index/20_battery.htm
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/postinst
|
||||
#!/bin/sh
|
||||
set -e
|
||||
FILE="/etc/apk/repositories.d/distfeeds.list"
|
||||
ROOT="$${IPKG_INSTROOT:-/}"
|
||||
TARGET_FILE="$$ROOT$$FILE"
|
||||
|
||||
if [ -f "$$TARGET_FILE" ]; then
|
||||
sed -i '\|/targets/msm89xx/msm8916/packages|d' "$$TARGET_FILE" || true
|
||||
fi
|
||||
|
||||
exit 0
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,$(PKG_NAME)))
|
||||
@@ -0,0 +1,69 @@
|
||||
<%-
|
||||
local sys = require "luci.sys"
|
||||
local utl = require "luci.util"
|
||||
|
||||
local bms_path = "/sys/class/power_supply/pm8916-bms-vm"
|
||||
local charger_path = "/sys/class/power_supply/pm8916-lbc-chgr"
|
||||
|
||||
local function read_file(path)
|
||||
local f = io.open(path, "r")
|
||||
if f then
|
||||
local val = f:read("*all")
|
||||
f:close()
|
||||
return utl.trim(val)
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local voltage = read_file(bms_path .. "/voltage_now")
|
||||
local status = read_file(bms_path .. "/status")
|
||||
local health = read_file(bms_path .. "/health")
|
||||
local vmax = read_file(bms_path .. "/voltage_max_design")
|
||||
local vmin = read_file(bms_path .. "/voltage_min_design")
|
||||
local online = read_file(charger_path .. "/online")
|
||||
|
||||
-- Calcular porcentaje aproximado basado en voltaje
|
||||
local percentage = "N/A"
|
||||
if voltage and vmax and vmin then
|
||||
local v = tonumber(voltage)
|
||||
local vmax_n = tonumber(vmax)
|
||||
local vmin_n = tonumber(vmin)
|
||||
if v and vmax_n and vmin_n then
|
||||
local pct = ((v - vmin_n) / (vmax_n - vmin_n)) * 100
|
||||
pct = math.max(0, math.min(100, pct))
|
||||
percentage = string.format("%.0f%%", pct)
|
||||
end
|
||||
end
|
||||
-%>
|
||||
|
||||
<% if voltage then %>
|
||||
<div class="cbi-section">
|
||||
<legend><%:Battery Status%></legend>
|
||||
<div class="table">
|
||||
<div class="tr cbi-section-table-titles">
|
||||
<div class="th"><%:Property%></div>
|
||||
<div class="th"><%:Value%></div>
|
||||
</div>
|
||||
<div class="tr">
|
||||
<div class="td left"><%:Estimated Capacity%></div>
|
||||
<div class="td left"><strong><%=percentage%></strong></div>
|
||||
</div>
|
||||
<div class="tr">
|
||||
<div class="td left"><%:Voltage%></div>
|
||||
<div class="td left"><%=string.format("%.2f V", tonumber(voltage)/1000000)%></div>
|
||||
</div>
|
||||
<div class="tr">
|
||||
<div class="td left"><%:Status%></div>
|
||||
<div class="td left"><%=status%></div>
|
||||
</div>
|
||||
<div class="tr">
|
||||
<div class="td left"><%:Health%></div>
|
||||
<div class="td left"><%=health%></div>
|
||||
</div>
|
||||
<div class="tr">
|
||||
<div class="td left"><%:Charger%></div>
|
||||
<div class="td left"><%=online == "1" and "Connected" or "Disconnected"%></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
Binary file not shown.
@@ -0,0 +1,47 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Enabling WiFi
|
||||
uci set wireless.@wifi-device[0].disabled='0'
|
||||
uci set wireless.@wifi-iface[0].disabled='0'
|
||||
|
||||
# Create modem interface
|
||||
uci set network.modem=interface
|
||||
uci set network.modem.proto='modemmanager'
|
||||
uci set network.modem.device='qcom-soc'
|
||||
uci set network.modem.auth='none'
|
||||
uci set network.modem.apn='internet'
|
||||
uci set network.modem.allowedmode='4g|3g'
|
||||
uci set network.modem.preferredmode='4g'
|
||||
uci set network.modem.ifname='wwan0'
|
||||
uci del_list firewall.@zone[1].network='modem'
|
||||
uci add_list firewall.@zone[1].network='modem'
|
||||
|
||||
# We don't have eth0
|
||||
uci -q del_list "network.@device[0].ports=eth0" 2>/dev/null || true
|
||||
sed -i 's/"device": "eth0"/"device": "br-lan"/g' /etc/board.json
|
||||
|
||||
# Commit all changes
|
||||
uci commit
|
||||
|
||||
# Apply network and wireless configuration
|
||||
wifi reload
|
||||
/etc/init.d/network restart
|
||||
|
||||
cat > /etc/rc.button/power << 'EOF'
|
||||
#!/bin/sh
|
||||
|
||||
SECONDS=3
|
||||
|
||||
[ "${ACTION}" = "pressed" ] && exit ${SECONDS}
|
||||
|
||||
[ "${ACTION}" = "timeout" ] && {
|
||||
logger "Power held for ${SECONDS}: Shutting down system"
|
||||
poweroff
|
||||
exit 0
|
||||
}
|
||||
|
||||
exit 0
|
||||
EOF
|
||||
chmod +x /etc/rc.button/power
|
||||
|
||||
exit 0
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=configs-uz801
|
||||
@@ -11,13 +10,13 @@ include $(INCLUDE_DIR)/package.mk
|
||||
define Package/$(PKG_NAME)
|
||||
SECTION:=Utilities
|
||||
CATEGORY:=Utilities
|
||||
TITLE:=Defaults Setting For uz801v3
|
||||
TITLE:=Default Settings For uz801v3
|
||||
DEPENDS:=+PACKAGE_luci:luci-proto-modemmanager
|
||||
endef
|
||||
|
||||
# (Opcional) Descripción
|
||||
# Optional description
|
||||
define Package/$(PKG_NAME)/description
|
||||
Tweaks y defaults para uz801v3, incluyendo limpieza de feeds APK problemáticos.
|
||||
Tweaks and defaults for uz801v3, including cleanup of problematic APK feeds.
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
@@ -26,7 +25,7 @@ endef
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
# Instala ficheros de configuración y payload que ya tenías
|
||||
# Install configuration files and payload you already had
|
||||
define Package/$(PKG_NAME)/install
|
||||
$(INSTALL_DIR) $(1)/etc/uci-defaults
|
||||
$(INSTALL_BIN) ./files/uci_defaults $(1)/etc/uci-defaults/99-default-config
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
include $(INCLUDE_DIR)/kernel.mk
|
||||
|
||||
PKG_NAME:=fbtft-gc9107
|
||||
PKG_RELEASE:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define KernelPackage/fbtft-gc9107
|
||||
SUBMENU:=Video Support
|
||||
TITLE:=GC9107 Framebuffer Driver
|
||||
DEPENDS:=@TARGET_msm89xx +kmod-backlight
|
||||
KCONFIG:= \
|
||||
CONFIG_FB=y \
|
||||
CONFIG_FB_BACKLIGHT=y \
|
||||
CONFIG_FB_DEFERRED_IO=y \
|
||||
CONFIG_FB_SYS_FILLRECT=y \
|
||||
CONFIG_FB_SYS_COPYAREA=y \
|
||||
CONFIG_FB_SYS_IMAGEBLIT=y \
|
||||
CONFIG_FB_SYS_FOPS=y \
|
||||
CONFIG_FB_DMAMEM_HELPERS=y \
|
||||
CONFIG_BACKLIGHT_CLASS_DEVICE=y \
|
||||
CONFIG_BACKLIGHT_PWM=y \
|
||||
CONFIG_FONTS=y \
|
||||
CONFIG_FONT_8x16=y \
|
||||
CONFIG_FRAMEBUFFER_CONSOLE=y \
|
||||
CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER=n \
|
||||
CONFIG_VT_HW_CONSOLE_BINDING=y \
|
||||
CONFIG_VT_CONSOLE_SLEEP=y \
|
||||
CONFIG_STAGING=y \
|
||||
CONFIG_FB_TFT=y \
|
||||
CONFIG_FB_TFT_GC9107=y
|
||||
FILES:= \
|
||||
$(LINUX_DIR)/drivers/staging/fbtft/fbtft.ko \
|
||||
$(LINUX_DIR)/drivers/staging/fbtft/fb_gc9107.ko
|
||||
AUTOLOAD:=$(call AutoProbe,fbtft fb_gc9107)
|
||||
endef
|
||||
|
||||
define KernelPackage/fbtft-gc9107/description
|
||||
GC9107 framebuffer driver for MF68E device with boot logo support.
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define KernelPackage/fbtft-gc9107/install
|
||||
$(INSTALL_DIR) $(1)/etc
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
$(INSTALL_DIR) $(1)/lib/preinit
|
||||
$(INSTALL_DATA) ./files/boot_logo.fb $(1)/etc/boot_logo.fb
|
||||
$(INSTALL_DATA) ./files/poweroff_logo.fb $(1)/etc/poweroff_logo.fb
|
||||
$(INSTALL_BIN) ./files/05_display_logo $(1)/lib/preinit/05_display_logo
|
||||
$(INSTALL_BIN) ./files/01_poweroff_logo $(1)/etc/init.d/01_poweroff_logo
|
||||
endef
|
||||
|
||||
$(eval $(call KernelPackage,fbtft-gc9107))
|
||||
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=99
|
||||
STOP=01
|
||||
|
||||
start() {
|
||||
return 0
|
||||
}
|
||||
|
||||
stop() {
|
||||
cat /etc/poweroff_logo.fb > /dev/fb0 2>/dev/null
|
||||
sleep 2
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#!/bin/sh
|
||||
|
||||
show_logo() {
|
||||
(
|
||||
local BACKLIGHT="/sys/class/backlight/backlight"
|
||||
local i=0
|
||||
|
||||
while [ ! -c /dev/fb0 ] && [ $i -lt 100 ]; do
|
||||
usleep 100000 # 100ms = 0.1s
|
||||
i=$((i + 1))
|
||||
done
|
||||
|
||||
if [ -c /dev/fb0 ] && [ -f /etc/boot_logo.fb ]; then
|
||||
cat /etc/boot_logo.fb > /dev/fb0 2>/dev/null
|
||||
fi
|
||||
|
||||
i=0
|
||||
while [ ! -d "$BACKLIGHT" ] && [ $i -lt 50 ]; do
|
||||
usleep 100000 # 100ms = 0.1s
|
||||
i=$((i + 1))
|
||||
done
|
||||
|
||||
if [ -d "$BACKLIGHT" ]; then
|
||||
echo 0 > $BACKLIGHT/bl_power 2>/dev/null
|
||||
echo 1 > $BACKLIGHT/brightness 2>/dev/null
|
||||
fi
|
||||
) &
|
||||
}
|
||||
|
||||
boot_hook_add preinit_main show_logo
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,5 @@
|
||||
## Create boot image for framebuffer
|
||||
We are converting the image using `ffmpeg`. Ensure you have it installed.
|
||||
```
|
||||
ffmpeg -i <image> -vf "scale=128:128" -pix_fmt rgb565le -f rawvideo <output>.fb
|
||||
```
|
||||
@@ -0,0 +1,67 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=router-display
|
||||
PKG_VERSION:=1.0
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
|
||||
|
||||
PKG_QRGEN_NAME:=QR-Code-generator
|
||||
PKG_QRGEN_VERSION:=v1.8.0
|
||||
PKG_QRGEN_SOURCE:=$(PKG_QRGEN_VERSION).tar.gz
|
||||
PKG_QRGEN_URL:=https://github.com/nayuki/QR-Code-generator/archive/refs/tags
|
||||
PKG_QRGEN_HASH:=skip
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/router-display
|
||||
SECTION:=utils
|
||||
CATEGORY:=Utilities
|
||||
TITLE:=Framebuffer router status display
|
||||
DEPENDS:=+libfreetype +kmod-button-hotplug +dejavu-fonts-ttf-DejaVuSans-Bold +dejavu-fonts-ttf-DejaVuSans
|
||||
endef
|
||||
|
||||
define Package/router-display/description
|
||||
Display router status on RGB565 framebuffer
|
||||
endef
|
||||
|
||||
define Download/qrcodegen
|
||||
URL:=$(PKG_QRGEN_URL)
|
||||
FILE:=qrcodegen-$(PKG_QRGEN_VERSION).tar.gz
|
||||
URL_FILE:=$(PKG_QRGEN_VERSION).tar.gz
|
||||
HASH:=$(PKG_QRGEN_HASH)
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
mkdir -p $(PKG_BUILD_DIR)
|
||||
$(CP) ./src/main.c $(PKG_BUILD_DIR)/
|
||||
$(eval $(call Download,qrcodegen))
|
||||
tar -xzf $(DL_DIR)/qrcodegen-$(PKG_QRGEN_VERSION).tar.gz -C $(PKG_BUILD_DIR)
|
||||
$(CP) $(PKG_BUILD_DIR)/$(PKG_QRGEN_NAME)-*/c/qrcodegen.c $(PKG_BUILD_DIR)/
|
||||
$(CP) $(PKG_BUILD_DIR)/$(PKG_QRGEN_NAME)-*/c/qrcodegen.h $(PKG_BUILD_DIR)/
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
$(TARGET_CC) $(TARGET_CFLAGS) -O3 -ffast-math \
|
||||
$(TARGET_CPPFLAGS) \
|
||||
-I$(STAGING_DIR)/usr/include/freetype2 \
|
||||
$(TARGET_LDFLAGS) \
|
||||
-o $(PKG_BUILD_DIR)/router-display \
|
||||
$(PKG_BUILD_DIR)/main.c \
|
||||
$(PKG_BUILD_DIR)/qrcodegen.c \
|
||||
-lfreetype -lm
|
||||
endef
|
||||
|
||||
define Package/router-display/install
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/router-display $(1)/usr/bin/
|
||||
|
||||
$(INSTALL_DIR) $(1)/usr/sbin
|
||||
$(INSTALL_BIN) ./files/update-display.sh $(1)/usr/sbin/update-display
|
||||
|
||||
$(INSTALL_DIR) $(1)/etc/hotplug.d/button
|
||||
$(INSTALL_BIN) ./files/hotplugs/20_power_dimm $(1)/etc/hotplug.d/button/20_power_dimm
|
||||
$(INSTALL_BIN) ./files/hotplugs/30_power_update $(1)/etc/hotplug.d/button/30_power_update
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,router-display))
|
||||
@@ -0,0 +1,91 @@
|
||||
#!/bin/sh
|
||||
# /etc/hotplug.d/button/20_power_dimm
|
||||
|
||||
# Only process power button events
|
||||
[ "$BUTTON" = "power" ] || exit 0
|
||||
|
||||
# Configuration variables
|
||||
TIMEOUT_DIM=5
|
||||
TIMEOUT_OFF=3
|
||||
BACKLIGHT_PATH="/sys/class/backlight/backlight"
|
||||
BRIGHTNESS_DIM_DIVISOR=8
|
||||
BRIGHTNESS_OFF=1
|
||||
|
||||
# Calculated variables
|
||||
MAX_BRIGHTNESS=$(cat $BACKLIGHT_PATH/max_brightness 2>/dev/null || echo 1785)
|
||||
BRIGHTNESS_FULL=$MAX_BRIGHTNESS
|
||||
BRIGHTNESS_DIM=$((MAX_BRIGHTNESS / BRIGHTNESS_DIM_DIVISOR))
|
||||
|
||||
# PID file for timer management
|
||||
TIMER_PID_FILE="/tmp/screen_timer.pid"
|
||||
|
||||
maybe_set_lockscreen(){
|
||||
# Check if system is shutting down
|
||||
if pgrep poweroff >/dev/null 2>&1 || \
|
||||
pgrep halt >/dev/null 2>&1 || \
|
||||
pgrep reboot >/dev/null 2>&1; then
|
||||
logger -t display "System shutting down - skipping lockscreen"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Show lockscreen if brightness is OFF
|
||||
[ -n "$1" ] && [ "$1" = "$BRIGHTNESS_OFF" ] && [ -f /etc/boot_logo.fb ] && \
|
||||
cat /etc/boot_logo.fb > /dev/fb0 2>/dev/null
|
||||
}
|
||||
|
||||
# Set brightness level
|
||||
set_brightness() {
|
||||
echo "$1" > "$BACKLIGHT_PATH/brightness"
|
||||
|
||||
# Check if we should show lockscreen
|
||||
maybe_set_lockscreen "$1"
|
||||
}
|
||||
|
||||
# Function to start a timer
|
||||
# Parameters: $1=timeout (seconds), $2=brightness level, $3=log message
|
||||
start_timer() {
|
||||
local timeout=$1
|
||||
local brightness=$2
|
||||
local log_msg=$3
|
||||
|
||||
(
|
||||
sleep "$timeout"
|
||||
logger -t display "$log_msg"
|
||||
set_brightness "$brightness"
|
||||
) >/dev/null 2>&1 </dev/null &
|
||||
|
||||
echo $!
|
||||
}
|
||||
|
||||
# Cancel all active timers
|
||||
cancel_timers() {
|
||||
if [ -f "$TIMER_PID_FILE" ]; then
|
||||
while read pid; do
|
||||
kill "$pid" 2>/dev/null
|
||||
done < "$TIMER_PID_FILE"
|
||||
rm -f "$TIMER_PID_FILE"
|
||||
fi
|
||||
}
|
||||
|
||||
# Only act on button release
|
||||
[ "${ACTION}" = "released" ] && {
|
||||
logger -t display "Button event detected"
|
||||
|
||||
# Cancel previous timers if any
|
||||
cancel_timers
|
||||
|
||||
# Set full brightness immediately
|
||||
logger -t display "Backlight: FULL"
|
||||
set_brightness $BRIGHTNESS_FULL
|
||||
|
||||
# Start timer 1: DIM after TIMEOUT_DIM seconds
|
||||
pid1=$(start_timer $TIMEOUT_DIM $BRIGHTNESS_DIM "Backlight: DIM")
|
||||
echo "$pid1" >> "$TIMER_PID_FILE"
|
||||
|
||||
# Start timer 2: OFF after (TIMEOUT_DIM + TIMEOUT_OFF) seconds
|
||||
TOTAL_TIMEOUT=$((TIMEOUT_DIM + TIMEOUT_OFF))
|
||||
pid2=$(start_timer $TOTAL_TIMEOUT $BRIGHTNESS_OFF "Backlight: OFF")
|
||||
echo "$pid2" >> "$TIMER_PID_FILE"
|
||||
}
|
||||
|
||||
exit 0
|
||||
@@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
# /etc/hotplug.d/button/30_power_update
|
||||
|
||||
# Only process power button events
|
||||
[ "$BUTTON" = "power" ] || exit 0
|
||||
|
||||
# Execute update-display on button release
|
||||
[ "${ACTION}" = "released" ] && {
|
||||
# Check if system is shutting down
|
||||
if pgrep poweroff >/dev/null 2>&1 || \
|
||||
pgrep halt >/dev/null 2>&1 || \
|
||||
pgrep reboot >/dev/null 2>&1; then
|
||||
logger -t display "System shutting down - skipping update-display"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
/usr/sbin/update-display
|
||||
}
|
||||
|
||||
exit 0
|
||||
@@ -0,0 +1,85 @@
|
||||
#!/bin/sh
|
||||
# /usr/sbin/update-display
|
||||
# Optimized display update script - caches operator name (requires reboot to change SIM)
|
||||
|
||||
# === BATTERY ===
|
||||
BMS_PATH="/sys/class/power_supply/pm8916-bms-vm"
|
||||
|
||||
VOLTAGE=$(cat "$BMS_PATH/voltage_now" 2>/dev/null)
|
||||
VMAX=$(cat "$BMS_PATH/voltage_max_design" 2>/dev/null)
|
||||
VMIN=$(cat "$BMS_PATH/voltage_min_design" 2>/dev/null)
|
||||
|
||||
if [ -n "$VOLTAGE" ] && [ -n "$VMAX" ] && [ -n "$VMIN" ]; then
|
||||
BATTERY=$(awk "BEGIN {pct = (($VOLTAGE - $VMIN) / ($VMAX - $VMIN)) * 100; if(pct < 0) pct=0; if(pct > 100) pct=100; printf \"%.0f\", pct}")
|
||||
else
|
||||
BATTERY=100
|
||||
fi
|
||||
|
||||
# === WiFi AP ===
|
||||
SHOW_QR=0
|
||||
if ip link show phy0-ap0 2>/dev/null | grep -q "state UP"; then
|
||||
SHOW_QR=1
|
||||
fi
|
||||
|
||||
# === MODEM (OPTIMIZED - single mmcli call + operator cache) ===
|
||||
OPERATOR_CACHE="/tmp/modem_operator.cache"
|
||||
MODEM_IDX=$(mmcli -L 2>/dev/null | grep -oE 'Modem/[0-9]+' | head -1 | cut -d'/' -f2)
|
||||
|
||||
if [ -n "$MODEM_IDX" ]; then
|
||||
# Single mmcli call - cache all modem data
|
||||
MODEM_DATA=$(mmcli -m "$MODEM_IDX" -K 2>/dev/null)
|
||||
|
||||
# Try to get operator from cache first (SIM doesn't change without reboot)
|
||||
if [ -f "$OPERATOR_CACHE" ]; then
|
||||
OPERATOR=$(cat "$OPERATOR_CACHE")
|
||||
else
|
||||
# Cache miss - fetch operator from SIM
|
||||
SIM_IDX=$(echo "$MODEM_DATA" | grep 'modem.generic.sim' | awk -F': ' '{print $2}' | grep -oE '[0-9]+$')
|
||||
|
||||
if [ -n "$SIM_IDX" ]; then
|
||||
OPERATOR=$(mmcli -i "$SIM_IDX" -K 2>/dev/null | grep 'sim.properties.operator-name' | awk -F': ' '{print $2}')
|
||||
fi
|
||||
|
||||
# Fallback: operator from network (use cached modem data)
|
||||
if [ -z "$OPERATOR" ]; then
|
||||
OPERATOR=$(echo "$MODEM_DATA" | grep 'modem.3gpp.operator-name' | awk -F': ' '{print $2}')
|
||||
fi
|
||||
|
||||
# Cache operator for future calls
|
||||
if [ -n "$OPERATOR" ]; then
|
||||
echo "$OPERATOR" > "$OPERATOR_CACHE"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Access technology (use cached modem data)
|
||||
ACCESS_TECH=$(echo "$MODEM_DATA" | grep 'modem.generic.access-technologies' | awk -F': ' '{print $2}')
|
||||
|
||||
# Determine network type only if connected
|
||||
if [ -n "$ACCESS_TECH" ] && [ "$ACCESS_TECH" != "unknown" ]; then
|
||||
case "$ACCESS_TECH" in
|
||||
*lte*) NETWORK="4G" ;;
|
||||
*umts*|*hspa*|*hsupa*|*hsdpa*) NETWORK="3G" ;;
|
||||
*edge*|*gprs*|*gsm*) NETWORK="2G" ;;
|
||||
*) NETWORK="$ACCESS_TECH" ;;
|
||||
esac
|
||||
else
|
||||
# No connection: show operator but no network type
|
||||
NETWORK=""
|
||||
fi
|
||||
else
|
||||
# No modem
|
||||
OPERATOR=""
|
||||
NETWORK=""
|
||||
fi
|
||||
|
||||
# === WiFi Info ===
|
||||
SSID=$(uci get wireless.@wifi-iface[0].ssid 2>/dev/null || echo "WiFi")
|
||||
PASSWORD=$(uci get wireless.@wifi-iface[0].key 2>/dev/null || echo "")
|
||||
HOSTNAME=$(uci get system.@system[0].hostname 2>/dev/null || echo "Router")
|
||||
|
||||
# === Update Display ===
|
||||
if [ "$SHOW_QR" -eq 1 ]; then
|
||||
/usr/bin/router-display -q -b "$BATTERY" -n "$OPERATOR" -t "$NETWORK" -s "$SSID" -p "$PASSWORD" -h "$HOSTNAME" > /dev/fb0
|
||||
else
|
||||
/usr/bin/router-display -b "$BATTERY" -n "$OPERATOR" -t "$NETWORK" -s "$SSID" -p "$PASSWORD" -h "$HOSTNAME" > /dev/fb0
|
||||
fi
|
||||
@@ -0,0 +1,292 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <getopt.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include "qrcodegen.h"
|
||||
|
||||
#define WIDTH 128
|
||||
#define HEIGHT 128
|
||||
#define RGB565(r,g,b) (((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3))
|
||||
|
||||
#define COLOR_WHITE RGB565(255, 255, 255)
|
||||
#define COLOR_BLACK RGB565(0, 0, 0)
|
||||
|
||||
#define QR_SIZE 108
|
||||
#define QR_TOP_MARGIN 6
|
||||
#define TEXT_HEIGHT 13
|
||||
#define MIN_MODULE_SIZE 3 // Minimum pixels per QR module for readability
|
||||
|
||||
typedef struct {
|
||||
uint16_t data[WIDTH * HEIGHT];
|
||||
} Framebuffer;
|
||||
|
||||
typedef struct {
|
||||
int battery;
|
||||
char operator[32];
|
||||
char network_type[8];
|
||||
char ssid[64];
|
||||
char password[64];
|
||||
char hostname[32];
|
||||
int show_qr;
|
||||
int uppercase;
|
||||
} DisplayConfig;
|
||||
|
||||
void fb_init(Framebuffer *fb) {
|
||||
memset(fb->data, 0, sizeof(fb->data));
|
||||
}
|
||||
|
||||
void fb_put_pixel(Framebuffer *fb, int x, int y, uint16_t color) {
|
||||
if (x >= 0 && x < WIDTH && y >= 0 && y < HEIGHT) {
|
||||
fb->data[y * WIDTH + x] = color;
|
||||
}
|
||||
}
|
||||
|
||||
void fb_blend_pixel(Framebuffer *fb, int x, int y, unsigned char gray) {
|
||||
if (x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT) return;
|
||||
if (gray == 0) return;
|
||||
|
||||
uint16_t bg_color = fb->data[y * WIDTH + x];
|
||||
|
||||
uint8_t bg_r = (bg_color >> 11) << 3;
|
||||
uint8_t bg_g = ((bg_color >> 5) & 0x3F) << 2;
|
||||
uint8_t bg_b = (bg_color & 0x1F) << 3;
|
||||
|
||||
float alpha = gray / 255.0f;
|
||||
uint8_t r = (uint8_t)(255 * alpha + bg_r * (1.0f - alpha));
|
||||
uint8_t g = (uint8_t)(255 * alpha + bg_g * (1.0f - alpha));
|
||||
uint8_t b = (uint8_t)(255 * alpha + bg_b * (1.0f - alpha));
|
||||
|
||||
fb->data[y * WIDTH + x] = RGB565(r, g, b);
|
||||
}
|
||||
|
||||
void fb_draw_rect(Framebuffer *fb, int x, int y, int w, int h, uint16_t color) {
|
||||
for (int j = 0; j < h; j++) {
|
||||
for (int i = 0; i < w; i++) {
|
||||
fb_put_pixel(fb, x + i, y + j, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fb_draw_text(Framebuffer *fb, FT_Face face, const char *text, int x, int y, int size) {
|
||||
int pen_x = x;
|
||||
|
||||
for (const char *p = text; *p; p++) {
|
||||
FT_Set_Pixel_Sizes(face, 0, size);
|
||||
|
||||
if (FT_Load_Char(face, *p, FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FT_GlyphSlot slot = face->glyph;
|
||||
FT_Bitmap bitmap = slot->bitmap;
|
||||
|
||||
for (unsigned int row = 0; row < bitmap.rows; row++) {
|
||||
for (unsigned int col = 0; col < bitmap.width; col++) {
|
||||
int px = pen_x + slot->bitmap_left + col;
|
||||
int py = y - slot->bitmap_top + row;
|
||||
|
||||
unsigned char gray = bitmap.buffer[row * bitmap.pitch + col];
|
||||
|
||||
if (gray > 0) {
|
||||
fb_blend_pixel(fb, px, py, gray);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pen_x += slot->advance.x >> 6;
|
||||
}
|
||||
}
|
||||
|
||||
int fb_get_text_width(FT_Face face, const char *text, int size) {
|
||||
int width = 0;
|
||||
FT_Set_Pixel_Sizes(face, 0, size);
|
||||
|
||||
for (const char *p = text; *p; p++) {
|
||||
if (FT_Load_Char(face, *p, FT_LOAD_RENDER)) {
|
||||
continue;
|
||||
}
|
||||
width += face->glyph->advance.x >> 6;
|
||||
}
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
int fb_draw_qr(Framebuffer *fb, const char *text, int x, int y, int size) {
|
||||
uint8_t qr_data[qrcodegen_BUFFER_LEN_MAX];
|
||||
uint8_t temp_buffer[qrcodegen_BUFFER_LEN_MAX];
|
||||
|
||||
bool ok = qrcodegen_encodeText(text, temp_buffer, qr_data,
|
||||
qrcodegen_Ecc_LOW,
|
||||
qrcodegen_VERSION_MIN,
|
||||
qrcodegen_VERSION_MAX,
|
||||
qrcodegen_Mask_AUTO, true);
|
||||
|
||||
if (!ok) {
|
||||
fprintf(stderr, "QR generation failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qr_modules = qrcodegen_getSize(qr_data);
|
||||
int module_size = size / qr_modules;
|
||||
|
||||
// Check if QR modules are too small (minimum pixels per module)
|
||||
if (module_size < MIN_MODULE_SIZE) {
|
||||
fprintf(stderr, "QR too large for display area (needs %d modules, only fits %dpx modules)\n",
|
||||
qr_modules, module_size);
|
||||
return 0; // Don't draw, QR would be unreadable
|
||||
}
|
||||
|
||||
// Calculate actual QR size and center horizontally, align top vertically
|
||||
int actual_qr_size = qr_modules * module_size;
|
||||
int offset_x = (size - actual_qr_size) / 2; // Center horizontally
|
||||
int offset_y = 0; // Top aligned
|
||||
|
||||
for (int row = 0; row < qr_modules; row++) {
|
||||
for (int col = 0; col < qr_modules; col++) {
|
||||
if (qrcodegen_getModule(qr_data, col, row)) {
|
||||
fb_draw_rect(fb,
|
||||
x + offset_x + col * module_size,
|
||||
y + offset_y + row * module_size,
|
||||
module_size, module_size,
|
||||
COLOR_WHITE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1; // QR drawn successfully
|
||||
}
|
||||
|
||||
void str_to_upper(char *str) {
|
||||
for (char *p = str; *p; p++) {
|
||||
*p = toupper((unsigned char)*p);
|
||||
}
|
||||
}
|
||||
|
||||
void generate_display(Framebuffer *fb, DisplayConfig *cfg, FT_Face face) {
|
||||
fb_init(fb);
|
||||
|
||||
char operator_text[32], network_text[8], hostname_text[32];
|
||||
strncpy(operator_text, cfg->operator, 31);
|
||||
strncpy(network_text, cfg->network_type, 7);
|
||||
strncpy(hostname_text, cfg->hostname, 31);
|
||||
|
||||
if (cfg->uppercase) {
|
||||
str_to_upper(operator_text);
|
||||
str_to_upper(network_text);
|
||||
str_to_upper(hostname_text);
|
||||
}
|
||||
|
||||
// Calculate QR position: centered horizontally, at top with margin
|
||||
int qr_x = (WIDTH - QR_SIZE) / 2;
|
||||
int qr_y = QR_TOP_MARGIN;
|
||||
|
||||
if (cfg->show_qr) {
|
||||
char wifi_qr[256];
|
||||
snprintf(wifi_qr, sizeof(wifi_qr),
|
||||
"WIFI:T:WPA;S:%s;P:%s;;", cfg->ssid, cfg->password);
|
||||
|
||||
// Try to draw QR, if it doesn't fit (returns 0), screen stays black
|
||||
fb_draw_qr(fb, wifi_qr, qr_x, qr_y, QR_SIZE);
|
||||
}
|
||||
// If no QR or QR too large: stay black (fb_init already cleared to black)
|
||||
|
||||
int fontsz = 12;
|
||||
int line1_y = HEIGHT - fontsz - 3;
|
||||
int line2_y = HEIGHT - 3;
|
||||
|
||||
fb_draw_text(fb, face, operator_text, 2, line1_y, fontsz);
|
||||
|
||||
int net_width = fb_get_text_width(face, network_text, fontsz);
|
||||
fb_draw_text(fb, face, network_text, WIDTH - net_width - 2, line1_y, fontsz);
|
||||
|
||||
fb_draw_text(fb, face, hostname_text, 2, line2_y, fontsz);
|
||||
|
||||
char battery_text[8];
|
||||
snprintf(battery_text, sizeof(battery_text), "%d%%", cfg->battery);
|
||||
int battery_width = fb_get_text_width(face, battery_text, fontsz);
|
||||
fb_draw_text(fb, face, battery_text, WIDTH - battery_width - 2, line2_y, fontsz);
|
||||
}
|
||||
|
||||
void print_usage(const char *prog) {
|
||||
fprintf(stderr, "Usage: %s [OPTIONS]\n", prog);
|
||||
fprintf(stderr, " -b NUM Battery (0-100)\n");
|
||||
fprintf(stderr, " -n NAME Operator name\n");
|
||||
fprintf(stderr, " -t TYPE Network type (4G, LTE)\n");
|
||||
fprintf(stderr, " -s SSID WiFi SSID\n");
|
||||
fprintf(stderr, " -p PASS WiFi password\n");
|
||||
fprintf(stderr, " -h HOST Hostname\n");
|
||||
fprintf(stderr, " -q Show QR code (default: show logo)\n");
|
||||
fprintf(stderr, " -c Convert text to UPPERCASE\n");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
DisplayConfig cfg = {
|
||||
.battery = 100,
|
||||
.operator = "Unknown",
|
||||
.network_type = "4G",
|
||||
.ssid = "WiFi",
|
||||
.password = "password",
|
||||
.hostname = "Router",
|
||||
.show_qr = 0,
|
||||
.uppercase = 0
|
||||
};
|
||||
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "b:n:t:s:p:h:qc")) != -1) {
|
||||
switch (opt) {
|
||||
case 'b': cfg.battery = atoi(optarg); break;
|
||||
case 'n': strncpy(cfg.operator, optarg, 31); break;
|
||||
case 't': strncpy(cfg.network_type, optarg, 7); break;
|
||||
case 's': strncpy(cfg.ssid, optarg, 63); break;
|
||||
case 'p': strncpy(cfg.password, optarg, 63); break;
|
||||
case 'h': strncpy(cfg.hostname, optarg, 31); break;
|
||||
case 'q': cfg.show_qr = 1; break;
|
||||
case 'c': cfg.uppercase = 1; break;
|
||||
default:
|
||||
print_usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
FT_Library ft;
|
||||
if (FT_Init_FreeType(&ft)) {
|
||||
fprintf(stderr, "FreeType init failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
FT_Face face;
|
||||
const char *fonts[] = {
|
||||
"/usr/share/fonts/ttf-dejavu/DejaVuSans.ttf",
|
||||
"/usr/share/fonts/ttf-dejavu/DejaVuSans-Bold.ttf",
|
||||
NULL
|
||||
};
|
||||
|
||||
int found = 0;
|
||||
for (int i = 0; fonts[i]; i++) {
|
||||
if (FT_New_Face(ft, fonts[i], 0, &face) == 0) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
fprintf(stderr, "No font found\n");
|
||||
FT_Done_FreeType(ft);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Framebuffer fb;
|
||||
generate_display(&fb, &cfg, face);
|
||||
|
||||
fwrite(fb.data, sizeof(uint16_t), WIDTH * HEIGHT, stdout);
|
||||
|
||||
FT_Done_Face(face);
|
||||
FT_Done_FreeType(ft);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user