From fc2ff86853ade9acdb68628e4e231a5910a4e967 Mon Sep 17 00:00:00 2001 From: Michael Keller Date: Thu, 5 Jun 2025 18:07:13 +1200 Subject: [PATCH] Garmin: Add MTP Support for More Models. Add MTP support for more of the newer Garmin Descent models. Signed-off-by: Michael Keller --- src/garmin.c | 36 ++++++++++++++++++++++++++++++++---- src/garmin.h | 10 ++++++++++ src/garmin_parser.c | 29 +++++------------------------ 3 files changed, 47 insertions(+), 28 deletions(-) diff --git a/src/garmin.c b/src/garmin.c index 43161039..a3db4058 100644 --- a/src/garmin.c +++ b/src/garmin.c @@ -39,8 +39,8 @@ #include "libmtp.h" #define GARMIN_VENDOR 0x091E -#define DESCENT_MK2 0x4CBA -#define DESCENT_MK2_APAC 0x4E76 + +#define DESCENT_MK2 3258 // deal with ancient libmpt found on older Linux distros #ifndef LIBMTP_FILES_AND_FOLDERS_ROOT @@ -59,6 +59,24 @@ typedef struct garmin_device_t { #endif } garmin_device_t; +// Ids can be found at https://developer.garmin.com/connect-iq/reference-guides/devices-reference/ +// (look for 'Part Number') + +const garmin_model_t garmin_models[] = { + { "Descent™ G1 / G1 Solar", 4005, true }, + { "Descent™ G2", 4588, true }, + { "Descent™ Mk1", 2859, false }, + { "Descent™ Mk1 APAC", 2991, false }, + { "Descent™ Mk2(i)", 3258, true }, + { "Descent™ Mk2(i) APAC", 3702, true }, + { "Descent™ Mk2 S", 3542, true }, + { "Descent™ Mk2 S APAC", 3930, true }, + { "Descent™ Mk3(i) 43mm", 4222, true }, + { "Descent™ Mk3(i) 51mm", 4223, true }, + { "Descent™ X50i", 4518, true }, + { NULL, 0, false } +}; + static dc_status_t garmin_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size); static dc_status_t garmin_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata); static dc_status_t garmin_device_close (dc_device_t *abstract); @@ -99,7 +117,7 @@ garmin_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_t *ios // for a Descent Mk2/Mk2i, we have to use MTP to access its storage; // for Garmin devices, the model number corresponds to the lower three nibbles of the USB product ID // in order to have only one entry for the Mk2, we don't use the Mk2/APAC model number in our code - device->use_mtp = (model == (0x0FFF & DESCENT_MK2)); + device->use_mtp = model == DESCENT_MK2; device->mtp_device = NULL; #endif @@ -335,7 +353,17 @@ mtp_get_file_list(dc_device_t *abstract, struct file_list *files) rawdevices[i].device_entry.vendor_id, rawdevices[i].device_entry.product_id); continue; } - if (rawdevices[i].device_entry.product_id != DESCENT_MK2 && rawdevices[i].device_entry.product_id != DESCENT_MK2_APAC) { + + bool mtp_capable = false; + for (unsigned j = 0; garmin_models[j].name; j++) { + if ((garmin_models[j].id | 0x4000) == rawdevices[i].device_entry.product_id) { + mtp_capable = garmin_models[j].mtp_capable; + + break; + } + } + + if (!mtp_capable) { DEBUG(abstract->context, "Garmin/mtp: skipping Garmin raw device %04x/%04x, as it is not a dive computer / does not support MTP", rawdevices[i].device_entry.vendor_id, rawdevices[i].device_entry.product_id); continue; diff --git a/src/garmin.h b/src/garmin.h index 88bb6523..ca2ca8b4 100644 --- a/src/garmin.h +++ b/src/garmin.h @@ -22,6 +22,8 @@ #ifndef GARMIN_H #define GARMIN_H +#include + #include #include #include @@ -31,6 +33,14 @@ extern "C" { #endif /* __cplusplus */ +typedef struct { + const char *name; + int id; + bool mtp_capable; +} garmin_model_t; + +extern const garmin_model_t garmin_models[]; + dc_status_t garmin_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream, unsigned int model); diff --git a/src/garmin_parser.c b/src/garmin_parser.c index 109951f2..05b9b048 100644 --- a/src/garmin_parser.c +++ b/src/garmin_parser.c @@ -1648,25 +1648,6 @@ static void add_sensor_string(garmin_parser_t *garmin, const char *desc, const s static dc_status_t garmin_parser_set_data (garmin_parser_t *garmin, const unsigned char *data, unsigned int size) { - // Ids can be found at https://developer.garmin.com/connect-iq/reference-guides/devices-reference/ - // (look for 'Part Number') - static const struct { - const char *name; - int id; - } models[] = { - { "Descent™ G1 / G1 Solar", 4005 }, - { "Descent™ G2", 4588 }, - { "Descent™ Mk1", 2859 }, - { "Descent™ Mk1 APAC", 2991 }, - { "Descent™ Mk2(i)", 3258 }, - { "Descent™ Mk2(i) APAC", 3702 }, - { "Descent™ Mk2 S", 3542 }, - { "Descent™ Mk2 S APAC", 3930 }, - { "Descent™ Mk3(i) 43mm", 4222 }, - { "Descent™ Mk3(i) 51mm", 4223 }, - { "Descent™ X50i", 4518 }, - }; - /* Walk the data once without a callback to set up the core fields */ garmin->callback = NULL; garmin->userdata = NULL; @@ -1683,13 +1664,13 @@ garmin_parser_set_data (garmin_parser_t *garmin, const unsigned char *data, unsi dc_field_add_string_fmt(&garmin->cache, "Firmware", "%u.%02u", garmin->dive.firmware / 100, garmin->dive.firmware % 100); if (garmin->dive.product) { - int i = 0; - for (i = 0; i < C_ARRAY_SIZE(models); i++) - if (models[i].id == garmin->dive.product) + unsigned i; + for (i = 0; garmin_models[i].name; i++) + if (garmin_models[i].id == garmin->dive.product) break; - if (i < C_ARRAY_SIZE(models)) - dc_field_add_string_fmt(&garmin->cache, "Model", "%s", models[i].name); + if (garmin_models[i].name) + dc_field_add_string_fmt(&garmin->cache, "Model", "%s", garmin_models[i].name); else dc_field_add_string_fmt(&garmin->cache, "Model", "Unknown model ID: %u", garmin->dive.product); }