mikebean233/sane-airscan-macos

GitHub: mikebean233/sane-airscan-macos

将 sane-airscan 移植到 macOS,使仅支持 WSD 协议的网络扫描仪通过 eSCL 桥接原生出现在 Image Capture 中。

Stars: 0 | Forks: 0

# macOS 上的 sane-airscan [sane-airscan](https://github.com/alexpevzner/sane-airscan) 的 macOS 移植版, 外加必要的连接代码,使**仅支持 WSD 的网络扫描仪**能够出现在 Image Capture、Preview 以及任何其他基于 Apple 的 ImageCapture 框架构建的软件中。 sane-airscan 上游不支持 macOS。此代码库是针对它的 补丁,而不是分叉。 ## 此方案解决的症状 你的网络多功能打印机打印正常,但**无法从 Mac 扫描**。它没有 出现在 Image Capture 中。它在“打印机和扫描仪”中显示时没有“扫描” 选项卡,或者显示“未检测到扫描仪”。制造商的 macOS 软件 是 32 位的、已停止维护或根本不存在,而且规格表上只字未提 **AirPrint Scanning** 或 **AirScan**。在 Windows 上,同一设备 却能毫无困难地进行扫描。 如果这听起来很熟悉,原因通常是协议不匹配,而 不是设备损坏了。 ## 这适合你吗? macOS 恰好只支持一种网络扫描协议:**eSCL**(作为 AirScan 进行市场营销)。如果你的扫描仪支持 eSCL,macOS 已经能识别它,并且你 不需要这些。 许多大约 2010–2015 年间的网络多功能打印机仅支持 **WSD**(Web Services for Devices,微软的等效方案,基于 PWG Scan Model 分层构建)。macOS 根本无法与它们通信,而对于 那些超出固件支持范围的设备,这一点永远无法改变。它们通过 AirPrint 或 IPP 打印正常, 只是无法用来扫描。 此方案弥合了这一差距: ``` scanner ──WSD──> sane-airscan ──> SANE ──> AirSane ──eSCL/Bonjour──> macOS (ported here) (upstream, builds on macOS) ``` sane-airscan 实现了 WSD,但仅限 Linux/BSD 使用——这里的补丁将其移植 到了 Darwin 上。[AirSane](https://github.com/SimulPiscator/AirSane) 随后 通过 Bonjour 将 SANE 设备重新发布为 eSCL 扫描仪,这 正是 macOS 能够理解的方式。 对于由于其他原因(子网错误、mDNS 被阻止)导致 macOS 无法访问的 eSCL 扫描仪, 同样适用此路径,因为 sane-airscan 同时支持这两种 协议。 ## 要求 -搭载 [Homebrew](https://brew.sh) 的 Apple Silicon 或 Intel Mac - Xcode Command Line Tools (`xcode-select --install`) - 与 Mac 位于同一子网的扫描仪——WS-Discovery 是多播的, 不会在 VLAN 之间路由,也不会跨越访客 SSID ## 安装 ``` ./build-macos.sh ``` 此操作将安装 Homebrew 依赖项,克隆 sane-airscan,应用 补丁,构建并安装后端,然后将 AirSane 构建并安装 为 LaunchDaemon。首次运行预计需要几分钟;`sudo` 提示 用于该守护进程及其位于 `/usr/local` 下的配置。 这两部分是相互独立的——`./build-macos.sh airscan` 可为你提供一个能在 命令行运行的 `scanimage`,除了 Homebrew 之外不需要守护进程,也不需要 `sudo`。`./build-macos.sh airsane` 则会添加面向 macOS 的桥接程序。 ### 上游修订版本已锁定 `macos-port.patch` 是一个上下文 diff,因此它与特定的上游 修订版本绑定。构建脚本将 sane-airscan 和 AirSane 都固定在 此移植版本已验证的提交上,这使得克隆构建是 可重现的,而不是依赖于你克隆它的具体日期。 要检查此移植版是否仍适用于当前上游: ``` AIRSCAN_REF=origin/master ./build-macos.sh airscan ``` 如果补丁不再适用,脚本会提示并停止, 而不会触碰你已安装的后端。这意味着该补丁需要 rebase—— 请提交一个 issue,最好能指出失败的代码块(hunks)。 ## 按顺序验证 每个步骤都隔离了一层。如果某一步失败,后面的步骤就无法 工作,因此不要跳过。 **1. sane-airscan 能看到扫描仪吗?** ``` airscan-discover ``` 预期会看到一个 `[devices]` 块,其中包含带有 `WSD`(或 `eSCL`)endpoint URL 的设备名称。 这是 WS-Discovery 多播,不涉及 Bonjour。 **2. SANE 能看到它吗?** ``` scanimage -L ``` 预期输出 `device 'airscan:w0:' is a WSD `。 **3. 它能扫描吗?** ``` scanimage -d "$(scanimage -L | head -1 | cut -d\' -f2)" \ --format=png --resolution 300 > ~/Desktop/test-scan.png ``` **4. macOS 能看到它吗?** ``` dns-sd -B _uscan._tcp # Bonjour advert curl -s http://127.0.0.1:8090/eSCL/ScannerCapabilities # eSCL endpoint ``` 然后打开 Image Capture——扫描仪应该会出现在侧边栏中,并且 在“系统设置” → “打印机和扫描仪”中显示为 Bonjour Scanner。 ## 故障排除 **`airscan-discover` 什么也没找到。** 这是网络问题,而不是构建问题。 检查扫描仪和 Mac 是否位于同一子网;在出现提示时 允许该二进制文件通过 macOS 防火墙;确认在扫描仪的 嵌入式 Web 服务器中启用了 WSD(通常位于“网络” → “高级” -> “Web Services”下)。 如果还是不行,请完全跳过发现过程——将 `airscan.conf.template` 复制 覆盖你的 `airscan.conf`(见下文),然后手动输入设备 URL。 **AirSane 运行时 `scanimage -L` 什么也没找到。** 你运行的是 在 `SO_REUSEPORT` 修复之前构建的后端。在 macOS 上,如果没有它,两个进程就无法共享 WS-Discovery 端口,因此守护进程会静默地将所有 其他进程锁定在外部。请重新构建并重新安装后端。 **Image Capture 没有显示任何内容,并且 `/eSCL/ScannerCapabilities` 返回 404。** AirSane 没有注册任何扫描仪。请检查日志: ``` grep -E 'found:|ignoring|published' /var/log/airsaned.log ``` `ignoring airscan:...` 表示 AirSane 的忽略列表匹配到了你的设备—— 请查看 `airsane-ignore.conf`,此代码库安装该文件正是为了解决这个问题。 **`brew upgrade sane-backends` 后一切都坏了。** Homebrew 的 libsane 将其配置和后端目录编译为*带版本的 Cellar 路径*,因此升级会使两者都被孤立。请重新运行 `./build-macos.sh airscan`。 **配置文件位置。** 并不是你在 Homebrew 上所期望的位置—— `$(brew --prefix)/etc/sane.d` 只包含符号链接,而 libsane 从不读取 它。真正的路径是: ``` echo "$(pkg-config --variable=prefix sane-backends)/etc/sane.d" ``` ## 范围与限制 **特意未实现 eSCL mDNS 浏览。** avahi 是一个 Linux 守护进程,没有 macOS 构建版本,因此该发现 路径已被编译排除。WSD 发现是一条独立的 代码路径,从不使用 avahi,因此不受影响。 实际影响是,eSCL 扫描仪不会在 macOS 上被*自动发现*, 尽管如果手动配置它仍然可以工作。在 Bonjour 上方 实现这一点将是一个合理的贡献。 **主机名解析是真实的,而不是存根。** WSD 发现会产生 必须解析的主机名,因此什么都不返回会 彻底破坏自动发现。它在 worker thread 上使用 `getaddrinfo(3)`, 在 macOS 上,它通过 mDNSResponder 解析 `.local`。 **Linux 和 BSD 路径未受影响。** 每一项更改都位于平台条件判断之后。 ## 已测试 基于 **HP LaserJet Pro 200 color MFP M276nw**(仅支持 WSD, 最后固件版本为 2012 年)在 Apple Silicon、macOS 26 上开发。完成了端到端验证: 发现、`scanimage -L`、300 dpi 彩色扫描、Bonjour 广播 以及 Image Capture。 仅测试了该设备型号和 OS 版本。此移植版并不特定于扫描仪—— 其中没有任何针对 M276nw 的特定内容——因此预计其他 WSD 扫描仪也能正常工作,但无论如何都欢迎提供反馈报告。 ## 代码库内容 | 路径 | 用途描述 | |---|---| | `macos-port.patch` | 移植版本身,针对 sane-airscan `master` 分支。涉及 11 个文件,约 1,700 行代码。 | | `build-macos.sh` | 依赖项、克隆、打补丁、构建、安装,适用于两大部分。 | | `airsaned.plist` | AirSane 的 LaunchDaemon,包含原版缺失的日志记录。 | | `airsane-ignore.conf` | AirSane 设备忽略列表,范围已缩小,因此 WSD 设备不会被列入黑名单。 | | `airscan.conf.template` | 手动设备输入,用于多播发现不可用时。 | | `test-compat-eloop.c` | 用于替代 avahi 的事件循环的独立测试。 | | `PORTING.md` | 技术说明:补丁的作用、损坏的内容以及尚未验证的内容。 | ## 许可证 sane-airscan 采用 **GPL-2.0-or-later** 许可,因此此补丁——作为其衍生作品—— 遵循相同的条款。详见 `LICENSE`。 `build-macos.sh` 会在构建时从它们各自的 代码库中获取 sane-airscan 和 AirSane;此处不会重新分发它们的代码。 ## 合并到上游 尚未将其提交到上游。保留平台条件判断结构 正是出于此考虑,并且 `PORTING.md` 记录了每项决策背后的 理由。特别是 `SO_REUSEPORT` 修复,这是一个真正的 Linux/BSD 可移植性 bug,值得单独提交到上游。
标签:Cutter, eSCL, SANE, WSD, 协议转换, 网络扫描仪, 驱动适配