Supported os are windows and linux, macos shouldn't be a big deal either, this is just a little socket-action.
Remark:
It is only one connection at once allowed, but this should be enough anyway.
I was too lazy to add multi connections support.
Code: Select all
;*******************************************
;*
;* Filename: IrDA.pbi
;* Version: V1.0.0
;* Date: 31.07.2015
;* Author: HeX0R
;* http://hex0rs.coderbu.de
;*
;* License: BEER-WARE
;* Thomas 'HeX0R' Milz wrote this file. As long as you retain this notice you
;* can do whatever you want with this stuff. If we meet some day, and you think
;* this stuff is worth it, you can buy me a beer in return.
;* HeX0R@coderbu.de
;*
;* OS: [x] Windows
;* [x] Linux
;* [ ] MacOS (someone needs to add the correct api calls and constants)
;*
;* Description: This is an include to use IrDA adapters
;* I only needed it for serial IrDA adapters, don't know if others will work also
;*
;* useful links: [win] https://msdn.microsoft.com/de-de/library/windows/desktop/ms738544%28v=vs.85%29.aspx
;* [linux] http://lxr.free-electrons.com/source/include/uapi/linux/irda.h#L124
;*
;*
;* Usage
;* Please have a look at the comments and at the example at the bottom of the code.
;*
;*
;*******************************************
DeclareModule IrDA
Declare Init()
Declare ExamineIrdaDevices()
Declare NextIrdaDevice()
Declare.s GetIrdaDeviceName()
Declare GetIrdaDeviceID()
Declare FinishExamineIrda()
Declare Connect(DeviceID)
Declare Disconnect()
Declare SendData(*Buffer, BufferLen)
Declare ReceiveData(*Buffer, BufferLen)
Declare IsDataAvailable()
Declare GetSockID()
Declare GetLastError()
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
;Error Handling
#ERROR_NONE = #ERROR_SUCCESS
#ERROR_NO_INIT_NETWORK = #WSANOTINITIALISED
#ERROR_NETWORK_DOWN = #WSAENETDOWN
#ERROR_NO_IRDA_SUPPORT = #WSAEAFNOSUPPORT
#ERROR_NO_MORE_DEVICES = #WSAEMFILE
#ERROR_ADDRESS_IN_USE = #WSAEADDRINUSE
#ERROR_NO_MEMORY = #WSAENOBUFS
#ERROR_PROTOCOL_NOT_SUPPORTED = #WSAEPROTONOSUPPORT
#ERROR_PROTOCOLTYPE_WRONG = #WSAEPROTOTYPE
#ERROR_NOT_YET_CONNECTED = 1
#ERROR_SOCKET_ALREADY_CONNECTED = #WSAEISCONN
#ERROR_NO_EXAMINE_IRDA_DEVICES = 2
#ERROR_TIMED_OUT = #WSAETIMEDOUT
#ERROR_INVALID_SOCKET = #INVALID_SOCKET
CompilerCase #PB_OS_Linux
;Error Handling
;Errors
#EAGAIN = 11
#EACCES = 13
#EAFNOSUPPORT = 97
#EINVAL = 22
#EMFILE = 24
#ENFILE = 23
#ENOBUFS = 105
#ENOMEM = 12
#EPROTONOSUPPORT = 93
#ERROR_NONE = 0
#ERROR_NO_INIT_NETWORK = -4
#ERROR_NETWORK_DOWN = 0
#ERROR_NO_IRDA_SUPPORT = #EAGAIN
#ERROR_NO_MORE_DEVICES = -2
#ERROR_ADDRESS_IN_USE = 0
#ERROR_NO_MEMORY = #ENOBUFS
#ERROR_PROTOCOL_NOT_SUPPORTED = #EINVAL
#ERROR_PROTOCOLTYPE_WRONG = #EACCES
#ERROR_NOT_YET_CONNECTED = -5
#ERROR_SOCKET_ALREADY_CONNECTED = 0
#ERROR_NO_EXAMINE_IRDA_DEVICES = -3
#ERROR_TIMED_OUT = 0
#ERROR_INVALID_SOCKET = -1
CompilerEndSelect
EndDeclareModule
Module IrDa
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
Procedure __GetLastError()
ProcedureReturn WSAGetLastError_()
EndProcedure
Structure SOCKADDR_IRDA
irdaAddressFamily.w
irdaDeviceID.l
irdaServiceName.b[25]
EndStructure
Structure IRDA_DEVICE_INFO
irdaDeviceID.l
irdaDeviceName.b[22]
Reserved.b[2]
EndStructure
Structure DEVICELIST
numDevice.l
Device.IRDA_DEVICE_INFO[0]
EndStructure
#AF_IRDA = 26
#PF_IRDA = #AF_IRDA
#SOL_IRLMP = $00FF;
#IRLMP_ENUMDEVICES = $00000010;
#IRLMP_IAS_SET = $00000011;
#IRLMP_IAS_QUERY = $00000012;
#IRLMP_SEND_PDU_LEN = $00000013;
#IRLMP_EXCLUSIVE_MODE = $00000014;
#IRLMP_IRLPT_MODE = $00000015;
#IRLMP_9WIRE_MODE = $00000016;
#IRLMP_TINYTP_MODE = $00000017;
#IRLMP_PARAMETERS = $00000018;
#IRLMP_DISCOVERY_MODE = $00000019;
#IAS_ATTRIB_NO_CLASS = $00000010;
#IAS_ATTRIB_NO_ATTRIB = $00000000;
#IAS_ATTRIB_INT = $00000001;
#IAS_ATTRIB_OCTETSEQ = $00000002;
#IAS_ATTRIB_STR = $00000003;
#IAS_MAX_USER_STRING = 256;
#IAS_MAX_OCTET_STRING = 1024;
#IAS_MAX_CLASSNAME = 64;
#IAS_MAX_ATTRIBNAME = 256;
CompilerCase #PB_OS_Linux
ImportC ""
errno_location() As "__errno_location"
EndImport
Procedure __GetLastError()
ProcedureReturn PeekL(errno_location())
EndProcedure
#AF_IRDA = 23
#FIONREAD = $541B
#SOL_IRLMP = 266
#SOL_IRDA = 266
#IRLMP_ENUMDEVICES = 1
#SOCK_STREAM = 1
Structure SOCKADDR_IRDA
irdaAddressFamily.w
sir_lsap_sel.b
irdaDeviceID.l
irdaServiceName.b[25]
EndStructure
Structure IRDA_DEVICE_INFO
saddr.l
irdaDeviceID.l
irdaDeviceName.b[22]
charset.b
hints.b[2]
EndStructure
Structure DEVICELIST
numDevice.l
Device.IRDA_DEVICE_INFO[0]
EndStructure
CompilerEndSelect
InitNetwork()
EnableExplicit
Global DestSockAddr.SOCKADDR_IRDA
Global *pDevList.DEVICELIST
Global Socket, DeviceNum, LastError
Procedure Init()
;Always use Init first and also check the result
;After a Disconnect() you need to call Init() again before you can use Connect()!!
LastError = #ERROR_NONE
DestSockAddr\irdaAddressFamily = #AF_IRDA
DestSockAddr\irdaDeviceID = 0
PokeS(@DestSockAddr\irdaServiceName[0], "SampleIrDAService", -1, #PB_Ascii)
Socket = SOCKET_(#AF_IRDA, #SOCK_STREAM, 0)
If Socket = #ERROR_INVALID_SOCKET
Socket = 0
LastError = __GetLastError()
ProcedureReturn #False
EndIf
ProcedureReturn Socket
EndProcedure
Procedure ExamineIrdaDevices()
;Start examination of Irda Devices
Protected pDevListLen
LastError = #ERROR_NONE
If Socket = 0
LastError = #ERROR_NO_INIT_NETWORK
ProcedureReturn #False
EndIf
*pDevList = AllocateMemory(4096)
*pDevList\numDevice = 0
pDevListLen = MemorySize(*pDevList)
If getsockopt_(Socket, #SOL_IRLMP, #IRLMP_ENUMDEVICES, *pDevList, @pDevListLen) = #ERROR_INVALID_SOCKET
LastError = __GetLastError()
ProcedureReturn #False
EndIf
If *pDevList\numDevice = 0
LastError = #ERROR_NO_MORE_DEVICES
Debug "No IRDA devices were discovered or cached"
ProcedureReturn #False
EndIf
DeviceNum = 0
ProcedureReturn #True
EndProcedure
Procedure NextIrdaDevice()
;Lets examine the next Irda device
LastError = #ERROR_NONE
If Socket = 0
LastError = #ERROR_NO_INIT_NETWORK
ProcedureReturn #False
ElseIf *pDevList = 0
LastError = #ERROR_NO_EXAMINE_IRDA_DEVICES
ProcedureReturn #False
ElseIf *pDevList\numDevice = 0
Lasterror = #ERROR_NO_MORE_DEVICES
ProcedureReturn #False
EndIf
DeviceNum + 1
If DeviceNum > *pDevList\numDevice
Lasterror = #ERROR_NO_MORE_DEVICES
ProcedureReturn #False
EndIf
ProcedureReturn #True
EndProcedure
Procedure.s GetIrdaDeviceName()
;this is th current DeviceName
LastError = #ERROR_NONE
If Socket = 0
LastError = #ERROR_NO_INIT_NETWORK
ProcedureReturn ""
ElseIf *pDevList = 0
LastError = #ERROR_NO_EXAMINE_IRDA_DEVICES
ProcedureReturn ""
ElseIf *pDevList\numDevice < DeviceNum
Lasterror = #ERROR_NO_MORE_DEVICES
ProcedureReturn ""
EndIf
ProcedureReturn PeekS(@*pDevList\Device[DeviceNum - 1]\irdaDeviceName[0], -1, #PB_Ascii)
EndProcedure
Procedure GetIrdaDeviceID()
;this is the current examined DeviceID
LastError = #ERROR_NONE
If Socket = 0
LastError = #ERROR_NO_INIT_NETWORK
ProcedureReturn #False
ElseIf *pDevList = 0
LastError = #ERROR_NO_EXAMINE_IRDA_DEVICES
ProcedureReturn #False
ElseIf *pDevList\numDevice < DeviceNum
Lasterror = #ERROR_NO_MORE_DEVICES
ProcedureReturn #False
EndIf
ProcedureReturn *pDevList\Device[DeviceNum - 1]\irdaDeviceID
EndProcedure
Procedure FinishExamineIrda()
;Finish examination previously started with ExamineIrdaDevices()
LastError = #ERROR_NONE
If Socket = 0
LastError = #ERROR_NO_INIT_NETWORK
ProcedureReturn #False
EndIf
If *pDevList
FreeMemory(*pDevList)
*pDevList = 0
EndIf
DeviceNum = 0
EndProcedure
Procedure Connect(DeviceID)
;Connect to the IrDA Decide #DeviceID
;You can get the Device ID with the examine procedures:
;ExamineDevices(), NextIrdaDevice(), GetIrdaDeviceID(), GetIrdaDeviceName(), FinishExamineIrda()
LastError = #ERROR_NONE
If Socket = 0
LastError = #ERROR_NO_INIT_NETWORK
ProcedureReturn #False
ElseIf DestSockAddr\irdaDeviceID <> 0
LastError = #ERROR_SOCKET_ALREADY_CONNECTED
ProcedureReturn #False
EndIf
DestSockAddr\irdaDeviceID = DeviceID
If connect_(Socket, @DestSockAddr, SizeOf(SOCKADDR_IRDA)) = #ERROR_INVALID_SOCKET
DestSockAddr\irdaDeviceID = 0
LastError = __GetLastError()
ProcedureReturn #False
EndIf
ProcedureReturn #True
EndProcedure
Procedure Disconnect()
;IF YOU WANT TO REOPEN A IRDA SOCKET, RECALL INIT()!!
;A SIMPLE CONNECT() WILL NOT BE ENOUGH!
LastError = #ERROR_NONE
If Socket = 0
LastError = #ERROR_NO_INIT_NETWORK
Else
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
If closesocket_(Socket) = #ERROR_INVALID_SOCKET
LastError = __GetLastError()
EndIf
CompilerCase #PB_OS_Linux
If close_(Socket) = #ERROR_INVALID_SOCKET
LastError = __GetLastError()
EndIf
CompilerEndSelect
EndIf
Socket = 0
DestSockAddr\irdaDeviceID = 0
ProcedureReturn #True
EndProcedure
Procedure SendData(*Buffer, BufferLen)
;send data in *Buffer via IrDA
Protected Length
LastError = #ERROR_NONE
If Socket = 0
LastError = #ERROR_NO_INIT_NETWORK
ProcedureReturn #False
ElseIf DestSockAddr\irdaDeviceID = 0
LastError = #ERROR_NOT_YET_CONNECTED
ProcedureReturn #False
EndIf
Length = send_(Socket, *Buffer, BufferLen, 0)
If Length = #ERROR_INVALID_SOCKET
LastError = __GetLastError()
EndIf
ProcedureReturn Length
EndProcedure
Procedure IsDataAvailable()
;Checks if data is available and will then return the amount of data waiting.
;similar to AvailableSerialPortInput
Protected Length
If Socket = 0
LastError = #ERROR_NO_INIT_NETWORK
ProcedureReturn -1
ElseIf DestSockAddr\irdaDeviceID = 0
LastError = #ERROR_NOT_YET_CONNECTED
ProcedureReturn -1
EndIf
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
ioctlsocket_(Socket, #FIONREAD, @Length)
CompilerCase #PB_OS_Linux
ioctl_(Socket, #FIONREAD, @Length)
CompilerEndSelect
ProcedureReturn Length
EndProcedure
Procedure ReceiveData(*Buffer, BufferLen)
;Receive data from the IrDA into *Buffer
;Will return the length it has been received.
Protected Length
LastError = #ERROR_NONE
If Socket = 0
LastError = #ERROR_NO_INIT_NETWORK
ProcedureReturn #False
ElseIf DestSockAddr\irdaDeviceID = 0
LastError = #ERROR_NOT_YET_CONNECTED
ProcedureReturn #False
EndIf
Length = recv_(Socket, *Buffer, BufferLen, 0)
If Length = #ERROR_INVALID_SOCKET
LastError = __GetLastError()
EndIf
ProcedureReturn Length
EndProcedure
Procedure GetSockID()
;Get the os handle of our socket
If Socket = 0
LastError = #ERROR_NO_INIT_NETWORK
ProcedureReturn #False
EndIf
ProcedureReturn Socket
EndProcedure
Procedure GetLastError()
ProcedureReturn LastError
EndProcedure
EndModule
;Example Code
CompilerIf #PB_Compiler_IsMainFile
Procedure.s ParseErrorMessages()
Protected Error, Result.s
Select IrDA::GetLastError()
Case IRDA::#ERROR_NONE
Result = "There were no error!"
Case IRDA::#ERROR_NO_INIT_NETWORK
Result = "It seems you have network problems or didn't call IRDA::Init()!"
Case IRDA::#ERROR_NETWORK_DOWN
Result = "Network down!"
Case IRDA::#ERROR_NO_IRDA_SUPPORT
Result = "Check that the local computer has an infrared device and a device driver is installed!"
Case IRDA::#ERROR_NO_MORE_DEVICES
Result = "No (more) IrDA deviced found"
Case IRDA::#ERROR_ADDRESS_IN_USE
Result = "The Socket seems to be in use!"
Case IRDA::#ERROR_NO_MEMORY
Result = "Memory problems!"
Case IRDA::#ERROR_PROTOCOL_NOT_SUPPORTED
Result = "The protocol is not supported?!"
Case IRDA::#ERROR_PROTOCOLTYPE_WRONG
Result = "Wrong protocol type!"
Case IRDA::#ERROR_NOT_YET_CONNECTED
Result = "The socket is not connected!"
Case IRDA::#ERROR_SOCKET_ALREADY_CONNECTED
Result = "This socket is already connected!"
Case IRDA::#ERROR_NO_EXAMINE_IRDA_DEVICES
Result = "You didn't call IRDA::ExamineIrdaDevices() first!"
Case IRDA::#ERROR_TIMED_OUT
Result = "Request timed out!"
EndSelect
ProcedureReturn Result
EndProcedure
Procedure main()
Protected i
If IrDA::Init() = #False
Debug "Init failed!"
Debug ParseErrorMessages()
ProcedureReturn
EndIf
If IrDa::ExamineIrdaDevices()
While IrDA::NextIrdaDevice()
Debug IrDA::GetIrdaDeviceName()
Debug IrDA::GetIrdaDeviceID()
i = IrDA::GetIrdaDeviceID() ;<- keep the first device in mind
Wend
IrDA::FinishExamineIrda()
If IrDA::Connect(i)
Debug "ok"
Debug IrDA::Disconnect()
Else
Debug "Connection failed!"
Debug ParseErrorMessages()
EndIf
Else
Debug "Examination failed!"
Debug ParseErrorMessages()
EndIf
EndProcedure
main()
CompilerEndIf