((text))

Back to my Homepage

An example IrDA (TinyTP) client (irdaWinsockCli.cpp)

An example (IrDA) IrLPT (IrLMP) client (irdaWinsockCliIrLpt.c)

 

Last update 20th November 2005, change log at bottom.

 

 

Copyright © 2001-2005 Alan J. McFarlane

 

1         Microsoft Windows Winsock IrDA programming (IrSock?)

Table of Contents

1     Microsoft Windows Winsock IrDA programming (IrSock?) 1

1.1      Scope. 2

1.2      References. 2

1.3      Keywords. 3

2     Introduction. 3

2.1      IrCOMM API and no Virtual COM Ports. 3

2.2      OBEX.. 3

3     Programming Concepts. 4

3.1      A summary. 4

3.2      IrCOMM programming. 5

3.3      Character set issues. 6

4     Reference. 7

4.1      Header and Library requirements. 7

4.2      List of Socket Options. 7

4.3      Device Discovery. 8

4.3.1       Lazy Discovery. 9

4.4      Socket type. 10

4.5      Connections to a Service name. 10

4.6      Connections to a specific LSAP selector 11

4.7      Data transfer 11

4.8      Server operation (bind) 11

4.9      Advanced socket options. 12

4.9.1       IAS Local access (set) 12

4.9.2       IAS Remote access (query) 13

4.9.3       IrCOMM Cooked mode. 13

4.9.4       IrLMP (Non-TinyTP) mode. 14

4.9.5       IrLMP mode maximum send segment size. 14

4.9.6       IrLMP Exclusive mode. 14

4.10    Other features. 15

4.10.1     getpeername, getsockname. 15

4.10.2     getXbyY.. 15

4.10.3     Setting Hint bits. 15

5     Other information. 15

5.1      Table of AF_Irda.h Socket Options. 15

5.2      Comparison with Linux’s IrSock API. 16

5.3      Behaviour on Windows CE.. 16

5.3.1       Structure and Constants Differences. 17

 

1.1        Scope

Only covers Windows 2000 family.

Winsock

Not TDI

1.2        References

An example IrDA client program (TinyTP)

http://www.alanjmcf.me.uk/comms/infrared/irdaWinsockCli.cpp.html

An example IrLPT client program (IrLMP)

http://www.alanjmcf.me.uk/comms/infrared/irdaWinsockCliIrLpt.c.html

IrDA SDK documentation

http://msdn.microsoft.com/library/en-us/irda/irda/irda_start_page.asp

Window Sockets 2 SDK documentation

http://msdn.microsoft.com/library/en-us/winsock/winsock/windows_sockets_start_page_2.asp

My “IrDA FAQ”

http://www.alanjmcf.me.uk/comms/infrared/IrDA faq.html

My Homepage

http://www.alanjmcf.me.uk/

IrDA website; with specifications

http://www.irda.org/

 

1.3        Keywords

Microsoft Windows Winsock IrDA programming SDK API Infrared Winsock IrSock AF_IRDA

2         Introduction

Microsoft provides an API for IrDA communication through Winsock (IrSock?).  This document describes the API as found in Windows 2000, it is thought to be the same in Windows XP.  A similar API exists in Windows 98, Windows ME and Windows CE (Pocket PC) but there are differences in some of the features.  This document does not attempt to describe the API on those platforms; it seems thought that the support on ME and CE is very similar, with 98 being more different.  No support for IrDA exists in Windows NT though a third-party solution from Extended Systems does exist; see my FAQ.  It is not believe to have any support for this API.

This document is provided as information on the IrDA Winsock API elsewhere is incomplete and often contains errors.  The Microsoft documentation at MSDN fits this description.  A typical error within the Microsoft documentation is that the socket option to control non-TinyTP is in places referred to as IRLMP_RAW_MODE, IRLMP_EXCLUSIVE_MODE or (correctly) IRLMP_IRLPT_MODE.  There are a number of other sources on the Internet but these seem to be based on the Microsoft document and propagate the same mistakes and even add some of their own.  The information in this document has all been verified manually.

An example client program in C is provided to show the basic of the interface in use.  See the References section, 1.2, for its location.  It shows the process involved in connecting to a peer IrDA service such as OBEX or IrLAN etc, that is opening the socket, running a discovery and connecting.

2.1        IrCOMM API and no Virtual COM Ports

In Windows 95 and 98, the main method of using IrDA was through IrCOMM Virtual COM Ports.  A Virtual COM Port was provided by the system; it could be used by any application that previously used ‘real’ serial ports to communicate with peer devices and now would communicate with them over IrCOMM.  This is of course required that the peer device has IrCOMM support added and treated communications over it like those over the ‘real’ serial port.  This was popular for use with PalmOS HotSync, Psion synchronisation etc and use with Mobile Phones for network dialling, address book, logo and ring-tone updating etc.

The Virtual COM Port was no longer present in Windows 2000 to much consternation.  Access to IrCOMM communications was only available through the Winsock API.  For information on the IrCOMM API see sections 3.2, 4.9.3 etc below.  Manufacturers could thus update their software to use the Winsock IrCOMM API support.

Palm for one updated their software—HotSync Manager—with this Winsock IrCOMM support.  Also in Windows XP, and available as a patch to Windows 2000, was IrCOMM Modem support, this allowed for dial-out communications and also other outgoing IrCOMM usage.  A third-party IrCOMM Virtual COM Port solution also became available, see IrComm2k in the FAQ.

Note a really enlightened manufacturer would update their device and PC software to communication over a non-IrCOMM channel thus avoiding the multiple application conflicts over IrCOMM that exist and thus making setup and operation much easier.

2.2        OBEX

There is no API for OBEX usage in Windows 2000.  All OBEX functionality is contained within the “Wireless Link”/irftp.exe application, the only way to send objects it to execute the irftp program with a filename supplied on the command line (i.e. in the format described by “irftp [/h] [[drive:][path]filename [morefiles]]”.  The only way to handle received items is to operate on them once they have been written to the “location for received files” directory on disk.

MSDN contains information on an OBEX API in Windows CE .NET.  There is thought to be no support for this API in any desktop platform (as yet?).

The software produced by the OpenObex project (http://openobex.sourceforge.net) is believed to be usable on Windows 2000.  I have no experience of its use.

3         Programming Concepts

Due to the mobile, ad-hoc nature of the environment and to support the often low-power and embedded or hardware implementation of the devices that can be in use, the behaviour of the IrDA protocol suite is rather different in many aspects than those one normally programs through WinSock.  Firstly in the device addressing scheme: where unlike TCP/IP, IPX etc the device addressing is highly dynamic, addresses are not in any way pre-assigned and are often not long lived either.  In addition, the set of devices that can be connected to at a moment, unlike with TCP/IP or IPX networks, is highly dynamic and will normally be a small number, often one.  Devices agree on their address (Device Address, a 32-bit identifier) when they discover each other.  Devices normally attempt to keep the same address over time but address conflicts or lack of local persistent storage can prevent this from occurring[1].

There is also obviously no centralised nor shared device registration and lookup service available like TCP/IP’s DNS, Windows 2000’s ActiveDirectory, IPX’s SAP etc as these are provided by shared server machines or routers.  An application thus has to ask the stack what devices it has discovered to be in range and what names (Device Name) they are using.  It can then chose one of them, by asking the user to select one by name, and store the address that the device selected is using.

The scheme used for service multiplexing on a device also differs from that used in TCP/IP, IPX etc.  Due to the small number of ‘port’ addresses (~127) available, it is not possible to assign port numbers to applications statically.  Thus a central static registration database c.f. IANA’s TCP Port registry or the similar pre-agreed socket numbers used in IPX is not possible.  In other words it is not possible to do the equivalent of the “connect to TCP port 80” for HTTP in the TCP/IP suite.  Services need to find a free port at startup and then allow the clients to discover this port number at connection time.  A database of “Service Name” to port number is kept on the device and the client device queries this remote database by Service Name to find the port number to use.  This database service is called the Information Access Service i.e. IAS.  A port is known as a Link Service Access Point i.e. LSAP and a port number is known as a “LSAP selector” i.e. LSAP-SEL.

To summarise:

3.1        A summary

The process for a client to connect to a service is thus:

  1. Get a list of discovered peer devices.
  2. Select one and get its address.
  3. Get LSAP selector[2] value from the peer’s IAS database for the Service name.
  4. Connect to the device address and LSAP selector.
  5. Transfer data.
  6. Disconnect.

Note that Windows will automatically carry-out steps 3 and 4 as one; if given a Service name in a ‘connect’ operation it will find the LSAP identifier automatically.

 

Compare this to the process for a client using TCP/IP:

  1. Get the name (or address) of the server from the user or configuration settings.
  2. If given a hostname resolve it to an address using DNS etc.
  3. Connect to the address and a pre-agreed Port number e.g. 80 for HTTP.
  4. Transfer data.
  5. Disconnect.

 

The process for a server is:

  1. Ask the system for a free LSAP selector.
  2. Create a mapping in the IAS database connecting the LSAP selector against the Service name.
  3. Listen on the given LSAP selector.
  4. Wait for incoming connections.
  5. Transfer data
  6. Disconnect

Again Windows will automatically carry out steps 1 and 2 together; on a ‘bind’ operation given a Service name, it will automatically create the IAS database entry.

3.2        IrCOMM programming

As noted above there is no Virtual COM Port for IrCOMM communication provided in Windows 2000 but programmatic access remains available.  I won’t cover the IrCOMM specification in detail here but a quick summary is useful, see the specification itself for more information.

IrCOMM is intended for use as a “cable replacement” for use where a serial or parallel cable was originally used and is now replaced by an IrDA link.  It operates in one of two major types (or “camps” as they are called by the specification), divided on whether data only is transferred or whether non-data signals are also transferred, see Table 1.

Feature  /  Camp

Raw

Cooked

Carries non-data signals

No

Yes

Over IrDA protocol

IrLMP, thus requires exclusive use of the link

TinyTP

Modes

3-Wire-Raw and IrLPT

3-Wire, 9-Wire and Centronics

Table 1—The two IrCOMM camps

Non-data signals include signal lines that exist in the replaced cable e.g. RTS, DCE etc from serial cables and also information about the line’s format e.g. data rate, data format including number of bits, number of stop bits and (parallel cable) IEEE 1284 mode etc.  The difference between 3-Wire and 9-Wire is that 9-Wire carries both types of control information whereas 3-Wire only carries the format information.  Note in the Winsock interface to IrCOMM no access to the control information is available, null control information is sent and received control information is discarded.

The Service Name used is generally “IrDA:IrCOMM” except for IrLPT, which uses “IrLPT”.  To provide information about which modes are supported a “Parameters” entry is published in IAS.  See the IrCOMM specification for the format of this entry.

The various IrCOMM features may need to be configured; these include the configuration of Cooked Mode, the disabling of TinyTP mode and the setting or reading of the Parameters IAS entry for server and client respectively.  Socket Options exist that allow these features to be controlled, see sections 4.9.3, 4.9.4 and 4.9.1 or 4.9.2 respectively.

For example programs see the following references.

References:

                http://msdn.microsoft.com/library/en-us/irda/irda/ircomm.asp

                http://msdn.microsoft.com/library/en-us/dnirda/html/irdawp.asp

                http://www.calsoft.co.in/techcenter/network/Infrared.html

3.3        Character set issues

IrLMP, the IrDA protocol exposed by the API, has international character support for its character string values that can be displayed to the user.  The protocol accomplishes this by carrying a value identifying the respective character set along with each string value.  The IAS User String (UsrStr) type is carried by the protocol in the following format (note also that it is length and not null terminated):

Type = 3

Char. Set

Length

Characters

1 octet

1 octet

1 octet

“Length” octets

The Device Name (i.e. irdaDeviceName) also carries the character set value (both in its IAS entry version and in its Device Nickname format used in discovery).

There are eleven character set values defined in the IrLMP specification, they are “ASCII” which I presume is 7-bit US-ASCII, nine character sets from ISO 8859 and lastly Unicode (“16 bit characters”).  The header file AF_Irda.h (see more below) provides a definition for each of these eleven values in the form “LmCharSet*”, the table below shows the character set values.

Character set name

Code

AF_IrDA.h definition

ASCII (i.e. US-ASCII)

0

LmCharSetASCII

ISO-8859-1

1

LmCharSetISO_8859_1

ISO-8859-X

X

LmCharSetISO_8859_X

ISO-8859-9

9

LmCharSetISO_8859_9

Unicode

0xFF

LmCharSetUNICODE

Table 2--Character Sets

The other string types used in the protocol do not come with a character set value: they are the IAS ClassName and AttribName types and Service Name (which is of course actually an IAS ClassName).  They appear to always be in single byte character formats and restricted to the US-ASCII character set.  In fact, the values are probably best seen as octet strings and not as character strings at all, in the base IrLMP spec the attribute names are actually defined in their hexadecimal format as well as text strings.

The API exposes this use of characters set pretty faithfully.  In the structures that carry a User String or a Device Name there is also the corresponding character set value, this pair is the pair of values are carried in the IrLMP packets.  However, the IRDA_DEVICE_INFO structure, which carries the Device Name field, does not contain a length value, which can make using the value more difficult.

With values received from a peer you have to accept the character set that the peer has used, this will mean converting the received value into your locally usable character set for display, in most Windows 2000 etc programs this will be into the native Unicode (with function MultiByteToWideChar).

When writing a program that sets such values, careful thought should be given to the character set used.  It is not compulsory for an IrDA device to support all character set types, in particular embedded devices, mobile phones etc, will likely have only limited character set support.  On this, all that the specification says is, “It should be noted that a device may not support the specified character set. In this case, it is up to the displaying device to display the string as best it can”.  So it would be sensible to use the simplest character set possible that supports your string value; using ASCII or 8859-1 would be prudent.

References:

                “Infrared Data Association, Link Management Protocol”, IrLMP11.pdf.  Section 4.3.3.2.4, 3.4.1.2

                AF_IrDA.h

4         Reference

4.1        Header and Library requirements

The IrDA specific definitions are contained in header file “Af_Irda.h” and thus it needs to be included.  In addition, as it itself says:

“One of _WIN32_WINNT | _WIN32_WINDOWS | _WIN32_WCE must be defined.”.

 

This is due to different support for, and different definitions for IrDA on the different platforms, the respective definition must thus exist in your program prior to the includes.  Unless your program is very simple, it will anyway require these definitions to use other Windows functionality.

As with all Windows header files, “Af_Irda.h” is supplied in the Platform SDK, get it at http://www.microsoft.com/msdownload/platformsdk/sdkupdate/

Unlike most of the NT API there is no difference in the API when using Unicode (#define UNICODE/_UNICODE) and not.  As described above in Section 3.3 the API uses character sets and types in the same way that the corresponding IrDA protocol (IrLMP specifically) does.

The functionality is of course accessed through the Winsock interface and thus the respective Winsock header file also needs to be included (first) and its library linked to.  Normally this will be the inclusion of “WinSock2.h” and linking to “WS2_32.Lib”.  Also of course, the program needs to call WSAStartup before calling any other Winsock functions.

Be aware that the value of AF_IRDA is different on Window CE from the desktop platforms and that the Windows 98 support seems to only work when linked to “wsock32.lib”.  Some have suggested using WSASocket with protocol enumeration (with PROTOCOL_INFO etc) to avoid some of the problems.

4.2        List of Socket Options

All at socket level SOL_IRLMP.

Name

 

Section

Type

Notes

IRLMP_ENUMDEVICES

GET

4.3

DEVICELIST

Gets the list of devices in range.

IRLMP_IAS_SET

SET

4.9.1

IAS_SET

Sets an entry in the local IAS database.

IRLMP_IAS_QUERY

GET

4.9.2

IAS_QUERY

Gets an entry from a remote peer’s IAS database.

IRLMP_SEND_PDU_LEN

GET

4.9.5

int

In IrLMP mode, gets the maximum send segment size.

IRLMP_EXCLUSIVE_MODE

SET

4.9.6

int (Boolean)

Fails with error.  Assumed it is intended to control IrLMP Exclusive mode.

IRLMP_IRLPT_MODE

SET

4.9.4

int (Boolean)

Disables TinyTP mode, data is thus sent directly over IrLMP frames (as used by the IrLPT protocol).

IRLMP_9WIRE_MODE

SET

4.9.3

int (Boolean)

Enables IrCOMM Cooked mode.

Table 3—List of Socket Options

Four other options are defined in AF_IrDA.h (IRLMP_TINYTP_MODE, IRLMP_PARAMETERS, IRLMP_DISCOVERY_MODE and IRLMP_SHARP_MODE) these are marked there as being for Windows 98 and/or Windows CE only and are not supported on Windows 2000.  See Section 5.1 for more information.

There is one WSAIoctl constant, SIO_LAZY_DISCOVERY, defined, for its usage see below (Section 4.3.1).

The Microsoft MSDN documentation is very unclear as to the purpose of the IRLMP_EXCLUSIVE_MODE and IRLMP_IRLPT_MODE options; it mixes up and confuses the purpose of the two options.  Testing has shown that IRLMP_IRLPT_MODE enables the transfer of data over IrLMP directly (without the normal TinyTP encapsulation).  IRLMP_EXCLUSIVE_MODE would seem them to be left to allow the enabling of IrLMP’s Exclusive Mode; a setsockopt call using it fails however.  See the specific sections below for more detail.

4.3        Device Discovery

Unlike with TCP/IP the set of devices available to an IrDA peer and their addresses is highly dynamic.  A discovery process must be run, it finds the set of devices in range and what addresses they have auto-configured.  Each device also has a name, as noted above it can be provided in a number of different character sets.

To help in selecting a device from a number of available devices Hint bits are available, each device publishes these to peers at discovery.  The defined Hint bits are as follows.

 

bit

Function

0

PnP compatible

1

PDA/Palmtop

2

Computer

3

Printer

4

Modem

5

Fax

6

LAN Access

7

extension

Table 4—Hint Byte1 bits

bit

Function

8

Telephony

9

File Server

10

IrCOMM

11

Resv

12

Resv

13

OBEX

14

Resv

15

extension

Table 5—Hint Byte2 bits

Definitions of these constants are provided in AF_IrDA.h as “LM_HB*” respectively e.g. LM_HB1_PDA_Palmtop.

The socket option IRLMP_ENUMDEVICES gets the list of discovered devices.  It returns a DEVICELIST structure, which is defined as:

struct

{

   ULONG               numDevice;

   IRDA_DEVICE_INFO    Device[1];

}

 

and the IRDA_DEVICE_INFO structure is defined as:

struct

{

   u_char  irdaDeviceID[4];

   char    irdaDeviceName[22];

   u_char  irdaDeviceHints1;

   u_char  irdaDeviceHints2;

   u_char  irdaCharSet;

}

 

The buffer provided to the function should be sized to hold a DEVICELIST structure and a number of IRDA_DEVICE_INFO structures to extend the device array (note that the DEVICELIST structure itself contains one IRDA_DEVICE_INFO structure).  The resultant buffer’s size, as always for getsockopt, should be passed into the function.

An example is:

#define DEVICE_LIST_LEN   4

BYTE                    xBuff[ sizeof(DEVICELIST) +
                      sizeof(IRDA_DEVICE_INFO) * DEVICE_LIST_LEN ]

int                      xDevLen       = sizeof(xBuff);

PDEVICELIST       xpDevList     = (PDEVICELIST) &xBuff;

 

pDevList->numDevice      = 0;

 

// xSock is not in connected state

getsockopt ( xSock, SOL_IRLMP, IRLMP_ENUMDEVICES,

   (char *) xpDevList, & xDevLen );

 

//ERROR handling

 

// Use the result

xNumDiscovered    = pDevList->numDevice;

if ( xNumDiscovered > 0 )

{

xFirstDeviceCharset      = pDevList->Device[0].irdaCharSet;

xFirstDeviceName = pDevList->Device[0].irdaDeviceName;

}

 

References:

                http://msdn.microsoft.com/library/en-us/winsock/winsock/getsockopt_2.asp

                http://msdn.microsoft.com/library/en-us/irda/irda/irda_and_getsockopt_using_irlmp_enumdevices.asp

4.3.1       Lazy Discovery

To know immediately when a new device comes into range during a program’s life one would have to run discovery queries continually, this is not the best use of resources particularly on low-power devices.  The Microsoft documentation refers to a mode known as “Lazy Discovery”, this mode causes a discovery operation to block until a new device comes into range.  It is likely that the “Wireless Link” application uses this mode.  However there is no explanation of how to use this mode in the documentation.  There is an IOCTL value (SIO_LAZY_DISCOVERY) defined in AF_IrDA.h but again no information on its use is provided.

I have finally discovered how to use this feature.  In usage, it is very similar to the non-lazy-discovery method, in that it is supplied a buffer to fill with a DEVICELIST structure.  Of course, with WSAIoctl comes the ability to use the various Winsock I/O Models; suitable values for the final two parameters should thus be supplied.  Finally null parameters should be supplied for the input buffer.  Note, if the parameters passed are not suitable, a WSAEINVAL (10022) error occurs.

When the list of devices in range of the system changes, the buffer is updated and this is signalled as appropriate (by returning, by signalling the supplied event etc).  Note that both device arrival and departure cause a change in the device list.

Finally, however it appears that Administrator rights are to be necessary to use this feature.  If not being run as an Administrator, the call again fails with a WSAEINVAL (10022) error.  I can see no reason why such high privileges would be required for this feature and can only assume that this aspect of its usage is a bug.

The call to getsockopt in the example above can thus be replaced by the following lazy blocking call to WSAIoctl.

WSAIoctl ( xSock, SIO_LAZY_DISCOVERY, NULL, 0,

   xpDevList, xDevLen, & xDevLenOut,

   NULL, NULL );

 

References:

                AF_IrDA.h

                http://msdn.microsoft.com/library/en-us/winsock/winsock/getsockopt_2.asp

                http://msdn.microsoft.com/library/en-us/irda/irda/irda_and_getsockopt_using_irlmp_enumdevices.asp

4.4        Socket type

IrDA programming on Windows is done through WinSock a socket of type AF_IRDA, SOCK_STREAM is used, e.g.

xSock      = socket ( AF_IRDA, SOCK_STREAM, 0 );

 

Note a SOCK_STREAM socket is as its name suggests, a byte stream, no boundaries in the data are respected.  This is how TCP/IP’s TCP protocol behaves.  This socket type is used for all IrDA connections, which by default use TinyTP.  Non-TinyTP mode i.e. direct over IrLMP can be selected by socket option IRLMP_IRLPT_MODE, see Section 4.9.4

Note, from the TinyTP specification, “…TTP may be used to implement either: a sequenced packet service, … or a byte-stream service …”.  As noted above Windows uses a byte stream socket through Winsock.  Whether it behaves truly as an octet stream, or as a sequenced packet socket, is not clear.

The IrLMP protocol does not do any segmentation or re-assembly.  It is presumed that when the socket is in IrLMP mode the socket does not present stream semantics.

References:

                http://msdn.microsoft.com/library/en-us/irda/irda/irda_and_socket.asp

                http://msdn.microsoft.com/library/en-us/winsock/winsock/socket_2.asp

                http://msdn.microsoft.com/library/en-us/irda/irda/data_transfer_and_connection_close.asp

4.5        Connections to a Service name

By default connections are made with TinyTP and take a Service name, Windows automatically does an IAS database lookup to find the LSAP identifier.  The SOCKADDR_IRDA structure, along with the Address Family and the Service name being set, needs to have the Device identifier copied from the discovery process when supplied to the connect call.

The SOCKADDR_IRDA structure is defined as:

struct

{

   u_short irdaAddressFamily;

   u_char  irdaDeviceID[4];

   char    irdaServiceName[25];

}

 

An example of a connect call is:

SOCKADDR_IRDA xPeerSockAddr = { AF_IRDA, 0, 0, 0, 0, "OBEX" };

 

memcpy ( xPeerSockAddr.irdaDeviceID, pDevList‑>Device[xSelectedDevice].irdaDeviceID, 4 );

 

connect ( xSock, (const struct sockaddr *) &xPeerSockAddr, sizeof(SOCKADDR_IRDA) );

 

//ERROR handling

 

The automatic lookup works correctly in both TinyTP and IrLMP modes.  That is it looks up respectively the attribute “IrDA:TinyTP:LsapSel” and “IrDA:IrLMP:LsapSel”.

References:

                http://msdn.microsoft.com/library/en-us/winsock/winsock/connect_2.asp

4.6        Connections to a specific LSAP selector

If the LSAP selector (numerical) of a service is known it can be used in the sockaddr structure, it needs to be supplied in the form “LSAP-SELx”, where x is a number from 1 to 127.  e.g.

sprintf ( xPeerSockAddr.irdaServiceName, "LSAP-SEL%d", xSelId );

 

Note that the documentation defines the string as “LSAP-SELxxx” but leading zeros do not seem to be required.

4.7        Data transfer

Data transfer is carried out by using the normal recv and send functions.

References:

                http://msdn.microsoft.com/library/en-us/irda/irda/irda_and_send_and_recv.asp

                http://msdn.microsoft.com/library/en-us/irda/irda/data_transfer_and_connection_close.asp

4.8        Server operation (bind)

Creating an IrDA server is much the same as creating a server under other Winsock protocols, a ‘binding’ to a local port is created, which is ‘listened’ to then incoming connections are ‘accepted’ as new sockets.  In the IrDA case, the ‘port’ is an LSAP-SEL.  Similar to connect, either a numerical LSAP selector (“LSAP-SELx”) or a textual “Service Name” can be supplied—in the latter, Windows handles the selection of a free LSAP-SEL and respective IAS entry creation.

If a server is already listening on a given Service Name, as always with a bind call, an error of type WSAEADDRINUSE (10048) will occur.  See my general IrDA FAQ for information on which services Windows listens on (e.g. OBEX), and how to disable them.

SOCKADDR_IRDA xServSockAddr = { AF_IRDA, 0, 0, 0, 0, "IrDA:IrCOMM" };

 

bind ( xServSock, (const struct sockaddr *)&xServSockAddr, sizeof(SOCKADDR_IRDA) );

 

//ERROR handling

 

// listen, accept, etc…

References:

                http://msdn.microsoft.com/library/en-us/irda/irda/irda_and_bind.asp

4.9        Advanced socket options

4.9.1       IAS Local access (set)

If it is necessary to set information into the local IAS database then the socket option IRLMP_IAS_SET can be used.  This can be useful if information other than the Service name to LSAP selector mapping needs to be provided, an example is that an IrCOMM server can provide information about which modes it supports using a “Parameter” IAS entry.  If an IAS entry of the same class and attribute name already exist then an error of type WSAENOBUFS (10055) will occur.

It is believed that there is no equivalent mechanism (? IAS_DELETE) to remove IAS entries thus created.

To create an IAS entry an IAS_SET structure needs to be filled and passed to the setsockopt function, the structure contains a union with name “irdaAttribute” to allow it to hold the various data types that IAS can hold.  The type being used should be set in the irdaAttribType field using one of the “IAS_ATTRIB_*” constants e.g. IAS_ATTRIB_STR. The maximum lengths of values allowed in the various fields are provided in the constants “IAS_MAX_*” e.g. IAS_MAX_ATTRIBNAME.

An example is:

IAS_SET    xSet;

 

strcpy ( xSet.irdaClassName,    "MyProt" );

strcpy ( xSet.irdaAttribName,   "MyIntegerParam" );

 

xSet.irdaAttribType                   = IAS_ATTRIB_INT;

xSet.irdaAttribute.irdaAttribInt      = 99;

 

setsockopt ( xSock, SOL_IRLMP, IRLMP_IAS_SET, (const char *) &xSet, sizeof (xSet) );

 

//ERROR handling

 

Note that the above usage of IAS_SET is not valid on Windows CE.  On that platform, the definitions of IAS_SET and IAS_QUERY do not allocate space for the attribute value of OctetSeq or UsrStr types (on desktop Windows they are sized to 1024 and 256 bytes respectively).  When using IAS_SET or IAS_QUERY on Windows CE a form of code similar to the following should be used:

#define MAX_USRSTR_LEN 256

 

u_char     xSetBuf [ sizeof IAS_SET + MAX_USRSTR_LEN ];

int               xSetLen       = sizeof xSetBuf;

 

PIAS_SET   xpSet         = &xSetBuf;

 

References:

                http://msdn.microsoft.com/library/en-us/irda/irda/irda_and_ias.asp

                http://msdn.microsoft.com/library/en-us/winsock/winsock/setsockopt_2.asp

4.9.2       IAS Remote access (query)

Information can be read from a peer’s IAS database using the socket option IRLMP_IAS_QUERY.  An IAS_QUERY structure needs to be filled with the query and passed to the getsockopt function, it returns the structure filled with the IAS entry found or an error.  The structure is similar to the IAS_SET structure.  If no entry of the given class and attribute name tuple exists an error of WSAECONNREFUSED (10061) will occur.

Note, the IAS protocol (IAP) carries “User Strings” with length delimiting, and not with null-termination.  The IAS_QUERY structure uses the same format and thus the UsrStr strings fields will not be null-terminated; the Len field must be used.  A few types of devices, apparently Windows and PalmOS, send their “User Strings” including a null-terminator, this must not be relied upon.

An example is:

IAS_QUERY xQuery;

int               xQrySize;

 

xQrySize   = sizeof(xQuery);

 

memcpy ( xQuery.irdaDeviceID, pDevList‑>Device[xSelectedDevice].irdaDeviceID, 4 );

 

strcpy ( xQuery.irdaClassName, "MyProt" );

strcpy ( xQuery.irdaAttribName,       "MyIntegerParam" );

 

getsockopt ( xSock, SOL_IRLMP, IRLMP_IAS_QUERY, (char *) &xQuery, &xQrySize );

 

//ERROR handling

 

if ( xQuery.irdaAttribType == IAS_ATTRIB_INT )

{

xResult    = xQuery.irdaAttribute.irdaAttribInt;

}

 

See the note in the previous section about sizing IAS_SET and IAS_QUERY on Windows CE.

References:

                http://msdn.microsoft.com/library/en-us/irda/irda/irda_and_ias.asp

                http://msdn.microsoft.com/library/en-us/winsock/winsock/getsockopt_2.asp

                http://msdn.microsoft.com/library/en-us/wcewinsk/htm/_wcesdk_getsockopt.asp (CE .NET)

4.9.3       IrCOMM Cooked mode

In the IrCOMM protocol two types of connection exist; one where data alone is communicated and another where both data and control information are communicated.  Control information includes the value of control signals RTS, DCD etc and baud rate information etc.  The former mode is used by 3-Wire Raw and IrLPT, the latter is used by 9-Wire, 3-Wire and Centronics.

The latter type is called “Cooked Mode”, the option IRLMP_9WIRE_MODE causes sockets to use cooked mode on the data transferred.  Note that no access to the received control information is available in Windows and null control information is sent.

Note also that it is not possible to neither manually add control information alongside outgoing data nor intercept incoming control information.  Control information is carried as the first bytes in a TinyTP frame and the stream socket type as used for TinyTP does not guarantee to provide access to the individual frames but only a stream of data.  It is believed that access to the control information is available through the lower level TDI interface but I have no knowledge of this API.

References:

                AF_IrDA.h

                http://msdn.microsoft.com/library/en-us/irda/irda/ircomm.asp

                http://msdn.microsoft.com/library/en-us/dnirda/html/irdawp.asp (Windows 2000, TechNote)

4.9.4       IrLMP (Non-TinyTP) mode

Normal connections run over TinyTP, which is to some extent the IrDA equivalent of TCP in the TCP/IP suite.  It provides for multiple connections to be active with flow control, and optionally with segmentation and reassembly.  For a simple implementation without TinyTP, data can be transferred directly over IrLMP, flow control is provided only at the link level and therefore deadlock can occur if multiple service connections are active.  The mode can be selected with the IRLMP_IRLPT_MODE socket option.

The Microsoft MSDN documentation is very unclear as to the use of the two options IRLMP_IRLPT_MODE and IRLMP_EXCLUSIVE_MODE.  For instance, on the Windows CE 3.0 setsockopt reference page the table listing the options includes only the IRLMP_IRLPT_MODE but the description following lists only the IRLMP_EXCLUSIVE_MODE option and says that it “allows the application to switch between TinyTP mode and unreliable IrLMP mode”.  The option IRLMP_RAW_MODE seems never to have existed except at one time on that page: it does not exist in AF_IrDA.h.

Testing has verified that, on Windows 2000 at least, this option (IRLMP_IRLPT_MODE) does set non-TinyTP mode i.e. IrLMP mode.  Note the option would seem to be called “IrLPT mode” because the IrLPT protocol—as described in the IrCOMM specification—transfers its data over IrLMP.  This leaves the option IRLMP_EXCLUSIVE_MODE, see below, to control IrLMP’s Exclusive mode, which seems eminently sensible.

See Section 4.9.5 for information on the maximum data size possible to send in this mode.

Note however that this mode is not supported on server side sockets.  This was discussed online and confirmed by Mazahir Poonawala of Microsoft, see the link below.

References:

                AF_IrDA.h

                http://msdn.microsoft.com/library/en-us/wcesdkr/htm/_wcesdk_setsockopt.asp (CE 3.0)

                http://groups.google.co.uk/group/microsoft.public.win32.programmer.networks/browse_frm/thread/79c2312aaeaaae69/4d4bd512e8ea1c36 , my debugging on July 6th and Mazahir’s confirmation on the 26th.

4.9.5       IrLMP mode maximum send segment size

In IrLMP mode (IRLMP_IRLPT_MODE) there is a maximum size of data segment that can be sent, the IRLMP_SEND_PDU_LEN option gets that size.  It should be used on a connected but not yet used socket.  If used on a non-connected socket it fails with WSAENOTSOCK (10038)—surely WSAENOTCONN (10057) would have been more suitable…

If you attempt to send a buffer of data longer than this value on an IrLMP mode socket then a WSAECONNABORTED (10053) occurs, no data is sent and the socket is closed by the local host.

References:

                AF_IrDA.h

                http://msdn.microsoft.com/library/en-us/wcesdkr/htm/_wcesdk_getsockopt.asp (CE 3.0)

4.9.6       IrLMP Exclusive mode

Does not work on Windows 2000, WSAEINVAL.

IrLMP can be put into “Exclusive mode” this requires that only one LSAP connection be active.  This can be used in situations where controlled latency is required e.g. for voice over infrared etc.

The mode would see to be meant to be selected with the IRLMP_EXCLUSIVE_MODE socket option, however attempted use on Windows 2000 causes a WSAEINVAL (10022) error to occur.

References:

                AF_IrDA.h

                http://msdn.microsoft.com/library/en-us/wcesdkr/htm/_wcesdk_setsockopt.asp (CE 3.0)

4.10    Other features

4.10.1  getpeername, getsockname

These functions can be used much as normal.  In some situations, they will show which LSAP-SEL is being used.

For the client side of a connection the numerical LSAP-SEL actually being used will be returned, for the server side of a connection the value supplied in the irdaServiceName field will be returned.  That is when the local program makes a client connection then getsockname will return the numerical LSAP-SEL and getpeername will be the supplied value of irdaServiceName, and vice versa for a program that acts as a server, getpeername returns the numerical LSAP-SEL.

Local socket mode

getsockname()—local

getpeername()—remote

Client

Numerical LSAP-SEL

Value of irdaServiceName as supplied to connect()

Server

Value of irdaServiceName as supplied to bind()

Numerical LSAP-SEL

Table 6—Value returned by getXXXXname on an IrDA socket

4.10.2  getXbyY

There is no corresponding set of definitions in the IrDA protocol similar to IP’s “/etc/services”, DNS, “/etc/hosts” etc, these functions are thus not supported.

4.10.3  Setting Hint bits

There is no API to allow setting the local device’s Hint Bits, however there is a Registry value that can be used to override the default (of 8425). It is a three byte value that contains the two Hint Bytes and the Charset byte, and is stored in the Registry at:

Key:        HKLM\System\CurrentControlSet\Services\irda\Parameters

Value Name: HINTCHARSET

Type:       DWORD

 

For instance if the Printer hint bit is to be set, then a hexadecimal value of 84C500 should be used.  For the Hint Bit definitions see Section 4.3.

This was discussed in group microsoft.public.win32.programmer.networks (etc) in June 2005 in thread “IrDa print server - howto?”, see http://groups.google.co.uk/group/microsoft.public.platformsdk.networking/msg/9c3fc85f716e3081?hl=en.

5         Other information

5.1        Table of AF_Irda.h Socket Options

AF_Irda.h contains the definitions of the IrDA Socket Options, they are divided into sections for combinations of “WinNT”, “Win98” and “WinCE” support, this is shown in the table below. Of course, “WinNT” actually represents Windows 2000 etc support, as there is, of course, no support on NT 4/3/etc.

There is also a (new) table of Socket Options in MSDN, at http://msdn.microsoft.com/library/en-us/winsock/winsock/socket_options.asp?FRAME=true#SOL_IRLMP.  It is a table of which options are available on which platforms.  However it does not agree with AF_Irda.h, I feel that it is more likely that the information in the header file is correct.  I have emailed MSDN on this issue.

 

Option Name

value

WinNT

Win98

WinCE

// WINNT, WIN98, WINCE

 

 

 

 

(option level) SOL_IRLMP

0x00FF

ü

ü

ü

 

 

 

 

 

IRLMP_ENUMDEVICES

0x00000010

ü

ü

ü

IRLMP_IAS_SET

0x00000011

ü

ü

ü

IRLMP_IAS_QUERY

0x00000012

ü

ü

ü

 

 

 

 

 

// WINNT, WINCE

 

 

 

 

IRLMP_SEND_PDU_LEN

0x00000013

ü

 

ü

IRLMP_EXCLUSIVE_MODE

0x00000014

ü

 

ü

IRLMP_IRLPT_MODE

0x00000015

ü

 

ü

IRLMP_9WIRE_MODE

0x00000016

ü

 

ü

 

 

 

 

 

// WIN98

 

 

 

 

IRLMP_TINYTP_MODE

0x00000017

 

ü

 

IRLMP_PARAMETERS

0x00000018

 

ü

 

IRLMP_DISCOVERY_MODE

0x00000019

 

ü

 

 

 

 

 

 

// WINCE

 

 

 

 

IRLMP_SHARP_MODE

0x00000020

 

 

ü

Table 7—Socket Option support on different platforms; from AF_Irda.h

5.2        Comparison with Linux’s IrSock API

I have no experience of programming for IrDA under Linux but on information provided the two APIs are fairly similar.  For Linux programmers the differences in the Windows API include:

5.3        Behaviour on Windows CE

Later: more information on the Windows CE platform shows that the behaviour is largely the same as on Windows 2000. For instance, setting IRLMP_IRLMP_MODE behaves as it does on Windows 2000: it sets non-TinyTP mode and also looks up the correct “IrDA:IrLMP:LsapSel” IAS entry.  See e.g. http://groups.google.co.uk/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&safe=off&selm=%2359WIw0EEHA.1452%40TK2MSFTNGP09.phx.gbl

5.3.1       Structure and Constants Differences

AF_IrDA.h includes the following differences for Windows CE as opposed to Windows 2000 etc.

 

Change log

DRAFT, 25th August 2002

DRAFT, Updated: 2nd September 2002

DRAFT, Updated: 23rd September 2002

 Updated: 28th October 2002

 Updated: 03rd November 2002 — No substantive changes, typos mainly.

 Updated: 05th April 2003 — Minor updates and a more compact HTML conversion!

 Updated: 18th May 2003 — Minor additions.

 Updated: 5th June 2003 — Changed error code instances to remove the “L” (C long constant) suffix.

 Updated: 16th June 2003 — Typos mainly.

 Updated 24th July 2003 — Addition of Header file, character set and Windows CE structure sizing information.

 Updated 8th September 2003 — Minor changes plus link to example client source code.

 Updated 16th April 2004 — Minor changes on Linux and Windows CE (Pocket PC) behaviour.

 Updated 23rd August 2004 — Addition of Lazy Discover information and some minor changes(+),

 Updated 11th January 2005 — Correcting some language usage: LSAP-SEL rather than LSAP-ID and on socket types.

 Updated 20th February 2005 — Links at top of document, note on User String length termination, and on Device Address persistence.

 Updated 30th Jun 2005 — Information on setting a device’s Hint Bits.

Updated 28th September 2005 — Note that IRLMP_IRLPT_MODE mode is not supported on server side sockets.

 Updated 13th November 2005 — Renumbered the Hint Bits (to start from 0), and added more words on the differences in the IRDA_DEVICE_INFO structure on CE.

 Updated 20th November 2005 — Note that Windows CE IRDA_DEVICE_INFO struct may not be as described in AF_IrDA.h, plus two typos.

 

Copyright © 2001-2005 Alan J. McFarlane

 



[1] From the IrLMP spec (IrLMP11.pdf).

“Device Address—The IrLAP device address of a station. This is a 32-bit identifier that is randomly selected by a station. It is expected to be relatively static between successive initializations of the IrLAP communication services. However, it may change between successive initializations when duplicate use of the same device address is detected during the XID discovery process.”

[2] This originally said “LSAP identifier”. It is correctly an LSAP selector.  The following definitions are from the IrLMP spec (IrLMP11.pdf).

LSAP-SEL—“distinguishes between LSAPs within a Station.”

LSAP-ID—“identifies a particular LSAP at a particular station and is represented as the concatenation of <DeviceAddress> and <LSAPSEL>.”