📄 bthsco.cxx
字号:
}
int iRet = ERROR_SUCCESS;
int iResult = StatusToError(status, ERROR_PROTOCOL_UNREACHABLE);
if (status == 0) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ConnectionComplete_Event :: creating link\n"));
Link *pLink = new Link;
if (pLink) {
pLink->b = *pba;
pLink->hScoConnection = connection_handle;
pLink->hAclConnection = pCall->uParameters.Connect.hAclConnection;
pLink->pNext = gpLayerState->pLinks;
gpLayerState->pLinks = pLink;
} else {
IFDBG(DebugOut (DEBUG_ERROR, L"SCO :: sco_ConnectionComplete_Event ERROR_OUTOFMEMORY\n"));
iResult = ERROR_OUTOFMEMORY;
iRet = ERROR_OUTOFMEMORY;
}
}
// set params
if (pCall->fCallType == CALL_TYPE_CONNECT) {
pCall->uParameters.Connect.hScoConnection = connection_handle;
} else if (pCall->fCallType == CALL_TYPE_ACCEPT_INCOMING_CONNECTION) {
pCall->uParameters.AcceptIncomingConnection.Address = *pba;
pCall->uParameters.AcceptIncomingConnection.hScoConnection = connection_handle;
} else {
SVSUTIL_ASSERT(!"wrong fCallType!");
iResult = ERROR_INTERNAL_ERROR;
iRet = ERROR_INTERNAL_ERROR;
}
// finish the call
CallRemove (pCall);
CallSignal (pCall, iResult);
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ConnectionComplete_Event :: Completed call 0x%08x\n", pCall));
gpLayerState->Unlock ();
return iRet;
}
static int sco_DisconnectionComplete_Event (void *pUserContext,
void *pCallContext,
unsigned char status,
unsigned short connection_handle,
unsigned char reason)
{
if (! gpLayerState) {
return ERROR_SERVICE_NOT_ACTIVE;
}
gpLayerState->Lock ();
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_DisconnectionComplete_Event :: call 0x%08x, status 0x%02x handle 0x%04x reason %#x\n", pCallContext, status, connection_handle, reason));
if (! gpLayerState->fIsRunning) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_DisconnectionComplete_Event :: shutting down\n"));
gpLayerState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
if (status == 0) {
Link *pLink = gpLayerState->pLinks;
Link *pParent = NULL;
// find the link
while (pLink) {
if (pLink->hScoConnection == connection_handle)
break;
pParent = pLink;
pLink = pLink->pNext;
}
if (pLink) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_DisconnectionComplete_Event :: deleting Link h=0x%04x\n", connection_handle));
if (pParent)
pParent->pNext = pLink->pNext;
else
gpLayerState->pLinks = pLink->pNext;
delete pLink;
StackNotifyUser(SCO_LINK_DISCONNECT);
} else {
IFDBG(DebugOut (DEBUG_WARN, L"SCO :: sco_DisconnectionComplete_Event :: h=0x%04x not found\n", connection_handle));
}
} else {
IFDBG(DebugOut (DEBUG_WARN, L"SCO :: sco_DisconnectionComplete_Event :: h=0x%04x status=%d\n", connection_handle, status));
}
Call *pCall = CallVerify ((Call*)pCallContext, CALL_TYPE_DISCONNECT);
if (! pCall) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_DisconnectionComplete_Event :: no context\n"));
gpLayerState->Unlock ();
return ERROR_NOT_FOUND;
}
// finish the call
CallRemove (pCall);
CallSignal (pCall, StatusToError(status, ERROR_PROTOCOL_UNREACHABLE));
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_DisconnectionComplete_Event :: Completed call 0x%08x\n", pCall));
gpLayerState->Unlock ();
return ERROR_SUCCESS;
}
static int sco_ConnectionRequest_Event (void *pUserContext,
void *pCallContext, // NULL
BD_ADDR *pba,
unsigned int class_of_device,
unsigned char link_type)
{
if (! gpLayerState) {
return ERROR_SERVICE_NOT_ACTIVE;
}
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ConnectionRequest_Event :: pCallContext=%#x, addr=%04x%08x, class_of_device=%#x, link_type=%#x\n",
pCallContext, pba->NAP, pba->SAP, class_of_device, link_type));
if (link_type != BT_LINK_TYPE_SCO) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ConnectionRequest_Event :: non-SCO link type recved\n"));
return ERROR_PROTOCOL_UNREACHABLE;
}
gpLayerState->Lock ();
if (! gpLayerState->fIsRunning) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ConnectionRequest_Event :: shutting down\n"));
gpLayerState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
//
// NOTE NOTE NOTE NOTE NOTE
// CallInsert() inserts into the head of the list.
// We must find the LAST Call on the list that meets the address filter requirements
// so that the first person who called sco_RecvConnection is the first one to be released
//
Call *pCall = NULL;
Call *pProbe = gpLayerState->pCalls;
while (pProbe)
{
if (pProbe->fCallType == CALL_TYPE_WAIT_FOR_INCOMING_CONNECTION) {
if ( (pProbe->uParameters.WaitIncomingConnection.bAllAddresses)
|| (pProbe->uParameters.WaitIncomingConnection.Address == *pba)) {
pCall = pProbe;
}
}
pProbe = pProbe->pNext;
}
if (pCall) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ConnectionRequest_Event %#x :: accepting connection\n", pCall));
pCall->fCallType = CALL_TYPE_ACCEPT_INCOMING_CONNECTION;
pCall->fInvokedHCI = TRUE;
HCI_AcceptConnectionRequest_In pFunction = gpLayerState->hci_if.hci_AcceptConnectionRequest_In;
HANDLE hHCI = gpLayerState->hHCI;
int iRes = ERROR_INTERNAL_ERROR;
gpLayerState->AddRef ();
gpLayerState->Unlock ();
__try {
iRes = pFunction (hHCI, pCall, pba, BT_NO_ROLE_SWITCH);
} __except (1) {
IFDBG(DebugOut (DEBUG_ERROR, L"SCO :: sco_ConnectionRequest_Event :: exception in hci_AcceptConnectionRequest_In\n"));
}
gpLayerState->Lock ();
gpLayerState->DelRef ();
if (iRes) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ConnectionRequest_Event :: hci_AcceptConnectionRequest_In failed %d\n", iRes));
if (CallVerify(pCall, CALL_TYPE_ACCEPT_INCOMING_CONNECTION)) {
CallRemove(pCall);
CallSignal(pCall, iRes);
}
gpLayerState->Unlock();
return iRes;
}
if (!(gpLayerState->fIsRunning && gpLayerState->fConnected)) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ConnectionRequest_Event :: ERROR_SHUTDOWN_IN_PROGRESS\n"));
gpLayerState->Unlock();
return ERROR_SHUTDOWN_IN_PROGRESS;
}
} else {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ConnectionRequest_Event :: rejecting connection (no context)\n"));
HCI_RejectConnectionRequest_In pFunction = gpLayerState->hci_if.hci_RejectConnectionRequest_In;
HANDLE hHCI = gpLayerState->hHCI;
int iRes = ERROR_INTERNAL_ERROR;
gpLayerState->AddRef ();
gpLayerState->Unlock ();
__try {
iRes = pFunction (hHCI, NULL, pba, BT_ERROR_HOST_REJECTED_LIMITED_RESOURCES);
} __except (1) {
IFDBG(DebugOut (DEBUG_ERROR, L"SCO :: sco_ConnectionRequest_Event :: exception in hci_RejectConnectionRequest_In\n"));
}
gpLayerState->Lock ();
gpLayerState->DelRef ();
if (iRes) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ConnectionRequest_Event :: hci_RejectConnectionRequest_In failed %d\n", iRes));
gpLayerState->Unlock();
return iRes;
}
if (!(gpLayerState->fIsRunning && gpLayerState->fConnected)) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ConnectionRequest_Event :: ERROR_SHUTDOWN_IN_PROGRESS\n"));
gpLayerState->Unlock();
return ERROR_SHUTDOWN_IN_PROGRESS;
}
}
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ConnectionRequest_Event :: return ERROR_SUCCESS\n", pCall));
gpLayerState->Unlock ();
return ERROR_SUCCESS;
}
static int sco_NumberOfCompletedPackets_Event (void *pUserContext,
void *pCallContext,
unsigned short connection_handle,
unsigned short num_of_completed_packets)
{
if (! gpLayerState) {
return ERROR_SERVICE_NOT_ACTIVE;
}
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_NumberOfCompletedPackets_Event :: pCallContext=%#x, handle=%#x, num_completed=%d",
pCallContext, connection_handle, num_of_completed_packets));
gpLayerState->Lock ();
if (! gpLayerState->fIsRunning) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_NumberOfCompletedPackets_Event :: shutting down\n"));
gpLayerState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
SCO_CALLBACK_PacketsCompleted pCallBack = gpLayerState->sco_callbacks.PacketsCompleted;
if (pCallBack) {
int iRes = ERROR_INTERNAL_ERROR;
void *pUserData = gpLayerState->pUserData;
gpLayerState->AddRef ();
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_NumberOfCompletedPackets_Event :: going into callback\n"));
gpLayerState->Unlock ();
__try {
iRes = pCallBack (pUserData, connection_handle, num_of_completed_packets);
} __except (1) {
IFDBG(DebugOut (DEBUG_ERROR, L"SCO :: sco_NumberOfCompletedPackets_Event :: exception in callback\n"));
}
gpLayerState->Lock ();
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_NumberOfCompletedPackets_Event :: came from callback\n"));
gpLayerState->DelRef ();
if (!(gpLayerState->fIsRunning && gpLayerState->fConnected)) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_NumberOfCompletedPackets_Event :: ERROR_SHUTDOWN_IN_PROGRESS\n"));
gpLayerState->Unlock();
return ERROR_SHUTDOWN_IN_PROGRESS;
}
}
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_NumberOfCompletedPackets_Event :: return ERROR_SUCCESS\n"));
gpLayerState->Unlock ();
return ERROR_SUCCESS;
}
static int sco_DataPacketUp_Event(void *pUserContext, unsigned short connection_handle, BD_BUFFER *pBuffer)
{
if (! gpLayerState) {
return ERROR_SERVICE_NOT_ACTIVE;
}
IFDBG(DebugOut (DEBUG_DATA_PACKET_DOWN, L"SCO :: sco_DataPacketUp_Event :: handle=%#x, bd_buffer=%#x", connection_handle, pBuffer));
gpLayerState->Lock ();
if (! gpLayerState->fIsRunning) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_DataPacketUp_Event :: shutting down\n"));
gpLayerState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
SCO_CALLBACK_DataPacketUp pCallBack = gpLayerState->sco_callbacks.DataPacketUp;
if (pCallBack) {
int iRes = ERROR_INTERNAL_ERROR;
void *pUserData = gpLayerState->pUserData;
PUCHAR pDataBuffer = &pBuffer->pBuffer[pBuffer->cStart];
DWORD dwDataBufferLen = pBuffer->cEnd - pBuffer->cStart;
gpLayerState->AddRef ();
IFDBG(DebugOut (DEBUG_DATA_PACKET_DOWN, L"SCO :: sco_DataPacketUp_Event :: going into callback\n"));
gpLayerState->Unlock ();
__try {
iRes = pCallBack (pUserData, connection_handle, pDataBuffer, dwDataBufferLen);
} __except (1) {
IFDBG(DebugOut (DEBUG_ERROR, L"SCO :: sco_DataPacketUp_Event :: exception in callback\n"));
}
gpLayerState->Lock ();
IFDBG(DebugOut (DEBUG_DATA_PACKET_DOWN, L"SCO :: sco_DataPacketUp_Event :: came from callback\n"));
gpLayerState->DelRef ();
if (!(gpLayerState->fIsRunning && gpLayerState->fConnected)) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_DataPacketUp_Event :: ERROR_SHUTDOWN_IN_PROGRESS\n"));
gpLayerState->Unlock();
return ERROR_SHUTDOWN_IN_PROGRESS;
}
}
IFDBG(DebugOut (DEBUG_DATA_PACKET_DOWN, L"SCO :: sco_DataPacketUp_Event :: return ERROR_SUCCESS\n"));
gpLayerState->Unlock ();
return ERROR_SUCCESS;
}
///////////////////////////////////////////////////////////
// Interface functions
///////////////////////////////////////////////////////////
static int sco_AbortCall(Call *pCall, BOOL bHciAbort)
{
if (!gpLayerState) {
return ERROR_SERVICE_DOES_NOT_EXIST;
}
SVSUTIL_ASSERT(pCall);
SVSUTIL_ASSERT(gpLayerState->IsLocked());
if (!pCall) {
return ERROR_INVALID_PARAMETER;
} else if (!gpLayerState) {
return ERROR_SHUTDOWN_IN_PROGRESS;
} else if (!gpLayerState->IsLocked()) {
return ERROR_NOT_LOCKED;
}
if (bHciAbort) {
//
// HCI was invoked using this pCall, so tell HCI to abort that call.
// invoke hci_AbortCall.
// This will induce a sco_CallAborted_Out callback
//
BT_LAYER_ABORT_CALL pFunction = gpLayerState->hci_if.hci_AbortCall;
HANDLE hHCI = gpLayerState->hHCI;
int iRes = ERROR_INTERNAL_ERROR;
gpLayerState->AddRef ();
gpLayerState->Unlock ();
__try {
iRes = pFunction (hHCI, pCall);
} __except (1) {
IFDBG(DebugOut (DEBUG_ERROR, L"SCO :: sco_AbortCall :: exception in hci_AbortCall\n"));
}
gpLayerState->Lock ();
gpLayerState->DelRef ();
} else {
//
// HCI has not been invoked using this pCall so remove it from pCalls and signal it
//
CallRemove(pCall);
CallSignal(pCall, ERROR_OPERATION_ABORTED);
}
return ERROR_SUCCESS;
}
static int sco_AbortUserCall_In (SCO_USER_CALL* pUserCall)
{
if (!gpLayerState) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -