rubyfit 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+