rubyfit 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,439 @@
1
+ ////////////////////////////////////////////////////////////////////////////////
2
+ // The following .FIT software provided may be used with .FIT devices only and
3
+ // remains the copyrighted property of Dynastream Innovations Inc.
4
+ // The software is being provided on an "as-is" basis and as an accommodation,
5
+ // and therefore all warranties, representations, or guarantees of any kind
6
+ // (whether express, implied or statutory) including, without limitation,
7
+ // warranties of merchantability, non-infringement, or fitness for a particular
8
+ // purpose, are specifically disclaimed.
9
+ //
10
+ // Copyright 2008 Dynastream Innovations Inc.
11
+ // All rights reserved. This software may not be reproduced by any means
12
+ // without express written approval of Dynastream Innovations Inc.
13
+ ////////////////////////////////////////////////////////////////////////////////
14
+
15
+ #include <string.h>
16
+
17
+ #include "fit_convert.h"
18
+ #include "fit_crc.h"
19
+
20
+ //////////////////////////////////////////////////////////////////////////////////
21
+ // Private Variables
22
+ //////////////////////////////////////////////////////////////////////////////////
23
+
24
+ #if !defined(FIT_CONVERT_MULTI_THREAD)
25
+ static FIT_CONVERT_STATE state_struct;
26
+ #define state (&state_struct)
27
+ #endif
28
+
29
+ //////////////////////////////////////////////////////////////////////////////////
30
+ // Public Functions
31
+ //////////////////////////////////////////////////////////////////////////////////
32
+
33
+ ///////////////////////////////////////////////////////////////////////
34
+ #if defined(FIT_CONVERT_MULTI_THREAD)
35
+ void FitConvert_Init(FIT_CONVERT_STATE *state, FIT_BOOL read_file_header)
36
+ #else
37
+ void FitConvert_Init(FIT_BOOL read_file_header)
38
+ #endif
39
+ {
40
+ state->mesg_offset = 0;
41
+ state->data_offset = 0;
42
+
43
+ #if defined(FIT_CONVERT_CHECK_CRC)
44
+ state->crc = 0;
45
+ #endif
46
+ #if defined(FIT_CONVERT_TIME_RECORD)
47
+ state->timestamp = 0;
48
+ state->last_time_offset = 0;
49
+ #endif
50
+
51
+ if (read_file_header)
52
+ {
53
+ state->file_bytes_left = 3; // Header size byte + CRC.
54
+ state->decode_state = FIT_CONVERT_DECODE_FILE_HDR;
55
+ }
56
+ else
57
+ {
58
+ state->file_bytes_left = 0; // Don't read header or check CRC.
59
+ state->decode_state = FIT_CONVERT_DECODE_RECORD;
60
+ }
61
+ }
62
+
63
+ ///////////////////////////////////////////////////////////////////////
64
+ #if defined(FIT_CONVERT_MULTI_THREAD)
65
+ FIT_CONVERT_RETURN FitConvert_Read(FIT_CONVERT_STATE *state, const void *data, FIT_UINT32 size)
66
+ #else
67
+ FIT_CONVERT_RETURN FitConvert_Read(const void *data, FIT_UINT32 size)
68
+ #endif
69
+ {
70
+ while (state->data_offset < size)
71
+ {
72
+ FIT_UINT8 datum = *((FIT_UINT8 *) data + state->data_offset);
73
+ state->data_offset++;
74
+
75
+ //printf("fit_convert: 0x%02X - %d\n",datum, state->decode_state);
76
+
77
+ if (state->file_bytes_left > 0)
78
+ {
79
+ #if defined(FIT_CONVERT_CHECK_CRC)
80
+ state->crc = FitCRC_Get16(state->crc, datum);
81
+ #endif
82
+
83
+ state->file_bytes_left--;
84
+
85
+ if (state->file_bytes_left == 1) // CRC low byte.
86
+ {
87
+ if (state->decode_state != FIT_CONVERT_DECODE_RECORD)
88
+ return FIT_CONVERT_ERROR;
89
+
90
+ continue; // Next byte.
91
+ }
92
+ else if (state->file_bytes_left == 0) // CRC high byte.
93
+ {
94
+ #if defined(FIT_CONVERT_CHECK_CRC)
95
+ if (state->crc != 0)
96
+ return FIT_CONVERT_ERROR;
97
+ #endif
98
+
99
+ return FIT_CONVERT_END_OF_FILE;
100
+ }
101
+ }
102
+
103
+ switch (state->decode_state)
104
+ {
105
+ case FIT_CONVERT_DECODE_FILE_HDR:
106
+ *((FIT_UINT8 *) &state->u.file_hdr + state->mesg_offset) = datum;
107
+
108
+ if (state->mesg_offset == 0)
109
+ state->file_bytes_left = state->u.file_hdr.header_size + 2; // Increase to read header and CRC.
110
+
111
+ state->mesg_offset++;
112
+
113
+ if (state->mesg_offset >= state->u.file_hdr.header_size)
114
+ {
115
+ state->file_bytes_left = *((FIT_UINT8 *) &state->u.file_hdr.data_size);
116
+ state->file_bytes_left |= (FIT_UINT32)*((FIT_UINT8 *) &state->u.file_hdr.data_size + 1) << 8;
117
+ state->file_bytes_left |= (FIT_UINT32)*((FIT_UINT8 *) &state->u.file_hdr.data_size + 2) << 16;
118
+ state->file_bytes_left |= (FIT_UINT32)*((FIT_UINT8 *) &state->u.file_hdr.data_size + 3) << 24;
119
+ state->file_bytes_left += 2; // CRC.
120
+
121
+ if ((state->u.file_hdr.protocol_version & FIT_PROTOCOL_VERSION_MAJOR_MASK) > (FIT_PROTOCOL_VERSION_MAJOR << FIT_PROTOCOL_VERSION_MAJOR_SHIFT))
122
+ return FIT_CONVERT_PROTOCOL_VERSION_NOT_SUPPORTED;
123
+
124
+ #if defined(FIT_CONVERT_CHECK_FILE_HDR_DATA_TYPE)
125
+ if (memcmp(state->u.file_hdr.data_type, ".FIT", 4) != 0)
126
+ return FIT_CONVERT_DATA_TYPE_NOT_SUPPORTED;
127
+ #endif
128
+
129
+ state->decode_state = FIT_CONVERT_DECODE_RECORD;
130
+ }
131
+ break;
132
+
133
+ case FIT_CONVERT_DECODE_RECORD:
134
+ if (datum & FIT_HDR_TIME_REC_BIT)
135
+ {
136
+ // This is a message data record with time.
137
+ state->mesg_index = (datum & FIT_HDR_TIME_TYPE_MASK) >> FIT_HDR_TIME_TYPE_SHIFT;
138
+
139
+ #if defined(FIT_CONVERT_TIME_RECORD)
140
+ {
141
+ FIT_UINT8 time_offset = datum & FIT_HDR_TIME_OFFSET_MASK;
142
+ state->timestamp += (time_offset - state->last_time_offset) & FIT_HDR_TIME_OFFSET_MASK;
143
+ state->last_time_offset = time_offset;
144
+ }
145
+ #endif
146
+
147
+ state->decode_state = FIT_CONVERT_DECODE_FIELD_DATA;
148
+ }
149
+ else
150
+ {
151
+ state->mesg_index = datum & FIT_HDR_TYPE_MASK;
152
+
153
+ if ((datum & FIT_HDR_TYPE_DEF_BIT) == 0)
154
+ {
155
+ // This is a message data record.
156
+ state->decode_state = FIT_CONVERT_DECODE_FIELD_DATA;
157
+ }
158
+ else
159
+ {
160
+ // This is a message definition record.
161
+ state->mesg_sizes[state->mesg_index] = 0;
162
+ state->decode_state = FIT_CONVERT_DECODE_RESERVED1;
163
+ }
164
+ }
165
+
166
+ if (state->decode_state == FIT_CONVERT_DECODE_FIELD_DATA)
167
+ {
168
+ if (state->mesg_index < FIT_LOCAL_MESGS)
169
+ {
170
+ state->mesg_def = Fit_GetMesgDef(state->convert_table[state->mesg_index].global_mesg_num);
171
+ Fit_InitMesg(state->mesg_def, state->u.mesg);
172
+
173
+ #if defined(FIT_CONVERT_TIME_RECORD)
174
+ if (datum & FIT_HDR_TIME_REC_BIT)
175
+ {
176
+ FIT_UINT8 field_offset = Fit_GetFieldOffset(state->mesg_def, FIT_TIMESTAMP_FIELD_NUM);
177
+
178
+ if (field_offset != FIT_UINT8_INVALID)
179
+ memcpy(&state->u.mesg[field_offset], &state->timestamp, sizeof(state->timestamp));
180
+ }
181
+ #endif
182
+ }
183
+
184
+ if (state->mesg_sizes[state->mesg_index] == 0)
185
+ state->decode_state = FIT_CONVERT_DECODE_RECORD;
186
+ }
187
+
188
+ state->mesg_offset = 0; // Reset the message byte count.
189
+ state->field_index = 0;
190
+ state->field_offset = 0;
191
+ break;
192
+
193
+ case FIT_CONVERT_DECODE_RESERVED1:
194
+ if (state->mesg_index < FIT_LOCAL_MESGS)
195
+ state->convert_table[state->mesg_index].reserved_1 = datum;
196
+
197
+ state->decode_state = FIT_CONVERT_DECODE_ARCH;
198
+ break;
199
+
200
+ case FIT_CONVERT_DECODE_ARCH:
201
+ if (state->mesg_index < FIT_LOCAL_MESGS)
202
+ state->convert_table[state->mesg_index].arch = datum;
203
+
204
+ state->decode_state = FIT_CONVERT_DECODE_GTYPE_1;
205
+ break;
206
+
207
+ case FIT_CONVERT_DECODE_GTYPE_1:
208
+ if (state->mesg_index < FIT_LOCAL_MESGS)
209
+ state->convert_table[state->mesg_index].global_mesg_num = datum;
210
+
211
+ state->decode_state = FIT_CONVERT_DECODE_GTYPE_2;
212
+ break;
213
+
214
+ case FIT_CONVERT_DECODE_GTYPE_2:
215
+ if (state->mesg_index < FIT_LOCAL_MESGS)
216
+ {
217
+ if ((state->convert_table[state->mesg_index].arch & FIT_ARCH_ENDIAN_MASK) == FIT_ARCH_ENDIAN_BIG)
218
+ {
219
+ state->convert_table[state->mesg_index].global_mesg_num <<= 8;
220
+ state->convert_table[state->mesg_index].global_mesg_num |= datum;
221
+ }
222
+ else
223
+ {
224
+ state->convert_table[state->mesg_index].global_mesg_num |= ((FIT_UINT16) datum << 8);
225
+ }
226
+
227
+ state->convert_table[state->mesg_index].num_fields = 0; // Initialize.
228
+ state->mesg_def = Fit_GetMesgDef(state->convert_table[state->mesg_index].global_mesg_num);
229
+ }
230
+
231
+ state->decode_state = FIT_CONVERT_DECODE_NUM_FIELD_DEFS;
232
+ break;
233
+
234
+ case FIT_CONVERT_DECODE_NUM_FIELD_DEFS:
235
+ state->num_fields = datum;
236
+
237
+ if (state->num_fields == 0)
238
+ {
239
+ state->decode_state = FIT_CONVERT_DECODE_RECORD;
240
+ break;
241
+ }
242
+
243
+ state->field_index = 0;
244
+ state->decode_state = FIT_CONVERT_DECODE_FIELD_DEF;
245
+ break;
246
+
247
+ case FIT_CONVERT_DECODE_FIELD_DEF:
248
+ state->field_num = FIT_FIELD_NUM_INVALID;
249
+
250
+ if (state->mesg_index < FIT_LOCAL_MESGS)
251
+ {
252
+ if (state->mesg_def != FIT_NULL)
253
+ {
254
+ FIT_UINT8 local_field_index;
255
+ FIT_UINT8 local_field_offset = 0;
256
+
257
+ // Search for the field definition in the local mesg definition.
258
+ for (local_field_index = 0; local_field_index < state->mesg_def->num_fields; local_field_index++)
259
+ {
260
+ FIT_UINT8 field_size = state->mesg_def->fields[FIT_MESG_DEF_FIELD_OFFSET(size, local_field_index)];
261
+
262
+ if (state->mesg_def->fields[FIT_MESG_DEF_FIELD_OFFSET(field_def_num, local_field_index)] == datum)
263
+ {
264
+ state->field_num = datum;
265
+ state->convert_table[state->mesg_index].fields[state->convert_table[state->mesg_index].num_fields].offset_in = state->mesg_offset;
266
+ state->convert_table[state->mesg_index].fields[state->convert_table[state->mesg_index].num_fields].offset_local = local_field_offset;
267
+ state->convert_table[state->mesg_index].fields[state->convert_table[state->mesg_index].num_fields].size = field_size;
268
+ break;
269
+ }
270
+
271
+ local_field_offset += field_size;
272
+ }
273
+ }
274
+ }
275
+
276
+ state->decode_state = FIT_CONVERT_DECODE_FIELD_DEF_SIZE;
277
+ break;
278
+
279
+ case FIT_CONVERT_DECODE_FIELD_DEF_SIZE:
280
+ if (state->mesg_index < FIT_LOCAL_MESGS)
281
+ {
282
+ state->mesg_offset += datum;
283
+
284
+ if (state->field_num != FIT_FIELD_NUM_INVALID)
285
+ {
286
+ if (datum < state->convert_table[state->mesg_index].fields[state->convert_table[state->mesg_index].num_fields].size)
287
+ state->convert_table[state->mesg_index].fields[state->convert_table[state->mesg_index].num_fields].size = datum;
288
+ }
289
+ }
290
+
291
+ state->mesg_sizes[state->mesg_index] += datum;
292
+
293
+ state->decode_state = FIT_CONVERT_DECODE_FIELD_BASE_TYPE;
294
+ break;
295
+
296
+ case FIT_CONVERT_DECODE_FIELD_BASE_TYPE:
297
+ if (state->field_num != FIT_FIELD_NUM_INVALID)
298
+ {
299
+ state->convert_table[state->mesg_index].fields[state->convert_table[state->mesg_index].num_fields].base_type = datum;
300
+ state->convert_table[state->mesg_index].num_fields++;
301
+ }
302
+
303
+ state->field_index++;
304
+
305
+ if (state->field_index >= state->num_fields)
306
+ state->decode_state = FIT_CONVERT_DECODE_RECORD;
307
+ else
308
+ state->decode_state = FIT_CONVERT_DECODE_FIELD_DEF;
309
+ break;
310
+
311
+ case FIT_CONVERT_DECODE_FIELD_DATA:
312
+ state->mesg_offset++;
313
+
314
+ if (state->mesg_offset >= state->mesg_sizes[state->mesg_index])
315
+ {
316
+ state->decode_state = FIT_CONVERT_DECODE_RECORD;
317
+ }
318
+
319
+ if (state->mesg_index < FIT_LOCAL_MESGS)
320
+ {
321
+ if ((state->mesg_def != FIT_NULL) && (state->field_index < state->convert_table[state->mesg_index].num_fields))
322
+ {
323
+ if (state->mesg_offset == (state->convert_table[state->mesg_index].fields[state->field_index].offset_in + state->field_offset + 1))
324
+ {
325
+ FIT_UINT8 *field = &state->u.mesg[state->convert_table[state->mesg_index].fields[state->field_index].offset_local];
326
+
327
+ field[state->field_offset] = datum; // Store the incoming byte in the local mesg buffer.
328
+ state->field_offset++;
329
+
330
+ if (state->field_offset >= state->convert_table[state->mesg_index].fields[state->field_index].size)
331
+ {
332
+ if (
333
+ (state->convert_table[state->mesg_index].fields[state->field_index].base_type & FIT_BASE_TYPE_ENDIAN_FLAG) &&
334
+ ((state->convert_table[state->mesg_index].arch & FIT_ARCH_ENDIAN_MASK) != (Fit_GetArch() & FIT_ARCH_ENDIAN_MASK))
335
+ )
336
+ {
337
+ FIT_UINT8 type_size = fit_base_type_sizes[state->convert_table[state->mesg_index].fields[state->field_index].base_type & FIT_BASE_TYPE_NUM_MASK];
338
+ FIT_UINT8 element_size = state->convert_table[state->mesg_index].fields[state->field_index].size / type_size;
339
+ FIT_UINT8 element;
340
+ FIT_UINT8 index;
341
+
342
+ for (element = 0; element < element_size; element++)
343
+ {
344
+ for (index = 0; index < (type_size / 2); index++)
345
+ {
346
+ FIT_UINT8 tmp = field[element * type_size + index];
347
+ field[element * type_size + index] = field[element * type_size + type_size - 1 - index];
348
+ field[element * type_size + type_size - 1 - index] = tmp;
349
+ }
350
+ }
351
+ }
352
+
353
+ state->field_offset = 0; // Reset the offset.
354
+ state->field_index++; // Move on to the next field.
355
+
356
+ if (state->field_index >= state->convert_table[state->mesg_index].num_fields)
357
+ {
358
+ #if defined(FIT_CONVERT_TIME_RECORD)
359
+ {
360
+ FIT_UINT8 timestamp_offset = Fit_GetFieldOffset(state->mesg_def, FIT_TIMESTAMP_FIELD_NUM);
361
+
362
+ if (timestamp_offset != FIT_UINT8_INVALID)
363
+ {
364
+ if (*((FIT_UINT32 *)&state->u.mesg[timestamp_offset]) != FIT_DATE_TIME_INVALID)
365
+ {
366
+ memcpy(&state->timestamp, &state->u.mesg[timestamp_offset], sizeof(state->timestamp));
367
+ state->last_time_offset = (FIT_UINT8)(state->timestamp & FIT_HDR_TIME_OFFSET_MASK);
368
+ }
369
+ }
370
+ }
371
+ #endif
372
+
373
+ // We have successfully decoded a mesg.
374
+ return FIT_CONVERT_MESSAGE_AVAILABLE;
375
+ }
376
+ }
377
+ }
378
+ }
379
+ }
380
+ break;
381
+
382
+ default:
383
+ // This shouldn't happen.
384
+ return FIT_CONVERT_ERROR;
385
+ }
386
+ }
387
+
388
+ state->data_offset = 0;
389
+ return FIT_CONVERT_CONTINUE;
390
+ }
391
+
392
+ ///////////////////////////////////////////////////////////////////////
393
+ #if defined(FIT_CONVERT_MULTI_THREAD)
394
+ FIT_UINT16 FitConvert_GetMessageNumber(FIT_CONVERT_STATE *state)
395
+ #else
396
+ FIT_UINT16 FitConvert_GetMessageNumber(void)
397
+ #endif
398
+ {
399
+ return state->convert_table[state->mesg_index].global_mesg_num;
400
+ }
401
+
402
+ ///////////////////////////////////////////////////////////////////////
403
+ #if defined(FIT_CONVERT_MULTI_THREAD)
404
+ const FIT_UINT8 *FitConvert_GetMessageData(FIT_CONVERT_STATE *state)
405
+ #else
406
+ const FIT_UINT8 *FitConvert_GetMessageData(void)
407
+ #endif
408
+ {
409
+ return state->u.mesg;
410
+ }
411
+
412
+ ///////////////////////////////////////////////////////////////////////
413
+ #if defined(FIT_CONVERT_MULTI_THREAD)
414
+ void FitConvert_RestoreFields(FIT_CONVERT_STATE *state, const void *mesg)
415
+ #else
416
+ void FitConvert_RestoreFields(const void *mesg)
417
+ #endif
418
+ {
419
+ FIT_UINT8 offset = 0;
420
+ FIT_UINT8 field_index;
421
+ FIT_UINT8 convert_field;
422
+
423
+ if (state->mesg_def == FIT_NULL)
424
+ return;
425
+
426
+ for (field_index = 0; field_index < state->mesg_def->num_fields; field_index++)
427
+ {
428
+ for (convert_field=0; convert_field < state->convert_table[state->mesg_index].num_fields; convert_field++)
429
+ {
430
+ if (state->convert_table[state->mesg_index].fields[convert_field].offset_local == offset)
431
+ break;
432
+ }
433
+
434
+ if (convert_field == state->convert_table[state->mesg_index].num_fields)
435
+ memcpy(&state->u.mesg[offset], &((FIT_UINT8 *)mesg)[offset], state->mesg_def->fields[FIT_MESG_DEF_FIELD_OFFSET(size, field_index)]);
436
+
437
+ offset += state->mesg_def->fields[FIT_MESG_DEF_FIELD_OFFSET(size, field_index)];
438
+ }
439
+ }
@@ -0,0 +1,154 @@
1
+ ////////////////////////////////////////////////////////////////////////////////
2
+ // The following .FIT software provided may be used with .FIT devices only and
3
+ // remains the copyrighted property of Dynastream Innovations Inc.
4
+ // The software is being provided on an "as-is" basis and as an accommodation,
5
+ // and therefore all warranties, representations, or guarantees of any kind
6
+ // (whether express, implied or statutory) including, without limitation,
7
+ // warranties of merchantability, non-infringement, or fitness for a particular
8
+ // purpose, are specifically disclaimed.
9
+ //
10
+ // Copyright 2008 Dynastream Innovations Inc.
11
+ // All rights reserved. This software may not be reproduced by any means
12
+ // without express written approval of Dynastream Innovations Inc.
13
+ ////////////////////////////////////////////////////////////////////////////////
14
+
15
+ #if !defined(FIT_CONVERT_H)
16
+ #define FIT_CONVERT_H
17
+
18
+ #include "fit_product.h"
19
+
20
+
21
+ //////////////////////////////////////////////////////////////////////////////////
22
+ // Public Definitions
23
+ //////////////////////////////////////////////////////////////////////////////////
24
+
25
+ typedef enum
26
+ {
27
+ FIT_CONVERT_CONTINUE = 0,
28
+ FIT_CONVERT_MESSAGE_AVAILABLE,
29
+ FIT_CONVERT_ERROR,
30
+ FIT_CONVERT_END_OF_FILE,
31
+ FIT_CONVERT_PROTOCOL_VERSION_NOT_SUPPORTED,
32
+ FIT_CONVERT_DATA_TYPE_NOT_SUPPORTED
33
+ } FIT_CONVERT_RETURN;
34
+
35
+ typedef enum
36
+ {
37
+ FIT_CONVERT_DECODE_FILE_HDR,
38
+ FIT_CONVERT_DECODE_RECORD,
39
+ FIT_CONVERT_DECODE_RESERVED1,
40
+ FIT_CONVERT_DECODE_ARCH,
41
+ FIT_CONVERT_DECODE_GTYPE_1,
42
+ FIT_CONVERT_DECODE_GTYPE_2,
43
+ FIT_CONVERT_DECODE_NUM_FIELD_DEFS,
44
+ FIT_CONVERT_DECODE_FIELD_DEF,
45
+ FIT_CONVERT_DECODE_FIELD_DEF_SIZE,
46
+ FIT_CONVERT_DECODE_FIELD_BASE_TYPE,
47
+ FIT_CONVERT_DECODE_FIELD_DATA
48
+ } FIT_CONVERT_DECODE_STATE;
49
+
50
+ typedef struct
51
+ {
52
+ FIT_UINT32 file_bytes_left;
53
+ FIT_UINT32 data_offset;
54
+ #if defined(FIT_CONVERT_TIME_RECORD)
55
+ FIT_UINT32 timestamp;
56
+ #endif
57
+ union
58
+ {
59
+ FIT_FILE_HDR file_hdr;
60
+ FIT_UINT8 mesg[FIT_MESG_SIZE];
61
+ }u;
62
+ FIT_MESG_CONVERT convert_table[FIT_LOCAL_MESGS];
63
+ const FIT_MESG_DEF *mesg_def;
64
+ #if defined(FIT_CONVERT_CHECK_CRC)
65
+ FIT_UINT16 crc;
66
+ #endif
67
+ FIT_CONVERT_DECODE_STATE decode_state;
68
+ FIT_UINT8 mesg_index;
69
+ FIT_UINT8 mesg_sizes[FIT_MAX_LOCAL_MESGS];
70
+ FIT_UINT8 mesg_offset;
71
+ FIT_UINT8 num_fields;
72
+ FIT_UINT8 field_num;
73
+ FIT_UINT8 field_index;
74
+ FIT_UINT8 field_offset;
75
+ #if defined(FIT_CONVERT_TIME_RECORD)
76
+ FIT_UINT8 last_time_offset;
77
+ #endif
78
+ } FIT_CONVERT_STATE;
79
+
80
+
81
+ //////////////////////////////////////////////////////////////////////////////////
82
+ // Public Function Prototypes
83
+ //////////////////////////////////////////////////////////////////////////////////
84
+
85
+ #if defined(__cplusplus)
86
+ extern "C" {
87
+ #endif
88
+
89
+ #if defined(FIT_CONVERT_MULTI_THREAD)
90
+ void FitConvert_Init(FIT_CONVERT_STATE *state, FIT_BOOL read_file_header);
91
+ #else
92
+ void FitConvert_Init(FIT_BOOL read_file_header);
93
+ #endif
94
+ ///////////////////////////////////////////////////////////////////////
95
+ // Initialize the state of the converter to start parsing the file.
96
+ ///////////////////////////////////////////////////////////////////////
97
+
98
+ #if defined(FIT_CONVERT_MULTI_THREAD)
99
+ FIT_CONVERT_RETURN FitConvert_Read(FIT_CONVERT_STATE *state, const void *data, FIT_UINT32 size);
100
+ #else
101
+ FIT_CONVERT_RETURN FitConvert_Read(const void *data, FIT_UINT32 size);
102
+ #endif
103
+ ///////////////////////////////////////////////////////////////////////
104
+ // Convert a stream of bytes.
105
+ // Parameters:
106
+ // state Pointer to converter state.
107
+ // data Pointer to a buffer containing bytes from the file stream.
108
+ // size Number of bytes in the data buffer.
109
+ //
110
+ // Returns FIT_CONVERT_CONTINUE when the all bytes in data have
111
+ // been decoded successfully and ready to accept next bytes in the
112
+ // file stream. No message is available yet.
113
+ // Returns FIT_CONVERT_MESSAGE_AVAILABLE when a message is
114
+ // complete. The message is valid until this function is called
115
+ // again.
116
+ // Returns FIT_CONVERT_ERROR if a decoding error occurs.
117
+ // Returns FIT_CONVERT_END_OF_FILE when the file has been decoded successfully.
118
+ ///////////////////////////////////////////////////////////////////////
119
+
120
+ #if defined(FIT_CONVERT_MULTI_THREAD)
121
+ FIT_MESG_NUM FitConvert_GetMessageNumber(FIT_CONVERT_STATE *state);
122
+ #else
123
+ FIT_MESG_NUM FitConvert_GetMessageNumber(void);
124
+ #endif
125
+ ///////////////////////////////////////////////////////////////////////
126
+ // Returns the global message number of the decoded message.
127
+ ///////////////////////////////////////////////////////////////////////
128
+
129
+ #if defined(FIT_CONVERT_MULTI_THREAD)
130
+ const FIT_UINT8 *FitConvert_GetMessageData(FIT_CONVERT_STATE *state);
131
+ #else
132
+ const FIT_UINT8 *FitConvert_GetMessageData(void);
133
+ #endif
134
+ ///////////////////////////////////////////////////////////////////////
135
+ // Returns a pointer to the data of the decoded message.
136
+ // Copy or cast to FIT_*_MESG structure.
137
+ ///////////////////////////////////////////////////////////////////////
138
+
139
+ #if defined(FIT_CONVERT_MULTI_THREAD)
140
+ void FitConvert_RestoreFields(FIT_CONVERT_STATE *state, const void *mesg_data);
141
+ #else
142
+ void FitConvert_RestoreFields(const void *mesg_data);
143
+ #endif
144
+ ///////////////////////////////////////////////////////////////////////
145
+ // Restores fields that are not in decoded message from mesg_data.
146
+ // Use when modifying an existing file.
147
+ ///////////////////////////////////////////////////////////////////////
148
+
149
+ #if defined(__cplusplus)
150
+ }
151
+ #endif
152
+
153
+ #endif // !defined(FIT_CONVERT_H)
154
+
@@ -0,0 +1,43 @@
1
+ ////////////////////////////////////////////////////////////////////////////////
2
+ // The following .FIT software provided may be used with .FIT devices only and
3
+ // remains the copyrighted property of Dynastream Innovations Inc.
4
+ // The software is being provided on an "as-is" basis and as an accommodation,
5
+ // and therefore all warranties, representations, or guarantees of any kind
6
+ // (whether express, implied or statutory) including, without limitation,
7
+ // warranties of merchantability, non-infringement, or fitness for a particular
8
+ // purpose, are specifically disclaimed.
9
+ //
10
+ // Copyright 2008 Dynastream Innovations Inc.
11
+ // All rights reserved. This software may not be reproduced by any means
12
+ // without express written approval of Dynastream Innovations Inc.
13
+ ////////////////////////////////////////////////////////////////////////////////
14
+
15
+ #include "fit_crc.h"
16
+
17
+ //////////////////////////////////////////////////////////////////////////////////
18
+ // Public Functions
19
+ //////////////////////////////////////////////////////////////////////////////////
20
+
21
+ ///////////////////////////////////////////////////////////////////////
22
+ FIT_UINT16 FitCRC_Get16(FIT_UINT16 crc, FIT_UINT8 byte)
23
+ {
24
+ static const FIT_UINT16 crc_table[16] =
25
+ {
26
+ 0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401,
27
+ 0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400
28
+ };
29
+ FIT_UINT16 tmp;
30
+
31
+ // compute checksum of lower four bits of byte
32
+ tmp = crc_table[crc & 0xF];
33
+ crc = (crc >> 4) & 0x0FFF;
34
+ crc = crc ^ tmp ^ crc_table[byte & 0xF];
35
+
36
+ // now compute checksum of upper four bits of byte
37
+ tmp = crc_table[crc & 0xF];
38
+ crc = (crc >> 4) & 0x0FFF;
39
+ crc = crc ^ tmp ^ crc_table[(byte >> 4) & 0xF];
40
+
41
+ return crc;
42
+ }
43
+