大家好,我又来了。这次来折腾点不一样的。
起因是收到了一台来自群友的 ThinkPad,尝试通过恢复介质为其重装系统(四张 CD)。
然后很不幸我手头的光盘质量不太行,刻了好几张都是 CRC 校验错误。
于是想起了群友 driver1998 利用 Linux Gadget File CD 功能搓了一个光驱模拟器,并且还是用 Milk-V Duo 实现的,RISC-V + Retro Computing 这一波确实是我没想到的。
介绍视频见 史前大坑,USB光驱模拟器终于做完了[藏狐]。虽然主要工作就是这个UI[辣眼睛]_哔哩哔哩_bilibili
本次登场嘉宾:
- Milk-V Duo (CV1800B, 64M)
- EC11 旋转编码器(某宝售价 ~¥3.6)
- 128*96 OLED 屏幕一块(SSD1306 驱动,SPI/I²C 双接口,本次使用 SPI,某宝售价 ~¥10)
- 杜邦线、XH2.54 排针若干(或者面包板,我只有杜邦线,就这样吧 xD)
- 存储卡一张
- USB Type-C 数据线一条
使用到的系统镜像:duo-buildroot-sdk-v2
测试报告见:https://matrix.ruyisdk.org/reports/Duo-BuildRoot-README_v2/
使用到的开源项目 DiscEmu:https://github.com/driver1998/DiscEmu
Fork 版,添加了 I2C 屏幕和 Duo 256M / Duo S 支持: https://github.com/slzKud/DiscEmu
(两个版本主要区别是 Duo 256M/Duo S 支持,按需取用即可,这里用的是 fork 版。注意 pinmux 可能不一样。)
步骤比较简单:
- 烧好系统镜像
- 连好外设
- 上电开机,给分区扩个容。
- (可选)编译并配置 uMTP-REsponder 以支持 MTP 文件传输
- 将所有需要的二进制和配置文件等传输到开发板
- 把需要的光盘镜像放进去
- Enjoy
准备工作
烧镜像比较简单,直接 dd 进存储卡即可,当然也可以考虑使用 ruyi device provison。
外设连接因为 pin 比较多,还请慢慢来。
可以对着 Duo 的文档看看 Duo Pinmux: https://milkv.io/zh/docs/duo/application-development/pinmux
OLED 屏幕一共六条线:
(建议对照供应商的 datasheet,比如我手上这个是双模的,靠电阻切换,SCK 的丝印就是 I²C 的 SCL,而数据管脚 MOSI 则写的是 SDA,另有一些模块这个地方会标记 D0/D1,以实际情况为准)
| Duo | OLED |
|---|---|
| GP7/PIN#10 | MOSI/数据 |
| GP6/PIN#9 | SCK/时钟 |
| GP22/PIN#29 | RES |
| GP21/PIN#27 | DC |
| 任一 GND,如 PIN#28 | GND |
| 3V3(OUT)/PIN#36 | VCC |
EC11 旋转编码器五条线:
| Duo | EC11 |
|---|---|
| GP20 | S1 |
| GP19 | S2 |
| GP18 | KEY |
| VBUS/PIN#40 | 5V/VCC |
| 任一 GND,如 PIN#38 | GND |
软件准备
下载 DiscEmu 的 release 二进制并解压。
将 disc-emu二进制和 run_usb.sh放在 /mnt/data目录下。
在 /mnt/data新建一个脚本auto.sh:
OLD_PWD=$PWD
cd /mnt/data
nohup ./disc-emu
cd $OLD_PWD
移除/mnt/system/usb.sh以免冲突。
因为我打算在 Duo 上用 MTP,所以还需要手动编译 uMTP-REsponder。
这一步因为需要用到 Duo 的交叉编译工具链,使用了 ruyi 包管理器来简化配置过程。
#安装 ruyi 包管理器
wget https://mirror.iscas.ac.cn/ruyisdk/ruyi/tags/0.41.0/ruyi-0.41.0.amd64
chmod +x ruyi-0.41.0.amd64
sudo cp ruyi-0.41.0.amd64 /usr/local/bin/ruyi
#更新元数据,安装工具链并创建虚拟环境
ruyi update
ruyi install gnu-milkv-milkv-duo-musl-bin
ruyi venv -t gnu-milkv-milkv-duo-musl-bin milkv-duo venv-duo
source venv-duo/bin/ruyi-activate
#检查工具链版本
riscv64-unknown-linux-musl-gcc -v
#拉取源码并编译
git clone https://github.com/viveris/uMTP-Responder
cd uMTP-Responder
CC=riscv64-unknown-linux-musl-gcc make -j$(nproc)
然后就可以在当前目录下找到编译好的 umtprd二进制了。
将umtprd二进制放在 /usr/bin下,并在/etc/umtprd/umtprd.conf写入如下内容:
loop_on_disconnect 1
storage "/mnt/data/isos" "isos" "rw"
# Set the USB manufacturer string
manufacturer "Cvitek"
# Set the USB Product string
product "DiscEmu"
# Set the USB Serial number string
serial "0123456789"
# Set the MTP firmware version
firmware_version "Rev A"
# Set the USB interface string. Should be always "MTP"
interface "MTP"
# Set the USB Vendor ID, Product ID and class
usb_vendor_id 0x1D6B # Linux Foundation
usb_product_id 0x0100 # PTP Gadget
usb_class 0x6 # Image
usb_subclass 0x1 # Still Imaging device
usb_protocol 0x1 #
# Device version
usb_dev_version 0x3008
#
# USB gadget device driver path
#
########################################################################
#
# -- Generic FunctionFS Mode --
#
########################################################################
usb_functionfs_mode 0x1
usb_dev_path "/dev/usb-ffs/mtp/ep0"
usb_epin_path "/dev/usb-ffs/mtp/ep1"
usb_epout_path "/dev/usb-ffs/mtp/ep2"
usb_epint_path "/dev/usb-ffs/mtp/ep3"
usb_max_packet_size 0x200
然后就可以把需要的 ISO 镜像放进 /mnt/data/isos了。放好后会在 Image Browser 里看到它们。
成品效果:
(前后两张图的线重新连过,请勿直接参考)
(手头没几条线了只好用相同颜色的了,勿喷 xD)
(MTP 不清楚为什么没有工作,可能和我用了 v2 的镜像有关系;各位如果想复刻的话可以试试用 v1 镜像。)
(对 ISO 镜像有 2.2GB 的限制,有内核补丁可以绕过,如遇到此问题,可以考虑用 driver1998 的 fork 版 duo-buildroot-sdk 镜像:https://github.com/driver1998/duo-buildroot-sdk/releases)
(虽然非常好用,但还是有个坏消息:兼容性确实可能有点问题,在部分老设备上真的会认不出来 xD)
欢迎各位复现/吐槽丁丑小队的所有测试结果。
如果有对我们的测试方法/结果有任何建议/问题,欢迎直接在 GitHub 开 issue,或者在论坛 @ 我们、回帖询问。





