📄 bthsco.cxx
字号:
}
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: Stack Is Down\n"));
gpLayerState->Unlock ();
return ERROR_SUCCESS;
}
static DWORD WINAPI StackUp (LPVOID lpVoid)
{
if (! gpLayerState) {
return ERROR_SERVICE_NOT_ACTIVE;
}
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: Stack Up received :: UP\n"));
// gpLayerState may be disconnecting, in which case StackDown does not need
// to do anything.
if(WaitForSingleObject(gpLayerState->hClosingEvent, 0) != WAIT_TIMEOUT) {
return 0;
}
StackInitDevice();
gpLayerState->Lock ();
if ((! gpLayerState->fIsRunning) || gpLayerState->fConnected) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: Stack Up received :: already up\n"));
gpLayerState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
gpLayerState->fConnected = TRUE;
gpLayerState->Unlock ();
StackNotifyUser(BTH_STACK_UP);
return ERROR_SUCCESS;
}
//////////////////////////////////////////////////////////////////
// Callbacks
//////////////////////////////////////////////////////////////////
static int sco_CallAborted_Out (void *pCallContext, int iError)
{
if (! gpLayerState)
return ERROR_SERVICE_NOT_ACTIVE;
gpLayerState->Lock ();
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: Call Aborted :: call 0x%08x, error %d\n", pCallContext, iError));
if (! gpLayerState->fIsRunning) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: Call Aborted :: system shutdown\n"));
gpLayerState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
Call *pCall = CallVerify ((Call*)pCallContext, 0);
if (! pCall) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: Call Aborted :: call not found\n"));
gpLayerState->Unlock ();
return ERROR_NOT_FOUND;
}
CallRemove (pCall);
CallSignal (pCall, iError);
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: Call Abort :: aborted call 0x%08x type %d\n", pCall, pCall->fCallType));
gpLayerState->Unlock ();
return ERROR_SUCCESS;
}
static int sco_FinishVoidCall(void *pCallContext, unsigned char status, unsigned char fCallType)
{
if (! gpLayerState) {
return ERROR_SERVICE_NOT_ACTIVE;
}
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_FinishVoidCall call 0x%08x, status 0x%02x, type %d\n", pCallContext, status, fCallType));
int iResult = StatusToError (status, ERROR_INTERNAL_ERROR);
if (status != 0) {
return sco_CallAborted_Out (pCallContext, iResult);
}
gpLayerState->Lock();
if (!gpLayerState->fIsRunning || !gpLayerState->fConnected) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_FinishVoidCall call 0x%08x :: system shutdown\n", pCallContext));
gpLayerState->Unlock();
return ERROR_SERVICE_NOT_ACTIVE;
}
Call *pCall = CallVerify((Call*)pCallContext, fCallType);
if (!pCall) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_FinishVoidCall call 0x%08x :: call not found\n", pCallContext));
gpLayerState->Unlock();
return ERROR_NOT_FOUND;
}
CallRemove (pCall);
CallSignal (pCall, iResult);
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_FinishVoidCall call 0x%08x :: completed call\n", pCallContext));
gpLayerState->Unlock ();
return ERROR_SUCCESS;
}
static int sco_Disconnect_Out (void *pCallContext, unsigned char status)
{
if (! gpLayerState) {
return ERROR_SERVICE_NOT_ACTIVE;
}
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: Disconnect_Out :: call 0x%08x, status 0x%02x\n", pCallContext, status));
if (status != 0) {
return sco_CallAborted_Out (pCallContext, StatusToError (status, ERROR_INTERNAL_ERROR));
}
return ERROR_SUCCESS;
}
static int sco_AcceptConnectionRequest_Out (void *pCallContext, unsigned char status)
{
if (! gpLayerState) {
return ERROR_SERVICE_NOT_ACTIVE;
}
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_AcceptConnectionRequest_Out :: call 0x%08x, status 0x%02x\n", pCallContext, status));
if (status != 0) {
return sco_CallAborted_Out (pCallContext, StatusToError (status, ERROR_INTERNAL_ERROR));
}
return ERROR_SUCCESS;
}
static int sco_AddSCOConnection_Out (void *pCallContext, unsigned char status)
{
if (! gpLayerState) {
return ERROR_SERVICE_NOT_ACTIVE;
}
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_AddSCOConnection_Out :: call 0x%08x, status 0x%02x\n", pCallContext, status));
if (status != 0) {
return sco_CallAborted_Out (pCallContext, StatusToError (status, ERROR_INTERNAL_ERROR));
}
return ERROR_SUCCESS;
}
static int sco_WriteSCOFlowControlEnable_Out (void *pCallContext, unsigned char status)
{
if (! gpLayerState) {
return ERROR_SERVICE_NOT_ACTIVE;
}
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_WriteSCOFlowControlEnable_Out :: call 0x%08x, status 0x%02x\n", pCallContext, status));
return sco_FinishVoidCall(pCallContext, status, CALL_TYPE_WRITE_SCO_FLOW_CONTROL);
}
static int sco_DataPacketDown_Out (void *pCallContext, int iError)
{
if (! gpLayerState) {
return ERROR_SERVICE_NOT_ACTIVE;
}
IFDBG(DebugOut (DEBUG_DATA_PACKET_DOWN, L"SCO :: sco_DataPacketDown_Out :: call 0x%08x, error %d\n", pCallContext, iError));
gpLayerState->Lock();
if (!gpLayerState->fIsRunning || !gpLayerState->fConnected) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_DataPacketDown_Out :: system shutdown\n"));
gpLayerState->Unlock();
return ERROR_SERVICE_NOT_ACTIVE;
}
// find the call
Call *pCall = CallVerify((Call*)pCallContext, 0);
if (!pCall) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_DataPacketDown_Out :: call not found\n"));
gpLayerState->Unlock();
return ERROR_NOT_FOUND;
}
if (pCall->fCallType == CALL_TYPE_DATA_PACKET_DOWN) {
void *pUserData = gpLayerState->pUserData;
void *pPacketUserContext = pCall->uParameters.DataPacketDown.pPacketUserContext;
USHORT hConnection = pCall->uParameters.DataPacketDown.hConnection;
CallRemove (pCall);
CallSignal (pCall, iError);
SCO_CALLBACK_DataPacketDown pCallBack = gpLayerState->sco_callbacks.DataPacketDown;
if (pCallBack) {
int iRes = ERROR_INTERNAL_ERROR;
gpLayerState->AddRef ();
IFDBG(DebugOut (DEBUG_DATA_PACKET_DOWN, L"SCO :: sco_DataPacketDown_Out :: going into callback\n"));
gpLayerState->Unlock ();
__try {
iRes = pCallBack (pUserData, pPacketUserContext, hConnection, (DWORD)iError);
} __except (1) {
IFDBG(DebugOut (DEBUG_ERROR, L"SCO :: sco_DataPacketDown_Out :: exception in callback\n"));
}
gpLayerState->Lock ();
IFDBG(DebugOut (DEBUG_DATA_PACKET_DOWN, L"SCO :: sco_DataPacketDown_Out :: came from callback\n"));
gpLayerState->DelRef ();
if (!(gpLayerState->fIsRunning && gpLayerState->fConnected)) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_DataPacketDown_Out :: ERROR_SHUTDOWN_IN_PROGRESS\n"));
gpLayerState->Unlock();
return ERROR_SHUTDOWN_IN_PROGRESS;
}
}
} else if (pCall->fCallType == CALL_TYPE_WRITE_PACKET) {
CallRemove (pCall);
CallSignal (pCall, iError);
} else {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_DataPacketDown_Out :: call not found\n"));
gpLayerState->Unlock();
return ERROR_NOT_FOUND;
}
IFDBG(DebugOut (DEBUG_DATA_PACKET_DOWN, L"SCO :: sco_DataPacketDown_Out :: Completed call 0x%08x\n", pCall));
gpLayerState->Unlock ();
return ERROR_SUCCESS;
}
static int sco_WriteVoiceSetting_Out (void *pCallContext, unsigned char status)
{
if (! gpLayerState) {
return ERROR_SERVICE_NOT_ACTIVE;
}
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_WriteVoiceSetting_Out :: call 0x%08x, status 0x%02x\n", pCallContext, status));
return sco_FinishVoidCall(pCallContext, status, CALL_TYPE_WRITE_VOICE_SETTING);
}
static int sco_ReadVoiceSetting_Out (void *pCallContext, unsigned char status, unsigned short voice_channel_setting)
{
if (! gpLayerState) {
return ERROR_SERVICE_NOT_ACTIVE;
}
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ReadVoiceSetting_Out :: call 0x%08x, status 0x%02x\n", pCallContext, status));
int iResult = StatusToError (status, ERROR_INTERNAL_ERROR);
if (status != 0) {
return sco_CallAborted_Out (pCallContext, iResult);
}
gpLayerState->Lock();
if (!gpLayerState->fIsRunning || !gpLayerState->fConnected) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ReadVoiceSetting_Out :: system shutdown\n"));
gpLayerState->Unlock();
return ERROR_SERVICE_NOT_ACTIVE;
}
Call *pCall = CallVerify((Call*)pCallContext, CALL_TYPE_READ_VOICE_SETTING);
if (!pCall) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ReadVoiceSetting_Out :: call not found\n"));
gpLayerState->Unlock();
return ERROR_NOT_FOUND;
}
CallRemove (pCall);
pCall->uParameters.ReadVoiceSetting.Setting.usSetting = voice_channel_setting;
CallSignal (pCall, iResult);
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ReadVoiceSetting_Out :: Completed call 0x%08x\n", pCall));
gpLayerState->Unlock ();
return ERROR_SUCCESS;
}
static int sco_ReadSCOFlowControlEnable_Out (void *pCallContext, unsigned char status, unsigned char SCO_flow_control_enable)
{
if (! gpLayerState) {
return ERROR_SERVICE_NOT_ACTIVE;
}
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ReadSCOFlowControlEnable_Out :: call 0x%08x, status 0x%02x enabled=%d\n",
pCallContext, status, SCO_flow_control_enable));
int iResult = StatusToError (status, ERROR_INTERNAL_ERROR);
if (status != 0) {
return sco_CallAborted_Out (pCallContext, iResult);
}
gpLayerState->Lock();
if (!gpLayerState->fIsRunning || !gpLayerState->fConnected) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ReadSCOFlowControlEnable_Out :: system shutdown\n"));
gpLayerState->Unlock();
return ERROR_SERVICE_NOT_ACTIVE;
}
Call *pCall = CallVerify((Call*)pCallContext, CALL_TYPE_READ_SCO_FLOW_CONTROL);
if (!pCall) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ReadSCOFlowControlEnable_Out :: call not found\n"));
gpLayerState->Unlock();
return ERROR_NOT_FOUND;
}
CallRemove (pCall);
pCall->uParameters.ReadScoFlowControl.bEnabled = SCO_flow_control_enable;
CallSignal (pCall, iResult);
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ReadSCOFlowControlEnable_Out :: Completed call 0x%08x\n", pCall));
gpLayerState->Unlock ();
return ERROR_SUCCESS;
}
//////////////////////////////////////////////////////////////////
// Events
//////////////////////////////////////////////////////////////////
static int sco_Stack_Event (void *pUserContext, int iEvent, void *pEventContext)
{
if (! gpLayerState) {
return ERROR_SERVICE_NOT_ACTIVE;
}
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: Stack EVENT :: %s\n", iEvent == BTH_STACK_DISCONNECT ? L"BTH_STACK_DISCONNECT" : (iEvent == BTH_STACK_DOWN ? L"BTH_STACK_DOWN" : (iEvent == BTH_STACK_UP ? L"UP" : L"Unknown"))));
if (iEvent == BTH_STACK_DISCONNECT)
CloseHandle (CreateThread (NULL, 0, StackDisconnect, NULL, 0, NULL));
else if (iEvent == BTH_STACK_DOWN)
CloseHandle (CreateThread (NULL, 0, StackDown, NULL, 0, NULL));
else if (iEvent == BTH_STACK_UP)
CloseHandle (CreateThread (NULL, 0, StackUp, NULL, 0, NULL));
return ERROR_SUCCESS;
}
static int sco_ConnectionComplete_Event(void *pUserContext,
void *pCallContext,
unsigned char status,
unsigned short connection_handle,
BD_ADDR *pba,
unsigned char link_type,
unsigned char encryption_mode)
{
if (! gpLayerState) {
return ERROR_SERVICE_NOT_ACTIVE;
}
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ConnectionComplete_Event :: call=%#x status=%#x handle=%#x pba=%04x%08x link=%d, encrypt=%d\n",
pCallContext, status, connection_handle, pba->NAP, pba->SAP, link_type, encryption_mode));
SVSUTIL_ASSERT (link_type == BT_LINK_TYPE_SCO);
gpLayerState->Lock ();
if (! gpLayerState->fIsRunning) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ConnectionComplete_Event :: shutting down\n"));
gpLayerState->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
Call *pCall = CallVerify ((Call*)pCallContext, 0);
if (!pCall) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ConnectionComplete_Event :: no context\n"));
gpLayerState->Unlock ();
return ERROR_NOT_FOUND;
}
if ( (pCall->fCallType != CALL_TYPE_CONNECT)
&& (pCall->fCallType != CALL_TYPE_ACCEPT_INCOMING_CONNECTION)) {
IFDBG(DebugOut (DEBUG_SCO_TRACE, L"SCO :: sco_ConnectionComplete_Event :: no context\n"));
gpLayerState->Unlock ();
return ERROR_NOT_FOUND;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -