1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
|
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "dive.h"
#include "gettext.h"
#include "divelist.h"
#include "libdivecomputer.h"
/*
* Returns a dc_descriptor_t structure based on dc model's number and family.
*/
static dc_descriptor_t *ostc_get_data_descriptor(int data_model, dc_family_t data_fam)
{
dc_descriptor_t *descriptor = NULL, *current = NULL;;
dc_iterator_t *iterator = NULL;
dc_status_t rc;
rc = dc_descriptor_iterator(&iterator);
if (rc != DC_STATUS_SUCCESS) {
fprintf(stderr,"Error creating the device descriptor iterator.\n");
return current;
}
while ((dc_iterator_next(iterator, &descriptor)) == DC_STATUS_SUCCESS) {
int desc_model = dc_descriptor_get_model(descriptor);
dc_family_t desc_fam = dc_descriptor_get_type(descriptor);
if (data_model == desc_model && data_fam == desc_fam) {
current = descriptor;
break;
}
dc_descriptor_free(descriptor);
}
dc_iterator_free(iterator);
return current;
}
/*
* Fills a device_data_t structure with known dc data and a descriptor.
*/
static int ostc_prepare_data(int data_model, dc_family_t dc_fam, device_data_t *dev_data)
{
device_data_t *ldc_dat = calloc(1, sizeof(device_data_t));
dc_descriptor_t *data_descriptor;
*ldc_dat = *dev_data;
ldc_dat->device = NULL;
ldc_dat->context = NULL;
data_descriptor = ostc_get_data_descriptor(data_model, dc_fam);
if (data_descriptor) {
ldc_dat->descriptor = data_descriptor;
ldc_dat->vendor = copy_string(data_descriptor->vendor);
ldc_dat->model = copy_string(data_descriptor->product);
*dev_data = *ldc_dat;
} else
return 0;
free(ldc_dat);
return 1;
}
/*
* OSTCTools stores the raw dive data in heavily padded files, one dive
* each file. So it's not necesary to iterate once and again on a parsing
* function. Actually there's only one kind of archive for every DC model.
*/
void ostctools_import(const char *file, struct dive_table *divetable)
{
FILE *archive;
device_data_t *devdata = calloc(1, sizeof(device_data_t));
dc_family_t dc_fam;
unsigned char *buffer = calloc(65536, 1), *uc_tmp;
char *tmp;
struct dive *ostcdive = alloc_dive();
dc_status_t rc = 0;
int model, ret, i = 0;
unsigned int serial;
struct extra_data *ptr;
// Open the archive
if ((archive = subsurface_fopen(file, "rb")) == NULL) {
report_error(translate("gettextFromC", "Failed to read '%s'"), file);
free(ostcdive);
goto out;
}
// Read dive number from the log
uc_tmp = calloc(2, 1);
fseek(archive, 258, 0);
fread(uc_tmp, 1, 2, archive);
ostcdive->number = uc_tmp[0] + (uc_tmp[1] << 8);
free(uc_tmp);
// Read device's serial number
uc_tmp = calloc(2, 1);
fseek(archive, 265, 0);
fread(uc_tmp, 1, 2, archive);
serial = uc_tmp[0] + (uc_tmp[1] << 8);
free(uc_tmp);
// Read dive's raw data, header + profile
fseek(archive, 456, 0);
while (!feof(archive)) {
fread(buffer+i, 1, 1, archive);
if (buffer[i] == 0xFD && buffer[i-1] == 0xFD)
break;
i++;
}
// Try to determine the dc family based on the header type
if (buffer[2] == 0x20 || buffer[2] == 0x21)
dc_fam = DC_FAMILY_HW_OSTC;
else {
switch (buffer[8]) {
case 0x22:
dc_fam = DC_FAMILY_HW_FROG;
break;
case 0x23:
dc_fam = DC_FAMILY_HW_OSTC3;
break;
default:
report_error(translate("gettextFromC", "Unknown DC in dive %d"), ostcdive->number);
free(ostcdive);
fclose(archive);
goto out;
}
}
// Try to determine the model based on serial number
switch (dc_fam) {
case DC_FAMILY_HW_OSTC:
if (serial > 7000)
model = 3; //2C
else if (serial > 2048)
model = 2; //2N
else if (serial > 300)
model = 1; //MK2
else
model = 0; //OSTC
break;
case DC_FAMILY_HW_FROG:
model = 0;
break;
default:
if (serial > 10000)
model = 0x12; //Sport
else
model = 0x0A; //OSTC3
}
// Prepare data to pass to libdivecomputer.
ret = ostc_prepare_data(model, dc_fam, devdata);
if (ret == 0){
report_error(translate("gettextFromC", "Unknown DC in dive %d"), ostcdive->number);
free(ostcdive);
fclose(archive);
goto out;
}
tmp = calloc(strlen(devdata->vendor)+strlen(devdata->model)+28,1);
sprintf(tmp, "%s %s (Imported from OSTCTools)", devdata->vendor, devdata->model);
ostcdive->dc.model = copy_string(tmp);
free(tmp);
// Parse the dive data
rc = libdc_buffer_parser(ostcdive, devdata, buffer, i+1);
if (rc != DC_STATUS_SUCCESS)
report_error(translate("gettextFromC","Error - %s - parsing dive %d"), errmsg(rc), ostcdive->number);
// Serial number is not part of the header nor the profile, so libdc won't
// catch it. If Serial is part of the extra_data, and set to zero, remove
// it from the list and add again.
tmp = calloc(12,1);
sprintf(tmp, "%d", serial);
ostcdive->dc.serial = copy_string(tmp);
free(tmp);
ptr = ostcdive->dc.extra_data;
while (strcmp(ptr->key, "Serial"))
ptr = ptr->next;
if (!strcmp(ptr->value, "0")) {
add_extra_data(&ostcdive->dc, "Serial", ostcdive->dc.serial);
*ptr = *(ptr)->next;
}
record_dive_to_table(ostcdive, divetable);
mark_divelist_changed(true);
sort_table(divetable);
fclose(archive);
out: free(devdata);
free(buffer);
}
|