|
| 1 | +#!/usr/bin/env bash |
| 2 | +# foo2zjs / foo2xqx 系列 HP host-based 打印机固件安装脚本。 |
| 3 | +# |
| 4 | +# 覆盖型号(均为"GDI / host-based"打印机,每次上电需主机上传固件): |
| 5 | +# foo2zjs: HP LaserJet 1000, 1005, 1018 |
| 6 | +# foo2xqx: HP LaserJet P1005, P1006/P1008, P1505 |
| 7 | +# |
| 8 | +# 注意:HP LaserJet 1020 的固件由 install-hp-laserjet1020.sh 独立处理(从 |
| 9 | +# GitHub Releases 下载 sihp1020.dl + 派生 A4-default PPD),本脚本跳过。 |
| 10 | +# |
| 11 | +# 固件来源:从公共镜像站下载 .tar.gz(含 .img 原始固件),用 arm2hpdl 工具 |
| 12 | +# 转换为 CUPS 可用的 .dl 格式。arm2hpdl 是 foo2zjs 项目的单文件 C 工具, |
| 13 | +# 构建期从 GitHub 克隆编译。 |
| 14 | +# |
| 15 | +# 安装路径:/lib/firmware/hp/(Debian foo2zjs 包所有 udev 脚本 hpljXXXX 的 |
| 16 | +# FWDIR 硬编码路径;merged-usr 下与 /usr/lib/firmware/hp/ 等价)。 |
| 17 | +# |
| 18 | +# 本脚本必须在 cleanup-build.sh 之前运行——编译 arm2hpdl 需要 gcc。 |
| 19 | + |
| 20 | +set -eo pipefail |
| 21 | + |
| 22 | +# ──────────────────────────────────────────────────────────────────── |
| 23 | +# 配置 |
| 24 | +# ──────────────────────────────────────────────────────────────────── |
| 25 | +FW_INSTALL_DIR="/lib/firmware/hp" |
| 26 | + |
| 27 | +# 公共固件下载源(按优先级排列,首个成功即停止) |
| 28 | +FIRMWARE_SOURCES=( |
| 29 | + "https://www.quirinux.org/printers" |
| 30 | + "https://mirrors.edge.kernel.org/pub/software/drivers/foo2zjs/firmware" |
| 31 | + "http://foo2zjs.rkkda.com/firmware" |
| 32 | +) |
| 33 | + |
| 34 | +# foo2zjs 系列固件(ZjStream 协议) |
| 35 | +FOO2ZJS_MODELS=(sihp1000 sihp1005 sihp1018) |
| 36 | + |
| 37 | +# foo2xqx 系列固件(XQX 协议) |
| 38 | +FOO2XQX_MODELS=(sihpP1005 sihpP1006 sihpP1505) |
| 39 | + |
| 40 | +# ──────────────────────────────────────────────────────────────────── |
| 41 | +# 编译 arm2hpdl 转换工具 |
| 42 | +# ──────────────────────────────────────────────────────────────────── |
| 43 | +echo "[foo2zjs-firmware] compiling arm2hpdl converter..." |
| 44 | + |
| 45 | +ARM2HPDL="" |
| 46 | +TMPDIR_BUILD="$(mktemp -d /tmp/foo2zjs-build.XXXXXX)" |
| 47 | +trap 'rm -rf "${TMPDIR_BUILD}"' EXIT |
| 48 | + |
| 49 | +wget -q "https://raw.githubusercontent.com/koenkooi/foo2zjs/master/arm2hpdl.c" \ |
| 50 | + -O "${TMPDIR_BUILD}/arm2hpdl.c" |
| 51 | +gcc -o "${TMPDIR_BUILD}/arm2hpdl" "${TMPDIR_BUILD}/arm2hpdl.c" |
| 52 | +ARM2HPDL="${TMPDIR_BUILD}/arm2hpdl" |
| 53 | +echo "[foo2zjs-firmware] arm2hpdl compiled: ${ARM2HPDL}" |
| 54 | + |
| 55 | +mkdir -p "${FW_INSTALL_DIR}" |
| 56 | + |
| 57 | +# ──────────────────────────────────────────────────────────────────── |
| 58 | +# 通用下载 & 转换函数 |
| 59 | +# ──────────────────────────────────────────────────────────────────── |
| 60 | +download_and_convert() { |
| 61 | + local fw_name="$1" |
| 62 | + local target_path="${FW_INSTALL_DIR}/${fw_name}.dl" |
| 63 | + |
| 64 | + # 跳过已存在的固件(sihp1020 由 install-hp-laserjet1020.sh 安装) |
| 65 | + if [ -s "${target_path}" ]; then |
| 66 | + echo "[foo2zjs-firmware] ${fw_name}.dl already exists, skipping" |
| 67 | + return 0 |
| 68 | + fi |
| 69 | + |
| 70 | + local tarball="${TMPDIR_BUILD}/${fw_name}.tar.gz" |
| 71 | + local downloaded=false |
| 72 | + |
| 73 | + for src in "${FIRMWARE_SOURCES[@]}"; do |
| 74 | + if wget -q --no-check-certificate "${src}/${fw_name}.tar.gz" -O "${tarball}" 2>/dev/null; then |
| 75 | + downloaded=true |
| 76 | + break |
| 77 | + fi |
| 78 | + done |
| 79 | + |
| 80 | + if ! $downloaded || [ ! -s "${tarball}" ]; then |
| 81 | + echo "[foo2zjs-firmware] WARNING: ${fw_name}.tar.gz download failed from all sources" |
| 82 | + return 1 |
| 83 | + fi |
| 84 | + |
| 85 | + # 解压并转换 |
| 86 | + tar xzf "${tarball}" -C "${TMPDIR_BUILD}" 2>/dev/null |
| 87 | + |
| 88 | + if [ -f "${TMPDIR_BUILD}/${fw_name}.img" ]; then |
| 89 | + "${ARM2HPDL}" "${TMPDIR_BUILD}/${fw_name}.img" > "${target_path}" 2>/dev/null |
| 90 | + rm -f "${TMPDIR_BUILD}/${fw_name}.img" |
| 91 | + elif [ -f "${TMPDIR_BUILD}/${fw_name}.dl" ]; then |
| 92 | + cp "${TMPDIR_BUILD}/${fw_name}.dl" "${target_path}" |
| 93 | + rm -f "${TMPDIR_BUILD}/${fw_name}.dl" |
| 94 | + else |
| 95 | + echo "[foo2zjs-firmware] WARNING: ${fw_name}.tar.gz contains neither .img nor .dl" |
| 96 | + rm -f "${tarball}" |
| 97 | + return 1 |
| 98 | + fi |
| 99 | + |
| 100 | + rm -f "${tarball}" |
| 101 | + |
| 102 | + if [ -s "${target_path}" ]; then |
| 103 | + echo "[foo2zjs-firmware] installed ${fw_name}.dl ($(wc -c < "${target_path}") bytes)" |
| 104 | + return 0 |
| 105 | + else |
| 106 | + echo "[foo2zjs-firmware] WARNING: ${fw_name}.dl is empty after conversion" |
| 107 | + rm -f "${target_path}" |
| 108 | + return 1 |
| 109 | + fi |
| 110 | +} |
| 111 | + |
| 112 | +# ──────────────────────────────────────────────────────────────────── |
| 113 | +# 下载 foo2zjs 系列固件 |
| 114 | +# ──────────────────────────────────────────────────────────────────── |
| 115 | +echo "[foo2zjs-firmware] === foo2zjs firmware (ZjStream) ===" |
| 116 | +ZJS_OK=0 |
| 117 | +ZJS_FAIL=0 |
| 118 | +for fw in "${FOO2ZJS_MODELS[@]}"; do |
| 119 | + if download_and_convert "$fw"; then |
| 120 | + ZJS_OK=$((ZJS_OK + 1)) |
| 121 | + else |
| 122 | + ZJS_FAIL=$((ZJS_FAIL + 1)) |
| 123 | + fi |
| 124 | +done |
| 125 | + |
| 126 | +# ──────────────────────────────────────────────────────────────────── |
| 127 | +# 下载 foo2xqx 系列固件 |
| 128 | +# ──────────────────────────────────────────────────────────────────── |
| 129 | +echo "[foo2zjs-firmware] === foo2xqx firmware (XQX) ===" |
| 130 | +XQX_OK=0 |
| 131 | +XQX_FAIL=0 |
| 132 | +for fw in "${FOO2XQX_MODELS[@]}"; do |
| 133 | + if download_and_convert "$fw"; then |
| 134 | + XQX_OK=$((XQX_OK + 1)) |
| 135 | + else |
| 136 | + XQX_FAIL=$((XQX_FAIL + 1)) |
| 137 | + fi |
| 138 | +done |
| 139 | + |
| 140 | +# ──────────────────────────────────────────────────────────────────── |
| 141 | +# 兼容符号链接 |
| 142 | +# ──────────────────────────────────────────────────────────────────── |
| 143 | +# P1007 使用与 P1005 相同的固件;P1008 使用与 P1006 相同的固件 |
| 144 | +if [ -f "${FW_INSTALL_DIR}/sihpP1005.dl" ] && [ ! -e "${FW_INSTALL_DIR}/sihpP1007.dl" ]; then |
| 145 | + ln -sf sihpP1005.dl "${FW_INSTALL_DIR}/sihpP1007.dl" |
| 146 | + echo "[foo2zjs-firmware] symlink: sihpP1007.dl → sihpP1005.dl" |
| 147 | +fi |
| 148 | +if [ -f "${FW_INSTALL_DIR}/sihpP1006.dl" ] && [ ! -e "${FW_INSTALL_DIR}/sihpP1008.dl" ]; then |
| 149 | + ln -sf sihpP1006.dl "${FW_INSTALL_DIR}/sihpP1008.dl" |
| 150 | + echo "[foo2zjs-firmware] symlink: sihpP1008.dl → sihpP1006.dl" |
| 151 | +fi |
| 152 | + |
| 153 | +# ──────────────────────────────────────────────────────────────────── |
| 154 | +# 权限修正 & 汇总 |
| 155 | +# ──────────────────────────────────────────────────────────────────── |
| 156 | +chmod 644 "${FW_INSTALL_DIR}"/sihp*.dl 2>/dev/null || true |
| 157 | + |
| 158 | +TOTAL_OK=$((ZJS_OK + XQX_OK)) |
| 159 | +TOTAL_FAIL=$((ZJS_FAIL + XQX_FAIL)) |
| 160 | + |
| 161 | +echo "[foo2zjs-firmware] === summary ===" |
| 162 | +echo "[foo2zjs-firmware] installed: ${TOTAL_OK}, failed: ${TOTAL_FAIL}" |
| 163 | +ls -la "${FW_INSTALL_DIR}"/sihp*.dl 2>/dev/null || true |
| 164 | + |
| 165 | +if [ "${TOTAL_OK}" -eq 0 ]; then |
| 166 | + echo "[foo2zjs-firmware] FATAL: no firmware files were installed" |
| 167 | + exit 1 |
| 168 | +fi |
0 commit comments