The real document is here. This is a textual version only to allow Google (etc?) to index the whole document.



((text))
Back to my Homepage
An example IrDA (TinyTP) client (irdaWinsockCli.cpp)
An example (IrDA) IrLPT (IrLMP) client (irdaWinsockCliIrLpt.c)

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.

Copyright (c) 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 .
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:
*	Dynamic set of peers.
*	Dynamic identifier (addresses).
*	Device Name is generally fixed and should be used for device selection.
*	Services listen on dynamically assigned LSAP selector.
*	Services register Name to LSAP-selector mapping in IAS database.
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  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".
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 "wsock23.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
1
PnP compatible
2
PDA/Palmtop
3
Computer
4
Printer
5
Modem
6
Fax
7
LAN Access
8
extension
Table 4-Hint Byte1 bits
bit
Function
1
Telephony
2
File Server
3
IrCOMM
4
Resv
5
Resv
6
OBEX
7
Resv
8
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.
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.  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.
References:
	AF_IrDA.h
	http://msdn.microsoft.com/library/en-us/wcesdkr/htm/_wcesdk_setsockopt.asp (CE 3.0)
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 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:
*	The only socket type is SOCK_STREAM.
*	IrLMP mode can be set, that is disabling TinyTP, by socket option.  [In Linux, this is available 
with a datagram socket.  Later: apparently, a datagram socket in Linux actually creates a 
socket for the Ultra protocol (connectionless and used by IrWW-Wrist watch) and not one 
for IrLMP.  There is apparently no way to use IrLMP with the sockets API there].
*	IrLMP Exclusive mode is alleged to exist, but in reality, it doesn't seem to.
*	No filtering of devices by Hint bit in Discovery.
*	Lazy Discovery is available.
*	No delete equivalent to the create IAS entry mechanism exists.
*	Hint bits can only be set with a Registry configuration change and not through an API call.
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.
*	The value of AF_IRDA / PF_IRDA is 22, and not 26 as it is on the desktop platforms.
*	The IRDA_DEVICE_INFO struct does not contain the 'Char Set' and 'Hint Bit' fields.  This 
may make discovery more difficult in the case where it is able to select from between more 
than one peer; for instance using the irdaDeviceName value may be tricky if the peer is using 
a different 'Char Set'.
*	Different sizing and type of fields in the IAS_QUERY and IAS_SET structs:
o	The Class and Attrib name fields are smaller than on the desktop, both being 61 long.  
The IrLMP specification defines the maximum size of both fields as "60 octets" so 
they are precisely large enough.
o	As noted in the body of the document, there is no space allocated in the structs for the 
OctetSeq and UsrStr type values.  Be sure to allocate space if you are using these 
types or you will overflow and corrupt the following memory.
o	Some of the (meta) fields are different primitive types.  For instance, in both of the 
IAS structures the irdaAttribType field is u_long on the desktop but u_short on CE, 
similarly the various Len fields are one of u_char, u_short or u_long on the desktop 
but int on CE.

Copyright (c) 2001-2005 Alan J. McFarlane
  
  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."
  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>."
 
 
 
 
		Page 1 of 17