📄 bthsco.cxx
字号:
{
if (!pCall) {
return;
}
SVSUTIL_ASSERT(!pCall->pNext);
SVSUTIL_ASSERT(!pCall->pPrev);
if (pCall->hEvent) {
CloseHandle(pCall->hEvent);
}
delete pCall;
}
//
// return NULL if pCall not found in list.
// return non-NULL if pCall found in list
//
// if fCallType is zero, then it is not checked.
//
static Call* CallVerify(Call* pCall, unsigned char fCallType)
{
SVSUTIL_ASSERT(gpLayerState->IsLocked());
Call *pRunner = gpLayerState->pCalls;
while (pRunner && (pRunner != pCall))
{
pRunner = pRunner->pNext;
}
// check fCallType field
if (pRunner && fCallType) {
if (pRunner->fCallType != fCallType) {
pRunner = NULL;
}
}
return pRunner;
}
static void CallInsert (Call* pCall)
{
if (!gpLayerState || !pCall) {
return;
}
SVSUTIL_ASSERT(gpLayerState->IsLocked());
// insert into head
pCall->pPrev = NULL;
if (gpLayerState->pCalls) {
pCall->pNext = gpLayerState->pCalls;
gpLayerState->pCalls->pPrev = pCall;
} else {
pCall->pNext = NULL;
}
gpLayerState->pCalls = pCall;
}
static void CallRemove (Call* pCall)
{
if (!gpLayerState || !pCall) {
return;
}
SVSUTIL_ASSERT(gpLayerState->IsLocked());
Call *pPrevCall = pCall->pPrev;
Call *pNextCall = pCall->pNext;
if (pNextCall) {
pNextCall->pPrev = pPrevCall;
}
if (pPrevCall) {
pPrevCall->pNext = pNextCall;
} else {
SVSUTIL_ASSERT(gpLayerState->pCalls == pCall);
gpLayerState->pCalls = pNextCall;
}
pCall->pNext = NULL;
pCall->pPrev = NULL;
}
// write any output data that is in the Call struct
// to the SCO_USER_CALL struct.
static void CallSetUserData(SCO_USER_CALL *pUserCall, Call *pCall)
{
SVSUTIL_ASSERT(pUserCall);
SVSUTIL_ASSERT(pCall);
if (!pUserCall || !pCall) {
return;
}
switch (pUserCall->dwUserCallType)
{
case UCT_CONNECT:
SVSUTIL_ASSERT(pCall->fCallType == CALL_TYPE_CONNECT);
pUserCall->uParameters.Connect.hScoConnection = pCall->uParameters.Connect.hScoConnection;
break;
case UCT_READ_VOICE_SETTING:
SVSUTIL_ASSERT(pCall->fCallType == CALL_TYPE_READ_VOICE_SETTING);
pUserCall->uParameters.ReadVoiceSetting.VoiceSetting.usSetting = pCall->uParameters.ReadVoiceSetting.Setting.usSetting;
break;
case UCT_RECV_CONNECTION:
SVSUTIL_ASSERT(pCall->fCallType == CALL_TYPE_ACCEPT_INCOMING_CONNECTION);
pUserCall->uParameters.RecvConnection.Address = pCall->uParameters.AcceptIncomingConnection.Address;
pUserCall->uParameters.RecvConnection.hScoConnection = pCall->uParameters.AcceptIncomingConnection.hScoConnection;
break;
// pCall does not have any return data for pUserCall
// i.e. there are no OUT parameters
case UCT_WRITE_VOICE_SETTING:
case UCT_DISCONNECT:
case UCT_WRITE_PACKET:
break;
default:
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: CallSetUserData :: unknown dwUserCallType\n"));
SVSUTIL_ASSERT(!"unknown eUserCallType");
break;
}
}
static void CallSignal (Call *pCall, int iResult)
{
if (!pCall) {
return;
}
SVSUTIL_ASSERT(!pCall->pNext);
SVSUTIL_ASSERT(!pCall->pPrev);
pCall->iResult = iResult;
SCO_USER_CALL *pUserCall = pCall->pUserCall;
if (pUserCall) {
DWORD dwOrgPerm = SetProcPermissions((DWORD)-1);
pUserCall->iResult = iResult;
if (pUserCall->hEvent) {
if (iResult == ERROR_SUCCESS) {
CallSetUserData(pUserCall, pCall);
}
SetEvent(pUserCall->hEvent);
}
SetProcPermissions(dwOrgPerm);
}
if (pCall->hEvent) {
SetEvent(pCall->hEvent);
} else {
// if there is no pCall->hEvent, then that means that no one is waiting
// on this pCall, which means no one has taken responsibility to delete
// it. so we shall delete it now.
CallDelete(pCall);
}
}
static Call* CallFindByUserCall(SCO_USER_CALL *pUserCall)
{
SVSUTIL_ASSERT(gpLayerState->IsLocked());
Call *pCall = gpLayerState->pCalls;
while (pCall)
{
if (pCall->pUserCall == pUserCall)
return pCall;
pCall = pCall->pNext;
}
return NULL;
}
//
// Init and Uninit functions:
//
// int sco_InitializeOnce (void)
// int sco_UninitializeOnce (void)
// int sco_CreateDriverInstance(void)
// int sco_CloseDriverInstance (void)
//
// int sco_Bind(void *pUserData, SCO_CALLBACKS *pCallbacks, SCO_INTERFACE *pInterface)
// int sco_Unbind()
//
int sco_InitializeOnce(void)
{
DebugInit();
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_InitializeOnce() entered\n"));
if (gpLayerState) {
IFDBG(DebugOut (DEBUG_ERROR, L"SCO :: sco_InitializeOnce() return ERROR_ALREADY_EXISTS\n"));
return ERROR_ALREADY_EXISTS;
}
SVSUTIL_ASSERT(!ghModBtd);
ghModBtd = LoadLibrary(L"btd.dll");
if (!ghModBtd) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_InitializeOnce() : LoadLibrary(btd.dll) failed\n"));
return GetLastError();
}
gpfHCI_EstablishDeviceContext = (HCI_EstablishDeviceContext_t) GetProcAddress(ghModBtd, L"HCI_EstablishDeviceContext");
gpfHCI_CloseDeviceContext = (HCI_CloseDeviceContext_t) GetProcAddress(ghModBtd, L"HCI_CloseDeviceContext");
if (!gpfHCI_EstablishDeviceContext || !gpfHCI_CloseDeviceContext) {
FreeLibrary(ghModBtd);
ghModBtd = NULL;
gpfHCI_EstablishDeviceContext = NULL;
gpfHCI_CloseDeviceContext = NULL;
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_InitializeOnce() : btd.dll is not exporting required functions\n"));
return ERROR_PROC_NOT_FOUND;
}
gpLayerState = new SCO;
if (!gpLayerState) {
IFDBG(DebugOut (DEBUG_ERROR, L"SCO :: sco_InitializeOnce() return ERROR_OUTOFMEMORY\n"));
return ERROR_OUTOFMEMORY;
}
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_InitializeOnce() return ERROR_SUCCESS\n"));
return ERROR_SUCCESS;
}
int sco_UninitializeOnce (void)
{
if (!gpLayerState) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_CreateDriverInstance :: ERROR_SERVICE_DOES_NOT_EXIST\n"));
return ERROR_SERVICE_DOES_NOT_EXIST;
}
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_UninitializeOnce() entered\n"));
gpLayerState->Lock();
// sco_CloseDriverInstance() has to be called before sco_UninitializeOnce()
if (gpLayerState->fIsRunning) {
IFDBG(DebugOut(DEBUG_ERROR, L"SCO :: sco_UninitializeOnce ERROR_DEVICE_IN_USE\n"));
gpLayerState->Unlock();
return ERROR_DEVICE_IN_USE;
}
// want gpLayerState to be NULL by the time we Unlock() so...
SCO *pTemp = gpLayerState;
gpLayerState = NULL;
pTemp->Unlock();
delete pTemp;
if (ghModBtd) {
FreeLibrary(ghModBtd);
ghModBtd = NULL;
gpfHCI_EstablishDeviceContext = NULL;
gpfHCI_CloseDeviceContext = NULL;
}
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_UninitializeOnce() return ERROR_SUCCESS\n"));
DebugDeInit();
return ERROR_SUCCESS;
}
int sco_CreateDriverInstance (void)
{
if (! gpLayerState) {
return ERROR_SERVICE_NOT_ACTIVE;
}
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_CreateDriverInstance\n"));
gpLayerState->Lock();
if (gpLayerState->hClosingEvent) {
CloseHandle(gpLayerState->hClosingEvent);
gpLayerState->hClosingEvent = NULL;
}
gpLayerState->hClosingEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (gpLayerState->fIsRunning) {
gpLayerState->Unlock();
return ERROR_ALREADY_EXISTS;
}
HCI_CALLBACKS hc;
HCI_EVENT_INDICATION hei;
memset (&hc, 0, sizeof (hc));
memset (&hei, 0, sizeof (hei));
// event handlers
hei.hci_ConnectionCompleteEvent = sco_ConnectionComplete_Event;
hei.hci_DisconnectionCompleteEvent = sco_DisconnectionComplete_Event;
hei.hci_StackEvent = sco_Stack_Event;
hei.hci_ConnectionRequestEvent = sco_ConnectionRequest_Event;
hei.hci_NumberOfCompletedPacketsEvent = sco_NumberOfCompletedPackets_Event;
hei.hci_DataPacketUp = sco_DataPacketUp_Event;
// callbacks
hc.hci_AddSCOConnection_Out = sco_AddSCOConnection_Out;
hc.hci_Disconnect_Out = sco_Disconnect_Out;
hc.hci_CallAborted = sco_CallAborted_Out;
hc.hci_WriteVoiceSetting_Out = sco_WriteVoiceSetting_Out;
hc.hci_ReadVoiceSetting_Out = sco_ReadVoiceSetting_Out;
hc.hci_AcceptConnectionRequest_Out = sco_AcceptConnectionRequest_Out;
hc.hci_DataPacketDown_Out = sco_DataPacketDown_Out;
hc.hci_WriteSCOFlowControlEnable_Out = sco_WriteSCOFlowControlEnable_Out;
hc.hci_ReadSCOFlowControlEnable_Out = sco_ReadSCOFlowControlEnable_Out;
SVSUTIL_ASSERT(gpfHCI_EstablishDeviceContext);
int iErr = gpfHCI_EstablishDeviceContext ( gpLayerState,
BTH_CONTROL_ROUTE_BY_LINKTYPE,
NULL,
0,
BT_LINK_TYPE_SCO,
&hei,
&hc,
&gpLayerState->hci_if,
&gpLayerState->cHciHeaders,
&gpLayerState->cHciTrailers,
&gpLayerState->hHCI
);
if (ERROR_SUCCESS != iErr) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_CreateDriverInstance :: Could not create device context\n"));
gpLayerState->Unlock();
return iErr;
}
gpLayerState->fIsRunning = TRUE;
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_CreateDriverInstance :: HCI_EstablishDeviceContext successful\n"));
//
// determine whether the stack is connected
//
int fConnected = FALSE;
__try {
int dwRet = 0;
BT_LAYER_IO_CONTROL pFunction = gpLayerState->hci_if.hci_ioctl;
HANDLE hHCI = gpLayerState->hHCI;
gpLayerState->AddRef ();
gpLayerState->Unlock ();
pFunction (hHCI, BTH_STACK_IOCTL_GET_CONNECTED, 0, NULL, sizeof(fConnected), (char *)&fConnected, &dwRet);
gpLayerState->Lock ();
gpLayerState->DelRef ();
if ((dwRet == sizeof(fConnected)) && fConnected)
gpLayerState->fConnected = TRUE;
} __except (1) {
IFDBG(DebugOut (DEBUG_ERROR, L"SCO :: sco_CreateDriverInstance :: exception in hci_ioctl BTH_STACK_IOCTL_GET_CONNECTED\n"));
}
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_CreateDriverInstance :: ConnectionState = %s\n", gpLayerState->fConnected ? L"CONNECTED" : L"DISCONNECTED"));
gpLayerState->Unlock();
if (fConnected) {
// if we are not connected right now, then StackInitDevice() will be invoked on BTH_STACK_UP event
StackInitDevice();
}
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_CreateDriverInstance :: ERROR_SUCCESS\n"));
return ERROR_SUCCESS;
}
int sco_CloseDriverInstance (void)
{
if (! gpLayerState) {
return ERROR_SERVICE_NOT_ACTIVE;
}
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_CloseDriverInstance\n"));
gpLayerState->Lock ();
if (! gpLayerState->fIsRunning) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_CloseDriverInstance :: ERROR_SERVICE_NOT_ACTIVE\n"));
gpLayerState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
SetEvent(gpLayerState->hClosingEvent);
gpLayerState->fIsRunning = FALSE;
while (gpLayerState->GetRefCount () > 1) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_CloseDriverInstance :: (RefCount=%d) Sleeping...\n", gpLayerState->GetRefCount()));
gpLayerState->Unlock ();
Sleep (200);
gpLayerState->Lock ();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -