Linux 上的 MIDI 2.0¶
通用¶
MIDI 2.0 是一个扩展协议,旨在提供比传统 MIDI 1.0 更高的分辨率和更精细的控制。为支持 MIDI 2.0 引入的根本性变化包括:
支持通用 MIDI 数据包 (UMP)
支持 MIDI 2.0 协议消息
UMP 和传统 MIDI 1.0 字节流之间的透明转换
用于属性和配置文件配置的 MIDI-CI
UMP 是一种新的容器格式,用于承载所有 MIDI 协议 1.0 和 MIDI 2.0 协议消息。与以前的字节流不同,它是 32 位对齐的,每个消息可以放在一个数据包中。UMP 可以将事件发送到多达 16 个“UMP 组”,每个 UMP 组包含多达 16 个 MIDI 通道。
MIDI 2.0 协议是一个扩展协议,旨在实现比旧 MIDI 1.0 协议更高的分辨率和更多的控制。
MIDI-CI 是一种高级协议,可以通过特殊 SysEx 的形式与 MIDI 设备进行灵活的配置文件和配置通信。
对于 Linux 实现,内核支持 UMP 传输以及 UMP 上 MIDI 协议的编码/解码,而 MIDI-CI 则通过标准 SysEx 在用户空间中得到支持。
截至本文撰写之时,只有 USB MIDI 设备原生支持 UMP 和 Linux 2.0。UMP 支持本身是相当通用的,因此它可以被其他传输层使用,尽管它也可以以不同方式实现(例如作为 ALSA sequencer 客户端)。
UMP 设备的访问方式有两种:通过 rawmidi 设备访问和通过 ALSA sequencer API 访问。
ALSA sequencer API 已扩展以允许 UMP 数据包的有效载荷。允许在 MIDI 1.0 和 MIDI 2.0 sequencer 客户端之间自由连接,并且事件可以透明转换。
内核配置¶
为支持 MIDI 2.0 添加了以下新配置:CONFIG_SND_UMP、CONFIG_SND_UMP_LEGACY_RAWMIDI、CONFIG_SND_SEQ_UMP、CONFIG_SND_SEQ_UMP_CLIENT 和 CONFIG_SND_USB_AUDIO_MIDI_V2。第一个可见的是 CONFIG_SND_USB_AUDIO_MIDI_V2,当您选择它(设置为 =y)时,将自动选择 UMP 的核心支持(CONFIG_SND_UMP)和 sequencer 绑定(CONFIG_SND_SEQ_UMP_CLIENT)。
此外,CONFIG_SND_UMP_LEGACY_RAWMIDI=y 将启用 UMP 端点的传统 raw MIDI 设备支持。
带 USB MIDI 2.0 的 Rawmidi 设备¶
当设备支持 MIDI 2.0 时,USB 音频驱动程序会探测并默认使用 MIDI 2.0 接口(始终在 altset 1 中找到),而不是 MIDI 1.0 接口(在 altset 0 中)。您也可以通过向 snd-usb-audio 驱动程序模块传递 midi2_enable=0 选项来切换回旧 MIDI 1.0 接口的绑定。
USB 音频驱动程序尝试查询 UMP v1.1 以来提供的 UMP 端点和 UMP 功能块信息,并根据这些信息构建拓扑。当设备较旧且不响应新的 UMP 查询时,驱动程序会回退并根据 USB 描述符中的组终端块 (GTB) 信息构建拓扑。某些设备可能会因意外的 UMP 命令而出现问题;在这种情况下,请向 snd-usb-audio 驱动程序传递 midi2_ump_probe=0 选项以跳过 UMP v1.1 查询。
当探测到 MIDI 2.0 设备时,内核会为设备的每个 UMP 端点创建一个 rawmidi 设备。其设备名称为 /dev/snd/umpC*D*,与 MIDI 1.0 的标准 rawmidi 设备名称 /dev/snd/midiC*D* 不同,以避免传统应用程序错误地访问 UMP 设备。
您可以直接从/向此 UMP rawmidi 设备读取和写入 UMP 数据包数据。例如,如下所示通过 hexdump 读取将以十六进制格式显示卡 0 设备 0 的传入 UMP 数据包。
% hexdump -C /dev/snd/umpC0D0
00000000 01 07 b0 20 00 07 b0 20 64 3c 90 20 64 3c 80 20 |... ... d<. d<. |
与 MIDI 1.0 字节流不同,UMP 是一个 32 位数据包,读取或写入设备的大小也对齐到 32 位(即 4 字节)。
UMP 数据包有效载荷中的 32 位字始终采用 CPU 本地字节序。传输驱动程序负责将 UMP 字从/到系统字节序转换为所需的传输字节序/字节顺序。
当设置了 CONFIG_SND_UMP_LEGACY_RAWMIDI 时,驱动程序会额外创建一个标准的 raw MIDI 设备,即 /dev/snd/midiC*D*。它包含 16 个子流,每个子流对应一个(基于 0 的)UMP 组。传统应用程序可以通过每个子流以 MIDI 1.0 字节流格式访问指定的组。使用 ALSA rawmidi API,您可以打开任意子流,而仅仅打开 /dev/snd/midiC*D* 将最终打开第一个子流。
每个 UMP 端点都可以提供额外信息,这些信息由通过 UMP 1.1 流消息或 USB MIDI 2.0 描述符查询到的信息构建。一个 UMP 端点可以包含一个或多个 UMP 块,其中 UMP 块是 ALSA UMP 实现中引入的抽象,用于表示 UMP 组之间的关联。UMP 块对应于 UMP 1.1 规范中的功能块。当 UMP 1.1 功能块信息不可用时,它会从 USB MIDI 2.0 规范中定义的组终端块 (GTB) 部分填充。
UMP 端点和 UMP 块的信息可以在 proc 文件 /proc/asound/card*/midi* 中找到。例如:
% cat /proc/asound/card1/midi0
ProtoZOA MIDI
Type: UMP
EP Name: ProtoZOA
EP Product ID: ABCD12345678
UMP Version: 0x0000
Protocol Caps: 0x00000100
Protocol: 0x00000100
Num Blocks: 3
Block 0 (ProtoZOA Main)
Direction: bidirection
Active: Yes
Groups: 1-1
Is MIDI1: No
Block 1 (ProtoZOA Ext IN)
Direction: output
Active: Yes
Groups: 2-2
Is MIDI1: Yes (Low Speed)
....
请注意,上面 proc 文件中显示的 Groups 字段表示基于 1 的 UMP 组号(从-到)。
这些额外的 UMP 端点和 UMP 块信息可以通过新的 ioctls SNDRV_UMP_IOCTL_ENDPOINT_INFO 和 SNDRV_UMP_IOCTL_BLOCK_INFO 分别获取。
rawmidi 名称和 UMP 端点名称通常是相同的,在 USB MIDI 的情况下,它是从相应 USB MIDI 接口描述符的 iInterface 中获取的。如果未提供,则作为备用从 USB 设备描述符的 iProduct 中复制。
端点产品 ID 是一个字符串字段,应是唯一的。对于 USB MIDI,它从设备的 iSerialNumber 中复制。
协议能力和实际协议位在 asound.h 中定义。
ALSA Sequencer 与 USB MIDI 2.0¶
除了 rawmidi 接口之外,ALSA sequencer 接口也支持新的 UMP MIDI 2.0 设备。现在,每个 ALSA sequencer 客户端可以设置其 MIDI 版本(0、1 或 2)来声明自己分别是传统、UMP MIDI 1.0 或 UMP MIDI 2.0 设备。第一个传统客户端是发送/接收旧 sequencer 事件的客户端。同时,UMP MIDI 1.0 和 2.0 客户端以 UMP 的扩展事件记录发送和接收。MIDI 版本可以在 snd_seq_client_info 的新 midi_version 字段中看到。
通过指定新的事件标志位 SNDRV_SEQ_EVENT_UMP,UMP 数据包可以嵌入在 sequencer 事件中进行发送/接收。当此标志设置时,事件有 16 字节(128 位)数据载荷用于承载 UMP 数据包。如果没有 SNDRV_SEQ_EVENT_UMP 位标志,事件将作为传统事件处理(最大 12 字节数据载荷)。
当设置了 SNDRV_SEQ_EVENT_UMP 标志时,UMP sequencer 事件的类型字段将被忽略(但应默认设置为 0)。
每个客户端的类型可以在 /proc/asound/seq/clients 中看到。例如:
% cat /proc/asound/seq/clients
Client info
cur clients : 3
....
Client 14 : "Midi Through" [Kernel Legacy]
Port 0 : "Midi Through Port-0" (RWe-)
Client 20 : "ProtoZOA" [Kernel UMP MIDI1]
UMP Endpoint: ProtoZOA
UMP Block 0: ProtoZOA Main [Active]
Groups: 1-1
UMP Block 1: ProtoZOA Ext IN [Active]
Groups: 2-2
UMP Block 2: ProtoZOA Ext OUT [Active]
Groups: 3-3
Port 0 : "MIDI 2.0" (RWeX) [In/Out]
Port 1 : "ProtoZOA Main" (RWeX) [In/Out]
Port 2 : "ProtoZOA Ext IN" (-We-) [Out]
Port 3 : "ProtoZOA Ext OUT" (R-e-) [In]
在这里,您可以找到两种类型的内核客户端,“Legacy”(传统)用于客户端 14,和“UMP MIDI1”(UMP MIDI 1)用于客户端 20,它是一个 USB MIDI 2.0 设备。USB MIDI 2.0 客户端总是将端口 0 赋予“MIDI 2.0”,其余端口从 1 开始用于每个 UMP 组(例如,端口 1 用于组 1)。在此示例中,该设备有三个活跃组(Main、Ext IN 和 Ext OUT),它们作为 sequencer 端口从 1 到 3 暴露。“MIDI 2.0”端口用于 UMP 端点,它与其他 UMP 组端口的区别在于 UMP 端点端口发送来自设备上所有端口的事件(“全捕获”),而每个 UMP 组端口仅发送来自给定 UMP 组的事件。此外,无组 UMP 消息(如 UMP 消息类型 0x0f)仅发送到 UMP 端点端口。
请注意,尽管每个 UMP sequencer 客户端通常创建 16 个端口,但那些不属于任何 UMP 块(或属于非活跃 UMP 块)的端口被标记为非活跃,它们不会出现在 proc 输出中。在上面的示例中,sequencer 端口 4 到 16 存在但未显示在那里。
上面的 proc 文件也显示了 UMP 块信息。在 rawmidi proc 输出中可以找到相同的条目(但有更详细的信息)。
当客户端在不同的 MIDI 版本之间连接时,事件会根据客户端的版本自动转换,不仅在传统和 UMP MIDI 1.0/2.0 类型之间,还在 UMP MIDI 1.0 和 2.0 类型之间进行转换。例如,在传统模式下运行 aseqdump 程序在 ProtoZOA 主端口上,将得到如下输出:
% aseqdump -p 20:1
Waiting for data. Press Ctrl+C to end.
Source Event Ch Data
20:1 Note on 0, note 60, velocity 100
20:1 Note off 0, note 60, velocity 100
20:1 Control change 0, controller 11, value 4
当您在 MIDI 2.0 模式下运行 aseqdump 时,它将接收高精度数据,如下所示:
% aseqdump -u 2 -p 20:1
Waiting for data. Press Ctrl+C to end.
Source Event Ch Data
20:1 Note on 0, note 60, velocity 0xc924, attr type = 0, data = 0x0
20:1 Note off 0, note 60, velocity 0xc924, attr type = 0, data = 0x0
20:1 Control change 0, controller 11, value 0x2000000
同时数据由 ALSA sequencer 核心自动转换。
Rawmidi API 扩展¶
通过新的 ioctl SNDRV_UMP_IOCTL_ENDPOINT_INFO 可以获取额外的 UMP 端点信息。它包含关联的卡和设备号、位标志、协议、UMP 块的数量、端点的名称字符串等。
协议在两个字段中指定:协议能力和当前协议。两者都包含位标志,用于在上字节中指定 MIDI 协议版本(SNDRV_UMP_EP_INFO_PROTO_MIDI1 或 SNDRV_UMP_EP_INFO_PROTO_MIDI2),并在下字节中指定抖动减少时间戳(SNDRV_UMP_EP_INFO_PROTO_JRTS_TX 和 SNDRV_UMP_EP_INFO_PROTO_JRTS_RX)。
一个 UMP 端点最多可以包含 32 个 UMP 块,当前分配的块的数量显示在端点信息中。
每个 UMP 块的信息可以通过另一个新的 ioctl SNDRV_UMP_IOCTL_BLOCK_INFO 获取。需要传递块 ID 号(基于 0)以查询块。接收到的数据包含关联的块方向、第一个关联的组 ID(基于 0)和组的数量、块的名称字符串等。
方向可以是 SNDRV_UMP_DIR_INPUT、SNDRV_UMP_DIR_OUTPUT 或 SNDRV_UMP_DIR_BIDIRECTION。
对于支持 UMP v1.1 的设备,可以通过“流配置请求”消息(UMP 类型 0x0f,状态 0x05)切换 UMP MIDI 协议。当 UMP 核心接收到此类消息时,它会更新 UMP EP 信息以及相应的 sequencer 客户端。
传统 rawmidi 设备号在 rawmidi 信息的新的 tied_device 字段中找到。另一方面,UMP rawmidi 设备号也在传统 rawmidi 信息的 tied_device 字段中找到。
传统 rawmidi 的每个子流都可以根据 UMP FB 状态动态启用/禁用。当选定的子流处于非活动状态时,它在传统 rawmidi 信息的 flags 字段中由位 0x10(SNDRV_RAWMIDI_INFO_STREAM_INACTIVE)表示。
控制 API 扩展¶
引入了新的 ioctl SNDRV_CTL_IOCTL_UMP_NEXT_DEVICE 用于查询下一个 UMP rawmidi 设备,而现有 ioctl SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE 仅查询传统 rawmidi 设备。
要设置要打开的子设备(子流号),请使用 ioctl SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE,就像正常的 rawmidi 一样。
两个新的 ioctl SNDRV_CTL_IOCTL_UMP_ENDPOINT_INFO 和 SNDRV_CTL_IOCTL_UMP_BLOCK_INFO 通过 ALSA control API 提供指定 UMP 设备的 UMP 端点和 UMP 块信息,而无需打开实际的 (UMP) rawmidi 设备。card 字段在查询时被忽略,始终与控制接口的卡绑定。
Sequencer API 扩展¶
midi_version 字段已添加到 snd_seq_client_info 中,用于指示每个客户端当前的 MIDI 版本(0、1 或 2)。当 midi_version 为 1 或 2 时,从 UMP sequencer 客户端读取的对齐方式也从之前的 28 字节更改为 32 字节,以适应扩展的有效载荷。写入的对齐大小不变,但每个事件的大小可能因以下新位标志而异。
SNDRV_SEQ_EVENT_UMP 标志位已添加到每个 sequencer 事件标志中。当此位标志设置时,sequencer 事件将扩展为具有 16 字节而非传统 12 字节的更大有效载荷,并且事件在有效载荷中包含 UMP 数据包。
新的 sequencer 端口类型位(SNDRV_SEQ_PORT_TYPE_MIDI_UMP)指示该端口支持 UMP。
sequencer 端口有新的能力位,用于指示非活动端口(SNDRV_SEQ_PORT_CAP_INACTIVE)和 UMP 端点端口(SNDRV_SEQ_PORT_CAP_UMP_ENDPOINT)。
ALSA sequencer 客户端的事件转换可以通过客户端信息中设置的新过滤位 SNDRV_SEQ_FILTER_NO_CONVERT 来抑制。例如,内核直通客户端(snd-seq-dummy)在内部设置此标志。
端口信息新增了 direction 字段,用于指示端口的方向(SNDRV_SEQ_PORT_DIR_INPUT、SNDRV_SEQ_PORT_DIR_OUTPUT 或 SNDRV_SEQ_PORT_DIR_BIDIRECTION)。
端口信息的另一个附加字段是 ump_group,它指定关联的 UMP 组号(基于 1)。当它非零时,UMP 数据包中的 UMP 组字段在传递到指定组时会更新(更正为基于 0)。如果每个 sequencer 端口是特定于某个 UMP 组的端口,则应设置此字段。
每个客户端可以在 group_filter 位图中设置 UMP 组的附加事件过滤器。该过滤器由基于 1 的组号的位图组成。例如,当位 1 设置时,来自组 1(即第一个组)的消息将被过滤且不被传递。位 0 用于过滤无组 UMP 消息。
为支持 UMP 的客户端新增了两个 ioctl:SNDRV_SEQ_IOCTL_GET_CLIENT_UMP_INFO 和 SNDRV_SEQ_IOCTL_SET_CLIENT_UMP_INFO。它们用于获取和设置与 sequencer 客户端关联的 snd_ump_endpoint_info 或 snd_ump_block_info 数据。USB MIDI 驱动程序从底层 UMP rawmidi 提供这些信息,而用户空间客户端可以通过 *_SET ioctl 提供自己的数据。对于端点数据,将 0 传递给 type 字段;对于块数据,将块号 + 1 传递给 type 字段。为内核客户端设置数据将导致错误。
使用 UMP 1.1,功能块信息可能会动态更改。当从设备接收到功能块更新时,ALSA sequencer 核心会相应地更改相应的 sequencer 端口名称和属性,并通过向 ALSA sequencer 系统端口的通知来通知更改,类似于正常的端口更改通知。
有两种扩展事件类型用于通过系统通知端口通知 UMP 端点和功能块更改:类型 68 (SNDRV_SEQ_EVENT_UMP_EP_CHANGE) 和类型 69 (SNDRV_SEQ_EVENT_UMP_BLOCK_CHANGE)。它们采用新的类型 snd_seq_ev_ump_notify 作为有效载荷,指示已更改的客户端号和功能块号。
MIDI2 USB Gadget 功能驱动程序¶
最新的内核包含对 USB MIDI 2.0 gadget 功能驱动程序的支持,可用于原型设计和调试 MIDI 2.0 功能。
MIDI2 gadget 驱动程序需要启用 CONFIG_USB_GADGET、CONFIG_USB_CONFIGFS 和 CONFIG_USB_CONFIGFS_F_MIDI2。
此外,要使用 gadget 驱动程序,您需要一个工作的 UDC 驱动程序。在下面的示例中,我们使用在 PC 和 VM 上用于调试目的的 dummy_hcd 驱动程序(通过 CONFIG_USB_DUMMY_HCD 启用)。还有其他 UDC 驱动程序,取决于平台,它们也可以用于真实设备。
首先,在运行 gadget 的系统上,加载 libcomposite 模块:
% modprobe libcomposite
然后您将在 configfs 空间(通常是现代操作系统上的 /sys/kernel/config)下找到 usb_gadget 子目录。然后创建一个 gadget 实例并在其中添加配置,例如:
% cd /sys/kernel/config
% mkdir usb_gadget/g1
% cd usb_gadget/g1
% mkdir configs/c.1
% mkdir functions/midi2.usb0
% echo 0x0004 > idProduct
% echo 0x17b3 > idVendor
% mkdir strings/0x409
% echo "ACME Enterprises" > strings/0x409/manufacturer
% echo "ACMESynth" > strings/0x409/product
% echo "ABCD12345" > strings/0x409/serialnumber
% mkdir configs/c.1/strings/0x409
% echo "Monosynth" > configs/c.1/strings/0x409/configuration
% echo 120 > configs/c.1/MaxPower
此时,必须存在一个子目录 ep.0,这是 UMP 端点的配置。您可以填充端点信息,例如:
% echo "ACMESynth" > functions/midi2.usb0/iface_name
% echo "ACMESynth" > functions/midi2.usb0/ep.0/ep_name
% echo "ABCD12345" > functions/midi2.usb0/ep.0/product_id
% echo 0x0123 > functions/midi2.usb0/ep.0/family
% echo 0x4567 > functions/midi2.usb0/ep.0/model
% echo 0x123456 > functions/midi2.usb0/ep.0/manufacturer
% echo 0x12345678 > functions/midi2.usb0/ep.0/sw_revision
默认 MIDI 协议可以设置为 1 或 2
% echo 2 > functions/midi2.usb0/ep.0/protocol
然后,您可以在此端点子目录下找到一个子目录 block.0。它定义了功能块信息:
% echo "Monosynth" > functions/midi2.usb0/ep.0/block.0/name
% echo 0 > functions/midi2.usb0/ep.0/block.0/first_group
% echo 1 > functions/midi2.usb0/ep.0/block.0/num_groups
最后,链接配置并启用它
% ln -s functions/midi2.usb0 configs/c.1
% echo dummy_udc.0 > UDC
其中 dummy_udc.0 是一个示例,它会因系统而异。您可以在 /sys/class/udc 中找到 UDC 实例,并传入找到的名称代替:
% ls /sys/class/udc
dummy_udc.0
现在,MIDI 2.0 gadget 设备已启用,gadget 主机将通过 f_midi2 驱动程序创建一个包含 UMP rawmidi 设备的新声卡实例
% cat /proc/asound/cards
....
1 [Gadget ]: f_midi2 - MIDI 2.0 Gadget
MIDI 2.0 Gadget
在连接的主机上,也应该出现类似的卡,但卡和设备名称是在上面的 configfs 中给出的
% cat /proc/asound/cards
....
2 [ACMESynth ]: USB-Audio - ACMESynth
ACME Enterprises ACMESynth at usb-dummy_hcd.0-1, high speed
您可以在 gadget 端播放 MIDI 文件
% aplaymidi -p 20:1 to_host.mid
这将显示为连接主机上的 MIDI 设备输入
% aseqdump -p 20:0 -u 2
反之亦然,连接主机上的播放也会在 gadget 上作为输入工作。
每个功能块可以有不同的方向和 UI 提示,通过 direction 和 ui_hint 属性指定。传递 1 表示仅输入,2 表示仅输出,3 表示双向(默认值)。例如:
% echo 2 > functions/midi2.usb0/ep.0/block.0/direction
% echo 2 > functions/midi2.usb0/ep.0/block.0/ui_hint
当您需要多个功能块时,可以动态创建子目录 block.1、block.2 等,并在链接之前在上述配置过程中对其进行配置。例如,为键盘创建第二个功能块:
% mkdir functions/midi2.usb0/ep.0/block.1
% echo "Keyboard" > functions/midi2.usb0/ep.0/block.1/name
% echo 1 > functions/midi2.usb0/ep.0/block.1/first_group
% echo 1 > functions/midi2.usb0/ep.0/block.1/num_groups
% echo 1 > functions/midi2.usb0/ep.0/block.1/direction
% echo 1 > functions/midi2.usb0/ep.0/block.1/ui_hint
block.* 子目录也可以动态删除(block.0 除外,它是持久的)。
要为 MIDI 1.0 I/O 分配一个功能块,请在 is_midi1 属性中进行设置。1 表示 MIDI 1.0,2 表示低速连接的 MIDI 1.0。
% echo 2 > functions/midi2.usb0/ep.0/block.1/is_midi1
要禁用 gadget 驱动程序中 UMP 流消息的处理,请在顶级配置中将 0 传递给 process_ump 属性
% echo 0 > functions/midi2.usb0/process_ump
altset 0 上的 MIDI 1.0 接口也受 gadget 驱动程序支持。当连接主机选择 MIDI 1.0 接口时,gadget 上的 UMP I/O 会相应地从/转换为 USB MIDI 1.0 数据包,而 gadget 驱动程序则通过 UMP rawmidi 与用户空间保持通信。
MIDI 1.0 端口根据每个功能块中的配置设置。例如:
% echo 0 > functions/midi2.usb0/ep.0/block.0/midi1_first_group
% echo 1 > functions/midi2.usb0/ep.0/block.0/midi1_num_groups
上面的配置将为 MIDI 1.0 接口启用组 1(索引 0)。请注意,这些组必须是为功能块本身定义的组。
gadget 驱动程序也支持一个以上的 UMP 端点。与功能块类似,您可以在卡顶层配置下创建新的子目录 ep.1 来启用新的端点
% mkdir functions/midi2.usb0/ep.1
并在那里创建一个新的功能块。例如,为这个新端点的功能块创建 4 个组:
% mkdir functions/midi2.usb0/ep.1/block.0
% echo 4 > functions/midi2.usb0/ep.1/block.0/num_groups
现在,您总共将拥有 4 个 rawmidi 设备:前两个是用于端点 0 和端点 1 的 UMP rawmidi 设备,另外两个是与 EP 0 和 EP 1 对应的传统 MIDI 1.0 rawmidi 设备。
gadget 上的当前 altsetting 可以通过 RAWMIDI 接口的控制元素“Operation Mode”来获取。例如,您可以通过在 gadget 主机上运行 amixer 程序来读取它,如下所示:
% amixer -c1 cget iface=RAWMIDI,name='Operation Mode'
; type=INTEGER,access=r--v----,values=1,min=0,max=2,step=0
: values=2
该值(在返回的第二行中显示为 : values=)表示 1 代表 MIDI 1.0 (altset 0),2 代表 MIDI 2.0 (altset 1),0 代表未设置。
目前,绑定后无法更改配置。