windows 创建SCO客户端配置文件驱动程序,用于从蓝牙耳机进行呼叫控制

0ejtzxu1  于 2023-11-21  发布在  Windows
关注(0)|答案(1)|浏览(305)

概述

大家好,我正在开发一个软件电话的功能(在Windows上运行),这是使接听/结束从蓝牙耳机或扬声器电话呼叫.我已经阅读并按照免提配置文件规范一步一步做:https://www.bluetooth.com/specifications/specs/hands-free-profile-1-8/
目前,我已经设置了“服务级连接”发送/接收AT命令遵循规范。

问题

1.我不知道如何设置音频连接,知道SCO连接.它似乎需要写一个自定义驱动程序,我没有经验.我从微软看到的唯一教程是非常难以理解:https://learn.microsoft.com/en-us/windows-hardware/drivers/bluetooth/creating-a-sco-client-connection-to-a-remote-device
1.有没有办法绕过这一步而不编写驱动程序?
1.如果我可以设置音频连接,那么我可以从蓝牙耳机接听/结束呼叫吗?
这是服务级连接图:https://i.stack.imgur.com/9KMlb.png
这是应答呼叫图:https://i.stack.imgur.com/M8WZf.png

uqjltbpv

uqjltbpv1#

分享我的发现和解决方案后,争取了几天。可能更适合反向工程stackexchange,但无论如何...
我不得不说,最近我对微软的技术决策越来越“印象深刻”,而蓝牙免提功能更是锦上添花。
免提配置文件已经提供了相当长的一段时间/几年了,当微软最终在Windows下原生地获得它时,没有公共API可以使用。就像OP一样,我想在SIP Softphone的实现中使用我的BT Handsfree(Plantronics PLT 70,如果重要的话)及其所有功能。

  • 以下内容适用于Microsoft蓝牙堆栈。在Win10 21 H2(19044.3086)下测试;
  • 设备应正常与Windows配对;
  • 必须在设备属性->服务选项卡中选中“免提电话”服务;
  • 一个人必须有“蓝牙音频网关服务”/ BTAGService停止(可能禁用,以保持它停止后,蓝牙无线电被插入)。
    第1部分打开一个设备驱动程序句柄,指向免提设备的bthenum驱动程序所公开的免提服务示例。我不会详细介绍如何找到设备路径,但可以使用SetupApi/Registry来找到它。代码如下( Delphi 风格,版本5):
  1. hBthf := CreateFile('\\?\BTHENUM#{0000111e-0000-1000-8000-00805f9b34fb}_VID&0001000f_PID&0000#8&F070F74&0&48C1ACF774C4_C00000000#{bd41df2d-addd-4fc9-a194-b9881d2a2efa}\service',
  2. GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE,
  3. nil, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);

字符串
路径中的48 C1 ACF 774 C4是我的设备MAC地址。需要FILE_FLAG_OVERLAPPED,因为必须同时向驱动程序发出请求。
旋转一个线程,该线程将连续发送0x 2A 0024 IOCTL(未记录,因此逆向工程)与4字节的输出缓冲区的设备驱动程序句柄。在这个线程上的驱动程序将通知你,并会提出请求,每当一个试图访问免提使用多媒体API的音频通道-即任何应用程序试图记录/播放它;在我的情况下,播放音频通道被命名为“耳机(PLT_M70免提AG音频)"。一旦IOCTL完成,通知/请求代码将在4字节缓冲区(DWORD/INT)中。

  1. ...
  2. var
  3. ol: TOverlapped;
  4. request: Integer;
  5. br: Cardinal;
  6. ...
  7. DeviceIoControl(hBthf, $2A0024, nil, 0, @request, 4, br, @ol)


一个人需要回答的“请求”是4、5和6。我怀疑其他代码是通知(1可能是SCO通道向上,2是SCO通道向下,0是其他的?)。应答用IOCTL代码0x 2A 0028和一个8字节的输入缓冲区发送回驱动程序。缓冲区的内容是:一个DWORD与请求代码,这是一个答复,然后另一个字节与0x 01和另一个与0x 02,然后两个零字节。)这些字节的含义是什么。我尝试了不同的值与1-1,3-3,它似乎(无疑)他们并不重要。代码:

  1. ...
  2. var
  3. b: array of byte;
  4. ...
  5. SetLength(b, 8);
  6. ...
  7. if (request = 4) or (request = 6) then
  8. begin
  9. PDWORD(@b[0])^ := request;
  10. PDWORD(@b[4])^ := $0201;
  11. DeviceIoControl(hBthf, $2A0028, @b[0], 8, nil, 0, br, @ol);
  12. end;

第2部分解决方案的另一部分是集成到OP已经制定的RFCOMM通道上的AT命令聊天中。一旦建立了服务级别连接,就必须向驱动程序发出这些IOCTL:

  1. // Service Level Connection status
  2. // -> 0x2A0004, inBuffer = 0x01 0x00 0x00 0x00 0x9B 0x00 0x00 0x00
  3. // -> 0x2A0020, null input, null output
  4. // Set codec
  5. // -> 0x2A0014, inBuffer 0x01 0x00 0x00 0x00 (DWORD Codec ID 1 or 2)


在上述“神奇”IOCTL之后,免提音频网关设备将被“发现”并在Windows中提供给应用程序播放/录制。
最后一点:在解决方案的第一部分中没有请求处理程序线程,设备仍然会出现在Windows中,但是任何尝试使用它的应用程序都会挂起。“取消挂起”的解决方案是删除无线电(如果它是可移动的USB加密狗)。不确定设备管理器中的“禁用”/“启用”是否有效。

展开查看全部

相关问题