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

📄 irdasocket.cpp

📁 WINCE下 红外遥控设备程序
💻 CPP
字号:
//////////////////////////////////////////////////////////////////////////
//
//  IrDASocket.cpp - IrDA socket support for Pocket PC
//
//  Written by Daniel Strigl (daniel.strigl@web.de).
//  Copyright (c) 2003. All Rights Reserved.
//
//  The original code was written by Ramon de Klein (R.de.Klein@iaf.nl).
//
//  The original IrDA socket support class can be found in
//  the "Bubbles for Pocket PC" application from Ramon de Klein
//  at http://www.codeproject.com/ce/bubbles.asp or
//  http://home.ict.nl/~ramklein/Projects/Bubbles.html.
//
//  Feel free to modify the source code and / or use it in your
//  own programs. By the way, I would appreciate and enjoy hearing
//  about them (just send an e-mail to daniel.strigl@web.de).
//
//  Please report any bug, comment, suggestion, etc. to the
//  following address: daniel.strigl@web.de
//
//  Contact:
//  --------
//
//    Daniel Strigl
//    daniel.strigl@web.de
//    http://www.hh-system.com/danielstrigl
//
//  History:
//  --------
//
//    02.04.2003: The original IrDA socket support class was written
//                to use in ATL/WTL applications. Modified the class
//                so that it can be used in every MFC application.
//
//    03.04.2003: Added the "VerifyService" function.
//
//    16.04.2003: Added a second "VerifyService" function and modified
//                the original "VerifyService" function.
//
//  ORIGINAL COPYRIGHT STATEMENTS:
//  ------------------------------
//
//    IrDASocket.cpp - Bubbles for Pocket PC (IrDA socket support)
//
//    Copyright (C) 2000 Ramon de Klein (R.de.Klein@iaf.nl)
//
//    This program is free software; you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation; either version 2 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program; if not, write to the Free Software
//    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//////////////////////////////////////////////////////////////////////////

#include "StdAfx.h"
#include "IrDASocket.h"
#include <atlconv.h>     // Need for ATL conversion macros!

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////////
// CWinSock class

int CWinSock::mg_iInstance = 0;

WSADATA CWinSock::mg_wsaData = {0};

CWinSock::CWinSock()
{
	// Only initialize WinSock the first time
	if (++mg_iInstance == 1)
	{
		WSAStartup(MAKEWORD(1,1), &mg_wsaData);
	}
}

CWinSock::~CWinSock()
{
	// Cleanup WinSock when the last instance is gone
	if (--mg_iInstance == 0)
	{
		WSACleanup();
	}
}

//////////////////////////////////////////////////////////////////////////
// CIrDASocket class

CIrDASocket::CIrDASocket() : m_sd(INVALID_SOCKET)
{
}

CIrDASocket::~CIrDASocket()
{
	// Close socket if left open
	if (m_sd != INVALID_SOCKET)
		closesocket(m_sd);
}

bool CIrDASocket::WaitForOperation(const bool fRead, const bool fWrite, const DWORD dwTimeout)
{
	// Check if the call would block
	const int iError = WSAGetLastError();
	if (iError != WSAEWOULDBLOCK)
	{
		TRACE(_T("WaitForOperation called unexpectedly (error=%08Xh).\n"),iError);
		return false;
	}

	// Setup the socket descriptors
	fd_set fdsRead = {0};
	fdsRead.fd_count = 1;
	fdsRead.fd_array[0] = m_sd;

	fd_set fdsWrite = {0};
	fdsWrite.fd_count = 1;
	fdsWrite.fd_array[0] = m_sd;

	// Setup the timeout structure
	struct timeval tv = {0};
	if (dwTimeout != INFINITE)
	{
		// Convert to correct values
		tv.tv_sec  = dwTimeout/1000;
		tv.tv_usec = dwTimeout%1000;
	}

	// Wait for the socket to accept
	if (select(0,fRead?&fdsRead:0,fWrite?&fdsWrite:0,0,(dwTimeout!=INFINITE)?&tv:0) == 0)
	{
		TRACE(_T("WaitForOperation select failed (error=%08Xh).\n"),WSAGetLastError());
		return false;
	}

	// Return successful
	TRACE(_T("WaitForOperation succeeded.\n"));
	return true;
}

bool CIrDASocket::EnumDevices(DEVICELIST* pDevList, int cbDevices)
{
	// Check pre-conditions
	ASSERT(m_sd != INVALID_SOCKET);
	ASSERT(pDevList != 0);

	// Obtain the available devices
	pDevList->numDevice = 0;
	if (getsockopt(m_sd,SOL_IRLMP,IRLMP_ENUMDEVICES,reinterpret_cast<char*>(pDevList),&cbDevices) == SOCKET_ERROR)
		return false;

	// Return successful
	return true;
}

bool CIrDASocket::VerifyService(PIAS_QUERY pIASQuery, int iasqlen)
{
    // Check pre-conditions
    ASSERT(m_sd != INVALID_SOCKET);
    ASSERT(pIASQuery != 0);
    ASSERT(iasqlen > 0);

    // Do the query
    if (getsockopt(m_sd,SOL_IRLMP,IRLMP_IAS_QUERY,reinterpret_cast<char*>(pIASQuery),&iasqlen) == SOCKET_ERROR)
        return false;

    // Check the query result - class not found?
    if (pIASQuery->irdaAttribType == IAS_ATTRIB_NO_CLASS)
        return false;

    // Check the query result - attribute not found?
    if (pIASQuery->irdaAttribType == IAS_ATTRIB_NO_ATTRIB)
        return false;

    // Return successful
    return true;
}

bool CIrDASocket::VerifyService(const LPBYTE pDeviceId, LPCSTR lpszClassName)
{
  	USES_CONVERSION;  // declare locals used by the ATL macros

    IAS_QUERY iasq = {0};

    // Check pre-conditions
	ASSERT(m_sd != INVALID_SOCKET);
	ASSERT(pDeviceId != 0);
    ASSERT(lpszClassName != 0);
	ASSERT(strlen(lpszClassName) < sizeof(iasq.irdaClassName));

    // Initialize the query structure
    int iasqlen = sizeof(iasq);
    memset(&iasq,0,iasqlen);

    // Copy the device id, classname and attribute
    memcpy(iasq.irdaDeviceID,pDeviceId,sizeof(iasq.irdaDeviceID));
    strcpy(iasq.irdaClassName,lpszClassName);

    // This mean that the LSAP-SEL will be returned
    strcpy(iasq.irdaAttribName,T2CA(_T("IrDA:TinyTP:LsapSel")));

    // Do the query
    return VerifyService(&iasq, iasqlen);
}

bool CIrDASocket::Open()
{
	// Check pre-conditions
	ASSERT(m_sd == INVALID_SOCKET);

	// Open socket
	m_sd = socket(AF_IRDA,SOCK_STREAM,0);
	if (m_sd == INVALID_SOCKET)
		return false;

	// Set socket as non-blocking socket
	u_long ulArg = 1;
	if (ioctlsocket(m_sd,FIONBIO,&ulArg) == SOCKET_ERROR)
		return false;

	// Return succcesful
	return true;
}

bool CIrDASocket::Close()
{
	// Only open sockets can be closed
	if (m_sd == INVALID_SOCKET)
		return false;

	// Close socket
	closesocket(m_sd);
	m_sd = INVALID_SOCKET;

	// Return succcesful
	return true;
}

bool CIrDASocket::Bind(LPCSTR lpszServiceName)
{
	SOCKADDR_IRDA sa = {0};

	// Check pre-conditions
	ASSERT(m_sd != INVALID_SOCKET);
	ASSERT(lpszServiceName != 0);
	ASSERT(strlen(lpszServiceName) < sizeof(sa.irdaServiceName));

	// Set the socket address
	sa.irdaAddressFamily = AF_IRDA;
	strcpy(sa.irdaServiceName,lpszServiceName);

	// Associate the server socket address with the server socket
	if (bind(m_sd,reinterpret_cast<SOCKADDR*>(&sa),sizeof(sa)) == SOCKET_ERROR)
		return false;

	// Return succcesful
	return true;
}

bool CIrDASocket::Listen(const int iBackLog)
{
	// Check pre-conditions
	ASSERT(m_sd != INVALID_SOCKET);

	// Establish a socket to listen for incoming connections
	if (listen(m_sd,iBackLog) == SOCKET_ERROR)
		return false;

	// Return succcesful
	return true;
}

bool CIrDASocket::Accept(SOCKET* psd, const DWORD dwTimeout)
{
	// Check pre-conditions
	ASSERT(m_sd != INVALID_SOCKET);
	ASSERT(psd != 0);

	// Accept a connection
	SOCKET sd = accept(m_sd,0,0);
	if (sd == INVALID_SOCKET)
	{
		// Wait for operation to complete
		if (!WaitForOperation(true,false,dwTimeout))
			return false;

		// Accept a connection
		sd = accept(m_sd,0,0);
		if (sd == INVALID_SOCKET)
			return false;
	}

	// Set socket as non-blocking socket
	u_long ulArg = 1;
	if (ioctlsocket(sd,FIONBIO,&ulArg) == SOCKET_ERROR)
		return false;

	// Set socket descriptor and return
	*psd = sd;
	return true;
}

bool CIrDASocket::Connect(LPCSTR lpszServiceName, const LPBYTE pDeviceId, const DWORD dwTimeout)
{
	SOCKADDR_IRDA sa = {0};

	// Check pre-conditions
	ASSERT(m_sd != INVALID_SOCKET);
	ASSERT(lpszServiceName != 0);
	ASSERT(strlen(lpszServiceName) < sizeof(sa.irdaServiceName));

	// Setup the IrDA address
	sa.irdaAddressFamily = AF_IRDA;
	strcpy(sa.irdaServiceName,lpszServiceName);
	memcpy(sa.irdaDeviceID,pDeviceId,sizeof(sa.irdaDeviceID));

	// Try to connect
	if (connect(m_sd,reinterpret_cast<SOCKADDR*>(&sa),sizeof(sa)) == SOCKET_ERROR)
	{
		// Wait for operation to complete
		if (!WaitForOperation(false,true,dwTimeout))
			return false;
	}

	// Return succesful
	return true;
}

bool CIrDASocket::Send(LPCVOID lpData, DWORD cbBytes, const DWORD dwTimeout)
{
	ASSERT(m_sd != INVALID_SOCKET);

	TRACE(_T("Send(%d) operation started.\n"),cbBytes);

	// Try to send the data
	DWORD dwBytes = send(m_sd,reinterpret_cast<const char*>(lpData),cbBytes,0);
	if (dwBytes != cbBytes)
	{
		TRACE(_T("Send(%d) operation cannot complete synchronous.\n"),cbBytes);

		// Wait for operation to complete
		if (!WaitForOperation(false,true,dwTimeout))
		{
			TRACE(_T("Send(%d) operation failed.\n"),cbBytes);
			return false;
		}

		// Retry the send operation
		dwBytes = send(m_sd,reinterpret_cast<const char*>(lpData),cbBytes,0);
		if (dwBytes != cbBytes)
			return false;
	}

	// Return succesful
	TRACE(_T("Send(%d) operation succeeded.\n"),cbBytes);
	return true;
}

bool CIrDASocket::Receive(LPVOID lpData, DWORD cbBytes, const DWORD dwTimeout)
{
	ASSERT(m_sd != INVALID_SOCKET);

	// Try to Receive the data
	DWORD dwBytes = recv(m_sd,reinterpret_cast<char*>(lpData),cbBytes,0);
	if (dwBytes != cbBytes)
	{
		TRACE(_T("Receive(%d) operation cannot complete synchronous.\n"),cbBytes);

		// Wait for operation to complete
		if (!WaitForOperation(true,false,dwTimeout))
		{
			TRACE(_T("Receive(%d) operation failed.\n"),cbBytes);
			return false;
		}

		// Retry the read operation
		dwBytes = recv(m_sd,reinterpret_cast<char*>(lpData),cbBytes,0);
		if (dwBytes != cbBytes)
			return false;
	}

	// Return succesful
	TRACE(_T("Receive(%d) operation succeeded.\n"),cbBytes);
	return true;
}

⌨️ 快捷键说明

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