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