⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bthlink.cxx

📁 Windows CE操作系统中适用的蓝牙驱动程序
💻 CXX
📖 第 1 页 / 共 3 页
字号:
				IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ScoConnect %04x%08x :: ERROR_PROTOCOL_UNREACHABLE\n", pbaddr->NAP, pbaddr->SAP));
			}
		} else {
			iRes = ERROR_SHUTDOWN_IN_PROGRESS;
			IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ScoConnect %04x%08x :: ERROR_SHUTDOWN_IN_PROGRESS\n", pbaddr->NAP, pbaddr->SAP));
		}
	}

	RemoveCallFromList (pCall);
	delete pCall;

	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ScoConnect 0x%08x 0x%08x :: %d\n", pbaddr, phScoConnection, iRes));
	gpLayerState->Unlock ();

	return iRes;
}

static int GetAddress
(
unsigned short h,
BD_ADDR *pba
) {
	// First, get the connection handle 
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: GETADDRESS :: 0x%04x : getting bluetooth address\n", h));

	if (! gpLayerState) {
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: GETADDRESS :: 0x%04x : service not active\n", h));
		return ERROR_SERVICE_NOT_ACTIVE;
	}

	gpLayerState->Lock ();
	if (! (gpLayerState->fIsRunning && gpLayerState->fConnected)) {
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: GETADDRESS :: 0x%04x : service not active\n", h));
		gpLayerState->Unlock ();

		return ERROR_SERVICE_NOT_ACTIVE;
	}

	HANDLE hHCI = gpLayerState->hHCI;
	BT_LAYER_IO_CONTROL pCallbackIOCTL = gpLayerState->hci_if.hci_ioctl;
	gpLayerState->AddRef ();
	gpLayerState->Unlock ();
	int iRes = ERROR_INTERNAL_ERROR;
	__try {
		int dwData = 0;
		iRes = pCallbackIOCTL (hHCI, BTH_HCI_IOCTL_GET_BD_FOR_HANDLE, sizeof(h), (char *)&h, sizeof(*pba), (char *)pba, &dwData);
		if ((iRes == ERROR_SUCCESS) && (dwData != sizeof(BD_ADDR))) {
			IFDBG(DebugOut (DEBUG_ERROR, L"BTHLINK :: GETADDRESS ::  0x%04x : incorrect return buffer in hci_ioctl\n", h));
			iRes = ERROR_INTERNAL_ERROR;
		}
	} __except (1) {
		IFDBG(DebugOut (DEBUG_ERROR, L"BTHLINK :: GETADDRESS :: 0x%04x : exception in hci_ioctl\n", h));
	}
	gpLayerState->Lock ();
	gpLayerState->DelRef ();

	if ((iRes == ERROR_SUCCESS) && (! gpLayerState->fConnected)) {
		iRes = ERROR_SERVICE_NOT_ACTIVE;
		IFDBG(DebugOut (DEBUG_WARN, L"BTHLINK :: GETADDRESS :: 0x%04x (rare event!) disconnected while in ioctl\n", h));
	}

	gpLayerState->Unlock ();
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: GETADDRESS 0x%04x :: %d\n", h, iRes));

	return iRes;
}


static int GetHandles
(
int				*pcReturned,
unsigned short	*phandles
) {
	// First, get the connection handle 
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: GETHANDLES :: getting list of active connections\n"));

	if (! gpLayerState) {
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: GETHANDLES : service not active\n"));
		return ERROR_SERVICE_NOT_ACTIVE;
	}

	gpLayerState->Lock ();
	if (! (gpLayerState->fIsRunning && gpLayerState->fConnected)) {
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: GETHANDLES :: service not active\n"));
		gpLayerState->Unlock ();

		return ERROR_SERVICE_NOT_ACTIVE;
	}

	HANDLE hHCI = gpLayerState->hHCI;
	BT_LAYER_IO_CONTROL pCallbackIOCTL = gpLayerState->hci_if.hci_ioctl;
	gpLayerState->AddRef ();
	gpLayerState->Unlock ();
	int iRes = ERROR_INTERNAL_ERROR;
	__try {
		int dwData = 0;
		iRes = pCallbackIOCTL (hHCI, BTH_HCI_IOCTL_GET_BASEBAND_HANDLES, 0, NULL, sizeof(unsigned short) * BTHLINK_MAX_HANDLES, (char *)phandles, &dwData);
		if (iRes == ERROR_SUCCESS) {
			*pcReturned = dwData / sizeof(unsigned short);
		}
	} __except (1) {
		IFDBG(DebugOut (DEBUG_ERROR, L"BTHLINK :: GETHANDLES :: exception in hci_ioctl\n"));
	}

	gpLayerState->Lock ();
	gpLayerState->DelRef ();

	if ((iRes == ERROR_SUCCESS) && (! gpLayerState->fConnected)) {
		iRes = ERROR_SERVICE_NOT_ACTIVE;
		IFDBG(DebugOut (DEBUG_WARN, L"BTHLINK :: GETHANDLES :: (rare event!) disconnected while in ioctl\n"));
	}

	gpLayerState->Unlock ();

	return iRes;
}

static int ClearFilter (void) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ClearFilter\n"));

	if (! gpLayerState) {
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ClearFilter\n : ERROR_SERVICE_NOT_ACTIVE"));
		return ERROR_SERVICE_NOT_ACTIVE;
	}

	gpLayerState->Lock ();
	if (! (gpLayerState->fIsRunning && gpLayerState->fConnected)) {
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ClearFilter\n : ERROR_SERVICE_NOT_ACTIVE"));
		gpLayerState->Unlock ();

		return ERROR_SERVICE_NOT_ACTIVE;
	}

	SCall *pCall = new SCall;
	if (! pCall) {
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ClearFilter\n : ERROR_OUTOFMEMORY"));
		gpLayerState->Unlock ();

		return ERROR_OUTOFMEMORY;
	}

	pCall->fWhat = CALL_HCI_EVENTFILTER;
	pCall->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
	pCall->hProcOwner = GetCallerProcess ();
	pCall->pNext = gpLayerState->pCalls;
	gpLayerState->pCalls = pCall;

	HCI_SetEventFilter_In pCallback = gpLayerState->hci_if.hci_SetEventFilter_In;
	HANDLE hHCI = gpLayerState->hHCI;

	unsigned char condition[7];

	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ClearFilter :: created call 0x%08x\n", pCall));
	gpLayerState->Unlock ();

	int iRes = ERROR_INTERNAL_ERROR;

	__try {
		iRes = pCallback (hHCI, pCall, 0, 0, condition);
	} __except (1) {
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ClearFilter :: exception in hci_Disconnect_In\n"));
	}

	if (iRes == ERROR_SUCCESS)
		WaitForSingleObject (pCall->hEvent, INFINITE);

	CloseHandle (pCall->hEvent);

	if (! gpLayerState) {
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ClearFilter:: ERROR_SHUTDOWN_IN_PROGRESS\n"));
		delete pCall;
		return ERROR_SHUTDOWN_IN_PROGRESS;
	}

	gpLayerState->Lock ();

	if (iRes == ERROR_SUCCESS)
		iRes = pCall->iResult;

	RemoveCallFromList (pCall);
	delete pCall;

	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ClearFilter:: %d\n", iRes));
	gpLayerState->Unlock ();
	return iRes;
}

static int SetInquiryFilter (BD_ADDR *pba) {
	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ClearFilter\n"));

	if (! gpLayerState) {
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ClearFilter\n : ERROR_SERVICE_NOT_ACTIVE"));
		return ERROR_SERVICE_NOT_ACTIVE;
	}

	gpLayerState->Lock ();
	if (! (gpLayerState->fIsRunning && gpLayerState->fConnected)) {
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ClearFilter\n : ERROR_SERVICE_NOT_ACTIVE"));
		gpLayerState->Unlock ();

		return ERROR_SERVICE_NOT_ACTIVE;
	}

	SCall *pCall = new SCall;
	if (! pCall) {
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ClearFilter\n : ERROR_OUTOFMEMORY"));
		gpLayerState->Unlock ();

		return ERROR_OUTOFMEMORY;
	}

	pCall->fWhat = CALL_HCI_EVENTFILTER;
	pCall->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
	pCall->hProcOwner = GetCallerProcess ();
	pCall->pNext = gpLayerState->pCalls;
	gpLayerState->pCalls = pCall;

	HCI_SetEventFilter_In pCallback = gpLayerState->hci_if.hci_SetEventFilter_In;
	HANDLE hHCI = gpLayerState->hHCI;

	unsigned char condition[7];
	memcpy (condition, pba, sizeof(*pba));

	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ClearFilter :: created call 0x%08x\n", pCall));
	gpLayerState->Unlock ();

	int iRes = ERROR_INTERNAL_ERROR;

	__try {
		iRes = pCallback (hHCI, pCall, 1, 2, condition);
	} __except (1) {
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ClearFilter :: exception in hci_Disconnect_In\n"));
	}

	if (iRes == ERROR_SUCCESS)
		WaitForSingleObject (pCall->hEvent, INFINITE);

	CloseHandle (pCall->hEvent);

	if (! gpLayerState) {
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ClearFilter:: ERROR_SHUTDOWN_IN_PROGRESS\n"));
		delete pCall;
		return ERROR_SHUTDOWN_IN_PROGRESS;
	}

	gpLayerState->Lock ();

	if (iRes == ERROR_SUCCESS)
		iRes = pCall->iResult;

	RemoveCallFromList (pCall);
	delete pCall;

	IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: ClearFilter:: %d\n", iRes));
	gpLayerState->Unlock ();
	return iRes;
}

//
//	Driver service funcs...
//
extern "C" BOOL WINAPI DllMain( HANDLE hInstDll, DWORD fdwReason, LPVOID lpvReserved) {
	switch(fdwReason) {
		case DLL_PROCESS_ATTACH:
			DisableThreadLibraryCalls((HMODULE) hInstDll);
			svsutil_Initialize ();
			break;

		case DLL_PROCESS_DETACH:
			svsutil_DeInitialize ();
			break;
	}
	return TRUE;
}

//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//		EXECUTION THREAD: Client-application!
//			These functions are only executed on the caller's thread
// 			i.e. the thread belongs to the client application
//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//	@func PVOID | BTL_Init | Device initialization routine
//  @parm DWORD | dwInfo | Info passed to RegisterDevice
//  @rdesc	Returns a DWORD which will be passed to Open & Deinit or NULL if
//			unable to initialize the device.
//	@remark	Routine exported by a device driver.  "PRF" is the string passed
//			in as lpszType in RegisterDevice
extern "C" DWORD BTL_Init (DWORD Index) {
	DebugInit();

	return (DWORD)(bthlink_CreateDriverInstance () == ERROR_SUCCESS);
}

//	@func PVOID | BTL_Deinit | Device deinitialization routine
//  @parm DWORD | dwData | value returned from CON_Init call
//  @rdesc	Returns TRUE for success, FALSE for failure.
//	@remark	Routine exported by a device driver.  "PRF" is the string
//			passed in as lpszType in RegisterDevice
extern "C" BOOL BTL_Deinit(DWORD dwData) {
	bthlink_CloseDriverInstance ();

	DebugDeInit();

	return TRUE;
}

//	@func PVOID | BTL_Open		| Device open routine
//  @parm DWORD | dwData		| value returned from CON_Init call
//  @parm DWORD | dwAccess		| requested access (combination of GENERIC_READ
//								  and GENERIC_WRITE)
//  @parm DWORD | dwShareMode	| requested share mode (combination of
//								  FILE_SHARE_READ and FILE_SHARE_WRITE)
//  @rdesc	Returns a DWORD which will be passed to Read, Write, etc or NULL if
//			unable to open device.
//	@remark	Routine exported by a device driver.  "PRF" is the string passed
//			in as lpszType in RegisterDevice
extern "C" DWORD BTL_Open (DWORD dwData, DWORD dwAccess, DWORD dwShareMode) {
	HANDLE *ph = (HANDLE *)g_funcAlloc (sizeof(HANDLE), g_pvAllocData);

	ph[0] = NULL;

	return (DWORD)ph;
}

//	@func BOOL | BTL_Close | Device close routine
//  @parm DWORD | dwOpenData | value returned from BTL_Open call
//  @rdesc	Returns TRUE for success, FALSE for failure
//	@remark	Routine exported by a device driver.  "PRF" is the string passed
//			in as lpszType in RegisterDevice
extern "C" BOOL BTL_Close (DWORD dwData)  {
	HANDLE *ph = (HANDLE *)dwData;

	if (ph && ph[0])
		ProcessExited (ph[0]);

	if (ph)
		g_funcFree (ph, g_pvFreeData);

	return TRUE;
}

//	@func DWORD | BTL_Write | Device write routine
//  @parm DWORD | dwOpenData | value returned from CON_Open call
//  @parm LPCVOID | pBuf | buffer containing data
//  @parm DWORD | len | maximum length to write [IN BYTES, NOT WORDS!!!]
//  @rdesc	Returns -1 for error, otherwise the number of bytes written.  The
//			length returned is guaranteed to be the length requested unless an
//			error condition occurs.
//	@remark	Routine exported by a device driver.  "PRF" is the string passed
//			in as lpszType in RegisterDevice
//
extern "C" DWORD BTL_Write (DWORD dwData, LPCVOID pInBuf, DWORD dwInLen) {
	return -1;
}

//	@func DWORD | BTL_Read | Device read routine
//  @parm DWORD | dwOpenData | value returned from CON_Open call
//  @parm LPVOID | pBuf | buffer to receive data
//  @parm DWORD | len | maximum length to read [IN BYTES, not WORDS!!]
//  @rdesc	Returns 0 for end of file, -1 for error, otherwise the number of
//			bytes read.  The length returned is guaranteed to be the length
//			requested unless end of file or an error condition occurs.
//	@remark	Routine exported by a device driver.  "PRF" is the string passed
//			in as lpszType in RegisterDevice
//
extern "C" DWORD BTL_Read (DWORD dwData, LPVOID pBuf, DWORD Len) {
	return -1;
}

//	@func DWORD | BTL_Seek | Device seek routine
//  @parm DWORD | dwOpenData | value returned from CON_Open call
//  @parm long | pos | position to seek to (relative to type)
//  @parm DWORD | type | FILE_BEGIN, FILE_CURRENT, or FILE_END
//  @rdesc	Returns current position relative to start of file, or -1 on error
//	@remark	Routine exported by a device driver.  "PRF" is the string passed
//		 in as lpszType in RegisterDevice

extern "C" DWORD BTL_Seek (DWORD dwData, long pos, DWORD type) {
	return (DWORD)-1;
}

//	@func void | BTL_PowerUp | Device powerup routine
//	@comm	Called to restore device from suspend mode.  You cannot call any
//			routines aside from those in your dll in this call.
extern "C" void BTL_PowerUp (void) {
	return;
}
//	@func void | BTL_PowerDown | Device powerdown routine
//	@comm	Called to suspend device.  You cannot call any routines aside from
//			those in your dll in this call.
extern "C" void BTL_PowerDown (void) {
	return;
}

//	@func BOOL | BTL_IOControl | Device IO control routine
//  @parm DWORD | dwOpenData | value returned from CON_Open call
//  @parm DWORD | dwCode | io control code to be performed
//  @parm PBYTE | pBufIn | input data to the device
//  @parm DWORD | dwLenIn | number of bytes being passed in
//  @parm PBYTE | pBufOut | output data from the device
//  @parm DWORD | dwLenOut |maximum number of bytes to receive from device
//  @parm PDWORD | pdwActualOut | actual number of bytes received from device
//  @rdesc	Returns TRUE for success, FALSE for failure
//	@remark	Routine exported by a device driver.  "PRF" is the string passed
//		in as lpszType in RegisterDevice
extern "C" BOOL BTL_IOControl(DWORD dwData, DWORD dwCode, PBYTE pBufIn,
			  DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut,
			  PDWORD pdwActualOut)
{
#if ! defined (SDK_BUILD)
	if (dwCode == IOCTL_PSL_NOTIFY) {
		PDEVICE_PSL_NOTIFY pPslPacket = (PDEVICE_PSL_NOTIFY)pBufIn;
		if ((pPslPacket->dwSize == sizeof(DEVICE_PSL_NOTIFY)) && (pPslPacket->dwFlags == DLL_PROCESS_EXITING)){
			SVSUTIL_ASSERT (*(HANDLE *)dwData == pPslPacket->hProc);
			ProcessExited ((HANDLE)pPslPacket->hProc);
		}

		return STATUS_SUCCESS;
	}
#endif

	HANDLE *ph = (HANDLE *)dwData;
	SVSUTIL_ASSERT (ph);

	if (! ph[0])
		ph[0] = GetCallerProcess ();

	SVSUTIL_ASSERT (ph[0] == GetCallerProcess());

	int iError = ERROR_SUCCESS;

	BTHLINK_PARMS *papi = (BTHLINK_PARMS *)pBufIn;
	if (dwLenIn != sizeof(BTHLINK_PARMS)) {
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: IOCTL :: ERROR_INVALID_PARAMETER\n"));
		return ERROR_INVALID_PARAMETER;
	}

	switch (dwCode) {
	case BTHLINK_IOCTL_CONNECT:
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: IOCTL :: BTHLINK_IOCTL_CONNECT\n"));
		iError = Connect (&papi->CONNECT.b, &papi->CONNECT.h);
		break;

	case BTHLINK_IOCTL_DISCONNECT:
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: IOCTL :: BTHLINK_IOCTL_DISCONNECT\n"));
		iError = Disconnect (papi->DISCONNECT.h);
		break;

	case BTHLINK_IOCTL_SCO_CONNECT:
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: IOCTL :: BTHLINK_IOCTL_SCO_CONNECT\n"));
		iError = ScoConnect (&papi->CONNECT.b, &papi->CONNECT.h);
		break;
		
	case BTHLINK_IOCTL_SCO_DISCONNECT:
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: IOCTL :: BTHLINK_IOCTL_SCO_DISCONNECT\n"));
		iError = Disconnect (papi->DISCONNECT.h);
		break;

	case BTHLINK_GET_HANDLES:
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: IOCTL :: BTHLINK_GET_HANDLES\n"));
		iError = GetHandles (&papi->GETHANDLES.cReturned, papi->GETHANDLES.aHandles);
		break;

	case BTHLINK_GET_ADDRESS:
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: IOCTL :: BTHLINK_GET_HANDLES\n"));
		iError = GetAddress (papi->GETADDR.h, &papi->GETADDR.b);
		break;

	case BTHLINK_SET_FILTER_CLEAR:
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: IOCTL :: BTHLINK_SET_FILTER_CLEAR\n"));
		iError = ClearFilter ();
		break;

	case BTHLINK_SET_FILTER_INQ_BA:
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: IOCTL :: BTHLINK_SET_FILTER_INQ_BA\n"));
		iError = SetInquiryFilter (&papi->BA.b);
		break;

	default:
		IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTHLINK :: IOCTL :: ERROR_CALL_NOT_IMPLEMENTED\n"));
		iError = ERROR_CALL_NOT_IMPLEMENTED;
	}

	if (iError != ERROR_SUCCESS) {
		SetLastError (iError);
		return FALSE;
	}

	return TRUE;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -