34
34
35
35
#define ISINSTANCE (device ) dc_device_isinstance((device), &cressi_goa_device_vtable)
36
36
37
- #define CMD_VERSION 0x00
38
- #define CMD_SET_TIME 0x13
39
- #define CMD_EXIT_PCLINK 0x1D
40
- #define CMD_LOGBOOK 0x21
41
- #define CMD_DIVE 0x22
37
+ #define CMD_VERSION 0x00
38
+ #define CMD_SET_TIME 0x13
39
+ #define CMD_EXIT_PCLINK 0x1D
40
+ #define CMD_LOGBOOK 0x21
41
+ #define CMD_DIVE 0x22
42
+ #define CMD_LOGBOOK_V4 0x23
42
43
43
44
#define CMD_LOGBOOK_BLE 0x02
44
45
#define CMD_DIVE_BLE 0x03
49
50
#define ACK 0x06
50
51
51
52
#define SZ_DATA 512
52
- #define SZ_PACKET 10
53
- #define SZ_HEADER 23
53
+ #define SZ_PACKET 12
54
54
55
- #define FP_OFFSET 0x11
56
55
#define FP_SIZE 6
57
56
58
57
#define NSTEPS 1000
@@ -64,6 +63,13 @@ typedef struct cressi_goa_device_t {
64
63
unsigned char fingerprint [FP_SIZE ];
65
64
} cressi_goa_device_t ;
66
65
66
+ typedef struct cressi_goa_conf_t {
67
+ unsigned int logbook_cmd ;
68
+ unsigned int logbook_len ;
69
+ unsigned int logbook_fp_offset ;
70
+ unsigned int dive_fp_offset ;
71
+ } cressi_goa_conf_t ;
72
+
67
73
static dc_status_t cressi_goa_device_set_fingerprint (dc_device_t * abstract , const unsigned char data [], unsigned int size );
68
74
static dc_status_t cressi_goa_device_foreach (dc_device_t * abstract , dc_dive_callback_t callback , void * userdata );
69
75
static dc_status_t cressi_goa_device_timesync (dc_device_t * abstract , const dc_datetime_t * datetime );
@@ -81,6 +87,11 @@ static const dc_device_vtable_t cressi_goa_device_vtable = {
81
87
cressi_goa_device_close /* close */
82
88
};
83
89
90
+ static const cressi_goa_conf_t version_conf [] = {
91
+ { CMD_LOGBOOK , 23 , 17 , 12 },
92
+ { CMD_LOGBOOK_V4 , 15 , 3 , 4 },
93
+ };
94
+
84
95
static dc_status_t
85
96
cressi_goa_device_send (cressi_goa_device_t * device , unsigned char cmd , const unsigned char data [], unsigned int size )
86
97
{
@@ -128,7 +139,7 @@ cressi_goa_device_send (cressi_goa_device_t *device, unsigned char cmd, const un
128
139
}
129
140
130
141
static dc_status_t
131
- cressi_goa_device_receive (cressi_goa_device_t * device , unsigned char data [], unsigned int size )
142
+ cressi_goa_device_receive (cressi_goa_device_t * device , dc_buffer_t * output )
132
143
{
133
144
dc_status_t status = DC_STATUS_SUCCESS ;
134
145
dc_device_t * abstract = (dc_device_t * ) device ;
@@ -137,13 +148,16 @@ cressi_goa_device_receive (cressi_goa_device_t *device, unsigned char data[], un
137
148
unsigned char packet [SZ_PACKET + 8 ];
138
149
139
150
if (transport == DC_TRANSPORT_BLE ) {
140
- if (size ) {
151
+ if (output ) {
141
152
return DC_STATUS_INVALIDARGS ;
142
153
} else {
143
154
return DC_STATUS_SUCCESS ;
144
155
}
145
156
}
146
157
158
+ // Clear the output buffer.
159
+ dc_buffer_clear (output );
160
+
147
161
// Read the header of the data packet.
148
162
status = dc_iostream_read (device -> iostream , packet , 4 , NULL );
149
163
if (status != DC_STATUS_SUCCESS ) {
@@ -185,14 +199,11 @@ cressi_goa_device_receive (cressi_goa_device_t *device, unsigned char data[], un
185
199
return DC_STATUS_PROTOCOL ;
186
200
}
187
201
188
- // Verify the payload length.
189
- if (length != size ) {
190
- ERROR (abstract -> context , "Unexpected payload size (%u)." , length );
191
- return DC_STATUS_PROTOCOL ;
192
- }
193
-
194
- if (length ) {
195
- memcpy (data , packet + 5 , length );
202
+ if (length && output ) {
203
+ if (!dc_buffer_append (output , packet + 5 , length )) {
204
+ ERROR (abstract -> context , "Could not append received data." );
205
+ return DC_STATUS_NOMEMORY ;
206
+ }
196
207
}
197
208
198
209
return status ;
@@ -332,7 +343,7 @@ static dc_status_t
332
343
cressi_goa_device_transfer (cressi_goa_device_t * device ,
333
344
unsigned char cmd ,
334
345
const unsigned char input [], unsigned int isize ,
335
- unsigned char output [], unsigned int osize ,
346
+ dc_buffer_t * output ,
336
347
dc_buffer_t * buffer ,
337
348
dc_event_progress_t * progress )
338
349
{
@@ -345,7 +356,7 @@ cressi_goa_device_transfer (cressi_goa_device_t *device,
345
356
}
346
357
347
358
// Receive the answer from the dive computer.
348
- status = cressi_goa_device_receive (device , output , osize );
359
+ status = cressi_goa_device_receive (device , output );
349
360
if (status != DC_STATUS_SUCCESS ) {
350
361
return status ;
351
362
}
@@ -453,8 +464,14 @@ cressi_goa_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, v
453
464
dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER ;
454
465
device_event_emit (abstract , DC_EVENT_PROGRESS , & progress );
455
466
467
+ dc_buffer_t * id = dc_buffer_new (11 );
468
+ if (id == NULL ) {
469
+ ERROR (abstract -> context , "Failed to allocate memory for the ID." );
470
+ status = DC_STATUS_NOMEMORY ;
471
+ goto error_exit ;
472
+ }
473
+
456
474
// Read the version information.
457
- unsigned char id [9 ] = {0 };
458
475
if (transport == DC_TRANSPORT_BLE ) {
459
476
/*
460
477
* With the BLE communication, there is no variant of the CMD_VERSION
@@ -471,7 +488,6 @@ cressi_goa_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, v
471
488
};
472
489
const size_t sizes [] = {5 , 2 , 2 };
473
490
474
- unsigned int offset = 0 ;
475
491
for (size_t i = 0 ; i < C_ARRAY_SIZE (characteristics ); ++ i ) {
476
492
unsigned char request [sizeof (dc_ble_uuid_t ) + 5 ] = {0 };
477
493
@@ -485,48 +501,89 @@ cressi_goa_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, v
485
501
char uuidstr [DC_BLE_UUID_SIZE ] = {0 };
486
502
ERROR (abstract -> context , "Failed to read the characteristic '%s'." ,
487
503
dc_ble_uuid2str (characteristics [i ], uuidstr , sizeof (uuidstr )));
488
- goto error_exit ;
504
+ goto error_free_id ;
489
505
}
490
506
491
507
// Copy the payload data.
492
- memcpy (id + offset , request + sizeof (dc_ble_uuid_t ), sizes [i ]);
493
- offset += sizes [i ];
508
+ if (!dc_buffer_append (id , request + sizeof (dc_ble_uuid_t ), sizes [i ])) {
509
+ ERROR (abstract -> context , "Insufficient buffer space available." );
510
+ status = DC_STATUS_NOMEMORY ;
511
+ goto error_free_id ;
512
+ }
494
513
}
495
514
} else {
496
- status = cressi_goa_device_transfer (device , CMD_VERSION , NULL , 0 , id , sizeof ( id ), NULL , NULL );
515
+ status = cressi_goa_device_transfer (device , CMD_VERSION , NULL , 0 , id , NULL , NULL );
497
516
if (status != DC_STATUS_SUCCESS ) {
498
517
ERROR (abstract -> context , "Failed to read the version information." );
499
- goto error_exit ;
518
+ goto error_free_id ;
500
519
}
501
520
}
502
521
522
+ const unsigned char * id_data = dc_buffer_get_data (id );
523
+ size_t id_size = dc_buffer_get_size (id );
524
+
525
+ if (id_size < 9 ) {
526
+ ERROR (abstract -> context , "Unexpected version length (" DC_PRINTF_SIZE ")." , id_size );
527
+ status = DC_STATUS_DATAFORMAT ;
528
+ goto error_free_id ;
529
+ }
530
+
531
+ // Get the device info.
532
+ unsigned int model = id_data [4 ];
533
+ unsigned int firmware = array_uint16_le (id_data + 5 );
534
+ unsigned int serial = array_uint32_le (id_data + 0 );
535
+
536
+ // Get the data format version.
537
+ unsigned int version = 0 ;
538
+ if (id_size == 11 ) {
539
+ version = array_uint16_le (id_data + 9 );
540
+ } else {
541
+ if (firmware >= 161 && firmware <= 165 ) {
542
+ version = 0 ;
543
+ } else if (firmware >= 166 && firmware <= 169 ) {
544
+ version = 1 ;
545
+ } else if (firmware >= 170 && firmware <= 179 ) {
546
+ version = 2 ;
547
+ } else if (firmware >= 100 && firmware <= 110 ) {
548
+ version = 3 ;
549
+ } else if (firmware >= 200 && firmware <= 205 ) {
550
+ version = 4 ;
551
+ } else {
552
+ ERROR (abstract -> context , "Unknown firmware version (%u)." , firmware );
553
+ status = DC_STATUS_DATAFORMAT ;
554
+ goto error_free_id ;
555
+ }
556
+ }
557
+
558
+ const cressi_goa_conf_t * conf = & version_conf [version >= 4 ];
559
+
503
560
// Emit a vendor event.
504
561
dc_event_vendor_t vendor ;
505
- vendor .data = id ;
506
- vendor .size = sizeof ( id ) ;
562
+ vendor .data = id_data ;
563
+ vendor .size = id_size ;
507
564
device_event_emit (abstract , DC_EVENT_VENDOR , & vendor );
508
565
509
566
// Emit a device info event.
510
567
dc_event_devinfo_t devinfo ;
511
- devinfo .model = id [ 4 ] ;
512
- devinfo .firmware = array_uint16_le ( id + 5 ) ;
513
- devinfo .serial = array_uint32_le ( id + 0 ) ;
568
+ devinfo .model = model ;
569
+ devinfo .firmware = firmware ;
570
+ devinfo .serial = serial ;
514
571
device_event_emit (abstract , DC_EVENT_DEVINFO , & devinfo );
515
572
516
573
// Allocate memory for the logbook data.
517
574
logbook = dc_buffer_new (4096 );
518
575
if (logbook == NULL ) {
519
- ERROR (abstract -> context , "Failed to allocate memory." );
576
+ ERROR (abstract -> context , "Failed to allocate memory for the logbook ." );
520
577
status = DC_STATUS_NOMEMORY ;
521
- goto error_exit ;
578
+ goto error_free_id ;
522
579
}
523
580
524
581
// Read the logbook data.
525
582
if (transport == DC_TRANSPORT_BLE ) {
526
583
unsigned char args [] = {0x00 };
527
- status = cressi_goa_device_transfer (device , CMD_LOGBOOK_BLE , args , sizeof (args ), NULL , 0 , logbook , & progress );
584
+ status = cressi_goa_device_transfer (device , CMD_LOGBOOK_BLE , args , sizeof (args ), NULL , logbook , & progress );
528
585
} else {
529
- status = cressi_goa_device_transfer (device , CMD_LOGBOOK , NULL , 0 , NULL , 0 , logbook , & progress );
586
+ status = cressi_goa_device_transfer (device , conf -> logbook_cmd , NULL , 0 , NULL , logbook , & progress );
530
587
}
531
588
if (status != DC_STATUS_SUCCESS ) {
532
589
ERROR (abstract -> context , "Failed to read the logbook data." );
@@ -539,17 +596,17 @@ cressi_goa_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, v
539
596
// Count the number of dives.
540
597
unsigned int count = 0 ;
541
598
unsigned int offset = logbook_size ;
542
- while (offset >= SZ_HEADER ) {
599
+ while (offset >= conf -> logbook_len ) {
543
600
// Move to the start of the logbook entry.
544
- offset -= SZ_HEADER ;
601
+ offset -= conf -> logbook_len ;
545
602
546
603
// Get the dive number.
547
604
unsigned int number = array_uint16_le (logbook_data + offset );
548
605
if (number == 0 )
549
606
break ;
550
607
551
608
// Compare the fingerprint to identify previously downloaded entries.
552
- if (memcmp (logbook_data + offset + FP_OFFSET , device -> fingerprint , sizeof (device -> fingerprint )) == 0 ) {
609
+ if (memcmp (logbook_data + offset + conf -> logbook_fp_offset , device -> fingerprint , sizeof (device -> fingerprint )) == 0 ) {
553
610
break ;
554
611
}
555
612
@@ -563,7 +620,7 @@ cressi_goa_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, v
563
620
// Allocate memory for the dive data.
564
621
dive = dc_buffer_new (4096 );
565
622
if (dive == NULL ) {
566
- ERROR (abstract -> context , "Failed to allocate memory." );
623
+ ERROR (abstract -> context , "Failed to allocate memory for the dive ." );
567
624
status = DC_STATUS_NOMEMORY ;
568
625
goto error_free_logbook ;
569
626
}
@@ -572,16 +629,16 @@ cressi_goa_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, v
572
629
offset = logbook_size ;
573
630
for (unsigned int i = 0 ; i < count ; ++ i ) {
574
631
// Move to the start of the logbook entry.
575
- offset -= SZ_HEADER ;
632
+ offset -= conf -> logbook_len ;
576
633
577
634
// Read the dive data.
578
635
if (transport == DC_TRANSPORT_BLE ) {
579
636
unsigned char number [2 ] = {
580
637
logbook_data [offset + 1 ],
581
638
logbook_data [offset + 0 ]};
582
- status = cressi_goa_device_transfer (device , CMD_DIVE_BLE , number , 2 , NULL , 0 , dive , & progress );
639
+ status = cressi_goa_device_transfer (device , CMD_DIVE_BLE , number , 2 , NULL , dive , & progress );
583
640
} else {
584
- status = cressi_goa_device_transfer (device , CMD_DIVE , logbook_data + offset , 2 , NULL , 0 , dive , & progress );
641
+ status = cressi_goa_device_transfer (device , CMD_DIVE , logbook_data + offset , 2 , NULL , dive , & progress );
585
642
}
586
643
if (status != DC_STATUS_SUCCESS ) {
587
644
ERROR (abstract -> context , "Failed to read the dive data." );
@@ -591,12 +648,11 @@ cressi_goa_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, v
591
648
const unsigned char * dive_data = dc_buffer_get_data (dive );
592
649
size_t dive_size = dc_buffer_get_size (dive );
593
650
594
- // Verify the header in the logbook and dive data are identical.
595
- // After the 2 byte dive number, the logbook header has 5 bytes
596
- // extra, which are not present in the dive header.
597
- if (dive_size < SZ_HEADER - 5 ||
598
- memcmp (dive_data + 0 , logbook_data + offset + 0 , 2 ) != 0 ||
599
- memcmp (dive_data + 2 , logbook_data + offset + 7 , SZ_HEADER - 7 ) != 0 ) {
651
+ // Verify the dive number and the fingerprint in the logbook and dive
652
+ // data are identical.
653
+ if (dive_size < conf -> dive_fp_offset + FP_SIZE ||
654
+ memcmp (dive_data , logbook_data + offset , 2 ) != 0 ||
655
+ memcmp (dive_data + conf -> dive_fp_offset , logbook_data + offset + conf -> logbook_fp_offset , FP_SIZE ) != 0 ) {
600
656
ERROR (abstract -> context , "Unexpected dive header." );
601
657
status = DC_STATUS_DATAFORMAT ;
602
658
goto error_free_dive ;
@@ -608,12 +664,12 @@ cressi_goa_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, v
608
664
// are prepended to the dive data, along with a small header containing
609
665
// their size.
610
666
const unsigned char header [] = {
611
- sizeof ( id ) ,
612
- SZ_HEADER ,
667
+ id_size ,
668
+ conf -> logbook_len ,
613
669
};
614
- unsigned int headersize = sizeof (header ) + sizeof ( id ) + SZ_HEADER ;
615
- if (!dc_buffer_prepend (dive , logbook_data + offset , SZ_HEADER ) ||
616
- !dc_buffer_prepend (dive , id , sizeof ( id ) ) ||
670
+ unsigned int headersize = sizeof (header ) + id_size + conf -> logbook_len ;
671
+ if (!dc_buffer_prepend (dive , logbook_data + offset , conf -> logbook_len ) ||
672
+ !dc_buffer_prepend (dive , id_data , id_size ) ||
617
673
!dc_buffer_prepend (dive , header , sizeof (header ))) {
618
674
ERROR (abstract -> context , "Out of memory." );
619
675
status = DC_STATUS_NOMEMORY ;
@@ -623,14 +679,16 @@ cressi_goa_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, v
623
679
dive_data = dc_buffer_get_data (dive );
624
680
dive_size = dc_buffer_get_size (dive );
625
681
626
- if (callback && !callback (dive_data , dive_size , dive_data + headersize + FP_OFFSET - 5 , sizeof (device -> fingerprint ), userdata ))
682
+ if (callback && !callback (dive_data , dive_size , dive_data + headersize + conf -> dive_fp_offset , sizeof (device -> fingerprint ), userdata ))
627
683
break ;
628
684
}
629
685
630
686
error_free_dive :
631
687
dc_buffer_free (dive );
632
688
error_free_logbook :
633
689
dc_buffer_free (logbook );
690
+ error_free_id :
691
+ dc_buffer_free (id );
634
692
error_exit :
635
693
return status ;
636
694
}
@@ -653,7 +711,7 @@ cressi_goa_device_timesync (dc_device_t *abstract, const dc_datetime_t *datetime
653
711
new_time [4 ] = datetime -> hour ;
654
712
new_time [5 ] = datetime -> minute ;
655
713
new_time [6 ] = datetime -> second ;
656
- status = cressi_goa_device_transfer (device , CMD_SET_TIME , new_time , sizeof (new_time ), NULL , 0 , NULL , NULL );
714
+ status = cressi_goa_device_transfer (device , CMD_SET_TIME , new_time , sizeof (new_time ), NULL , NULL , NULL );
657
715
if (status != DC_STATUS_SUCCESS ) {
658
716
ERROR (abstract -> context , "Failed to set the new time." );
659
717
return status ;
@@ -673,7 +731,7 @@ cressi_goa_device_close (dc_device_t *abstract)
673
731
return DC_STATUS_SUCCESS ;
674
732
}
675
733
676
- status = cressi_goa_device_transfer (device , CMD_EXIT_PCLINK , NULL , 0 , NULL , 0 , NULL , NULL );
734
+ status = cressi_goa_device_transfer (device , CMD_EXIT_PCLINK , NULL , 0 , NULL , NULL , NULL );
677
735
if (status != DC_STATUS_SUCCESS ) {
678
736
ERROR (abstract -> context , "Failed to exit PC Link." );
679
737
return status ;
0 commit comments