HFP 设备连接

本文讨论音频系统如何确定和处理蓝牙免持配置文件 (HFP) 设备的连接状态信息。

音频驱动程序必须支持 KSPROPERTY_JACK_DESCRIPTION 和维护筛选器工厂上下文中的 IsConnected 字段。 驱动程序在处理 KSPROPERTY_JACK_DESCRIPTION 属性时使用此值。

IOCTL_BTHHFP_DEVICE_GET_CONNECTION_STATUS_UPDATE 成功完成后,音频驱动程序会使用新的连接状态更新 IsConnected。 如果状态已更改,音频驱动程序会引发 KSEVENT_PINCAPS_JACKINFOCHANGE 事件,从而使音频系统重新评估连接状态。 然后,音频驱动程序会调用另一个 IOCTL_BTHHFP_DEVICE_GET_CONNECTION_STATUS_UPDATE 实例来接收下一个状态更改。 如果以前的状态更改请求仍在挂起,则第二次调用将失败,音频驱动程序不会更新其连接状态,且不会对状态更改信息发出另一个请求。

内核流式处理注意事项中所述,音频驱动程序必须支持 KSPROPERTY_ONESHOT_RECONNECTKSPROPERTY_ONESHOT_DISCONNECT。 这些属性的处理程序必须将 REQUESTCONNECT 和 REQUESTDISCONNECT IOCTL 分别发送到 HFP 驱动程序。 这些 IOCTL 会快速完成,并且音频驱动程序需要准备好响应返回的结果。

本文还介绍了音频驱动程序开发人员必须注意的其他蓝牙音频设备连接相关因素。

流声道

流声道表示音频驱动程序对无线带宽的分配。 在大多数情况下,这是 SCO 声道。 但是,管理 SCO 声道状态的一些详细信息完全在 HFP 驱动程序中进行处理。 例如,这包括远程断开连接,这可能是由于 HF 启动到 AG 的音频传输的调用场景(在这种情况下,电脑扮演 AG 的角色)。

音频筛选器引脚状态

音频驱动程序为两个 KS 引脚实现 KS 引脚状态处理程序。 这两个引脚之一需要 SCO 流声道才能无线传输数据。 当其中任一引脚转换为 KSSTATE_ACQUIRE 时,音频驱动程序会通过将 IOCTL_BTHHFP_STREAM_OPEN 发送到 HFP 驱动程序来打开声道。 此异步调用可能需要几秒钟才能完成。 音频驱动程序不需要实现自己的超时机制,应等待 IOCTL 完成再完成转换到 KSSTATE_ACQUIRE。

当两个 KS 引脚转换为 KSSTATE_STOP 时,音频驱动程序会将 IOCTL_BTHHFP_STREAM_CLOSE 发送到 HFP 驱动程序,这可快速完成。

若要确定何时发送 IOCTL_BTHHFP_STREAM_OPENIOCTL_BTHHFP_STREAM_CLOSE,音频驱动程序可以使用简单的引用计数机制来跟踪需要 SCO 流声道的引脚数。 当引用计数从 0 更改为 1 时,音频驱动程序将打开和关闭 SCO 流声道。

IOCTL_BTHHFP_STREAM_OPEN 上,HFP 驱动程序会请求 SCO 声道(如果尚未打开),并使用 SCO 请求的结果完成请求。 在 IOCTL_BTHHFP_STREAM_CLOSE 上,HFP 驱动程序会请求 SCO 声道断开连接(如果已打开)。

远程 SCO 连接和断开连接

在远程 SCO 断开连接时,如果流声道关闭,HFP 驱动程序将不执行任何操作。 如果打开流声道,HFP 驱动程序将启动重新连接计时器。 计时器过期时,如果 SCO 仍然断开连接并且流声道仍处于打开状态,驱动程序会请求 SCO 声道。 请注意,当 SCO 断开连接时,不会无线传输任何音频数据,因此在此期间音频会有一段空隙。 如果 SCO 请求失败,HFP 驱动程序会完成任何调用的 IOCTL_BTHHFP_STREAM_GET_STATUS_UPDATE,向音频驱动程序发出流声道状态更改信号。 这应该很少见,因为远程 SCO 断开连接通常与请求将调用音频传输到音频网关的 HF 设备相关联。 音频驱动程序应将此视为中间流错误条件。

此过程允许 VoIP 应用程序有时间从 CallButtons API 接收音频传输回调,并在 HFP 终结点上干净释放其音频资源,而不是导致流式处理错误。

在远程 SCO 连接上,如果流声道处于打开状态,驱动程序只是接受连接。 如果流声道已关闭,HFP 驱动程序会接受连接并启动断开连接计时器。 当断开连接计时器过期时,如果 SCO 仍处于连接状态并且流声道仍然关闭,驱动程序会中断 SCO 连接。

此过程允许 VoIP 应用程序有时间从 CallButtons API 接收音频传输回调,并在 HFP 终结点上建立音频资源,而无需过早拒绝或关闭 SCO 连接。