Scanning Devices Inc.



Sensors, Instruments and Controls
111 Terrace Hall Avenue
Burlington, Massachusetts (USA) 01803
1-781-272-5135
FAX: 1-781-272-4856
Email us: mail@scanningdevices.com


Programming Documentation for Scanning Devices 2500U Magnetic Stripe Readers for Palm Handhelds

This paper describes the programming interface for Scanning Devices 2500U Magnetic Stripe Readers for Palm OS. Topics are:


Control by the Palm Serial Port

When the Palm Serial Port is closed, the Magstripe reader is in "power-down" mode to conserve Palm battery life. Analog detection and decoding circuitry is not powered. The Palm OS program controls the Palm serial port and thus the power applied to the magnetic stripe reader. When the serial port is opened, the reader awakes and powers its analog detection and decoding circuitry. In this way the Palm OS application controls power consumption; the reader may be operated to consume power only when reading. (See timing control in Palm for a specific sequence.)

Making the Reader Ready to Read

The clipped-on magnetic stripe reader detects that the serial port has been opened, starts the reader, powers-up the analog detection and decoding circuitry and brings the reader to ready state. This operation requires 150 milliseconds.

The first step in the read operation is to define the card data format to the reader. There are four options depending on the magnetic coding of track 2 and (if present) track 3. Palm transmits one ascii character to the reader:

Card Format (track 1 - track 2 - track 3) Character Transmitted
(default)Alpha - numeric - numericA
Alpha - alpha - numeric B
Alpha - numeric - alphaC
Alpha - alpha - alpha D
if a character other than A,B,C, or D is passed, 'A' is assumed
characters must be upper case
reader acknowledges command with lower case response

Once readied by Palm, the read operation is initiated by the presence of a magnetic stripe card moving through the card guide. The reader must be in the ready state to detect a card and begin reading.

2500U Data read from the card and transmitted to Palm

Magnetic Stripe 2502U/2512U are two track readers; 2503U/2513Uare three-track readers.

Data from all tracks is transmitted to Palm as read from the card. Each data byte is encoded with a tag in its high order two bits to identify the source track.

Track 1 data (alpha numeric) consists of the 6-bit characters as read from the card with the track tag 01 imposed on the high order two bits to identify the track source. Track 2 and track 3 (for 2503U/2513U) data (alphanumeric or numeric, depending on command transmitted to start the read operation) is converted to ASCII in the reader prior to transmission. The track tag 10 for (track 2 data) or 11 (for track 3 data) is imposed on the high order two bits to identify track source. Start Sentinel and End Sentinel characters are included in each track's data stream.

Data decoding and conversion

Track 1 data is 6-bit alpha numeric data. The track tag 01 is imposed on the data as bits 8 and 7 prior to transmission to Palm. Data is not converted to 8-bit ASCII characters in the reader before being transmitted to Palm.

Track 2 and Track 3 data is either 4-bit numeric or 6-bit alphnumeric data. Numeric data is converted to 8-bit ASCII characters in the reader. The numeric character set consists of 10 numerals plus ": < = >; ?", using only the least significant 6 bits of the ASCII byte. Alpha numeric data is transmitted in its 6-bit code in the same manner as track 1 data. The track tags 10 (track 2) or 11 (track 3) are imposed on the data as bits 8 and 7 prior to transmission to Palm.

On receipt in Palm, data must be selected by track tag to reconstruct the track data. In addition, track 1 data and alpha-numeric data from tracks 2 and 3 and must be converted to ASCII. Scanning Devices software is available to demonstrate one way to do this. See the Sort It Out Function Listing below for details.

Error detection and reporting

A postamble byte is appended to the transmission after each track's end sentinel. If the track has been read without error, a character equivalent to ASCII "space" (decimal 32) is appended as the postamble. If the reader encountered either a parity or an LRC error error in the track, a character equivalent to ASCII "*" (asterisk) is appended as the postamble. No further error information is available.

If no start sentinel is detected on a track, then no data is read from that track and the data stream will have no characters with that track's tag.

If no end sentinel is detected on a track, then no error status byte will be appended. The Palm Application should make sure that an end sentinel is included for each track in the datastream. If an end sentinel is not detected for each track, then the Palm Application should assume that an error was encountered.

An end sentinel followed by a space, indicates an error-free read. An end sentinel followed by an "*" indicates an error in reading.

The Palm OS application should determine the error status of reading and make any required indication to the user.

Timing control in Palm

Transmision timing gives the Palm OS program cues to activity in the reader.

The reader begins to transmit data as soon as it becomes available. Receipt of data indicates that a card is moving through the reader. The Palm OS application should be ready to receive data anytime the serial port is opened.

The user may pass the card slowly, allowing up to 150 milliseconds between character transmissions. The Palm OS application should allow at least this much time prior to determining end of transmission.

The following sequence is the design center for Palm OS timing.


Palm Serial Port Settings for 2500U Readers

Port settings are: 57,600 baud, 1 stop bit, no parity.

Released: July 31, 2001
Updated: October 26, 2003

Scanning Devices Inc.
P.O Box 192
Lexington, MA 02420
Phone: 781-272-5135 -- Fax: 781-272-4856 -- Email:
mail@scanningdevices.com

Copyright © 2004 Scanning Devices Inc.

Appendix:
Palm OS C Function Source to reconstruct three track data from string received from MagStripe 2500U

Narrative of what the function does

Handle SortItOut(CharPtr dataP) { Handle sortH; CharPtr sortP; Handle track1H; CharPtr track1P; Handle track2H; CharPtr track2P; Handle track3H; CharPtr track3P; Handle dH; VoidPtr dP; unsigned int * data; unsigned int test=0; unsigned int trackNumber=0; unsigned int noTag = 0; char *s; //source pointer char *e; //end pointer char * t1; //destination pointers char * t2; char * t3; ULong size =0; dH = MemHandleNew(10); dP=MemHandleLock(dH); data = (unsigned int *)dP; *data=0; size = StrLen(dataP)+10; sortH = MemHandleNew(size); sortP = MemHandleLock(sortH); StrCopy(sortP,dataP); s=sortP; track1H = MemHandleNew(size); track1P = MemHandleLock(track1H); MemSet(track1P,size,0); t1=track1P; track2H = MemHandleNew(size); track2P = MemHandleLock(track2H); MemSet(track2P,size,0); t2=track2P; track3H = MemHandleNew(size); track3P = MemHandleLock(track3H); MemSet(track3P,size,0); t3=track3P; e=s+size-10; while(s<e) { *data=0; MemMove(data,s,1); test = (*data)/256; //shifts to low order byte trackNumber = test/64; //gets track number noTag = test%64; // remainder is stripe byte if(trackNumber==1) { noTag=256*(noTag+32); //to convert to ASCII MemMove(t1,&noTag,1); //add 32 and shift to upper byte t1++; } if(trackNumber==2) { noTag = 256*noTag; //shift to upper byte MemMove(t2,&noTag,1); t2++; } if(trackNumber==3) { noTag = 256*noTag; //shift to upper byte MemMove(t3,&noTag,1); t3++; } s++; } MemSet(sortP,size,0); s=sortP; StrCopy(s,track1P); s+=StrLen(s)+1; StrCopy(s,track2P); s+=StrLen(s)+1; StrCopy(s,track3P); MemHandleFree(dH); MemHandleFree(track1H); MemHandleFree(track2H); MemHandleFree(track3H); MemHandleUnlock(sortH); return sortH; }