| 
									
										
										
										
											2017-04-27 20:24:53 +02:00
										 |  |  | // SPDX-License-Identifier: GPL-2.0
 | 
					
						
							| 
									
										
										
										
											2015-04-04 01:07:59 +02:00
										 |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "dive.h"
 | 
					
						
							|  |  |  | #include "gettext.h"
 | 
					
						
							|  |  |  | #include "divelist.h"
 | 
					
						
							|  |  |  | #include "libdivecomputer.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Fills a device_data_t structure with known dc data and a descriptor. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-07-12 20:29:06 +02:00
										 |  |  | static int ostc_prepare_data(int data_model, dc_family_t dc_fam, device_data_t *dev_data) | 
					
						
							| 
									
										
										
										
											2015-04-04 01:07:59 +02:00
										 |  |  | { | 
					
						
							|  |  |  | 	dc_descriptor_t *data_descriptor; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-10 00:06:48 +02:00
										 |  |  | 	dev_data->device = NULL; | 
					
						
							|  |  |  | 	dev_data->context = NULL; | 
					
						
							| 
									
										
										
										
											2015-04-04 01:07:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-29 16:03:26 +01:00
										 |  |  | 	data_descriptor = get_descriptor(dc_fam, data_model); | 
					
						
							| 
									
										
										
										
											2015-04-04 01:07:59 +02:00
										 |  |  | 	if (data_descriptor) { | 
					
						
							| 
									
										
										
										
											2015-09-10 00:06:48 +02:00
										 |  |  | 		dev_data->descriptor = data_descriptor; | 
					
						
							| 
									
										
										
										
											2016-12-29 15:41:44 +01:00
										 |  |  | 		dev_data->vendor = copy_string(dc_descriptor_get_vendor(data_descriptor)); | 
					
						
							|  |  |  | 		dev_data->model = copy_string(dc_descriptor_get_product(data_descriptor)); | 
					
						
							| 
									
										
										
										
											2015-09-09 17:26:54 -07:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2015-07-12 20:29:06 +02:00
										 |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2015-09-09 17:26:54 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-07-12 20:29:06 +02:00
										 |  |  | 	return 1; | 
					
						
							| 
									
										
										
										
											2015-04-04 01:07:59 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * OSTCTools stores the raw dive data in heavily padded files, one dive | 
					
						
							| 
									
										
										
										
											2015-11-15 10:15:40 -08:00
										 |  |  |  * each file. So it's not necessary to iterate once and again on a parsing | 
					
						
							| 
									
										
										
										
											2015-04-04 01:07:59 +02:00
										 |  |  |  * 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; | 
					
						
							| 
									
										
										
										
											2015-07-06 22:02:03 +02:00
										 |  |  | 	unsigned char *buffer = calloc(65536, 1), *uc_tmp; | 
					
						
							| 
									
										
										
										
											2015-05-28 14:59:08 +02:00
										 |  |  | 	char *tmp; | 
					
						
							| 
									
										
										
										
											2015-04-04 01:07:59 +02:00
										 |  |  | 	struct dive *ostcdive = alloc_dive(); | 
					
						
							|  |  |  | 	dc_status_t rc = 0; | 
					
						
							| 
									
										
										
										
											2015-07-12 20:29:06 +02:00
										 |  |  | 	int model, ret, i = 0; | 
					
						
							| 
									
										
										
										
											2015-04-04 01:07:59 +02:00
										 |  |  | 	unsigned int serial; | 
					
						
							|  |  |  | 	struct extra_data *ptr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Open the archive
 | 
					
						
							|  |  |  | 	if ((archive = subsurface_fopen(file, "rb")) == NULL) { | 
					
						
							| 
									
										
										
										
											2015-07-12 20:29:06 +02:00
										 |  |  | 		report_error(translate("gettextFromC", "Failed to read '%s'"), file); | 
					
						
							| 
									
										
										
										
											2015-04-21 14:00:17 -03:00
										 |  |  | 		free(ostcdive); | 
					
						
							| 
									
										
										
										
											2015-07-12 20:29:06 +02:00
										 |  |  | 		goto out; | 
					
						
							| 
									
										
										
										
											2015-04-04 01:07:59 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Read dive number from the log
 | 
					
						
							| 
									
										
										
										
											2015-09-09 17:26:54 -07:00
										 |  |  | 	uc_tmp = calloc(2, 1); | 
					
						
							| 
									
										
										
										
											2015-04-04 01:07:59 +02:00
										 |  |  | 	fseek(archive, 258, 0); | 
					
						
							| 
									
										
										
										
											2015-07-06 22:02:03 +02:00
										 |  |  | 	fread(uc_tmp, 1, 2, archive); | 
					
						
							|  |  |  | 	ostcdive->number = uc_tmp[0] + (uc_tmp[1] << 8); | 
					
						
							|  |  |  | 	free(uc_tmp); | 
					
						
							| 
									
										
										
										
											2015-04-04 01:07:59 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Read device's serial number
 | 
					
						
							| 
									
										
										
										
											2015-07-06 22:02:03 +02:00
										 |  |  | 	uc_tmp = calloc(2, 1); | 
					
						
							| 
									
										
										
										
											2015-04-04 01:07:59 +02:00
										 |  |  | 	fseek(archive, 265, 0); | 
					
						
							| 
									
										
										
										
											2015-07-06 22:02:03 +02:00
										 |  |  | 	fread(uc_tmp, 1, 2, archive); | 
					
						
							|  |  |  | 	serial = uc_tmp[0] + (uc_tmp[1] << 8); | 
					
						
							|  |  |  | 	free(uc_tmp); | 
					
						
							| 
									
										
										
										
											2015-04-04 01:07:59 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Read dive's raw data, header + profile
 | 
					
						
							|  |  |  | 	fseek(archive, 456, 0); | 
					
						
							|  |  |  | 	while (!feof(archive)) { | 
					
						
							| 
									
										
										
										
											2015-09-09 17:26:54 -07:00
										 |  |  | 		fread(buffer + i, 1, 1, archive); | 
					
						
							|  |  |  | 		if (buffer[i] == 0xFD && buffer[i - 1] == 0xFD) | 
					
						
							| 
									
										
										
										
											2015-04-04 01:07:59 +02:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 		i++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Try to determine the dc family based on the header type
 | 
					
						
							| 
									
										
										
										
											2015-09-09 17:26:54 -07:00
										 |  |  | 	if (buffer[2] == 0x20 || buffer[2] == 0x21) { | 
					
						
							| 
									
										
										
										
											2015-06-21 21:58:10 -07:00
										 |  |  | 		dc_fam = DC_FAMILY_HW_OSTC; | 
					
						
							| 
									
										
										
										
											2015-09-09 17:26:54 -07:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2015-07-12 20:30:06 +02:00
										 |  |  | 		switch (buffer[8]) { | 
					
						
							| 
									
										
										
										
											2015-09-09 17:26:54 -07:00
										 |  |  | 		case 0x22: | 
					
						
							|  |  |  | 			dc_fam = DC_FAMILY_HW_FROG; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case 0x23: | 
					
						
							| 
									
										
										
										
											2016-12-29 16:05:05 +01:00
										 |  |  | 		case 0x24: | 
					
						
							| 
									
										
										
										
											2015-09-09 17:26:54 -07:00
										 |  |  | 			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; | 
					
						
							| 
									
										
										
										
											2015-07-12 20:30:06 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Try to determine the model based on serial number
 | 
					
						
							|  |  |  | 	switch (dc_fam) { | 
					
						
							| 
									
										
										
										
											2015-09-09 17:26:54 -07:00
										 |  |  | 	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
 | 
					
						
							| 
									
										
										
										
											2015-04-04 01:07:59 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-12 20:29:06 +02:00
										 |  |  | 	// Prepare data to pass to libdivecomputer.
 | 
					
						
							|  |  |  | 	ret = ostc_prepare_data(model, dc_fam, devdata); | 
					
						
							| 
									
										
										
										
											2015-09-09 17:26:54 -07:00
										 |  |  | 	if (ret == 0) { | 
					
						
							| 
									
										
										
										
											2015-07-12 20:29:06 +02:00
										 |  |  | 		report_error(translate("gettextFromC", "Unknown DC in dive %d"), ostcdive->number); | 
					
						
							|  |  |  | 		free(ostcdive); | 
					
						
							|  |  |  | 		fclose(archive); | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-09-09 17:26:54 -07:00
										 |  |  | 	tmp = calloc(strlen(devdata->vendor) + strlen(devdata->model) + 28, 1); | 
					
						
							| 
									
										
										
										
											2015-05-28 14:59:08 +02:00
										 |  |  | 	sprintf(tmp, "%s %s (Imported from OSTCTools)", devdata->vendor, devdata->model); | 
					
						
							| 
									
										
										
										
											2015-09-09 17:26:54 -07:00
										 |  |  | 	ostcdive->dc.model = copy_string(tmp); | 
					
						
							| 
									
										
										
										
											2015-04-04 01:07:59 +02:00
										 |  |  | 	free(tmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Parse the dive data
 | 
					
						
							| 
									
										
										
										
											2015-09-09 17:26:54 -07:00
										 |  |  | 	rc = libdc_buffer_parser(ostcdive, devdata, buffer, i + 1); | 
					
						
							| 
									
										
										
										
											2015-04-04 01:07:59 +02:00
										 |  |  | 	if (rc != DC_STATUS_SUCCESS) | 
					
						
							| 
									
										
										
										
											2015-09-09 17:26:54 -07:00
										 |  |  | 		report_error(translate("gettextFromC", "Error - %s - parsing dive %d"), errmsg(rc), ostcdive->number); | 
					
						
							| 
									
										
										
										
											2015-04-04 01:07:59 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// 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.
 | 
					
						
							| 
									
										
										
										
											2015-09-09 17:26:54 -07:00
										 |  |  | 	tmp = calloc(12, 1); | 
					
						
							| 
									
										
										
										
											2015-04-04 01:07:59 +02:00
										 |  |  | 	sprintf(tmp, "%d", serial); | 
					
						
							|  |  |  | 	ostcdive->dc.serial = copy_string(tmp); | 
					
						
							|  |  |  | 	free(tmp); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-13 21:27:33 +02:00
										 |  |  | 	if (ostcdive->dc.extra_data) { | 
					
						
							|  |  |  | 		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; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-09-09 17:26:54 -07:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2015-04-04 01:07:59 +02:00
										 |  |  | 		add_extra_data(&ostcdive->dc, "Serial", ostcdive->dc.serial); | 
					
						
							| 
									
										
										
										
											2015-09-09 17:26:54 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-04-04 01:07:59 +02:00
										 |  |  | 	record_dive_to_table(ostcdive, divetable); | 
					
						
							|  |  |  | 	mark_divelist_changed(true); | 
					
						
							|  |  |  | 	sort_table(divetable); | 
					
						
							|  |  |  | 	fclose(archive); | 
					
						
							| 
									
										
										
										
											2015-09-09 17:26:54 -07:00
										 |  |  | out: | 
					
						
							|  |  |  | 	free(devdata); | 
					
						
							| 
									
										
										
										
											2015-07-12 20:29:06 +02:00
										 |  |  | 	free(buffer); | 
					
						
							| 
									
										
										
										
											2015-04-04 01:07:59 +02:00
										 |  |  | } |