Two interchangeable channels — TCP and Serial — behave identically above the
byte layer (matches the reference Delphi USSP1126Channels.pas, where both the
network and serial read threads just accumulate raw bytes into one shared buffer
and the framing is done by a single CatchPosRawResponse).
The framing is asymmetric — this is the single most important detail of the
wire protocol and the easiest thing to get wrong:
Send (PC→POS): the bare ISO-8583 message. No length prefix, no header.
Receive (POS→PC): [2-byte BE length][5-byte header 60 00 00 00 00][ISO message],
where the length counts header + ISO. We emit the inner ISO
message with those 7 bytes stripped.
Both reference implementations agree, and so do the captures:
Delphi USSP1126Commander.SendCommand transmits the output of MACPack
verbatim; every capture in SSP1126 PC to POS 2007/log/*.txt logs
Send Command With Result : N where N is exactly the MACPack byte count
(212/35/27/30 bytes — never +7).
The C# SSP1126.PcPos.dll (NetworkChannel) overrides sendMessageHeader
to a no-op, never calls sendMessageLength from send(), and sets
setHeader(new byte[0]) on every request — while its receive path
(ReadCallback) does Array.Copy(Buffer, 7, …), i.e. skips exactly the
2 + 5 bytes above.
Prefixing outgoing messages with the receive-side envelope shifts every field by
7 bytes, so the terminal cannot parse the request; it answers immediately with a
well-formed rejection (DE39=98, DE3=000000) that looks deceptively like a
user-initiated cancel.
The shared framing/buffering/timeout logic lives in FrameTransport; TcpTransport
and SerialTransport only supply connect/send/close for their medium.
Transport layer for the SSP1126 terminal.
Two interchangeable channels — TCP and Serial — behave identically above the byte layer (matches the reference Delphi
USSP1126Channels.pas, where both the network and serial read threads just accumulate raw bytes into one shared buffer and the framing is done by a singleCatchPosRawResponse).The framing is asymmetric — this is the single most important detail of the wire protocol and the easiest thing to get wrong:
Send (PC→POS): the bare ISO-8583 message. No length prefix, no header. Receive (POS→PC):
[2-byte BE length][5-byte header 60 00 00 00 00][ISO message], where the length counts header + ISO. We emit the inner ISO message with those 7 bytes stripped.Both reference implementations agree, and so do the captures:
USSP1126Commander.SendCommandtransmits the output ofMACPackverbatim; every capture inSSP1126 PC to POS 2007/log/*.txtlogsSend Command With Result : Nwhere N is exactly the MACPack byte count (212/35/27/30 bytes — never +7).SSP1126.PcPos.dll(NetworkChannel) overridessendMessageHeaderto a no-op, never callssendMessageLengthfromsend(), and setssetHeader(new byte[0])on every request — while its receive path (ReadCallback) doesArray.Copy(Buffer, 7, …), i.e. skips exactly the 2 + 5 bytes above.Prefixing outgoing messages with the receive-side envelope shifts every field by 7 bytes, so the terminal cannot parse the request; it answers immediately with a well-formed rejection (DE39=
98, DE3=000000) that looks deceptively like a user-initiated cancel.The shared framing/buffering/timeout logic lives in
FrameTransport;TcpTransportandSerialTransportonly supply connect/send/close for their medium.