Fixed issue where the LRC of a card was the reverse of the start
[magread] / mslib.h
1 /*
2  * This file is part of mslib.
3  * mslib is free software: you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation, either version 3 of the License, or
6  * (at your option) any later version.
7  *
8  * mslib is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with nosebus.  If not, see <http://www.gnu.org/licenses/>.
15  */
16 #ifndef MSLIB_H
17 #define MSLIB_H
18
19 #ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
20 extern "C" {
21 #endif
22
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "llist.h"
29
30 #define PEAK_THRESHOLD  500
31 #define PEAK_OFFSET     3
32
33 #define MAX_BITSTREAM_LEN 1024
34
35 #define ABA_SS          "11010"
36 #define ABA_ES          "11111"
37 #define MAX_ABA_LEN     41
38 #define ABA_CHAR_LEN    5
39 #define ABA_ASCII_OFFSET 48
40
41 #define IATA_SS         "1010001"
42 #define IATA_ES         "1111100"
43 #define MAX_IATA_LEN    83 // some reports say max len is 79, but AAMVA says 82 ...
44 #define IATA_CHAR_LEN   7
45 #define IATA_ASCII_OFFSET 32
46
47 #define NUM_ASCII_OFFSET 48
48
49 /* This char will be put into the stream whenever the parity bit doesn't match.
50  * The default char, | (PIPE), is chosen because it does not appear in either
51  * of the two encoding schemes. */
52 #define BAD_CHAR        '|'
53
54 typedef enum {
55         UNSET = 0,
56         IATA,
57         ABA,
58         UNKNOWN = 9
59 } ms_dataType;
60
61
62 typedef struct {
63         int idx;
64         short amp;
65 } peakData;
66
67 typedef struct {
68         /* PCM Data */
69         short *pcmData;
70         int pcmDataLen;
71         
72         /* Peaks */
73         LListH *peakList;
74         int peakThreshold;
75         int peakOffset;
76
77         /* Decode */
78         ms_dataType dataType;
79         char *bitStream;
80         char *charStream;
81 } msData;
82
83
84 /* Init Functions */
85
86 /* internal helper function, do not use */
87 msData *_ms_create();
88
89 /* Create an msData object using the given 16bit array of PCM data
90  * pcmData - A 16bit signed array of PCM data.
91  * pcmDataLen - the number of elements in pcmData
92  * Returns an msData object on success and NULL on failure */
93 msData *ms_create( const short *pcmData, int pcmDataLen );
94
95 /* Garbage Collection */
96
97 /* Frees all data allocated for the given msData objected
98  * Always returns NULL.
99  * This function will not free any data that mslib did not allocate itself */
100 msData *ms_free( msData *ms );
101
102 void ms_reinit( msData *ms );
103
104 /* internal helper function, do not use */
105 void ms_free_peakList( msData *ms );
106
107 /* Configuration functions */
108
109 /* Set the peakThreshold value.
110  * The value determines the minimum amplitude to be considered a peak
111  * You probably can stay with the default value */
112 void ms_set_peakThreshold( msData *ms, int peakThreshold );
113
114 /* Set the peakOffset value.
115  * The value determines the offset to use when looking for intersects
116  * You probably can stay with the default value */
117 void ms_set_peakOffset( msData *ms, int peakOffset );
118
119
120 /* Get the bit stream.
121  * This would be the binary data that the peaks are decoded to.
122  * Can only be run after ms_decode_peaks().  Format is a NULL-terminated
123  * const char array.
124  * Returns NULL on error (such as if ms_decode_peaks() has not been run) */
125 const char *ms_get_bitStream( msData *ms );
126
127 /* Get the char stream.
128  * This is the decoded binary data that is human readable.
129  * Can only be run after ms_decode_bits().  Format is a NULL-terminated
130  * const char array.
131  * Returns NULL on error (such as if ms_decode_bits() has not been run) */
132 const char *ms_get_charStream( msData *ms );
133
134 /* Reverses a string in place */
135 void strrev( char *str );
136
137
138
139 /* Find Peaks Functions */
140
141 /* internal helper function, do not use */
142 int ms_range( int a, int b1, int b2 );
143
144 /* Finds the peaks in the stream.
145  * This should be run immediately after ms_create().
146  * Compares the stream against an offset of itself and searches for intersects.
147  * Intersections are marked as peaks.
148  */
149 void ms_peaks_find( msData *ms );
150
151 /* Finds the peaks in the stream.
152  * Marks the apex of any amplitude apex as a peak.
153  */
154 void ms_peaks_find_walk( msData *ms );
155
156 /* Filters the list of peaks found using a grouping method based on signedness
157  * of the amplitude.
158  * This typically should be run after ms_peaks_find().
159  */
160 void ms_peaks_filter_group( msData *ms );
161
162 /* internal helper function, do not use */
163 LListH *_ms_peaks_filter_groupFind( msData *ms, LListH *groupList );
164
165
166 /* Peak Decoding Functions */
167
168 /* internal helper function, do not use */
169 char _ms_closer( int *oneClock, int dif );
170
171 /* This decodes the peaks found through the ms_peaks*() functions.
172  * It should be run after them.
173  */
174 void ms_decode_peaks( msData *ms );
175
176 /* Bit Decoding functions */
177
178 /* This determines the type of encoding used: ABA or IATA.
179  * At present, only ABA is supported (as found on track 2 of most cards).
180  *
181  * This is generally used as a helper function internally, but can be run
182  * directly.  It will return 1 on error and 0 on success.
183  * Success means it was able to detect either ABA or IATA. */
184 int ms_decode_typeDetect( msData *ms );
185
186 /* This decodes the bits into the charstream.
187  * It should be run after ms_decode_peaks().
188  * The encoding is auto-detected using ms_decode_typeDetect()
189  * Returns -1 on error, 0 on success, and from the enum ms_dataType UNKNOWN (9)
190  * if the card format was not detected (de facto error) */
191 int ms_decode_bits( msData *ms );
192
193 /* internal helper function, do not use */
194 char _ms_decode_bits_char( char *bitStream, char *LRC, ms_dataType type );
195
196 /* Debug function.
197  * This saves the stream to the given filename with ".pcm" appended.
198  * It also saves the contents of the peakList to the filename with a ".peaks"
199  * extension.
200  *
201  * gnuplot is ideal for viewing the contents:
202  * plot "x.pcm" binary format="%int16" using l 1 w l, "x.peaks"
203  */
204 void ms_save( msData *ms, const char *filename );
205
206 #ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
207 }
208 #endif
209
210 #endif