Click here to Skip to main content
15,886,810 members
Articles / Mobile Apps / Windows Mobile

Infrared Communication with your Mobile Phone

Rate me:
Please Sign up or sign in to vote.
4.89/5 (88 votes)
17 Dec 2003CPOL7 min read 1.2M   3.6K   218  
Learn how to make your Pocket PC speak with your mobile phone.
// IrdaMobileDlg.cpp : Implementierungsdatei
//

#include "stdafx.h"
#include "IrdaMobile.h"
#include "IrdaMobileDlg.h"
#include "IrdaPort.h"

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

/////////////////////////////////////////////////////////////////////////////

#define TIMEOUT 5000  // Timeout for the phone response in milliseconds 

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg-Dialogfeld f�r Anwendungsbefehl "Info"

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialogfelddaten
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// Vom Klassenassistenten generierte �berladungen virtueller Funktionen
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV-Unterst�tzung
	//}}AFX_VIRTUAL

// Implementierung
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// Keine Nachrichten-Handler
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CIrdaMobileDlg Dialogfeld

CIrdaMobileDlg::CIrdaMobileDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CIrdaMobileDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CIrdaMobileDlg)
	//}}AFX_DATA_INIT

	// Beachten Sie, dass LoadIcon unter Win32 keinen nachfolgenden DestroyIcon-Aufruf ben�tigt
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CIrdaMobileDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CIrdaMobileDlg)
	DDX_Control(pDX, IDC_LIST1, m_ctrlList);
	DDX_Control(pDX, IDC_COMBO1, m_ctrlPort);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CIrdaMobileDlg, CDialog)
	//{{AFX_MSG_MAP(CIrdaMobileDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON1, OnRead)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CIrdaMobileDlg Nachrichten-Handler

BOOL CIrdaMobileDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Hinzuf�gen des Men�befehls "Info..." zum Systemmen�.

	// IDM_ABOUTBOX muss sich im Bereich der Systembefehle befinden.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{	
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Symbol f�r dieses Dialogfeld festlegen. Wird automatisch erledigt
	//  wenn das Hauptfenster der Anwendung kein Dialogfeld ist
	SetIcon(m_hIcon, TRUE);			// Gro�es Symbol verwenden
	SetIcon(m_hIcon, FALSE);		// Kleines Symbol verwenden
	
	// ZU ERLEDIGEN: Hier zus�tzliche Initialisierung einf�gen

	m_ctrlPort.ResetContent();

	for (int n = 0; n < 255; n++)
	{
		CString str;
		str.Format(_T("COM%d"), n + 1);
		m_ctrlPort.InsertString(n,str);
	}

	const int nPort = 3; // CIrdaPort::FindPortIndex();
	m_ctrlPort.SetCurSel((nPort > 0 && nPort <= 255) ? (nPort - 1) : 2);

	m_ctrlList.InsertColumn(0, _T("Name"), LVCFMT_LEFT);
	m_ctrlList.InsertColumn(1, _T("Number"), LVCFMT_LEFT);

	CRect rect;
	m_ctrlList.GetClientRect(rect);

	m_ctrlList.SetColumnWidth(0, rect.Width() / 2);
	m_ctrlList.SetColumnWidth(1, LVSCW_AUTOSIZE_USEHEADER);
	
	return TRUE;  // Geben Sie TRUE zur�ck, au�er ein Steuerelement soll den Fokus erhalten
}

void CIrdaMobileDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// Wollen Sie Ihrem Dialogfeld eine Schaltfl�che "Minimieren" hinzuf�gen, ben�tigen Sie 
//  den nachstehenden Code, um das Symbol zu zeichnen. F�r MFC-Anwendungen, die das 
//  Dokument/Ansicht-Modell verwenden, wird dies automatisch f�r Sie erledigt.

void CIrdaMobileDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // Ger�tekontext f�r Zeichnen

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Symbol in Client-Rechteck zentrieren
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Symbol zeichnen
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// Die Systemaufrufe fragen den Cursorform ab, die angezeigt werden soll, w�hrend der Benutzer
//  das zum Symbol verkleinerte Fenster mit der Maus zieht.
HCURSOR CIrdaMobileDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CIrdaMobileDlg::OnRead() 
{
	// TODO: Add your control notification handler code here

	CString strResponse;

	CWaitCursor wait;

	///////////////////////////////////////////////////////////////////////////
    //
    //  Try to open the IRDA port.
    //

	UpdateData(TRUE);

	const int nPort = m_ctrlPort.GetCurSel() + 1;

	if (nPort <= 0 || nPort > 255)
	{
        AfxMessageBox(_T("Invalid IRDA port."));

		return;
	}

	CIrdaPort port;

	if (!port.Open(nPort))
	{
		AfxMessageBox(_T("Failed to open IRDA port."));

		return;
	}

	GetDlgItem(IDC_PHONE)->SetWindowText(_T(""));
    GetDlgItem(IDC_PHONE)->UpdateWindow();

	GetDlgItem(IDC_MODEL)->SetWindowText(_T(""));
    GetDlgItem(IDC_MODEL)->UpdateWindow();

	GetDlgItem(IDC_ENTRIES)->SetWindowText(_T("0 Entries"));
    GetDlgItem(IDC_ENTRIES)->UpdateWindow();

	m_ctrlList.DeleteAllItems();
	m_ctrlList.Invalidate();
	m_ctrlList.UpdateWindow();

	///////////////////////////////////////////////////////////////////////////
    //
    //  Try to connect to the Mobile Phone.
    //
    //  Command       : AT<CR>
    //
    //  Valid response: <CR><LF>OK<CR><LF>
    //
    //  Error response: <CR><LF>ERROR<CR><LF>
    //
    //  <CR> ... Carriage return
    //  <LF> ... Line feed
    //

	if (!port.Send(_T("AT"), TIMEOUT))
	{
		port.Close();

		AfxMessageBox(_T("Failed to write request to device."));
		
		return;
	}

	if (!port.WaitForResponse(strResponse, TIMEOUT))
	{
		port.Close();

		AfxMessageBox(_T("Timeout, no response."));
		
		return;
	}

    strResponse.MakeUpper();

	if (strResponse.Find(_T("ERROR")) > -1)
	{
		port.Close();

		AfxMessageBox(_T("Invalid command."));

		return;
	}
	else if (strResponse.Find(_T("OK")) == -1)
	{
		port.Close();

		AfxMessageBox(_T("Wrong response."));

		return;
	}

    ///////////////////////////////////////////////////////////////////////////
    //
    //  Request the manufacturer identification.
    //
    //  Command       : AT+CGMI<CR>
    //
    //  Valid response: <CR><LF>manufacturer<CR><LF>
    //                  <CR><LF>OK<CR><LF>
    //
    //                  manufacturer ... manufacturer identification
    //
    //  Error response: <CR><LF>ERROR<CR><LF>
    //
    //  <CR> ... Carriage return
    //  <LF> ... Line feed
    //

	if (!port.Send(_T("AT+CGMI"), TIMEOUT))
	{
		port.Close();

		AfxMessageBox(_T("Failed to write request to device."));
		
		return;
	}

	if (!port.WaitForResponse(strResponse, TIMEOUT))
	{
		port.Close();

		AfxMessageBox(_T("Timeout, no response."));

		return;
	}

    const CString strPhone(strResponse);

    strResponse.MakeUpper();

	if (strResponse.Find(_T("ERROR")) > -1)
	{
		port.Close();

		AfxMessageBox(_T("Invalid command."));

		return;
	}

	if (!port.WaitForResponse(strResponse, TIMEOUT))
	{
		port.Close();

		AfxMessageBox(_T("Timeout, no response."));

		return;
	}

    strResponse.MakeUpper();

	if (strResponse.Find(_T("ERROR")) > -1)
	{
		port.Close();

		AfxMessageBox(_T("Invalid command."));

		return;
	}
	else if (strResponse.Find(_T("OK")) == -1)
	{
		port.Close();

		AfxMessageBox(_T("Wrong response."));

		return;
	}

	GetDlgItem(IDC_PHONE)->SetWindowText(strPhone);
    GetDlgItem(IDC_PHONE)->UpdateWindow();

	///////////////////////////////////////////////////////////////////////////
    //
    //  Request the model identification.
    //
    //  Command       : AT+CGMM<CR>
    //
    //  Valid response: <CR><LF>model<CR><LF>
    //                  <CR><LF>OK<CR><LF> 
    //
    //                  model ... model identification
    //
    //  Error response: <CR><LF>ERROR<CR><LF>
    //
    //  <CR> ... Carriage return
    //  <LF> ... Line feed
    //

	if (!port.Send(_T("AT+CGMM"), TIMEOUT))
	{
		port.Close();

		AfxMessageBox(_T("Failed to write request to device."));
		
		return;
	}

	if (!port.WaitForResponse(strResponse, TIMEOUT))
	{
		port.Close();

		AfxMessageBox(_T("Timeout, no response."));

		return;
	}

    const CString strModel(strResponse);

    strResponse.MakeUpper();

	if (strResponse.Find(_T("ERROR")) > -1)
	{
		port.Close();

		AfxMessageBox(_T("Invalid command."));

		return;
	}

	if (!port.WaitForResponse(strResponse, TIMEOUT))
	{
		port.Close();

		AfxMessageBox(_T("Timeout, no response."));

		return;
	}

    strResponse.MakeUpper();

	if (strResponse.Find(_T("ERROR")) > -1)
	{
		port.Close();

		AfxMessageBox(_T("Invalid command."));

		return;
	}
	else if (strResponse.Find(_T("OK")) == -1)
	{
		port.Close();

		AfxMessageBox(_T("Wrong response."));

		return;
	}

	GetDlgItem(IDC_MODEL)->SetWindowText(strModel);
    GetDlgItem(IDC_MODEL)->UpdateWindow();

	///////////////////////////////////////////////////////////////////////////
    //
    //  Select the phonebook memory storage where phonebook commands operate.
    // 
    //  Command       : AT+CPBS=storage<CR>
    //
    //                  storage ... memory where phonebook commands operate
    //
    //                  "FD" ... SIM fixdialling-phonebook
    //                  "LD" ... SIM last-dialling-phonebook
    //                  "ME" ... ME phonebook
    //                  "MT" ... combined ME and SIM phonebook
    //                  "SM" ... SIM phonebook
    //                  "TA" ... TA phonebook    
    //
    //  Valid response: <CR><LF>OK<CR><LF> 
    //
    //  Error response: <CR><LF>ERROR<CR><LF>
    //
    //  <CR> ... Carriage return
    //  <LF> ... Line feed
    //

    if (!port.Send(_T("AT+CPBS=\"SM\""), TIMEOUT))
	{
		port.Close();

		AfxMessageBox(_T("Failed to write request to device."));
		
		return;
	}

	if (!port.WaitForResponse(strResponse, TIMEOUT))
	{
		port.Close();

		AfxMessageBox(_T("Timeout, no response."));

		return;
	}

    strResponse.MakeUpper();

	if (strResponse.Find(_T("ERROR")) > -1)
	{
		port.Close();

		AfxMessageBox(_T("Invalid command."));

		return;
	}
	else if (strResponse.Find(_T("OK")) == -1)
	{
		port.Close();

		AfxMessageBox(_T("Wrong response."));

		return;
	}

	///////////////////////////////////////////////////////////////////////////
    //
    //  Read the size of the selected phonebook memory.
    //
    //  Command       : AT+CPBR=?<CR>
    //
    //  Valid response: <CR><LF>+CPBR: (index-list),nlength,tlength<CR><LF>
    //                  <CR><LF>OK<CR><LF> 
    //
    //                  index ..... integer type values in the range of 
    //                              location numbers of phonebook memory
    //                  list ...... integer type value indicating the size of 
    //                              the selected phonebook memory
    //                  nlength ... integer type value indicating the maximum 
    //                              length of the number field
    //                  tlength ... integer type value indicating the maximum 
    //                              length of name field
    //
    //  Error response: <CR><LF>ERROR<CR><LF>
    //
    //  <CR> ... Carriage return
    //  <LF> ... Line feed
    //

	if (!port.Send(_T("AT+CPBR=?"), TIMEOUT))
	{
		port.Close();

		AfxMessageBox(_T("Failed to write request to device."));
		
		return;
	}

    if (!port.WaitForResponse(strResponse, TIMEOUT))
	{
		port.Close();

	    AfxMessageBox(_T("Timeout, no response."));
		    
	    return;
	}

    const CString strMemory(strResponse);

    strResponse.MakeUpper();

	// Check the response

    int nPhoneBookSize = 0;

	if (strResponse.Find(_T("CPBR")) > -1)
	{
		if (!port.WaitForResponse(strResponse, TIMEOUT))
		{
			port.Close();

			AfxMessageBox(_T("Timeout, no response."));
		    
			return;
		}

        strResponse.MakeUpper();

		if (strResponse.Find(_T("OK")) > -1)
		{
            // Get the size of the phonebook memory
			
			const int nStart = strMemory.Find(_T('-'));
	    	const int nEnd = strMemory.Find(_T(')'), nStart + 1);

			nPhoneBookSize = _ttoi((LPCTSTR) strMemory.Mid(nStart + 1, nEnd - nStart - 1));

            ASSERT(nPhoneBookSize >= 0); 

		    // AfxMessageBox(strMemory.Mid(nStart + 1, nEnd - nStart - 1));
		}
		else
		{
			port.Close();

			AfxMessageBox(_T("Wrong response."));

			return;
		}
	}
    else if (strResponse.Find(_T("ERROR")) > -1)
	{
		port.Close();

		AfxMessageBox(_T("Invalid command."));

		return;
	}
	else
	{
		port.Close();

		AfxMessageBox(_T("Wrong response."));

		return;
	}

    ///////////////////////////////////////////////////////////////////////////
    //
    //  Read all phonebook entries.
    //
    //  Command       : AT+CPBR=index<CR>
    //
    //                  index ... integer type values in the range of 
    //                            location numbers of phonebook memory
    //
    //  Valid response: <CR><LF>+CPBR: index, "number", type, "name"<CR><LF>
    //                  <CR><LF>OK<CR><LF> 
    //
    //                  index .... integer type values in the range of 
    //                             location numbers of phonebook memory
    //                  number ... string type phone number of format type
    //                  type ..... type of address octet in integer format
    //                  name ..... the name of the phonebook entry
    //
    //  Response for 
    //  an empty entry: <CR><LF>OK<CR><LF>
    //
    //  Error response: <CR><LF>ERROR<CR><LF>
    //
    //  <CR> ... Carriage return
    //  <LF> ... Line feed
    //

	int nNumberOfEntries = 0;

    for (int n = 1; n <= nPhoneBookSize; n++)
	{
		CString strCommand;

		strCommand.Format(_T("AT+CPBR=%d"), n);

        if (!port.Send(strCommand, TIMEOUT))
		{
		    port.Close();

		    AfxMessageBox(_T("Failed to write request to device."));
		
		    return;
		}

		// Wait for response

	    if (!port.WaitForResponse(strResponse, TIMEOUT))
		{
			port.Close();

		    AfxMessageBox(_T("Timeout, no response."));
		    
		    return;
		}

        const CString strEntry(strResponse);

        strResponse.MakeUpper();

		// Check the response

		if (strResponse.Find(_T("CPBR")) > -1)
		{
			if (!port.WaitForResponse(strResponse, TIMEOUT))
			{
				port.Close();

				AfxMessageBox(_T("Timeout, no response."));
		    
				return;
			}

            strResponse.MakeUpper();

			if (strResponse.Find(_T("OK")) > -1)
			{
                // Insert the name and the number in the list box

    			int nStart = strEntry.Find(_T('\"'));
	    	    int nEnd = strEntry.Find(_T('\"'), nStart + 1);

		        const CString strNumber = strEntry.Mid(nStart + 1, nEnd - nStart - 1);

		        // AfxMessageBox(strNumber);

		        nStart = strEntry.Find(_T('\"'), nEnd + 1);
		        nEnd = strEntry.Find(_T('\"'), nStart + 1);

		        const CString strName = strEntry.Mid(nStart + 1, nEnd - nStart - 1);

                // AfxMessageBox(strName);

    		    m_ctrlList.InsertItem(0, strName);
	    	    m_ctrlList.SetItemText(0, 1, strNumber);
                m_ctrlList.Update(n);

				CString strEntries;
				strEntries.Format(_T("%d Entries"), ++nNumberOfEntries);
				GetDlgItem(IDC_ENTRIES)->SetWindowText(strEntries);
                GetDlgItem(IDC_ENTRIES)->UpdateWindow();
			}
			else
			{
				port.Close();

				AfxMessageBox(_T("Wrong response."));

				return;
			}
		}
        else if (strResponse.Find(_T("OK")) > -1)
		{
			continue;  // empty phonebook entry
		}
		else if (strResponse.Find(_T("ERROR")) > -1)
		{
			port.Close();

			AfxMessageBox(_T("Invalid command."));

			return;
		}
		else
		{
			port.Close();

			AfxMessageBox(_T("Wrong response."));

			return;
		}
	}

    ///////////////////////////////////////////////////////////////////////////
    //
    //  Close the IRDA port.
    // 

	port.Close();
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Austria Austria
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions