2012-09-25 14:28:47 +00:00
/*
* uemis - downloader . c
*
* Copyright ( c ) Dirk Hohndel < dirk @ hohndel . org >
* released under GPL2
*
* very ( VERY ) loosely based on the algorithms found in Java code by Fabian Gast < fgast @ only640k . net >
* which was released under the BSD - STYLE BEER WARE LICENSE
* I believe that I only used the information about HOW to do this ( download data from the Uemis
* Zurich ) but did not actually use any of his copyrighted code , therefore the license under which
* he released his code does not apply to this new implementation in C
*/
# include <fcntl.h>
2013-10-05 07:29:09 +00:00
# include <dirent.h>
2012-09-25 14:28:47 +00:00
# include <stdio.h>
# include <unistd.h>
# include <string.h>
2012-10-11 00:42:59 +00:00
2013-10-07 23:13:13 +00:00
# include "gettext.h"
2013-06-24 22:14:07 +00:00
# include "libdivecomputer.h"
2012-09-25 14:28:47 +00:00
# include "uemis.h"
# include "divelist.h"
2013-10-07 23:13:13 +00:00
2014-02-28 04:09:57 +00:00
# define ERR_FS_ALMOST_FULL QT_TRANSLATE_NOOP("gettextFromC", "Uemis Zurich: File System is almost full\nDisconnect / reconnect the dive computer\nand click \'Retry\'")
# define ERR_FS_FULL QT_TRANSLATE_NOOP("gettextFromC", "Uemis Zurich: File System is full\nDisconnect / reconnect the dive computer\nand try again")
# define ERR_FS_SHORT_WRITE QT_TRANSLATE_NOOP("gettextFromC", "Short write to req.txt file\nIs the Uemis Zurich plugged in correctly?")
2012-09-25 14:28:47 +00:00
# define BUFLEN 2048
2012-10-26 03:15:39 +00:00
# define NUM_PARAM_BUFS 10
2012-12-05 05:03:56 +00:00
2014-02-28 04:09:57 +00:00
# if UEMIS_DEBUG & 64 /* we are reading from a copy of the filesystem, not the device - no need to wait */
# define UEMIS_TIMEOUT 50 /* 50ns */
# define UEMIS_LONG_TIMEOUT 500 /* 500ns */
# define UEMIS_MAX_TIMEOUT 2000 /* 2ms */
2012-12-05 05:03:56 +00:00
# else
2014-02-28 04:09:57 +00:00
# define UEMIS_TIMEOUT 50000 /* 50ms */
# define UEMIS_LONG_TIMEOUT 500000 /* 500ms */
# define UEMIS_MAX_TIMEOUT 2000000 /* 2s */
2012-12-05 05:03:56 +00:00
# endif
2012-11-19 22:09:21 +00:00
2014-05-01 21:14:50 +00:00
# ifdef UEMIS_DEBUG
# define debugfile stderr
# endif
2012-09-25 14:28:47 +00:00
static char * param_buff [ NUM_PARAM_BUFS ] ;
static char * reqtxt_path ;
static int reqtxt_file ;
static int filenr ;
static int number_of_files ;
static char * mbuf = NULL ;
static int mbuf_size = 0 ;
2014-05-05 21:36:55 +00:00
static int nr_divespots = - 1 ;
2012-11-29 00:11:19 +00:00
/* helper function to parse the Uemis data structures */
static void uemis_ts ( char * buffer , void * _when )
{
struct tm tm ;
timestamp_t * when = _when ;
memset ( & tm , 0 , sizeof ( tm ) ) ;
2014-02-28 04:09:57 +00:00
sscanf ( buffer , " %d-%d-%dT%d:%d:%d " ,
& tm . tm_year , & tm . tm_mon , & tm . tm_mday ,
& tm . tm_hour , & tm . tm_min , & tm . tm_sec ) ;
tm . tm_mon - = 1 ;
2012-11-29 00:11:19 +00:00
tm . tm_year - = 1900 ;
* when = utc_mktime ( & tm ) ;
}
/* float minutes */
static void uemis_duration ( char * buffer , duration_t * duration )
{
2014-02-12 22:19:53 +00:00
duration - > seconds = rint ( ascii_strtod ( buffer , NULL ) * 60 ) ;
2012-11-29 00:11:19 +00:00
}
/* int cm */
static void uemis_depth ( char * buffer , depth_t * depth )
{
depth - > mm = atoi ( buffer ) * 10 ;
}
static void uemis_get_index ( char * buffer , int * idx )
{
* idx = atoi ( buffer ) ;
}
/* space separated */
2013-10-06 15:55:58 +00:00
static void uemis_add_string ( const char * buffer , char * * text )
2012-11-29 00:11:19 +00:00
{
2012-12-29 02:30:02 +00:00
/* do nothing if this is an empty buffer (Uemis sometimes returns a single
* space for empty buffers ) */
if ( ! buffer | | ! * buffer | | ( * buffer = = ' ' & & * ( buffer + 1 ) = = ' \0 ' ) )
2012-11-29 00:11:19 +00:00
return ;
if ( ! * text ) {
* text = strdup ( buffer ) ;
} else {
char * buf = malloc ( strlen ( buffer ) + strlen ( * text ) + 2 ) ;
strcpy ( buf , * text ) ;
strcat ( buf , " " ) ;
strcat ( buf , buffer ) ;
free ( * text ) ;
* text = buf ;
}
}
/* still unclear if it ever reports lbs */
static void uemis_get_weight ( char * buffer , weightsystem_t * weight , int diveid )
{
weight - > weight . grams = uemis_get_weight_unit ( diveid ) ?
2014-02-28 04:09:57 +00:00
lbs_to_grams ( ascii_strtod ( buffer , NULL ) ) :
ascii_strtod ( buffer , NULL ) * 1000 ;
weight - > description = strdup ( translate ( " gettextFromC " , " unknown " ) ) ;
2012-11-29 00:11:19 +00:00
}
2013-01-18 20:56:54 +00:00
static struct dive * uemis_start_dive ( uint32_t deviceid )
2012-11-29 00:11:19 +00:00
{
struct dive * dive = alloc_dive ( ) ;
2014-01-15 18:54:41 +00:00
dive - > downloaded = true ;
2012-11-29 00:11:19 +00:00
dive - > dc . model = strdup ( " Uemis Zurich " ) ;
dive - > dc . deviceid = deviceid ;
return dive ;
}
2014-10-12 11:11:34 +00:00
static void record_uemis_dive ( device_data_t * devdata , struct dive * dive )
{
if ( devdata - > create_new_trip ) {
if ( ! devdata - > trip )
devdata - > trip = create_and_hookup_trip_from_dive ( dive ) ;
else
add_dive_to_trip ( dive , devdata - > trip ) ;
}
record_dive ( dive ) ;
}
2012-09-25 14:28:47 +00:00
/* send text to the importer progress bar */
static void uemis_info ( const char * fmt , . . . )
{
2013-03-04 01:53:43 +00:00
static char buffer [ 256 ] ;
2012-09-25 14:28:47 +00:00
va_list ap ;
va_start ( ap , fmt ) ;
vsnprintf ( buffer , sizeof ( buffer ) , fmt , ap ) ;
va_end ( ap ) ;
progress_bar_text = buffer ;
}
static long bytes_available ( int file )
{
long result ;
long now = lseek ( file , 0 , SEEK_CUR ) ;
result = lseek ( file , 0 , SEEK_END ) ;
lseek ( file , now , SEEK_SET ) ;
2014-03-06 02:27:33 +00:00
if ( now = = - 1 | | result = = - 1 )
return 0 ;
2012-09-25 14:28:47 +00:00
return result ;
}
static int number_of_file ( char * path )
{
int count = 0 ;
2013-12-19 13:00:56 +00:00
# ifdef WIN32
struct _wdirent * entry ;
_WDIR * dirp = ( _WDIR * ) subsurface_opendir ( path ) ;
# else
struct dirent * entry ;
DIR * dirp = ( DIR * ) subsurface_opendir ( path ) ;
# endif
2013-10-05 07:29:09 +00:00
2013-12-19 13:00:56 +00:00
while ( dirp ) {
# ifdef WIN32
entry = _wreaddir ( dirp ) ;
if ( ! entry )
break ;
# else
entry = readdir ( dirp ) ;
if ( ! entry )
break ;
2013-10-07 04:04:25 +00:00
if ( entry - > d_type = = DT_REG ) /* If the entry is a regular file */
# endif
2014-02-28 04:09:57 +00:00
count + + ;
2013-10-05 07:29:09 +00:00
}
2013-12-19 13:00:56 +00:00
# ifdef WIN32
_wclosedir ( dirp ) ;
# else
2013-10-05 07:29:09 +00:00
closedir ( dirp ) ;
2013-12-19 13:00:56 +00:00
# endif
2012-09-25 14:28:47 +00:00
return count ;
}
2013-10-05 07:29:09 +00:00
static char * build_filename ( const char * path , const char * name )
{
2013-11-07 04:06:06 +00:00
int len = strlen ( path ) + strlen ( name ) + 2 ;
2013-10-05 07:29:09 +00:00
char * buf = malloc ( len ) ;
# if WIN32
2014-05-07 18:15:39 +00:00
snprintf ( buf , len , " %s \\ %s " , path , name ) ;
2013-10-05 07:29:09 +00:00
# else
snprintf ( buf , len , " %s/%s " , path , name ) ;
# endif
return buf ;
}
2012-09-25 14:28:47 +00:00
/* Check if there's a req.txt file and get the starting filenr from it.
* Test for the maximum number of ANS files ( I believe this is always
* 4000 but in case there are differences depending on firmware , this
* code is easy enough */
2013-10-05 07:29:09 +00:00
static bool uemis_init ( const char * path )
2012-09-25 14:28:47 +00:00
{
char * ans_path ;
int i ;
if ( ! path )
2014-01-15 18:54:41 +00:00
return false ;
2012-09-25 14:28:47 +00:00
/* let's check if this is indeed a Uemis DC */
2014-02-28 04:09:57 +00:00
reqtxt_path = build_filename ( path , " req.txt " ) ;
2013-12-19 13:00:51 +00:00
reqtxt_file = subsurface_open ( reqtxt_path , O_RDONLY , 0666 ) ;
2012-11-19 22:08:14 +00:00
if ( ! reqtxt_file ) {
2012-12-05 05:03:56 +00:00
# if UEMIS_DEBUG & 1
2012-11-19 22:08:14 +00:00
fprintf ( debugfile , " :EE req.txt can't be opened \n " ) ;
# endif
2014-01-15 18:54:41 +00:00
return false ;
2012-11-19 22:08:14 +00:00
}
2012-09-25 14:28:47 +00:00
if ( bytes_available ( reqtxt_file ) > 5 ) {
char tmp [ 6 ] ;
read ( reqtxt_file , tmp , 5 ) ;
tmp [ 5 ] = ' \0 ' ;
2012-12-05 05:03:56 +00:00
# if UEMIS_DEBUG & 2
2012-09-25 14:28:47 +00:00
fprintf ( debugfile , " ::r req.txt \" %s \" \n " , tmp ) ;
# endif
if ( sscanf ( tmp + 1 , " %d " , & filenr ) ! = 1 )
2014-01-15 18:54:41 +00:00
return false ;
2013-01-29 21:10:46 +00:00
} else {
2012-11-19 23:09:50 +00:00
filenr = 0 ;
2012-12-05 05:03:56 +00:00
# if UEMIS_DEBUG & 2
2012-09-25 14:28:47 +00:00
fprintf ( debugfile , " ::r req.txt skipped as there were fewer than 5 bytes \n " ) ;
# endif
2012-11-19 23:09:50 +00:00
}
2014-02-28 04:09:57 +00:00
close ( reqtxt_file ) ;
2012-09-25 14:28:47 +00:00
/* It would be nice if we could simply go back to the first set of
2012-11-29 00:11:19 +00:00
* ANS files . But with a FAT filesystem that isn ' t possible */
2013-10-05 07:29:09 +00:00
ans_path = build_filename ( path , " ANS " ) ;
2012-09-25 14:28:47 +00:00
number_of_files = number_of_file ( ans_path ) ;
2013-10-05 07:29:09 +00:00
free ( ans_path ) ;
2012-09-25 14:28:47 +00:00
/* initialize the array in which we collect the answers */
for ( i = 0 ; i < NUM_PARAM_BUFS ; i + + )
param_buff [ i ] = " " ;
2014-01-15 18:54:41 +00:00
return true ;
2012-09-25 14:28:47 +00:00
}
static void str_append_with_delim ( char * s , char * t )
{
int len = strlen ( s ) ;
snprintf ( s + len , BUFLEN - len , " %s{ " , t ) ;
}
/* The communication protocoll with the DC is truly funky.
* After you write your request to the req . txt file you call this function .
* It writes the number of the next ANS file at the beginning of the req . txt
* file ( prefixed by ' n ' or ' r ' ) and then again at the very end of it , after
* the full request ( this time without the prefix ) .
* Then it syncs ( not needed on Windows ) and closes the file . */
static void trigger_response ( int file , char * command , int nr , long tailpos )
{
char fl [ 10 ] ;
snprintf ( fl , 8 , " %s%04d " , command , nr ) ;
2012-12-05 05:03:56 +00:00
# if UEMIS_DEBUG & 4
2014-02-28 04:09:57 +00:00
fprintf ( debugfile , " :tr %s (after seeks) \n " , fl ) ;
2012-09-25 14:28:47 +00:00
# endif
2014-03-06 02:27:33 +00:00
if ( lseek ( file , 0 , SEEK_SET ) = = - 1 )
goto fs_error ;
if ( write ( file , fl , strlen ( fl ) ) = = - 1 )
goto fs_error ;
if ( lseek ( file , tailpos , SEEK_SET ) = = - 1 )
goto fs_error ;
if ( write ( file , fl + 1 , strlen ( fl + 1 ) ) = = - 1 )
goto fs_error ;
2012-09-25 14:28:47 +00:00
# ifndef WIN32
fsync ( file ) ;
# endif
2014-03-06 02:27:33 +00:00
fs_error :
2012-09-25 14:28:47 +00:00
close ( file ) ;
}
static char * next_token ( char * * buf )
{
char * q , * p = strchr ( * buf , ' { ' ) ;
2012-09-27 03:37:57 +00:00
if ( p )
* p = ' \0 ' ;
else
p = * buf + strlen ( * buf ) - 1 ;
2012-09-25 14:28:47 +00:00
q = * buf ;
* buf = p + 1 ;
return q ;
}
/* poor man's tokenizer that understands a quoted delimter ('{') */
static char * next_segment ( char * buf , int * offset , int size )
{
int i = * offset ;
int seg_size ;
2014-01-15 18:54:41 +00:00
bool done = false ;
2012-09-25 14:28:47 +00:00
char * segment ;
while ( ! done ) {
if ( i < size ) {
2013-12-11 13:26:49 +00:00
if ( i < size - 1 & & buf [ i ] = = ' \\ ' & &
2014-02-28 04:09:57 +00:00
( buf [ i + 1 ] = = ' \\ ' | | buf [ i + 1 ] = = ' { ' ) )
2012-09-25 14:28:47 +00:00
memcpy ( buf + i , buf + i + 1 , size - i - 1 ) ;
else if ( buf [ i ] = = ' { ' )
2014-01-15 18:54:41 +00:00
done = true ;
2012-09-25 14:28:47 +00:00
i + + ;
} else {
2014-01-15 18:54:41 +00:00
done = true ;
2012-09-25 14:28:47 +00:00
}
}
seg_size = i - * offset - 1 ;
if ( seg_size < 0 )
seg_size = 0 ;
segment = malloc ( seg_size + 1 ) ;
memcpy ( segment , buf + * offset , seg_size ) ;
segment [ seg_size ] = ' \0 ' ;
* offset = i ;
return segment ;
}
/* a dynamically growing buffer to store the potentially massive responses.
* The binary data block can be more than 100 k in size ( base64 encoded ) */
2012-09-27 07:16:42 +00:00
static void buffer_add ( char * * buffer , int * buffer_size , char * buf )
2012-09-25 14:28:47 +00:00
{
2012-10-26 03:15:39 +00:00
if ( ! buf )
return ;
2014-02-28 04:09:57 +00:00
if ( ! * buffer ) {
2012-10-26 03:15:39 +00:00
* buffer = strdup ( buf ) ;
* buffer_size = strlen ( * buffer ) + 1 ;
} else {
* buffer_size + = strlen ( buf ) ;
* buffer = realloc ( * buffer , * buffer_size ) ;
strcat ( * buffer , buf ) ;
}
2012-12-05 05:03:56 +00:00
# if UEMIS_DEBUG & 16
2014-02-28 04:09:57 +00:00
fprintf ( debugfile , " added \" %s \" to buffer - new length %d \n " , buf , * buffer_size ) ;
2012-09-25 14:28:47 +00:00
# endif
2012-10-26 03:15:39 +00:00
}
2012-09-25 14:28:47 +00:00
/* are there more ANS files we can check? */
2013-10-05 07:29:09 +00:00
static bool next_file ( int max )
2012-09-25 14:28:47 +00:00
{
if ( filenr > = max )
2014-01-15 18:54:41 +00:00
return false ;
2012-09-25 14:28:47 +00:00
filenr + + ;
2014-01-15 18:54:41 +00:00
return true ;
2012-09-25 14:28:47 +00:00
}
2014-08-17 21:44:43 +00:00
/* try and do a quick decode - without trying to get to fancy in case the data
* straddles a block boundary . . .
* we are parsing something that looks like this :
* object_id { int { 2 { date { ts { 2011 - 04 - 05 T12 : 38 : 04 { duration { float { 12.000 . . .
*/
2014-02-28 04:09:57 +00:00
static char * first_object_id_val ( char * buf )
2012-09-25 14:28:47 +00:00
{
2012-12-05 21:43:36 +00:00
char * object , * bufend ;
2012-12-05 20:32:16 +00:00
if ( ! buf )
return NULL ;
2012-12-05 21:43:36 +00:00
bufend = buf + strlen ( buf ) ;
2012-09-25 14:28:47 +00:00
object = strstr ( buf , " object_id " ) ;
2012-12-08 04:02:14 +00:00
if ( object & & object + 14 < bufend ) {
2012-12-05 20:32:16 +00:00
/* get the value */
2014-08-17 21:44:43 +00:00
char tmp [ 36 ] ;
2012-09-25 14:28:47 +00:00
char * p = object + 14 ;
char * t = tmp ;
2012-12-05 21:43:36 +00:00
# if UEMIS_DEBUG & 2
char debugbuf [ 50 ] ;
strncpy ( debugbuf , object , 49 ) ;
debugbuf [ 49 ] = ' \0 ' ;
fprintf ( debugfile , " buf |%s| \n " , debugbuf ) ;
# endif
while ( p < bufend & & * p ! = ' { ' & & t < tmp + 9 )
* t + + = * p + + ;
if ( * p = = ' { ' ) {
2014-08-17 21:44:43 +00:00
/* found the object_id - let's quickly look for the date */
if ( strncmp ( p , " {date{ts{ " , 9 ) = = 0 & & strstr ( p , " {duration{ " ) ! = NULL ) {
/* cool - that was easy */
* t + + = ' , ' ;
* t + + = ' ' ;
/* skip the 9 characters we just found and take the date, ignoring the seconds
* and replace the silly ' T ' in the middle with a space */
strncpy ( t , p + 9 , 16 ) ;
if ( * ( t + 10 ) = = ' T ' )
* ( t + 10 ) = ' ' ;
t + = 16 ;
}
2012-09-25 14:28:47 +00:00
* t = ' \0 ' ;
2012-12-05 21:43:36 +00:00
return strdup ( tmp ) ;
2012-09-25 14:28:47 +00:00
}
2012-12-05 20:32:16 +00:00
}
return NULL ;
}
/* ultra-simplistic; it doesn't deal with the case when the object_id is
* split across two chunks . It also doesn ' t deal with the discrepancy between
* object_id and dive number as understood by the dive computer */
2013-10-06 15:55:58 +00:00
static void show_progress ( char * buf , const char * what )
2012-12-05 20:32:16 +00:00
{
char * val = first_object_id_val ( buf ) ;
if ( val ) {
2014-02-28 04:09:57 +00:00
/* let the user know what we are working on */
2012-12-05 21:43:36 +00:00
# if UEMIS_DEBUG & 2
2014-08-17 21:44:43 +00:00
fprintf ( stderr , " reading %s %s %s \n " , what , val , buf ) ;
2012-12-05 21:43:36 +00:00
# endif
2014-08-17 21:44:43 +00:00
uemis_info ( translate ( " gettextFromC " , " %s %s " ) , what , val ) ;
2012-12-05 20:32:16 +00:00
free ( val ) ;
2012-09-25 14:28:47 +00:00
}
}
2012-11-19 22:09:21 +00:00
static void uemis_increased_timeout ( int * timeout )
{
if ( * timeout < UEMIS_MAX_TIMEOUT )
* timeout + = UEMIS_LONG_TIMEOUT ;
usleep ( * timeout ) ;
}
2012-09-25 14:28:47 +00:00
/* send a request to the dive computer and collect the answer */
2013-10-05 07:29:09 +00:00
static bool uemis_get_answer ( const char * path , char * request , int n_param_in ,
2014-02-28 04:09:57 +00:00
int n_param_out , const char * * error_text )
2012-09-25 14:28:47 +00:00
{
int i = 0 , file_length ;
char sb [ BUFLEN ] ;
char fl [ 13 ] ;
2012-09-27 07:16:42 +00:00
char tmp [ 101 ] ;
2014-02-28 04:09:57 +00:00
const char * what = translate ( " gettextFromC " , " data " ) ;
2014-01-15 18:54:41 +00:00
bool searching = true ;
bool assembling_mbuf = false ;
bool ismulti = false ;
bool found_answer = false ;
bool more_files = true ;
bool answer_in_mbuf = false ;
2012-09-25 14:28:47 +00:00
char * ans_path ;
int ans_file ;
2012-11-19 22:09:21 +00:00
int timeout = UEMIS_LONG_TIMEOUT ;
2012-09-25 14:28:47 +00:00
2013-12-19 13:00:51 +00:00
reqtxt_file = subsurface_open ( reqtxt_path , O_RDWR | O_CREAT , 0666 ) ;
2012-09-25 14:28:47 +00:00
snprintf ( sb , BUFLEN , " n%04d12345678 " , filenr ) ;
str_append_with_delim ( sb , request ) ;
for ( i = 0 ; i < n_param_in ; i + + )
str_append_with_delim ( sb , param_buff [ i ] ) ;
2014-02-28 04:09:57 +00:00
if ( ! strcmp ( request , " getDivelogs " ) | | ! strcmp ( request , " getDeviceData " ) | | ! strcmp ( request , " getDirectory " ) | |
! strcmp ( request , " getDivespot " ) | | ! strcmp ( request , " getDive " ) ) {
2014-01-15 18:54:41 +00:00
answer_in_mbuf = true ;
2012-09-25 14:28:47 +00:00
str_append_with_delim ( sb , " " ) ;
2014-02-28 04:09:57 +00:00
if ( ! strcmp ( request , " getDivelogs " ) )
2014-08-17 21:44:43 +00:00
what = translate ( " gettextFromC " , " divelog # " ) ;
2012-11-29 00:11:19 +00:00
else if ( ! strcmp ( request , " getDivespot " ) )
2014-08-17 21:44:43 +00:00
what = translate ( " gettextFromC " , " divespot # " ) ;
2012-11-29 00:11:19 +00:00
else if ( ! strcmp ( request , " getDive " ) )
2014-08-17 21:44:43 +00:00
what = translate ( " gettextFromC " , " details for # " ) ;
2012-09-25 14:28:47 +00:00
}
str_append_with_delim ( sb , " " ) ;
file_length = strlen ( sb ) ;
snprintf ( fl , 10 , " %08d " , file_length - 13 ) ;
memcpy ( sb + 5 , fl , strlen ( fl ) ) ;
2012-12-05 05:03:56 +00:00
# if UEMIS_DEBUG & 1
2014-02-28 04:09:57 +00:00
fprintf ( debugfile , " ::w req.txt \" %s \" \n " , sb ) ;
2012-09-25 14:28:47 +00:00
# endif
if ( write ( reqtxt_file , sb , strlen ( sb ) ) ! = strlen ( sb ) ) {
2014-02-28 04:09:57 +00:00
* error_text = translate ( " gettextFromC " , ERR_FS_SHORT_WRITE ) ;
2014-01-15 18:54:41 +00:00
return false ;
2012-09-25 14:28:47 +00:00
}
2014-02-28 04:09:57 +00:00
if ( ! next_file ( number_of_files ) ) {
* error_text = translate ( " gettextFromC " , ERR_FS_FULL ) ;
2014-01-15 18:54:41 +00:00
more_files = false ;
2012-09-25 14:28:47 +00:00
}
trigger_response ( reqtxt_file , " n " , filenr , file_length ) ;
2012-11-19 22:09:21 +00:00
usleep ( timeout ) ;
2012-09-25 14:28:47 +00:00
mbuf = NULL ;
mbuf_size = 0 ;
while ( searching | | assembling_mbuf ) {
2012-11-19 22:11:08 +00:00
if ( import_thread_cancelled )
2014-01-15 18:54:41 +00:00
return false ;
2012-09-25 14:28:47 +00:00
progress_bar_fraction = filenr / 4000.0 ;
snprintf ( fl , 13 , " ANS%d.TXT " , filenr - 1 ) ;
2013-10-05 07:29:09 +00:00
ans_path = build_filename ( build_filename ( path , " ANS " ) , fl ) ;
2013-12-19 13:00:51 +00:00
ans_file = subsurface_open ( ans_path , O_RDONLY , 0666 ) ;
2012-09-25 14:28:47 +00:00
read ( ans_file , tmp , 100 ) ;
close ( ans_file ) ;
2012-12-05 05:03:56 +00:00
# if UEMIS_DEBUG & 8
2014-02-28 04:09:57 +00:00
tmp [ 100 ] = ' \0 ' ;
2012-09-25 14:28:47 +00:00
fprintf ( debugfile , " ::t %s \" %s \" \n " , ans_path , tmp ) ;
2012-12-05 20:32:16 +00:00
# elif UEMIS_DEBUG & 4
2012-11-19 22:08:14 +00:00
char pbuf [ 4 ] ;
pbuf [ 0 ] = tmp [ 0 ] ;
pbuf [ 1 ] = tmp [ 1 ] ;
pbuf [ 2 ] = tmp [ 2 ] ;
pbuf [ 3 ] = 0 ;
fprintf ( debugfile , " ::t %s \" %s... \" \n " , ans_path , pbuf ) ;
2012-09-25 14:28:47 +00:00
# endif
2013-10-05 07:29:09 +00:00
free ( ans_path ) ;
2012-09-25 14:28:47 +00:00
if ( tmp [ 0 ] = = ' 1 ' ) {
2014-01-15 18:54:41 +00:00
searching = false ;
2012-09-25 14:28:47 +00:00
if ( tmp [ 1 ] = = ' m ' ) {
2014-01-15 18:54:41 +00:00
assembling_mbuf = true ;
ismulti = true ;
2012-09-25 14:28:47 +00:00
}
if ( tmp [ 2 ] = = ' e ' )
2014-01-15 18:54:41 +00:00
assembling_mbuf = false ;
2012-09-25 14:28:47 +00:00
if ( assembling_mbuf ) {
2014-02-28 04:09:57 +00:00
if ( ! next_file ( number_of_files ) ) {
* error_text = translate ( " gettextFromC " , ERR_FS_FULL ) ;
2014-01-15 18:54:41 +00:00
more_files = false ;
assembling_mbuf = false ;
2012-09-25 14:28:47 +00:00
}
2013-12-19 13:00:51 +00:00
reqtxt_file = subsurface_open ( reqtxt_path , O_RDWR | O_CREAT , 0666 ) ;
2012-09-25 14:28:47 +00:00
trigger_response ( reqtxt_file , " n " , filenr , file_length ) ;
}
} else {
2014-02-28 04:09:57 +00:00
if ( ! next_file ( number_of_files - 1 ) ) {
* error_text = translate ( " gettextFromC " , ERR_FS_FULL ) ;
2014-01-15 18:54:41 +00:00
more_files = false ;
assembling_mbuf = false ;
searching = false ;
2012-09-25 14:28:47 +00:00
}
2013-12-19 13:00:51 +00:00
reqtxt_file = subsurface_open ( reqtxt_path , O_RDWR | O_CREAT , 0666 ) ;
2012-09-25 14:28:47 +00:00
trigger_response ( reqtxt_file , " r " , filenr , file_length ) ;
2012-11-19 22:09:21 +00:00
uemis_increased_timeout ( & timeout ) ;
2012-09-25 14:28:47 +00:00
}
if ( ismulti & & more_files & & tmp [ 0 ] = = ' 1 ' ) {
int size ;
snprintf ( fl , 13 , " ANS%d.TXT " , assembling_mbuf ? filenr - 2 : filenr - 1 ) ;
2013-10-05 07:29:09 +00:00
ans_path = build_filename ( build_filename ( path , " ANS " ) , fl ) ;
2013-12-19 13:00:51 +00:00
ans_file = subsurface_open ( ans_path , O_RDONLY , 0666 ) ;
2012-09-25 14:28:47 +00:00
size = bytes_available ( ans_file ) ;
if ( size > 3 ) {
2014-03-06 02:27:33 +00:00
char * buf ;
int r ;
if ( lseek ( ans_file , 3 , SEEK_CUR ) = = - 1 )
goto fs_error ;
buf = malloc ( size - 2 ) ;
2014-05-01 21:14:50 +00:00
if ( ( r = read ( ans_file , buf , size - 3 ) ) ! = size - 3 ) {
2014-03-06 02:27:33 +00:00
free ( buf ) ;
goto fs_error ;
}
buf [ r ] = ' \0 ' ;
2012-09-27 07:16:42 +00:00
buffer_add ( & mbuf , & mbuf_size , buf ) ;
2012-11-29 00:11:19 +00:00
show_progress ( buf , what ) ;
2012-09-25 14:28:47 +00:00
free ( buf ) ;
2012-09-27 07:16:42 +00:00
param_buff [ 3 ] + + ;
2012-09-25 14:28:47 +00:00
}
close ( ans_file ) ;
2012-11-19 22:09:21 +00:00
timeout = UEMIS_TIMEOUT ;
2012-09-27 07:16:42 +00:00
usleep ( UEMIS_TIMEOUT ) ;
2012-09-25 14:28:47 +00:00
}
}
if ( more_files ) {
int size = 0 , j = 0 ;
char * buf = NULL ;
if ( ! ismulti ) {
snprintf ( fl , 13 , " ANS%d.TXT " , filenr - 1 ) ;
2013-10-05 07:29:09 +00:00
ans_path = build_filename ( build_filename ( path , " ANS " ) , fl ) ;
2013-12-19 13:00:51 +00:00
ans_file = subsurface_open ( ans_path , O_RDONLY , 0666 ) ;
2012-09-25 14:28:47 +00:00
size = bytes_available ( ans_file ) ;
if ( size > 3 ) {
2014-03-06 02:27:33 +00:00
int r ;
if ( lseek ( ans_file , 3 , SEEK_CUR ) = = - 1 )
goto fs_error ;
2012-09-25 14:28:47 +00:00
buf = malloc ( size - 2 ) ;
2014-03-06 02:27:33 +00:00
if ( ( r = read ( ans_file , buf , size - 3 ) ) ! = size - 3 ) {
free ( buf ) ;
goto fs_error ;
}
buf [ r ] = ' \0 ' ;
2012-11-29 00:11:19 +00:00
buffer_add ( & mbuf , & mbuf_size , buf ) ;
show_progress ( buf , what ) ;
2012-12-05 05:03:56 +00:00
# if UEMIS_DEBUG & 8
2012-09-25 14:28:47 +00:00
fprintf ( debugfile , " ::r %s \" %s \" \n " , ans_path , buf ) ;
# endif
}
2012-09-27 07:16:42 +00:00
size - = 3 ;
2012-09-25 14:28:47 +00:00
close ( ans_file ) ;
free ( ans_path ) ;
} else {
2014-01-15 18:54:41 +00:00
ismulti = false ;
2012-09-25 14:28:47 +00:00
}
2012-12-05 05:03:56 +00:00
# if UEMIS_DEBUG & 8
2014-02-28 04:09:57 +00:00
fprintf ( debugfile , " :r: %s \n " , buf ) ;
2012-09-25 14:28:47 +00:00
# endif
if ( ! answer_in_mbuf )
for ( i = 0 ; i < n_param_out & & j < size ; i + + )
param_buff [ i ] = next_segment ( buf , & j , size ) ;
2014-01-15 18:54:41 +00:00
found_answer = true ;
2012-09-30 03:57:48 +00:00
free ( buf ) ;
2012-09-25 14:28:47 +00:00
}
2012-12-05 05:03:56 +00:00
# if UEMIS_DEBUG & 1
2012-09-25 14:28:47 +00:00
for ( i = 0 ; i < n_param_out ; i + + )
2014-02-28 04:09:57 +00:00
fprintf ( debugfile , " ::: %d: %s \n " , i , param_buff [ i ] ) ;
2012-09-25 14:28:47 +00:00
# endif
return found_answer ;
2014-03-06 02:27:33 +00:00
fs_error :
2014-03-06 22:11:59 +00:00
close ( ans_file ) ;
2014-03-06 02:27:33 +00:00
return false ;
2012-09-25 14:28:47 +00:00
}
2012-11-29 00:11:19 +00:00
static void parse_divespot ( char * buf )
{
char * bp = buf + 1 ;
char * tp = next_token ( & bp ) ;
char * tag , * type , * val ;
2013-03-04 01:53:43 +00:00
char locationstring [ 1024 ] = " " ;
2012-11-29 00:11:19 +00:00
int divespot , len ;
2013-04-08 02:50:26 +00:00
double latitude = 0.0 , longitude = 0.0 ;
2012-11-29 00:11:19 +00:00
if ( strcmp ( tp , " divespot " ) )
return ;
do
tag = next_token ( & bp ) ;
while ( * tag & & strcmp ( tag , " object_id " ) ) ;
2014-02-28 04:09:57 +00:00
if ( ! * tag )
2012-11-29 00:11:19 +00:00
return ;
2014-03-04 05:24:52 +00:00
next_token ( & bp ) ;
2012-11-29 00:11:19 +00:00
val = next_token ( & bp ) ;
divespot = atoi ( val ) ;
do {
tag = next_token ( & bp ) ;
type = next_token ( & bp ) ;
val = next_token ( & bp ) ;
if ( ! strcmp ( type , " string " ) & & * val & & strcmp ( val , " " ) ) {
len = strlen ( locationstring ) ;
snprintf ( locationstring + len , sizeof ( locationstring ) - len ,
2014-02-28 04:09:57 +00:00
" %s%s " , len ? " , " : " " , val ) ;
2012-11-29 00:11:19 +00:00
} else if ( ! strcmp ( type , " float " ) ) {
if ( ! strcmp ( tag , " longitude " ) )
2013-10-05 07:29:09 +00:00
longitude = ascii_strtod ( val , NULL ) ;
2012-11-29 00:11:19 +00:00
else if ( ! strcmp ( tag , " latitude " ) )
2013-10-05 07:29:09 +00:00
latitude = ascii_strtod ( val , NULL ) ;
2012-11-29 00:11:19 +00:00
}
} while ( tag & & * tag ) ;
2013-01-23 19:55:29 +00:00
uemis_set_divelocation ( divespot , locationstring , latitude , longitude ) ;
2012-11-29 00:11:19 +00:00
}
2012-12-05 17:59:52 +00:00
static void track_divespot ( char * val , int diveid , char * * location , degrees_t * latitude , degrees_t * longitude )
2012-11-29 00:11:19 +00:00
{
int id = atoi ( val ) ;
if ( id > = 0 & & id > nr_divespots )
nr_divespots = id ;
uemis_mark_divelocation ( diveid , id , location , latitude , longitude ) ;
return ;
}
2014-02-28 04:09:57 +00:00
static char * suit [ ] = { " " , QT_TRANSLATE_NOOP ( " gettextFromC " , " wetsuit " ) , QT_TRANSLATE_NOOP ( " gettextFromC " , " semidry " ) , QT_TRANSLATE_NOOP ( " gettextFromC " , " drysuit " ) } ;
static char * suit_type [ ] = { " " , QT_TRANSLATE_NOOP ( " gettextFromC " , " shorty " ) , QT_TRANSLATE_NOOP ( " gettextFromC " , " vest " ) , QT_TRANSLATE_NOOP ( " gettextFromC " , " long john " ) , QT_TRANSLATE_NOOP ( " gettextFromC " , " jacket " ) , QT_TRANSLATE_NOOP ( " gettextFromC " , " full suit " ) , QT_TRANSLATE_NOOP ( " gettextFromC " , " 2 pcs full suit " ) } ;
static char * suit_thickness [ ] = { " " , " 0.5-2mm " , " 2-3mm " , " 3-5mm " , " 5-7mm " , " 8mm+ " , QT_TRANSLATE_NOOP ( " gettextFromC " , " membrane " ) } ;
2012-11-29 00:11:19 +00:00
static void parse_tag ( struct dive * dive , char * tag , char * val )
{
/* we can ignore computer_id, water and gas as those are redundant
* with the binary data and would just get overwritten */
2014-02-28 04:09:57 +00:00
if ( ! strcmp ( tag , " date " ) ) {
2012-11-29 00:11:19 +00:00
uemis_ts ( val , & dive - > when ) ;
2013-02-04 04:50:14 +00:00
} else if ( ! strcmp ( tag , " duration " ) ) {
2013-01-23 18:25:31 +00:00
uemis_duration ( val , & dive - > dc . duration ) ;
2013-02-04 04:50:14 +00:00
} else if ( ! strcmp ( tag , " depth " ) ) {
2013-01-23 18:25:31 +00:00
uemis_depth ( val , & dive - > dc . maxdepth ) ;
2013-02-04 04:50:14 +00:00
} else if ( ! strcmp ( tag , " file_content " ) ) {
2012-11-29 00:11:19 +00:00
uemis_parse_divelog_binary ( val , dive ) ;
2013-02-04 04:50:14 +00:00
} else if ( ! strcmp ( tag , " altitude " ) ) {
2013-01-23 18:25:31 +00:00
uemis_get_index ( val , & dive - > dc . surface_pressure . mbar ) ;
2013-02-04 04:50:14 +00:00
} else if ( ! strcmp ( tag , " f32Weight " ) ) {
2012-11-29 00:11:19 +00:00
uemis_get_weight ( val , & dive - > weightsystem [ 0 ] , dive - > dc . diveid ) ;
2013-02-04 04:50:14 +00:00
} else if ( ! strcmp ( tag , " notes " ) ) {
2012-11-29 00:11:19 +00:00
uemis_add_string ( val , & dive - > notes ) ;
2013-02-04 04:50:14 +00:00
} else if ( ! strcmp ( tag , " u8DiveSuit " ) ) {
if ( * suit [ atoi ( val ) ] )
2014-02-28 04:09:57 +00:00
uemis_add_string ( translate ( " gettextFromC " , suit [ atoi ( val ) ] ) , & dive - > suit ) ;
2013-02-04 04:50:14 +00:00
} else if ( ! strcmp ( tag , " u8DiveSuitType " ) ) {
if ( * suit_type [ atoi ( val ) ] )
2014-02-28 04:09:57 +00:00
uemis_add_string ( translate ( " gettextFromC " , suit_type [ atoi ( val ) ] ) , & dive - > suit ) ;
2013-02-04 04:50:14 +00:00
} else if ( ! strcmp ( tag , " u8SuitThickness " ) ) {
if ( * suit_thickness [ atoi ( val ) ] )
2014-02-28 04:09:57 +00:00
uemis_add_string ( translate ( " gettextFromC " , suit_thickness [ atoi ( val ) ] ) , & dive - > suit ) ;
2013-02-04 04:50:14 +00:00
}
2012-11-29 00:11:19 +00:00
}
/* This function is called for both divelog and dive information that we get
* from the SDA ( what an insane design , btw ) . The object_id in the divelog
* matches the logfilenr in the dive information ( which has its own , often
* different object_id ) - we use this as the diveid .
* We create the dive when parsing the divelog and then later , when we parse
* the dive information we locate the already created dive via its diveid .
* Most things just get parsed and converted into our internal data structures ,
* but the dive location API is even more crazy . We just get an id that is an
* index into yet another data store that we read out later . In order to
* correctly populate the location and gps data from that we need to remember
* the adresses of those fields for every dive that references the divespot . */
2014-10-12 11:11:34 +00:00
static bool process_raw_buffer ( device_data_t * devdata , uint32_t deviceid , char * inbuf , char * * max_divenr , bool keep_number , int * for_dive )
2012-09-25 14:28:47 +00:00
{
char * buf = strdup ( inbuf ) ;
char * tp , * bp , * tag , * type , * val ;
2014-01-15 18:54:41 +00:00
bool done = false ;
2012-09-25 14:28:47 +00:00
int inbuflen = strlen ( inbuf ) ;
char * endptr = buf + inbuflen ;
2014-01-15 18:54:41 +00:00
bool log = false ;
2012-10-26 03:15:39 +00:00
char * sections [ 10 ] ;
int s , nr_sections = 0 ;
2012-11-29 00:11:19 +00:00
struct dive * dive = NULL ;
2012-09-25 14:28:47 +00:00
2014-05-05 21:36:55 +00:00
# if UEMIS_DEBUG & 4
fprintf ( debugfile , " p_r_b %s \n " , inbuf ) ;
# endif
2013-02-08 01:53:32 +00:00
if ( for_dive )
* for_dive = - 1 ;
2012-09-25 14:28:47 +00:00
bp = buf + 1 ;
tp = next_token ( & bp ) ;
2012-10-26 03:15:39 +00:00
if ( strcmp ( tp , " divelog " ) = = 0 ) {
/* this is a divelog */
2014-01-15 18:54:41 +00:00
log = true ;
2012-10-26 03:15:39 +00:00
tp = next_token ( & bp ) ;
2014-05-05 21:36:55 +00:00
/* is it a valid entry or nothing ? */
if ( strcmp ( tp , " 1.0 " ) ! = 0 | | strstr ( inbuf , " divelog{1.0{{{{ " ) ) {
2013-12-10 23:53:29 +00:00
free ( buf ) ;
2014-05-05 21:36:55 +00:00
return false ;
2013-12-10 23:53:29 +00:00
}
2012-10-26 03:15:39 +00:00
} else if ( strcmp ( tp , " dive " ) = = 0 ) {
/* this is dive detail */
tp = next_token ( & bp ) ;
2014-02-28 04:09:57 +00:00
if ( strcmp ( tp , " 1.0 " ) ! = 0 ) {
2013-12-10 23:53:29 +00:00
free ( buf ) ;
2014-05-05 21:36:55 +00:00
return false ;
2013-12-10 23:53:29 +00:00
}
2012-10-26 03:15:39 +00:00
} else {
/* don't understand the buffer */
2013-12-10 23:53:29 +00:00
free ( buf ) ;
2014-05-05 21:36:55 +00:00
return false ;
2012-10-26 03:15:39 +00:00
}
2014-05-05 21:36:55 +00:00
if ( log ) {
2012-11-29 00:11:19 +00:00
dive = uemis_start_dive ( deviceid ) ;
2014-05-05 21:36:55 +00:00
} else {
/* remember, we don't know if this is the right entry,
* so first test if this is even a valid entry */
if ( strstr ( inbuf , " deleted{bool{true " ) ) {
# if UEMIS_DEBUG & 4
fprintf ( debugfile , " p_r_b entry deleted \n " ) ;
# endif
/* oops, this one isn't valid, suggest to try the previous one */
return false ;
}
}
2012-09-25 14:28:47 +00:00
while ( ! done ) {
2012-10-26 03:15:39 +00:00
/* the valid buffer ends with a series of delimiters */
if ( bp > = endptr - 2 | | ! strcmp ( bp , " {{ " ) )
break ;
2012-09-25 14:28:47 +00:00
tag = next_token ( & bp ) ;
2012-10-26 03:15:39 +00:00
/* we also end if we get an empty tag */
if ( * tag = = ' \0 ' )
break ;
for ( s = 0 ; s < nr_sections ; s + + )
if ( ! strcmp ( tag , sections [ s ] ) ) {
tag = next_token ( & bp ) ;
break ;
}
2012-09-25 14:28:47 +00:00
type = next_token ( & bp ) ;
2012-10-26 03:15:39 +00:00
if ( ! strcmp ( type , " 1.0 " ) ) {
/* this tells us the sections that will follow; the tag here
* is of the format dive - < section > */
sections [ nr_sections ] = strchr ( tag , ' - ' ) + 1 ;
2012-12-05 05:03:56 +00:00
# if UEMIS_DEBUG & 4
2012-10-26 03:15:39 +00:00
fprintf ( debugfile , " Expect to find section %s \n " , sections [ nr_sections ] ) ;
# endif
if ( nr_sections < sizeof ( sections ) - 1 )
nr_sections + + ;
continue ;
}
2012-09-25 14:28:47 +00:00
val = next_token ( & bp ) ;
2014-02-28 04:09:57 +00:00
if ( log & & ! strcmp ( tag , " object_id " ) ) {
2012-09-25 14:28:47 +00:00
free ( * max_divenr ) ;
* max_divenr = strdup ( val ) ;
2012-11-29 00:11:19 +00:00
dive - > dc . diveid = atoi ( val ) ;
2012-12-05 18:24:21 +00:00
if ( keep_number )
dive - > number = atoi ( val ) ;
2014-02-28 04:09:57 +00:00
} else if ( ! log & & ! strcmp ( tag , " logfilenr " ) ) {
2012-11-29 00:11:19 +00:00
/* this one tells us which dive we are adding data to */
2014-05-12 17:10:13 +00:00
dive = get_dive_by_uemis_diveid ( atoi ( val ) , deviceid ) ;
2013-02-08 01:53:32 +00:00
if ( for_dive )
* for_dive = atoi ( val ) ;
2014-02-28 04:09:57 +00:00
} else if ( ! log & & dive & & ! strcmp ( tag , " divespot_id " ) ) {
2012-11-29 00:11:19 +00:00
track_divespot ( val , dive - > dc . diveid , & dive - > location , & dive - > latitude , & dive - > longitude ) ;
} else if ( dive ) {
parse_tag ( dive , tag , val ) ;
2012-09-25 14:28:47 +00:00
}
2014-02-28 04:09:57 +00:00
if ( log & & ! strcmp ( tag , " file_content " ) )
2014-01-15 18:54:41 +00:00
done = true ;
2012-09-27 03:37:57 +00:00
/* done with one dive (got the file_content tag), but there could be more:
* a ' { ' indicates the end of the record - but we need to see another " {{ "
* later in the buffer to know that the next record is complete ( it could
* be a short read because of some error */
if ( done & & + + bp < endptr & & * bp ! = ' { ' & & strstr ( bp , " {{ " ) ) {
2014-01-15 18:54:41 +00:00
done = false ;
2014-10-12 11:11:34 +00:00
record_uemis_dive ( devdata , dive ) ;
2014-01-15 18:54:41 +00:00
mark_divelist_changed ( true ) ;
2012-11-29 00:11:19 +00:00
dive = uemis_start_dive ( deviceid ) ;
2012-09-25 14:28:47 +00:00
}
}
2012-10-26 03:15:39 +00:00
if ( log ) {
2012-11-29 00:11:19 +00:00
if ( dive - > dc . diveid ) {
2014-10-12 11:11:34 +00:00
record_uemis_dive ( devdata , dive ) ;
2014-01-15 18:54:41 +00:00
mark_divelist_changed ( true ) ;
2012-11-29 00:11:19 +00:00
} else { /* partial dive */
free ( dive ) ;
2014-05-05 21:36:55 +00:00
free ( buf ) ;
return false ;
2012-11-29 00:11:19 +00:00
}
2012-10-26 03:15:39 +00:00
}
2012-09-25 14:28:47 +00:00
free ( buf ) ;
2014-05-05 21:36:55 +00:00
return true ;
2012-09-25 14:28:47 +00:00
}
2013-04-07 03:49:06 +00:00
static char * uemis_get_divenr ( char * deviceidstr )
2012-09-25 14:28:47 +00:00
{
2013-01-18 20:56:54 +00:00
uint32_t deviceid , maxdiveid = 0 ;
int i ;
2012-11-29 05:02:03 +00:00
char divenr [ 10 ] ;
2012-11-29 00:11:19 +00:00
deviceid = atoi ( deviceidstr ) ;
2014-05-19 21:37:19 +00:00
struct dive * d ;
for_each_dive ( i , d ) {
2014-05-13 22:32:45 +00:00
struct divecomputer * dc ;
for_each_dc ( d , dc ) {
2012-12-29 19:28:35 +00:00
if ( dc - > model & & ! strcmp ( dc - > model , " Uemis Zurich " ) & &
2013-01-18 20:48:15 +00:00
( dc - > deviceid = = 0 | | dc - > deviceid = = 0x7fffffff | | dc - > deviceid = = deviceid ) & &
dc - > diveid > maxdiveid )
2012-12-29 02:21:34 +00:00
maxdiveid = dc - > diveid ;
}
2012-09-25 14:28:47 +00:00
}
2012-11-29 05:02:03 +00:00
snprintf ( divenr , 10 , " %d " , maxdiveid ) ;
return strdup ( divenr ) ;
2012-09-25 14:28:47 +00:00
}
2014-10-12 10:57:32 +00:00
const char * do_uemis_import ( device_data_t * data )
2012-09-25 14:28:47 +00:00
{
2014-10-12 10:57:32 +00:00
const char * mountpath = data - > devname ;
short force_download = data - > force_download ;
2012-09-25 14:28:47 +00:00
char * newmax = NULL ;
2014-05-05 21:36:55 +00:00
int start , end = - 2 , i , offset ;
2013-01-18 20:56:54 +00:00
uint32_t deviceidnr ;
2012-10-26 03:15:39 +00:00
char objectid [ 10 ] ;
2012-09-30 03:57:48 +00:00
char * deviceid = NULL ;
2013-10-06 15:55:58 +00:00
const char * result = NULL ;
2012-09-27 07:16:42 +00:00
char * endptr ;
2014-01-15 18:54:41 +00:00
bool success , keep_number = false , once = true ;
2012-09-25 14:28:47 +00:00
2012-12-05 18:24:21 +00:00
if ( dive_table . nr = = 0 )
2014-01-15 18:54:41 +00:00
keep_number = true ;
2014-11-25 15:47:24 +00:00
uemis_info ( translate ( " gettextFromC " , " Initialise communication " ) ) ;
2014-02-28 04:09:57 +00:00
if ( ! uemis_init ( mountpath ) )
return translate ( " gettextFromC " , " Uemis init failed " ) ;
if ( ! uemis_get_answer ( mountpath , " getDeviceId " , 0 , 1 , & result ) )
2012-09-30 03:57:48 +00:00
goto bail ;
2012-09-25 14:28:47 +00:00
deviceid = strdup ( param_buff [ 0 ] ) ;
2012-11-29 00:11:19 +00:00
deviceidnr = atoi ( deviceid ) ;
2012-09-25 14:28:47 +00:00
/* the answer from the DeviceId call becomes the input parameter for getDeviceData */
2014-02-28 04:09:57 +00:00
if ( ! uemis_get_answer ( mountpath , " getDeviceData " , 1 , 0 , & result ) )
2012-09-30 03:57:48 +00:00
goto bail ;
2012-09-25 14:28:47 +00:00
/* param_buff[0] is still valid */
2014-02-28 04:09:57 +00:00
if ( ! uemis_get_answer ( mountpath , " initSession " , 1 , 6 , & result ) )
2012-09-30 03:57:48 +00:00
goto bail ;
2014-02-28 04:09:57 +00:00
uemis_info ( translate ( " gettextFromC " , " Start download " ) ) ;
if ( ! uemis_get_answer ( mountpath , " processSync " , 0 , 2 , & result ) )
2012-09-30 03:57:48 +00:00
goto bail ;
2012-11-19 22:11:08 +00:00
/* before starting the long download, check if user pressed cancel */
if ( import_thread_cancelled )
goto bail ;
2012-09-25 14:28:47 +00:00
param_buff [ 1 ] = " notempty " ;
2012-11-29 00:11:19 +00:00
/* if we have an empty divelist or force it, then we start downloading from the
* first dive on the Uemis ; otherwise check which was the last dive downloaded */
2013-06-27 06:31:46 +00:00
if ( ! force_download & & dive_table . nr > 0 )
2013-04-07 03:49:06 +00:00
newmax = uemis_get_divenr ( deviceid ) ;
2012-11-09 22:00:54 +00:00
else
newmax = strdup ( " 0 " ) ;
2012-11-29 00:11:19 +00:00
start = atoi ( newmax ) ;
2012-09-27 03:37:57 +00:00
for ( ; ; ) {
2014-05-05 21:36:55 +00:00
# if UEMIS_DEBUG & 4
fprintf ( debugfile , " d_u_i inner loop start %d end %d newmax %s \n " , start , end , newmax ) ;
# endif
2012-09-27 03:37:57 +00:00
param_buff [ 2 ] = newmax ;
2012-09-27 07:16:42 +00:00
param_buff [ 3 ] = 0 ;
2012-09-30 03:57:48 +00:00
success = uemis_get_answer ( mountpath , " getDivelogs " , 3 , 0 , & result ) ;
2012-09-27 07:16:42 +00:00
/* process the buffer we have assembled */
2012-11-29 00:11:19 +00:00
if ( mbuf )
2014-10-12 11:11:34 +00:00
if ( ! process_raw_buffer ( data , deviceidnr , mbuf , & newmax , keep_number , NULL ) ) {
2014-05-05 21:36:55 +00:00
/* if no dives were downloaded, mark end appropriately */
if ( end = = - 2 )
end = start - 1 ;
success = false ;
}
2012-12-05 20:32:16 +00:00
if ( once ) {
char * t = first_object_id_val ( mbuf ) ;
if ( t & & atoi ( t ) > start )
start = atoi ( t ) ;
free ( t ) ;
2014-01-15 18:54:41 +00:00
once = false ;
2012-12-05 20:32:16 +00:00
}
2014-05-05 21:36:55 +00:00
# if UEMIS_DEBUG & 4
fprintf ( debugfile , " d_u_i after download and parse start %d end %d newmax %s \n " , start , end , newmax ) ;
# endif
2012-11-29 00:11:19 +00:00
/* if the user clicked cancel, exit gracefully */
2012-11-19 22:11:08 +00:00
if ( import_thread_cancelled )
goto bail ;
2012-11-29 00:11:19 +00:00
/* if we got an error or got nothing back, stop trying */
if ( ! success | | ! param_buff [ 3 ] )
2012-09-27 03:37:57 +00:00
break ;
/* finally, if the memory is getting too full, maybe we better stop, too */
if ( progress_bar_fraction > 0.85 ) {
2014-02-28 04:09:57 +00:00
result = translate ( " gettextFromC " , ERR_FS_ALMOST_FULL ) ;
2012-09-27 03:37:57 +00:00
break ;
}
2012-09-27 07:16:42 +00:00
/* clean up mbuf */
endptr = strstr ( mbuf , " {{{ " ) ;
if ( endptr )
* ( endptr + 2 ) = ' \0 ' ;
2014-05-05 21:36:55 +00:00
/* last object_id we parsed */
sscanf ( newmax , " %d " , & end ) ;
2012-09-25 14:28:47 +00:00
}
2014-05-05 21:36:55 +00:00
if ( end = = - 2 & & sscanf ( newmax , " %d " , & end ) ! = 1 )
2012-10-26 03:15:39 +00:00
end = start ;
2012-12-05 05:03:56 +00:00
# if UEMIS_DEBUG & 2
2012-10-26 03:15:39 +00:00
fprintf ( debugfile , " done: read from object_id %d to %d \n " , start , end ) ;
# endif
2012-09-25 14:28:47 +00:00
free ( newmax ) ;
2013-02-08 01:53:32 +00:00
offset = 0 ;
for ( i = start ; i < = end ; i + + ) {
snprintf ( objectid , sizeof ( objectid ) , " %d " , i + offset ) ;
2012-10-26 03:15:39 +00:00
param_buff [ 2 ] = objectid ;
2012-12-05 20:32:16 +00:00
# if UEMIS_DEBUG & 2
2013-02-08 01:53:32 +00:00
fprintf ( debugfile , " getDive %d, object_id %s \n " , i , objectid ) ;
2012-12-05 20:32:16 +00:00
# endif
2013-02-08 01:53:32 +00:00
/* there is no way I have found to directly get the dive information
* for dive # i as the object_id and logfilenr can be different in the
* getDive call ; so we get the first one , compare the actual divenr
* with the one that we wanted , calculate the offset and try again .
* What an insane design . . . */
2012-10-26 03:15:39 +00:00
success = uemis_get_answer ( mountpath , " getDive " , 3 , 0 , & result ) ;
2013-02-08 01:53:32 +00:00
if ( mbuf ) {
int divenr ;
2014-10-12 11:11:34 +00:00
( void ) process_raw_buffer ( data , deviceidnr , mbuf , & newmax , false , & divenr ) ;
2014-05-05 21:36:55 +00:00
# if UEMIS_DEBUG & 2
fprintf ( debugfile , " got dive %d, looking for dive %d \n " , divenr , i ) ;
# endif
if ( divenr ! = i ) {
if ( divenr = = - 1 ) {
offset - - ;
} else {
2014-05-12 07:45:52 +00:00
offset + = i - divenr ;
2014-05-05 21:36:55 +00:00
}
2013-02-08 01:53:32 +00:00
# if UEMIS_DEBUG & 2
2014-05-05 21:36:55 +00:00
fprintf ( debugfile , " -> trying again with offset %d \n " , offset ) ;
2013-02-08 01:53:32 +00:00
# endif
i = start - 1 ;
2014-05-05 21:36:55 +00:00
if ( i + offset < 0 )
break ;
2013-02-08 01:53:32 +00:00
continue ;
}
}
2012-11-19 22:11:08 +00:00
if ( ! success | | import_thread_cancelled )
2012-10-26 03:15:39 +00:00
break ;
}
2014-01-15 18:54:41 +00:00
success = true ;
2012-11-29 00:11:19 +00:00
for ( i = 0 ; i < = nr_divespots ; i + + ) {
char divespotnr [ 10 ] ;
snprintf ( divespotnr , sizeof ( divespotnr ) , " %d " , i ) ;
param_buff [ 2 ] = divespotnr ;
2012-12-05 20:32:16 +00:00
# if UEMIS_DEBUG & 2
fprintf ( debugfile , " getDivespot %d \n " , i ) ;
# endif
2012-11-29 00:11:19 +00:00
success = uemis_get_answer ( mountpath , " getDivespot " , 3 , 0 , & result ) ;
if ( mbuf )
parse_divespot ( mbuf ) ;
}
2012-11-19 22:11:08 +00:00
bail :
2014-02-28 04:09:57 +00:00
( void ) uemis_get_answer ( mountpath , " terminateSync " , 0 , 3 , & result ) ;
if ( ! strcmp ( param_buff [ 0 ] , " error " ) ) {
if ( ! strcmp ( param_buff [ 2 ] , " Out of Memory " ) )
result = translate ( " gettextFromC " , ERR_FS_FULL ) ;
2012-09-27 03:37:57 +00:00
else
result = param_buff [ 2 ] ;
}
2012-09-30 03:57:48 +00:00
free ( deviceid ) ;
2012-09-27 03:37:57 +00:00
return result ;
2012-09-25 14:28:47 +00:00
}