安装教程 —— 把魔百和 CM201-2 变成「打印机服务器」

> OpenHW Lab · 智能硬件开放实验室 · 面向普通用户 / 开发者。约 40–60 分钟。
> 用一台吃灰的魔百和 CM201-2 机顶盒 + 一台 USB 打印机，做成局域网共享打印服务器：
> 手机扫码/网页传文件打印、电脑用 IPP/网络打印机、盒子屏幕全屏显示二维码、可打印二维码贴纸。
> 本项目在 魔百和 CM201-2（海思 Hi3798MV300 / Android 4.4.2 / armv7 / 1GB）实测通过。

---

0. 你需要

- 一台已 root 的魔百和 CM201-2 盒子（海思 Hi3798MV300 / armv7 / Android 4.4.2 / 1GB / eMMC）。
- 一台 USB 打印机（多品牌自适应：插上自动识别型号、从内置驱动库匹配；HP LaserJet 1018/1020/1022/1022n 主机型即插即用；联想/兄弟激光走 brlaser；认不出的可传 .ppd）。
- 电视/显示器（盒子有 HDMI）、路由器（组局域网，盒子有网口，DHCP 自动拿 IP）。
- 电脑一台（装 adb）。
- TTL 串口线（强烈建议，作 root 生命线）：本机串口是 ttyAMA0, 115200 8N1。

> 总思路：盒子里 chroot 一个 Ubuntu 20.04(armhf) 子系统（/data/linux），里面装
> CUPS（打印服务）+ 网页打印门户 printd（:8080）+ 打印机守护 printerwatch；
> 盒子屏幕装一个 打印桌面 App（开机即进，全屏显示打印页）；开机自动拉起全部服务。

---

1. 认清你的盒子（1 分钟）

getprop ro.product.model              # CM201-2
getprop ro.product.cpu.abi            # armeabi-v7a  (armv7)
getprop ro.build.version.release; getprop ro.build.version.sdk   # 4.4.2 / 19
cat /proc/meminfo | head; df -k

记下：架构 / 安卓版本 / 内存 / 分区。
> 本盒子是 海思 Hi3798MV300（armv7），所以要装 armhf 的 Ubuntu。内存只有 1GB，空间要省着用。

---

2. 打开控制通道（TTL 串口 / ADB）

- 串口(TTL)：ttyAMA0, 115200 8N1。上电即可拿到 root shell：
    Linux 3.18.24 ... console [ttyAMA0] enabled
  ...
  root@Hi3798MV300:/ #
  
- ADB over TCP：串口里执行
    setprop service.adb.tcp.port 5555
  start adbd
  
  电脑上 adb connect <盒子IP>:5555。
  > 本 ROM 默认 adb 口是 5114（/init.rc），改成 5555 只是方便；开机自启脚本里已带上 start adbd。

---

3. 搭 Linux 子系统（CUPS 跑在里面）

在盒子（root）里，把一个 Ubuntu 20.04 armhf 根文件系统放到 /data/linux：

电脑上下好 ubuntu-base-20.04.5-base-armhf.tar.gz，推到盒子：
adb push ubuntu-base-20.04.5-base-armhf.tar.gz /data/local/tmp/ubuntu20.tar.gz
盒子上（Android root shell / 串口）解包：
mkdir -p /data/linux
busybox tar -xzf /data/local/tmp/ubuntu20.tar.gz -C /data/linux
补挂内核文件系统：
busybox mount -t proc  proc  /data/linux/proc
busybox mount -t sysfs sysfs /data/linux/sys
busybox mount -o bind /dev   /data/linux/dev
busybox mount -t devpts devpts /data/linux/dev/pts

> ⚠ 子系统里必须有 /proc 和 /sys，否则 libusb / 打印机枚举读不到 USB。

✅ 本机 (Hi3798MV300) 的 chroot 里 apt 可用

和 CM201-1 不同，这台盒子的 chroot 里 apt install 可以联网直接装（CM201-1 会 socket: Permission denied）。
所以只要配好 DNS + 源即可：

/data/linux/etc/resolv.conf
nameserver 192.168.31.1
/data/linux/etc/apt/sources.list  （国内走 tuna 镜像）
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports/ focal main restricted universe multiverse
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports/ focal-updates main restricted universe multiverse
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports/ focal-security main restricted universe multiverse
装前放 policy-rc.d，避免 postinst 去起服务
echo '#!/bin/sh' > /data/linux/usr/sbin/policy-rc.d; echo 'exit 101' >> /data/linux/usr/sbin/policy-rc.d
chmod 755 /data/linux/usr/sbin/policy-rc.d

> ⚠️ 安卓自带 shell 没有 printf（用 echo）；busybox 1.16 没有 cp -n/grep -x。

进 chroot 跑命令的 helper（放在 /data/local/tmp/cr.sh）：
!/system/bin/sh
exec /system/bin/busybox chroot /data/linux /usr/bin/env -i \
  PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOME=/root LANG=C.UTF-8 \
  /bin/bash -lc "$*"


---

4. 装 CUPS + 驱动

sh /data/local/tmp/cr.sh "apt-get update"
sh /data/local/tmp/cr.sh "apt-get install -y --no-install-recommends \
  cups cups-daemon cups-filters cups-client \
  printer-driver-foo2zjs printer-driver-brlaser printer-driver-gutenprint printer-driver-cups-pdf \
  python3 python3-pil python3-usb python3-distutils \
  libusb-1.0-0 usbutils qrencode fonts-droid-fallback fontconfig"

- cups 打印服务；printer-driver-foo2zjs = HP 主机型驱动；printer-driver-brlaser = 联想/兄弟激光；
- python3-pil + fonts-droid-fallback 用于「二维码贴纸」，也让中文能正常打印。

---

5. 放固件 + 部署服务

HP 主机型(ZJS)打印机必须灌固件才能用。install/firmware/ 提供 HP 原厂固件：

adb push install/firmware/hp1018.img  /data/linux/lib/firmware/hp/sihp1018.img
adb push install/firmware/hp1020.img  /data/linux/lib/firmware/hp/sihp1020.img
adb push install/firmware/hp1022.img  /data/linux/lib/firmware/hp/sihp1022.img
adb push install/firmware/hp1022n.img /data/linux/lib/firmware/hp/sihp1022n.img
每个再复制一份 .dl （foo2zjs 需要）：
adb shell 'cd /data/linux/lib/firmware/hp && for m in 1018 1020 1022 1022n; do cp -f sihp$m.img sihp$m.dl; done'


部署服务（一键或手动）：

一键（电脑上，切到 install/ 目录）：
./一键安装.sh 192.168.31.223

手动：
adb push install/打印服务.py     /data/linux/root/printd.py
adb push install/printerwatch.py /data/linux/root/printerwatch.py
adb push install/二维码贴纸.py   /data/linux/root/qrsheet.py
adb push install/开机自启-子系统.sh /data/linux/root/printstart.sh

> ⚠ 本内核无 usblp → 固件走 libusb(pyusb) 直发（正是 printerwatch.py 干的事）。

配置 CUPS 开局域网（子系统里 /etc/cups/cupsd.conf）：
sh /data/local/tmp/cr.sh "python3 /root/patch_cups.py"   # 见下：确保只监听 0.0.0.0:631

> ⚠️ 坑：若 cupsd.conf 同时有 Listen localhost:631 和 Listen 0.0.0.0:631，第二个会报
> Address already in use，结果只绑了 127.0.0.1。删掉 Listen localhost:631，只留 Listen 0.0.0.0:631。

起服务：
sh /data/local/tmp/cr.sh "bash /root/printstart.sh"   # dbus(可选) + cupsd + printd + printerwatch


---

6. 插打印机，即插即用

- USB 打印机插到盒子 USB 口（不行换另一个口 / 用带供电的 HUB）。
- HP LaserJet 1018 / 1020 / 1022 / 1022n：printerwatch.py 每 8 秒扫一次 USB，认出后
  自动灌固件 + 建 CUPS 队列（foo2zjs 默认驱动）+ 设为默认，插上就能打。
- 联想 / 兄弟主机型（如 联想 M7206W）走 brlaser（本机实测：M7206W → brlaser br1600，
  自动识别 MFG:Lenovo;CMD:PJL,HBP;MDL:M7206W → 建队列 + 设默认 + 出纸正常）。
- 其它型号：浏览器开 http://<盒子IP>:8080/setup，打开即自动带出 USB 打印机型号并列出内置匹配驱动，
  选定即用；也可在管理页「更换驱动」。认不出的传 .ppd。
- 装完打一张测试页验证出纸（管理页 / 首页菜单都有）。

---

7. 装「打印桌面」+ 设为默认 HOME

adb push install/桌面.apk /data/local/tmp/printsrv.apk
adb shell 'pm install -r /data/local/tmp/printsrv.apk'


本 ROM 唯一 HOME 是 com.zte.iptvclient.android.launcher_ah/com.chinamobile.launcherjs.main，
Android 4.4 没有 pm set-home-activity，且 preferred-activities 为空 ——
用外科式禁用旧 HOME 的启动活动让打印桌面接管（只摘 HOME 入口，不卸载整个包）：

adb shell 'pm disable com.zte.iptvclient.android.launcher_ah/com.chinamobile.launcherjs.main'
回滚：pm enable com.zte.iptvclient.android.launcher_ah/com.chinamobile.launcherjs.main

装好后盒子屏幕就是打印服务器界面（左：网页打印界面 + 二维码；右：菜单）。

---

8. 开机自启（CM201-2 做法）

本 ROM 的 ramdisk init.bigfish.rc 里有 service bigfish-setup /system/etc/init.bigfish.sh
（on boot、root、oneshot）。不需要改 boot.img，直接在 /system/etc/init.bigfish.sh
末尾追加一段后台调用即可：

先备好 /data/printstart.sh（见 install/开机自启-盒子.sh）
adb push install/开机自启-盒子.sh /data/printstart.sh
adb shell 'chmod 755 /data/printstart.sh'

remount /system 可写，备份原文件，追加钩子
adb shell 'mount -o remount,rw /system'
adb shell 'busybox cp /system/etc/init.bigfish.sh /system/etc/init.bigfish.sh.bak-orig'
adb shell 'cat >> /system/etc/init.bigfish.sh <<EOF

OpenHW Lab print server (CM201-2) ###
if [ -f /data/printstart.sh ]; then
  /system/bin/busybox setsid /system/bin/sh /data/printstart.sh >/data/printstart.log 2>&1 &
fi
EOF'

/data/printstart.sh 负责：等子系统就绪 → 挂 proc / sysfs / dev → chroot 跑 /root/printstart.sh
→ 末尾延时 am start 起打印桌面（盖掉运营商桌面）。

装好后重启复查：http://<盒子IP>:8080/ 能开、桌面显示打印界面、/data/printstart.log 里有
printstart done: cupsd=1 printd=1 printerwatch=1。

---

完成！日常怎么用

- 手机传文件打印：同一 WiFi，扫盒子屏幕/网页上的二维码，或浏览器开 http://<盒子IP>:8080/，选/拖文件 → 打印。
- 电脑当网络打印机用：Windows/Mac「添加打印机 → 按地址/IP 添加」，填
  ipp://<盒子IP>:631/printers/<打印机名>（首页可一键复制）。
- 打印二维码贴纸：打印页二维码下面「打印此二维码（A4 一版 6 张）」。

---
可选：拖拽打印 / 扫码贴纸 / 换驱动 / 电视页
- 拖拽打印：网页打印页支持把文件拖进去即打印。支持 PDF / 图片 / txt，Word/Excel 先另存 PDF。
- 二维码贴纸：A4 一版自动排 6 张；需 python3-pil + 中文字体。
- 换驱动：管理页对每台打印机可「更换驱动 / 设默认 / 测试页 / 删除」。
- 电视页：http://<盒子IP>:8080/tv 全屏二维码。
- ⚠ 不支持 AirPrint：chroot 里 avahi 因 socket 限制起不来 → 请用 IPP 直连 + 网页打印。

---
—— OpenHW Lab · 智能硬件开放实验室 · hi@openhwlab.com
