This article may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. To maintain the flow of the article, we've left these URLs in the text, but disabled the links.


MIND


This article assumes you're familiar with WinSock and Windows CE Development
Download the code (63KB)

Get Your Windows CE Device Talking With IrDA
Michael S. Heydt

Palm-size PCs running Windows CE can communicate with your desktop machine through their wireless infrared features. If you know how to implement WinSock through this port, you can harness it for your own specialized use.
Over the last five years I've become quite an avid fan of home theater, collecting quite a bit of hardware and many remote controls. Now I've always thought that in some capacity I should be able to program a computer system to act like a really great universal remote control. Doing this would allow me to replace all of the remote controls with a single, programmable unit. Imagine writing macros that would solve complex tasks like watching a satellite program while listening to something else on the radio.

    Of course, designing such a system would require a computer system next to my sofa, taking up more space than the remotes themselves did. Then Microsoft introduced Windows® CE for the Palm-size PC (PPC) in 1998, and I decided that its form factor and built-in infrared communications would be my holy grail. All I would have to do is write a program for Windows CE to talk to my home theater devices via infrared.

    If only things were that easy!

    Even with the availability of the PPC there are still two issues to deal with in this type of system. The first problem, which I won't cover in this article, is that PPCs communicate via a protocol known as the Infrared Data Association (IrDA), while audio/visual equipment uses a Consumer IR (infrared) protocol. The two are not compatible and need a gateway to translate between them. Connecting a programmable consumer IR device to your system is fairly simple to operate via serial communications, so I won't discuss it here. Second, programming both the PPC and a desktop system (the gateway) to communicate with each other via IrDA is nowhere near as simple as it may seem at first.

    Let's examine the hardware and software requirements for this type of application. You'll obviously need a PPC, but you'll also need to add an infrared device to your desktop as well as software to run it.

    You'll also need to be familiar with developing for Windows CE. Windows CE is a small, scalable, 32-bit platform that can work in a wide range of products from embedded systems to handheld computers of different form factors. Windows CE 2.0 is based on the Windows Distributed interNet Applications (Windows DNA) architecture, a platform that defines the set of services required for modern distributed enterprise applications. Combining Internet and client-server computing, Windows DNA allows developers to create programs that can be delivered over any network.

    IrDA support under Windows was a major stumbling block because only Microsoft Windows 2000 beta 2 and later supports IrDA-based WinSock. Windows 2000 is expected to have a new process for installing hardware, so I'll show you how to use it to install IrDA and an infrared device to your desktop system. The next step is programming WinSock to use IrDA. I will provide an overview of IrDA that explains what it is and how it relates to TCP/IP, as well as examine sample programs that implement WinSock and IrDA.

Requirements

    When compiling and executing the programs that accompany this article, I used a number of tools and devices. To fully use these programs you will need a PPC. My personal preference is a Philips Nino (see Figure 1), although any PPC or handheld PC (H/PC) running Windows CE 2.x should work just as well. (If you target an H/PC, however, you'll need to tweak the user interface to account for display configuration differences.) Even without a PPC, the server application will function on its own and display useful information about WinSock transports and local IrDA devices.

Figure 1: Philips Nino
Figure 1: Philips Nino

    Your desktop system will need to be equipped with a device that allows it to communicate via infrared. I chose an Extended Systems JetEye ESI-9680 serial port device. I was pleased to find that Windows 2000 beta 2 actually included a driver specifically for the ESI-9680.

    You'll also need a few software tools. To develop the PPC application you will need Visual C++ 5.0 or higher, Visual C++ for Windows CE, and the Windows CE Toolkit for Visual C++. I used Visual C++ 6.0 and the beta of the Windows CE Toolkit for Visual C++ 6.0 to develop the programs.

    Last, but surely not least, you will need to run Windows 2000 beta 2 or later (either Workstation or Server) on the desktop. This is because it is the only non-CE version of Microsoft Windows that supports IrDA communication underneath WinSock. (More on this later.)

IrDA Support and Microsoft Windows

    After I finally got my hands on a Philips Nino in June 1998, the first little program that I wrote was very successful. It used WinSock on Windows CE to display a list of all infrared devices within range of the device. It worked quite well and could identify my digital camera and HP LaserJet 5P.

    The next step was to try to make the same program run on my desktop system. When I connected an infrared device to my Windows 98 desktop, I was able to establish connections and transfer contacts between my desktop and PPC. Next, it was time to fire up the compiler and rebuild the program for the desktop. I expected a little bit of modification to the program would be needed, but I did not expect that the compiler would not find the infrared extension file af_irda.h. The only place I located the include file was in the Windows CE toolkit. While this solved my compilation errors, the socket call with the AF_IRDA parameter was failing due to a WSAEAFNOSUPPORT error—IrDA was not supported. I found the same problem on my laptop, a Windows NT® 4.0-based system, and the first beta of Windows NT 5.0 (which was later renamed Windows 2000). As it turned out, WinSock communications with IrDA were not supported on any Windows version except for Windows CE. I had to wait until October 1998 and Windows 2000 beta 2 to get a desktop system that worked with IrDA and WinSock.

    This may sound surprising, since it has long been possible to transfer data between laptops and print using infrared ports. The natural assumption is that programs that do this use WinSock for their data transfer, which is not the case.

Installing IrDA on Windows 2000

    By default, IrDA protocol support is not installed with Windows 2000. You must first install an infrared device to enable it. If you run the server program that accompanies this article, it will show that the IrDA transport protocol is not installed.

    Installation of hardware under Windows 2000 is a bit different from the way hardware was installed under Windows NT 4.0. It's closer (but not identical) to the procedure used on Windows 98. Let's take a look at the installation of the JetEye infrared device as an example.
Figure 2: Hardware Wizard
Figure 2: Hardware Wizard

    Starting from within Control Panel, you will need to run two wizards. The Hardware Wizard is started by selecting its icon. Several steps into the Hardware Wizard, you'll start the New Hardware Wizard. When you're presented with the first dialog of the wizard (see Figure 2), click Next for the second dialog, which asks you to select a hardware task. Since you're installing new hardware, select Add new hardware and click Next (see Figure 3). The next dialog you'll see forces you to run the New Hardware Wizard. When you do so, a Welcome dialog will appear. At this point, click Next.
Figure 3: Choosing Your Hardware Task
Figure 3: Choosing Your Hardware Task

    Windows 2000 will now look for new plug and play hardware. The wizard will inform you that it is performing this task by displaying the detection status. When it finishes, it will present you with a dialog that asks you to press Next to continue and install any non-plug and play hardware.

    Then the wizard asks whether you want to have Windows 2000 look for non-plug and play hardware or you want to select it from a list. The JetEye device happens to be on the list of supported devices, so I selected No and clicked Next.
Figure 4: Add New Hardware
Figure 4: Add New Hardware

    You will now be presented with a dialog (see Figure 4) that should be familiar if you use Windows 98. This dialog lets you select the category of device that you want to install, infrared devices in the case of the JetEye. The wizard then asks for the hardware's manufacturer and model (see Figure 5). Select Extended Systems and ESI-9680 Serial Infrared Device (or the appropriate settings for your device), then press Next.
Figure 5: Specifying the Model
Figure 5: Specifying the Model

    At this point, the wizard lets you know that it will now inform you that it is ready to install drivers for the hardware that has been identified. Press Next and Windows NT will install the drivers for the devices.

    Since the device that you are installing requires informing Windows 2000 which COM port it is connected to, the wizard will pop up the dialog allowing you to specify how the device is connected. I have my JetEye installed on COM1, so I selected that option and pressed OK.

    At this point, the wizard has finished installing drivers for the particular device. It tells you that you might have to reboot your system in order for the device to function properly; in the case of the JetEye, it is now functional and does not require rebooting.

    Now press Finish and you will be taken back to the third screen of the original Hardware Wizard, with the Next button enabled. Press Next and you will be taken to the final page of the wizard, which simply informs you that you have completed your task.

    At this point, IrDA communications should be available to Windows 2000. To verify that it is functioning properly, you can
Figure 6
Figure 6
perform a number of tests like placing an infrared device within range of your desktop transceiver. If the desktop system sees the device, you will hear a beep and an infrared icon will appear in your system tray (see Figure 6).

    When your mouse hovers over this icon, you get various pieces of information about how your desktop is communicating via infrared. This information will change depending upon the system's current state of communication. Figure 7 shows that the desktop has identified an HP LaserJet 5P printer within range. If I print a document to that LaserJet,
Figure 7: Printer Identified
Figure 7: Printer Identified
the icon will change its appearance during communications, as shown in Figure 8. This visually identifies that communications with the device is in progress.

    If you use your PPC to verify connectivity, you will have to run an application on the PPC that uses infrared to communicate with the desktop. By default, the PPC does not broadcast any infrared signals because it would drain the batteries. To perform this task, you can start the Contacts application and attempt to transfer a contact. At this point, the PPC will start infrared communications and the desktop should identify it.
Figure 8: Print in Process
Figure 8: Print in Process

    Now your desktop system should be able to communicate using IrDA and WinSock. Before you continue, you should read the sidebar "Implementation of IrDA." It discusses the IrDA transport protocol, and will give you a better idea how to successfully program two systems to communicate over the wireless medium.

The Server Application

    This article has two accompanying applications that demonstrate most IrDA techniques. These programs form a client/server pair that are designed to communicate with each other. Even though they're coded to work together, each piece also shows how to gather information and communicate with arbitrary systems that use IrDA.

    The executable file for the server application is basic_irda_ server.exe. This program can be run on any Windows desktop operating system, although not all of the features can be utilized on operating systems other than Windows 2000 with IrDA installed.

    The server application enumerates the transport protocols available for WinSock. If you look at the top window in Figure 9, you will see all of the installed protocols listed by WinSock address family, with the service's descriptive name and protocol family ID provided.

    The top pane in Figure 9 shows the Protocols window from the server application after installing the JetEye infrared device. You can now see a highlighted line that reads:

 MSAFD Irda [IrDA]
This is the Microsoft IrDA transport protocol for WinSock. The server application is programmed to identify support of this protocol and highlight it. By running this application on various platforms you can easily identify whether the system is running an IrDA stack under WinSock.

    The lower-left pane of Figure 9 shows the devices MDI window, which lists all devices that IrDA has determined are currently within range. In this case, I have placed my digital camera, Nino, and HP LaserJet 5P within range of the JetEye. The server application recognizes them and displays the device ID, the device name, a human-friendly version of the device hints bitmask, and the character set used by the device. Again, this window will only display information if IrDA is installed on the system and if devices are within range. (In other words, it only functions on Windows 2000 with IrDA installed.)

    The server application also implements an IrDA service named basic_irda_server. This service simply allows clients to connect to it and send a string, which it will then display in the Data Communication window. The service will also acknowledge the client by sending a "Hello from the basic_irda_server" string back to the client.

    The status of this service is displayed in the Data Communication window. As connections are established, shut down, and data is received from clients, this service will display status information in this window.

    The lower-right pane of Figure 9 shows a simple, single connection from the client application, with the client sending the "Test for Echo!" string. In addition to this action, the service will display the address of the client device that caused the action and the associated LSAP-SEL that identifies the connection between client and server services.

The Client Application

    The client program, named basic_irda_ client.exe, is designed to be run on a Palm-size PC, although it should run quite well on an H/PC with just a few modifications to the user interface. Much like the server application, this client app has several functions. Figure 10 shows the basic dialog of the client application when it is started. The user interface of the application is divided into three areas. The top area consists of a listbox that shows the IrDA devices that the client can see at any given moment. Every five seconds the program will query an IrDA socket for a list of devices that are within range and update this information.
Figure 10: IrDA Client App
Figure 10: IrDA Client App

    Figure 10 shows the program detecting that my digital camera is placed within range of my Windows 2000 desktop. Notice that the listbox is populated with a list of devices and the device's ID and name are both shown on a line. My desktop system is configured with a NetBIOS name of NTFIVER. When the desktop IrDA protocol stack provides information to clients during device discovery, it provides the NetBIOS computer name as the name of the IrDA device.

    In the middle of the user interface is an Edit field which is initially populated with the string "basic_irda_server". This Edit field provides a user-configurable parameter to both the service verification and send data functions of the application. (I'll explain the send data functions shortly.)

    At the bottom of the user interface are two push buttons. Pressing the button labeled Verify Service will have the client perform an IrDA Directory Service (IAS) query to the device highlighted in the Devices listbox to see if the service specified by name in the Edit field is running on that remote device. If the device is running the specified service, you will be informed that the requested class and attribute have been verified on the remote machine. I'll look at how this query is performed later.

    Pressing the Send button will make the application attempt to connect to the basic_irda_server service on the device highlighted in the Devices listbox. If a connection is established, the application will send the contents of the Edit field to the server service as a message. If the message is successfully sent, you should see it appear in the server's Data Communication window (as well as in connect and disconnect messages). The client application should display the "Hello from the basic_irda_ server" message that is sent from the server service (see Figure 11). If the specified device does not support the basic_irda_server service, then the attempt to connect the socket will fail and you will receive an error message. Figure 12 shows what happened when I attempted to connect to my digital camera, which does not support the basic_irda_server service.
Figure 11: Hello
Figure 11: Hello

    Now that I've gone through the functionality of the client and server app, let's delve more deeply into some important features of the implementation.
Figure 12: Error
Figure 12: Error

Unique Data Structures

    Several WinSock functions require passing of data structures to them, either to pass data to the function or retrieve data from the network. The applications accompanying this article utilize four data structures unique to IrDA and WinSock: SOCKADDR_IRDA, DEVICELIST, IRDA_DEVICE_INFO, and IAS_QUERY.

    The bind and connect WinSock functions require you to pass in a data structure that specifies addressing information. When you're calling the bind function on a server, this data structure exposes information about the address where packets should be routed so the service receives them. On the client, the data structure passed to the connect function specifies the address of a remote machine to attempt communication with.

    In a typical WinSock application, the bind function requires that a SOCKADDR structure be passed in to specify addressing information. This structure is generic in that it specifies only two fields: a short integer to specify protocol family and a 14-character data field. Since addressing information formats vary in different protocol families, it is the responsibility of a protocol transport to specify a redefined SOCKADDR structure to be passed to the bind function. For the TCP/IP transport, the structure is defined as SOCKADD_ IN; for IrDA it is SOCKADDR_IRDA.

 typedef struct _SOCKADDR_IRDA
 {
     u_short irdaAddressFamily;
     u_char  irdaDeviceID[4];
     char    irdaServiceName[25];
 }  SOCKADDR_IRDA, *PSOCKADDR_IRDA;
I discuss the use of the SOCKADDR_IRA structure to register a service and establish connections later on in the article.

    After a socket is opened with the socket call, a second call can be issued to the getsockopt function to retrieve the devices that have been dynamically discovered within range of the local device. A pointer to a DEVICELIST structure is passed to the getsockopt function.

    The DEVICELIST structure is intended to be variable length, and consists of two fields. The first, numDevice, specifies the number of devices to be held by the structure. The second field allocates a single IRDA_DEVICE_INFO structure. When calling getsockopt, you'll typically allocate a chunk of memory that is the size of a single DEVICELIST, plus enough memory to cover additional IRDA_DEVICE_ INFO structures. The numDevice field will then be set to represent the total number of device information structures in the list, including the one in the original device list structure. You'll see how this is actually done in a little bit.

    The IRDA_DEVICE_INFO structure is used to hold descriptive information about devices that have been identified as being in the range of your infrared transceiver.

   typedef struct _IRDA_DEVICE_INFO
   {
       u_char  irdaDeviceID[4];
       char    irdaDeviceName[22];
       u_char  Reserved[2];
   } IRDA_DEVICE_INFO, *PIRDA_DEVICE_INFO, 
       FAR *LPIRDA_DEVICE_INFO;
The structure provides for a four-character device identifier and a 22-character device name. If the program is running on Windows 2000, it also provides hinting and character set information.

    In addition to using getsockopt to retrieve device information, IAS_QUERY can be used to query values in a remote machine's IAS database. To achieve this, it must be passed an IAS_QUERY structure that specifies the query information (see Figure 13). Within this structure, you specify the device ID of the remote machine, the class name of the object, and the attribute whose value is to be retrieved. The remainder of the structure amounts to a variant value that is returned from the remote machine if the specified class/attribute exists.

Verifying IrDA Installation

    Since IrDA is not necessarily installed on most desktop computer systems, it is probably a good idea to determine up front whether the transport protocol does indeed exist. There are two ways to do this. The simpler way is attempting to open a socket via a call to socket using the AF_IRDA value as the family ID. If this call fails, you can reasonably assume that IrDA is not installed.

    The server application I presented takes a different approach. I decided that this approach is more appropriate because AF_IRDA currently has different values on different platforms. Using this method, the server application first calls the build_protocol_list function (see Figure 14). This function is also used to generate the information displayed in the server application's Available Protocols window (see Figure 9), and builds a string that contains the names of all of the available WinSock transport protocols.

    Once this list is generated, it is passed to the get_irda_ family_id function (see Figure 15). This function parses the string looking for the phrase "MSAFD Irda [IrDA]". If this phrase is found, it means that IrDA is definitely installed on the system, and the associated family ID is returned from the function. If it is not found, then the function returns -1.

Client to Server Connections

    Establishing a connection to a server from a Windows CE-based client using IrDA is identical to the actions taken to connect a TCP/IP client, with the exception of two steps. The first is the call to socket, which must specify AF_IRDA as the protocol family instead of PF_INET. The only acceptable value for the type specification is SOCK_STREAM, as all IrDA communications are considered reliable.

    The second difference is in using the SOCKADDR_IRDA structure that is passed to the connect function call. In this structure, you must specify both the device ID of the server and the service name (see Figure 16). The value for the device ID can be obtained from the selection in the Devices listbox, where it was placed in ASCII format during the device identification process. I know that the name of the service that I'm connecting to is basic_irda_server, as I designed this client to communicate with that service in the server application.

    Once the SOCKADDR_IRDA structure is filled in, it can be passed to the connect function. The connect call then passes the information specified in the data structure to the IrDA protocol stack, where it is used to perform an IAS query to determine the actual LSAP-SEL of the service on the remote machine. If the LSAP-SEL is identified and a connection can be established, the function will return successfully.

Registering a Named Service on a Server

    A client must specify a service name before it connects to a server so the IrDA protocol stack can perform an IAS lookup for the correct connection identifier on the remote machine. For the lookup to succeed, the remote machine must have already registered this service by name so that it can reach agreement with client systems.

    Registering the service is handled on the server through the WinSock bind function. The second parameter of the bind function happens to be a pointer to a SOCKADDR_ IRDA structure (see Figure 17). Copying the basic_irda_server string into the irdaServiceName field of the structure before calling bind will inform the IrDA protocol stack that it is to accept (via the listen function) incoming connections from client connect calls that specify basic_irda_server as the service name for this particular socket.

Enumerating Devices and Retrieving Hints

    Identifying devices that are within range of the local computer system is handled in the server application via the build_device_list function (see Figure 18). The process first begins with the opening of an IrDA socket. This open socket can then be passed to the getsockopt function to enumerate the available devices.

    The getsockopt function takes five parameters. The first is the handle to the socket upon which devices should be identified. The second is a protocol-level specification value, which must be SOL_IRLMP. The third parameter is a value specifying the option to be performed; for device enumeration, this is IRLMP_ENUMDEVICES. The fourth parameter is a pointer to a buffer that will hold the information that's returned from the function call. If the third parameter is IRLMP_ENUMDEVICES, this value points to a buffer large enough to contain a single DEVICELIST structure followed by an arbitrary number of appended IRDA_DEVICE_INFO structures. The last parameter to getsockopt is a pointer to an integer that must contain the total size in bytes of this buffer. In Figure 18 you can see that the server allocates room for 50 devices to be identified (a DEVICELIST structure that already contains a single IRDA_DEVICE_INFO structure and 49 additional IRDA_DEVICE_INFO structures).

    If the getsockopt function executes successfully, it will fill the numDevice member of the DEVICELIST structure with the number of devices that were identified during the call. The application then loops through all of the identified devices, looking at each associated IRDA_DEVICE_INFO structure and constructing a string that is used by the device display routines.

    Each IRDA_DEVICE_INFO structure contains five fields. The first is a four-character (32-bit) device identifier. This identifier serves as a device address and can be used in subsequent connect calls to specify the desired remote machine. The second field is a 22-character device name that can be used as a human-friendly display string to identify the device.

    The next three fields contain hinting information that can help your application determine more information about the type of device and its preferred character set to use during communication. The first hinting field, irdaDeviceHints1, specifies the type of device. The types of devices that can be specified include palmtop, printer, modem, and so on. You determine the type of device by ANDing the field with the LM_HB1_xxx enumeration values declared in af_irda.h.

    The second hinting field, irdaDeviceHints2, specifies a general service category into which the particular device may fall. This can currently be either telephony or fileserver, and these can be determined by ANDing the field with the LM_ HB2_xxx values.

    The final field, irdaCharSet, specifies the type of character set the device uses. This value can be compared against the LmCharSetxxx definitions in the af_irda.h header file. Please note that all these hinting and character set fields are only supported on the Win32® platform. The Windows CE structure definitions do not include these fields, so this functionality is not supported on the handheld devices.

Verifying a Specified Service

    The IAS lets an application query values in the IAS database on remote machines. A good use of this service is to query a remote machine to determine if a particular service is running before attempting to connect to it. This is the process that the connect socket function performs for you under the hood.

    However, it may be advantageous for your application to dynamically determine the capabilities of a device when it is initially identified. For instance, suppose your client supports communication using several different services, and it has just determined that a new device is in range. By using an IAS query the client application can query the remote device to see if it also supports the same services. In a way, this is analogous to using QueryInterface on an unknown COM object to determine what interfaces it supports.

    This functionality is exposed to an application by using the getsockopt function and the IAS_QUERY structure. First, allocate an IAS_QUERY structure and initialize its fields (see Figure 19). This initialization will require setting the values of three fields. The first field, irdaDeviceID, is the device ID of the remote system to query. Just like the process for querying for visible devices, the value for this field is obtained from the current selection in the Devices listbox. Next, copy the name of the service to be verified into the irdaClassName field. The client application copies the contents of the Edit field. This allows the user of the client to query arbitrary service names on remote machines (in case you want to play around while you're testing). Finally, the irdaAttributeName field must be set. If you're performing an IAS query to determine if a service is running on a remote machine, the value for this field must be IrDA:TinyTP:LsapSel. This string tells the IrDA protocol stack to ask the remote machine to return the LSAP-SEL connection identifier for the service specified in the irdaClassName field.

    Now that the structure is initialized, the getsockopt function can be called. Pass the pointer to the IAS_QUERY structure as the fourth parameter of the function, and the value IRLMP_IAS_QUERY as the socket option value. Upon a successful return from the function call, the irdaAttribType field of the query structure will be filled with information that helps further define the success of the query.

    A value of IAS_ATTRIB_NO_CLASS signifies that the remote machine is not running the specified service. A value of IAS_ATTRIB_NO_ATTRIB specifies that the service was running, but the IrDA:TinyTP:LsapSel attribute could not be resolved. (Check to see if you spelled it wrong.) Any other values signify the data type of the returned value, signifying that the LSAP-SEL has been returned and that the service is running.

WinSock Platform Differences

    There is one significant difference in the model of programming WinSock applications on Windows CE versus Win32. WinSock on Windows CE does not support the asynchronous extensions to WinSock. Any attempt to use WSAAsyncSelect within a Windows CE-based application will result in a compile-time error, as the function is not declared in the WinSock headers.

    In effect, this means that in order for a Windows CE-based client to handle multiple simultaneous socket connections, it must be multithreaded. Fortunately, Windows CE does support multithreaded applications—as a matter of fact, the sample client application is multithreaded. To provide smooth (or at least smoother) operation, the client application performs device identification every five seconds on a separate background thread. This is done because the identification process takes a nontrivial amount of time, and to perform this task on the application's main thread would block the user from using the UI for an inordinate period of time.

IrDA Issues and Workarounds

    I would be lying if I said that writing these applications is easy. It's not that the programming is very hard—it's not. The IrDA application programming model is nearly identical to that of programming a generic TCP/IP server and client using WinSock. The difficulty in writing these applications relates to several issues, each of which I would like to explain a little to save others the trouble that I have experienced.

    The first issue is logistical. Support for IrDA from a platform and SDK level varies greatly across Windows platforms. As a result, I must have had to stop working on each application two or three times for about three months at a time over the last year.

    The second problem is that although there are some good (albeit hard to find) explanations of IrDA as a networking protocol, there were not too many robust examples of how to program sockets (in particular WinSock) to communicate using IrDA.

    Probably the most difficult issue to deal with was the availability of IrDA on Windows desktop systems. I initially developed a Windows CE-based application that used WinSock and IrDA without any difficulty. However, I naively assumed that I would just be able to develop an application for the desktop that would be able to communicate with it. But as I mentioned earlier, I had to wait for Windows 2000 beta2 to get full support for IrDA under WinSock.

    But that was just a minor annoyance compared to the fact that there was basically no SDK support for programming WinSock using IrDA on the Windows 2000 beta 2 Platform SDK, nor in Visual C++ 6.0. To be able to program WinSock to use IrDA you need to add several things to your development environment; I've included them all with the sample apps, available from the download at the top of this page.

    The first thing you need is a definition for a family class, which you need to know before you open a socket with the socket function. There is support for this in the Windows 2000 beta 2 WinSock2.h header file, since AF_IRDA is now defined as 26. This same constant is defined as 22 on the Windows CE Platform SDK. This inconsistency is more than just a pain—it makes code nonportable across the platforms. When I was developing the server program, I decided not to use this constant, instead choosing to determine the family value by enumerating WinSock transport protocols.

    Next, to pass to the bind function you'll need a redefined SOCKADDR structure that supports IrDA bind parameters. The Windows CE SDK has a definition of this structure, SOCKADDR_IRDA. Unfortunately, there was no mention of this in any of the Windows 2000 beta 2 Platform SDK materials. (In fact, none of the additional IrDA structures defined in the Windows CE SDK were present anywhere in the Windows 2000 beta 2 SDK.)

    This left me with the task of modifying the existing definitions on the Windows CE SDK in an attempt to get them to work under Windows 2000. These modifications came down to two tasks. First, I commented out the AF_IRDA definition, since the desktop defines it as 26, not 22. Next, I modified the IRDA_DEVICE_INFO structure to support hinting.

    For both applications I have included in the source code the af_irda.h header file that contains what I have determined to be the correct definitions for the desktop platform. Remember that my modifications aren't officially supported, and definitions may change before the release of Windows 2000. If you encounter any problems, let me know via email or on the microsoft.public.magazines.mind newsgroup.

There is no STL on Windows CE!

    I happen to be a fan of the standard template library (STL). Much to my surprise, this library (actually, its header files) is not included with the Windows CE 2.0 SDK. If you're used to using this library, be aware that it does not currently exist for building your Windows CE-based applications. When I tried to include them from the regular Visual C++ 6.0 header files, they caused compilation errors.

Conclusion

    The journey to IrDA-based WinSock connectivity between my PPC and desktop has been long and arduous. This entire project essentially took eleven months to complete! Windows CE programming is still bleeding edge, but that's what makes it exciting. I now have at my disposal a new type of network connectivity to add to my applications: wireless and mobile. This will open whole new worlds of possibility for new application architectures. I don't know about you, but I'm looking forward to these new possibilities.

MSDN
http://msdn.microsoft.com/library/wcedoc/wceppc/ppc_prog.htm

    


From the May 1999 issue of Microsoft Internet Developer.