Кто нибудь может подсказать данный вопрос.
Инфы в инете мало есть код с мсдн но как том мало помогает.
Сама связь между смартом (вообще тип уст-ва не важен) и компом есть.
Но вот аудипоток с хэдсета на телефон не удается перенаправить. Речь идет о разработке драйвера хандсфри.
Будет работать с определенным софтом. Инстументарий - vs2013, win 8.1, windbg x64 - отладчик. сам драйвер и софт крутятся на виртуальной машине x64 с win 8.1
Разработка только на чистом с и вин апи без вариантов.
Вот код с мсдна
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
MyTraceFunc(0, TRACE_LEVEL_INFORMATION, DBG_CONNECT, "%s:%s@%d Indication:0x%x\n", __FUNCTION__, __FILE__, __LINE__, Indication);
switch(Indication)
{
case ScoIndicationAddReference:
case ScoIndicationReleaseReference:
break;
case ScoIndicationRemoteConnect:
{
PEBTH_SERVER_CONTEXT devCtx = (PEBTH_SERVER_CONTEXT)Context;
// тут отрабатывает при исходящем и входящем звонках
EBthSrvSendConnectResponse(devCtx, Parameters);
break;
}
case ScoIndicationRemoteDisconnect:
{
//
// We register EBthSrvConnectionIndicationCallback for disconnect
//
//NT_ASSERT(FALSE);
break;
}
//case IndicationRemoteConfigRequest:
//case IndicationRemoteConfigResponse:
//case IndicationFreeExtraOptions:
break;
}
Далее сама функция - по сути наполнение BRB структуры и все пассы с ней
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
brb = (struct _BRB_SCO_OPEN_CHANNEL*) &(connection->ConnectDisconnectBrb);
DevCtx->Header.ProfileDrvInterface.BthReuseBrb((PBRB)brb, BRB_SCO_OPEN_CHANNEL_RESPONSE);
brb->Hdr.ClientContext[0] = connectionObject;
brb->BtAddress = ConnectParams->BtAddress;
brb->TransmitBandwidth = 8000;
brb->ReceiveBandwidth = 8000;
brb->MaxLatency = 0xffff;
brb->PacketType = SCO_HV1 | SCO_HV3 | SCO_EV3; // SCO_PKT_ALL;
brb->ContentFormat = SCO_VS_SETTING_DEFAULT; //SCO_VS_IN_CODING_LINEAR | SCO_VS_IN_SAMPLE_SIZE_8BIT | SCO_VS_AIR_CODING_FORMAT_CVSD;
//brb->Reserved = ;
brb->RetransmissionEffort = SCO_RETRANSMISSION_NONE;
brb->ChannelHandle = ConnectParams->ConnectionHandle;
brb->Response = SCO_CONNECT_RSP_RESPONSE_SUCCESS;
brb->ChannelFlags = SCO_CF_LINK_SUPPRESS_PIN | SCO_CF_LINK_AUTHENTICATED;
//
// Get notifications about disconnect
//
brb->CallbackFlags = CALLBACK_DISCONNECT;
brb->Callback = &EBthSrvConnectionIndicationCallback;
brb->CallbackContext = connectionObject;
brb->ReferenceObject = (PVOID) WdfDeviceWdmGetDeviceObject(DevCtx->Header.Device);
status = EBthSharedSendBrbAsync(
DevCtx->Header.IoTarget,
connection->ConnectDisconnectRequest,
(PBRB) brb,
sizeof(*brb),
EBthSrvRemoteConnectResponseCompletion,
brb
);
тут цепляю коллбэк функцию которая по логике должна отрабатывать по факту начала разговора
1.
status = EBthSrvConnectionStateConnected(connectionObject);
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
EBthSrvConnectionStateConnected(
WDFOBJECT ConnectionObject
)
/*++
Routine Description:
This routine is invoked by EBthSrvRemoteConnectResponseCompletion
when connect response is completed.
We initialize and submit continous readers in this routine.
Arguments:
ConnectionObject - Connection object for which connect response completed
--*/
{
PEBTH_CONNECTION connection;
NTSTATUS status = STATUS_SUCCESS;
TRACEFUNC();
connection = GetConnectionObjectContext(ConnectionObject);
status = EBthConnectionObjectInitializeContinuousReader(
connection,
EBthSrvConnectionObjectContReaderReadCompletedCallback,
EBthSrvConnectionObjectContReaderFailedCallback,
EBthMaxDataLength
);
if (!NT_SUCCESS(status))
{
goto exit;
}
status = EBthConnectionObjectContinuousReaderSubmitReaders(
connection
);
if (!NT_SUCCESS(status))
{
goto exit;
}
exit:
return status;
}
Вот сам кллбэк - EBthSrvConnectionObjectContReaderReadCompletedCallback,
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
VOID
EBthSrvConnectionObjectContReaderReadCompletedCallback(
_In_ PEBTH_DEVICE_CONTEXT_HEADER DevCtxHdr,
_In_ PEBTH_CONNECTION Connection,
_In_ PVOID Buffer,
_In_ size_t BufferLength
)
/*++
Routine Description:
This routine is invoked by the continous reader when read completes.
We in turn call EBthSrvSendEcho to perform echo.
Arguments:
DevCtxHdr - Device context
Connection - Connection whose continous reader had read completion
Bufer - Buffer which received read
SrcBufferLength - Length of read
--*/
{
TRACEFUNC();
EBthSrvSendEcho(
DevCtxHdr,
Connection,
Buffer,
BufferLength
);
}
В самой EBthSrvSendEcho идет собственно запихиваание инфы в буфер.
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
VOID
EBthSrvSendEcho(
_In_ PEBTH_DEVICE_CONTEXT_HEADER DevCtxHdr,
_In_ PEBTH_CONNECTION Connection,
_In_ PVOID SrcBuffer,
_In_ size_t SrcBufferLength
)
/*++
Routine Description:
Performs L2Cap transfer to client to do the echo.
This routine is invoked by continuous reader read completion callback
(EBthSrvConnectionObjectContReaderReadCompletedCallback).
Arguments:
DevCtxHdr - Device context
Connection - Connection whose continous reader had read completion
SrcBuffer - Source buffer for the echo
SrcBufferLength - Length of the source buffer
--*/
{
NTSTATUS status;
WDF_OBJECT_ATTRIBUTES attributes;
WDFREQUEST request = NULL;
WDFMEMORY memory = NULL;
PVOID dataBuffer = NULL;
//struct _BRB_L2CA_ACL_TRANSFER *brb = NULL;
struct _BRB_SCO_TRANSFER *brb = NULL;
TRACEFUNC();
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, BRB);
attributes.ParentObject = DevCtxHdr->Device;
status = WdfRequestCreate(
&attributes,
DevCtxHdr->IoTarget,
&request
);
MyTraceFunc(0, TRACE_LEVEL_VERBOSE, DBG_CONNECT, "WdfRequestCreate:0x%x\n", request);
if (!NT_SUCCESS(status))
{
MyTraceFunc(0, TRACE_LEVEL_ERROR, DBG_CONT_READER,
"Creating request for echo failed, Status code 0x%x\n",
status
);
goto exit;
}
if (SrcBufferLength <= 0)
{
MyTraceFunc(0, TRACE_LEVEL_ERROR, DBG_CONT_READER,
"SrcBufferLength has an invalid value: %I64d\n",
SrcBufferLength
);
status = STATUS_INVALID_PARAMETER;
goto exit;
}
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
attributes.ParentObject = request;
status = WdfMemoryCreate(
&attributes,
NonPagedPool,
POOLTAG_EBTH,
SrcBufferLength,
&memory,
&dataBuffer
);
if (!NT_SUCCESS(status))
{
MyTraceFunc(0, TRACE_LEVEL_ERROR, DBG_CONT_READER,
"Creating memory for pending read failed, Status code 0x%x\n",
status
);
goto exit;
}
memcpy(dataBuffer, SrcBuffer, SrcBufferLength);
//brb = (struct _BRB_L2CA_ACL_TRANSFER *)GetEchoRequestContext(request);
brb = (struct _BRB_SCO_TRANSFER *)GetEchoRequestContext(request);
status = EBthConnectionObjectFormatRequestForL2CaTransfer(
Connection,
request,
&brb,
memory,
ACL_TRANSFER_DIRECTION_OUT
);
if (!NT_SUCCESS(status))
{
goto exit;
}
//
// Set a CompletionRoutine callback function.
//
WdfRequestSetCompletionRoutine(
request,
EBthSrvWriteCompletion,
Connection
);
if (FALSE == WdfRequestSend(
request,
DevCtxHdr->IoTarget,
NULL
))
{
status = WdfRequestGetStatus(request);
MyTraceFunc(0, TRACE_LEVEL_ERROR, DBG_CONT_READER,
"Request send failed for request 0x%p, Brb 0x%p, Status code 0x%x\n",
request,
brb,
status
);
goto exit;
}
exit:
if (!NT_SUCCESS(status))
{
if (NULL != request)
{
MyTraceFunc(0, TRACE_LEVEL_VERBOSE, DBG_CONNECT, "WdfObjectDelete:0x%x\n", request);
WdfObjectDelete(request);
}
//
// If we failed disconnect
//
EBthSrvDisconnectConnection(Connection);
}
}
Код перенял от коллеги - объяснить он толком ничего не может.
У меня функция EBthSrvSendEcho отрабатывает изредка причем сразу после соединения - но никак не по факту голосовой передачи.
Вопрос главный таков - как отловить событие голосовой передачи - куда вешать коллбэк.
Как взять потоки из наушников ясно.