Кто нибудь может подсказать данный вопрос.
Инфы в инете мало есть код с мсдн но как том мало помогает.
Сама связь между смартом (вообще тип уст-ва не важен) и компом есть.
Но вот аудипоток с хэдсета на телефон не удается перенаправить. Речь идет о разработке драйвера хандсфри.
Будет работать с определенным софтом. Инстументарий - vs2013, win 8.1, windbg x64 - отладчик. сам драйвер и софт крутятся на виртуальной машине x64 с win 8.1
Разработка только на чистом с и вин апи без вариантов.
Вот код с мсдна
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 структуры и все пассы с ней
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
);
тут цепляю коллбэк функцию которая по логике должна отрабатывать по факту начала разговора
status = EBthSrvConnectionStateConnected(connectionObject);
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,
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 идет собственно запихиваание инфы в буфер.
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 отрабатывает изредка причем сразу после соединения - но никак не по факту голосовой передачи.
Вопрос главный таков - как отловить событие голосовой передачи - куда вешать коллбэк.
Как взять потоки из наушников ясно.