YYUUGGOO/psp-usb-midi
GitHub: YYUUGGOO/psp-usb-midi
为 PSP 自制程序提供符合 USB 标准的 MIDI 1.0 设备能力,支持通过 USB 与主机进行 MIDI 消息的收发。
Stars: 0 | Forks: 0
# PSP USB MIDI
一个适用于 PSP 自制程序的、可重用的、免驱 USB MIDI 1.0 设备库。它被拆分为一个用户态静态库和一个手动加载的内核 PRX。该 PRX 仅包含 USB 枚举和有界 MIDI 传输。
本项工作基于我对 USB 实现所做的一些逆向工程。你可以在 research.md 中查看我的笔记。
该实现仍处于实验阶段,但应该可以在大多数(即使不是全部)运行 ARK-4/5 的机型上工作。
## 功能
- 原生 USB Audio Class 1.0 / MIDIStreaming 1.0 描述符
- 批量 MIDI IN 和 OUT endpoint
- 音符、力度、CC、程序、弯音、系统通用、时钟、传输、活动感应和复位消息
- 1-8 条完整消息的原子非阻塞写入
- 按传输顺序非阻塞读取最多 8 条消息
- 固定容量队列和静态内核传输缓冲区
- 干净的停止、断开取消、PRX 卸载和重新连接
- 无 USB 音频、串口模拟、大容量存储、SysEx 流式传输、回调中的内存分配、闪存写入、插件安装或持久状态
SysEx 不是 1.0 API 的一部分,因为它需要单独的有状态流接口;短消息不会被静默当作 SysEx 处理。
## 构建
```
export PSPDEV="$HOME/pspdev"
export PATH="$PSPDEV/bin:$PATH"
psp-cmake -S . -B build
cmake --build build --parallel
```
该文件夹已在 `dist/` 下包含匹配的预构建工件。全新的构建会在 `build/dist/` 下重新创建相同的布局:
```
dist/PspUsbMidi/
PspUsbMidiConfig.cmake
include/psp_usb_midi.h
lib/libPspUsbMidi.a
kernel/UsbMidiDriver.prx
dist/UsbMidiExample/
EBOOT.PBP
UsbMidiDriver.prx
```
将完整的 `UsbMidiExample` 目录复制到 `ms0:/PSP/GAME/UsbMidiExample/` 以进行最小冒烟测试。
## 在其他 CMake 项目中使用
可以使用 `add_subdirectory` 添加此源码树,或者包含生成的 bundle 配置:
```
include("/path/to/PspUsbMidi/PspUsbMidiConfig.cmake")
target_link_libraries(MyPspApp PRIVATE PspUsbMidi::PspUsbMidi)
```
将 `${PSP_USB_MIDI_DRIVER}` 复制到你的 EBOOT 旁边。应用程序将完整的 Memory Stick 路径传递给 `UsbMidi_Init`:
```
#include
int result = UsbMidi_Init(
"ms0:/PSP/GAME/MyPspApp/UsbMidiDriver.prx");
if (result == 0) {
result = UsbMidi_Start();
}
/* Poll UsbMidi_GetStatus until link_established is nonzero. */
if (result == 0 && UsbMidi_IsConnected()) {
const UsbMidiEvent note_pair[2] = {
{0U, 0U, 0x90U, 60U, 100U},
{0U, 0U, 0x80U, 60U, 0U}
};
result = UsbMidi_Write(note_pair, 2);
}
/* Poll input from the normal application loop. */
UsbMidiEvent input[PSP_USB_MIDI_MAX_BATCH_EVENTS];
int count = UsbMidi_Read(input, PSP_USB_MIDI_MAX_BATCH_EVENTS);
/* Every exit and error path must perform guarded shutdown. */
result = UsbMidi_Shutdown();
```
`UsbMidi_Start` 将总线启动、驱动程序启动和激活作为一个具有逆序回滚的保护性操作来执行。`UsbMidi_Stop` 会停用 USB,但会保留已注册的 PRX 以供稍后的 `UsbMidi_Start` 使用。`UsbMidi_Shutdown` 会停止 USB、注销驱动程序、停止模块并将其卸载。
调用由用户库进行串行化。`UsbMidi_Write` 是非阻塞的,固定的 TX 队列可容纳三个最大大小的批次。`UsbMidi_Read` 是非阻塞的,RX 队列可容纳十个事件。务必检查返回值。在主机连接后保留两秒的保守稳定窗口,这是经过硬件验证的传输机制,之后才会开始队列输出和连续输入。
## 运行时安全性
PRX 仅从应用程序目录加载,并在关机时卸载(而不是作为全局插件加载)。
标签:Bash脚本, C/C++, PSP自制软件, USB MIDI, 事务性I/O, 云资产清单, 内核插件, 客户端加密, 嵌入式开发, 逆向工程, 音频驱动