From b69b142f6ae92f5ce96ec48c23868639d6c653df Mon Sep 17 00:00:00 2001 From: Henrik Grimler Date: Wed, 5 Dec 2018 19:38:23 +0100 Subject: [PATCH 1/5] Move definitions into new file ttblue.h Remove structs with files as they are mostly identical between V1 and V2 devices. Use similar format as the ttwatch project do, to simplify a potential future merge of the projects. Some interesting information: * There seem to be 11 bluetooth commands in total used by the android app * There are at least 3 types of notifications: phone call, text message and voice mail/misc.(?) --- ttblue.c | 41 ++++++++++++++++++++++------------------- ttblue.h | 42 ++++++++++++++++++++++++++++++++++++++++++ ttops.c | 29 +++++------------------------ ttops.h | 2 -- 4 files changed, 69 insertions(+), 45 deletions(-) create mode 100644 ttblue.h diff --git a/ttblue.c b/ttblue.c index f1fa24a..9f2273a 100644 --- a/ttblue.c +++ b/ttblue.c @@ -29,6 +29,7 @@ #include "bbatt.h" #include "ttops.h" #include "util.h" +#include "ttblue.h" const char *PLEASE_SETCAP_ME = "**********************************************************\n" @@ -228,12 +229,12 @@ read_gqf_status(TTDEV *ttd, int debug) time_t last_update = 0; uint8_t *fbuf; int length; - if ((length=tt_read_file(ttd, ttd->files->gps_status, debug, &fbuf)) < 0) { - fprintf(stderr, "WARNING: Could not read GPS status file 0x%08x from watch.\n", ttd->files->gps_status); + if ((length=tt_read_file(ttd, TTBLUE_FILE_GPS_STATUS, debug, &fbuf)) < 0) { + fprintf(stderr, "WARNING: Could not read GPS status file 0x%08x from watch.\n", TTBLUE_FILE_GPS_STATUS); last_update = -1; } else { #ifdef DUMP_0x00020001 - save_buf_to_file(make_tt_filename(ttd->files->gps_status, "bin"), "wxb", fbuf, length, 2, true); + save_buf_to_file(make_tt_filename(TTBLUE_FILE_GPS_STATUS, "bin"), "wxb", fbuf, length, 2, true); #endif if (length > 6 && (fbuf[0x02] | fbuf[0x03] | fbuf[0x04] | fbuf[0x05]) != 0) { struct tm tmp = { .tm_mday = fbuf[0x05], .tm_mon = fbuf[0x04]-1, .tm_year = (((int)fbuf[0x02])<<8) + fbuf[0x03] - 1900 }; @@ -529,23 +530,25 @@ int main(int argc, const char **argv) int length; fprintf(stderr, "Setting PHONE menu to '%s'.\n", hostname); - tt_delete_file(ttd, ttd->files->hostname); - tt_write_file(ttd, ttd->files->hostname, false, (uint8_t*)hostname, strlen(hostname), write_delay); + tt_delete_file(ttd, TTBLUE_FILE_HOSTNAME1); + tt_write_file(ttd, TTBLUE_FILE_HOSTNAME1, false, (uint8_t*)hostname, strlen(hostname), write_delay); + tt_delete_file(ttd, TTBLUE_FILE_HOSTNAME2); // Write name to two files as V1 and V2 devices seem to use different files + tt_write_file(ttd, TTBLUE_FILE_HOSTNAME2, false, (uint8_t*)hostname, strlen(hostname), write_delay); #ifdef DUMP_0x000f20000 - fprintf(stderr, "Reading preference file 0x%08x from watch...\n", ttd->files->preference); - if ((length=tt_read_file(ttd, ttd->files->preference, debug, &fbuf)) < 0) { - fprintf(stderr, "WARNING: Could not read preferences file 0x%08x from watch.\n", ttd->files->preference); + fprintf(stderr, "Reading preference file 0x%08x from watch...\n", TTBLUE_FILE_PREFERENCES_XML); + if ((length=tt_read_file(ttd, TTBLUE_FILE_PREFERENCES_XML, debug, &fbuf)) < 0) { + fprintf(stderr, "WARNING: Could not read preferences file 0x%08x from watch.\n", TTBLUE_FILE_PREFERENCES_XML); } else { - save_buf_to_file(make_tt_filename(ttd->files->preference, "xml"), "wxb", fbuf, length, 2, true); + save_buf_to_file(make_tt_filename(TTBLUE_FILE_PREFERENCES_XML, "xml"), "wxb", fbuf, length, 2, true); free(fbuf); } #endif if (set_time) { - fprintf(stderr, "Checking watch settings manifest file 0x%08x...\n", ttd->files->manifest); - if ((length = tt_read_file(ttd, ttd->files->manifest, debug, &fbuf)) < 0) { - fprintf(stderr, "WARNING: Could not read settings manifest file 0x%08x from watch!\n", ttd->files->manifest); + fprintf(stderr, "Checking watch settings manifest file 0x%08x...\n", TTBLUE_FILE_MANIFEST1); + if ((length = tt_read_file(ttd, TTBLUE_FILE_MANIFEST1, debug, &fbuf)) < 0) { + fprintf(stderr, "WARNING: Could not read settings manifest file 0x%08x from watch!\n", TTBLUE_FILE_MANIFEST1); } else { // based on: https://github.com/ryanbinns/ttwatch/tree/master/manifest // the position of the UTC-offset in the manifest is 169 in all known firmware versions, so lazily hard-coded here for now @@ -565,8 +568,8 @@ int main(int argc, const char **argv) if (btohl(*watch_timezone) != lt->tm_gmtoff) { fprintf(stderr, " Changing timezone from UTC%+d to UTC%+ld.\n", btohl(*watch_timezone), lt->tm_gmtoff); *watch_timezone = htobl(lt->tm_gmtoff); - tt_delete_file(ttd, ttd->files->manifest); - tt_write_file(ttd, ttd->files->manifest, false, fbuf, length, write_delay); + tt_delete_file(ttd, TTBLUE_FILE_MANIFEST1); + tt_write_file(ttd, TTBLUE_FILE_MANIFEST1, false, fbuf, length, write_delay); needs_reboot = true; } } @@ -576,7 +579,7 @@ int main(int argc, const char **argv) if (get_activities) { uint16_t *list; - int n_files = tt_list_sub_files(ttd, ttd->files->activity_start, &list); + int n_files = tt_list_sub_files(ttd, TTBLUE_FILE_TTBIN_DATA, &list); if (n_files < 0) { fprintf(stderr, "Could not list activity files on watch!\n"); @@ -584,7 +587,7 @@ int main(int argc, const char **argv) } fprintf(stderr, "Found %d activity files on watch.\n", n_files); for (int ii=0; iifiles->activity_start + list[ii]; + uint32_t fileno = TTBLUE_FILE_TTBIN_DATA + list[ii]; fprintf(stderr, " Reading activity file 0x%08X ...\n", fileno); term_title("ttblue: Transferring activity %d/%d", ii+1, n_files); @@ -668,8 +671,8 @@ int main(int argc, const char **argv) goto fail; } else { fclose (f); - tt_delete_file(ttd, ttd->files->quickgps); - result = tt_write_file(ttd, ttd->files->quickgps, debug, fbuf, length, write_delay); + tt_delete_file(ttd, TTBLUE_FILE_GPSQUICKFIX_DATA); + result = tt_write_file(ttd, TTBLUE_FILE_GPSQUICKFIX_DATA, debug, fbuf, length, write_delay); free(fbuf); if (result < 0) { fputs("Failed to send QuickFixGPS update to watch.\n", stderr); @@ -678,7 +681,7 @@ int main(int argc, const char **argv) // official TomTom Android app seems to only issue this // "magic" update command when the GPS is brand new or // after a factory reset, or with 3x --update-gps - att_wrreq(ttd->fd, ttd->h->cmd_status, BARRAY(0x05, 0x01, 0x00, 0x01), 4); + att_wrreq(ttd->fd, ttd->h->cmd_status, BARRAY(MSG_UPDATE_EPHEMERIS, 0x01, 0x00, 0x01), 4); time_t last_gqf_update = read_gqf_status(ttd, debug-1); if (last_gqf_update != -1 && last_gqf_update != 0) diff --git a/ttblue.h b/ttblue.h new file mode 100644 index 0000000..d79f364 --- /dev/null +++ b/ttblue.h @@ -0,0 +1,42 @@ +#ifndef __TTBLUE_H__ +#define __TTBLUE_H__ +/*****************************************************************************/ + +/****************************************************************************** +* Messages * +******************************************************************************/ +#define MSG_OPEN_FILE_WRITE (0x02) +#define MSG_WRITE (0x00) +#define MSG_READ (0x01) +#define MSG_CANCEL_TRANSFER (0x02) +#define MSG_LIST_FILES (0x03) +#define MSG_DELETE (0x04) +#define MSG_UPDATE_EPHEMERIS (0x05) // Used on the quickgps file +#define MSG_UPDATE_GOLF_MAPS (0x06) // No idea how this one works +#define MSG_RESET_DEVICE (0x07) +#define MSG_SET_TIME (0x08) +#define MSG_UIPROD (0x09) // Used on the rest_proto_file and for phone notifications +#define MSG_WRITE_RECOVERABLE (0x0a) // Used on V2 devices instead of MSG_WRITE +#define MSG_READ_RECOVERABLE (0x0b) // Used on V2 devices instead of MSG_READ + +/****************************************************************************** +* File IDs * +******************************************************************************/ +#define TTBLUE_FILE_NOTIFICATION (0x00b50000) // for text messages, phone calls +#define TTBLUE_FILE_GPS_STATUS (0x00020001) +#define TTBLUE_FILE_HOSTNAME1 (0x00020002) // Hostname on V1 devices +#define TTBLUE_FILE_HOSTNAME2 (0x00020003) // Hostname on V2 devices (offical + // tomtom app only sets this one) +#define TTBLUE_FILE_GOLF_MANIFEST (0x00b00000) +#define TTBLUE_FILE_STEP_BUCKET (0x00b10000) +#define TTBLUE_FILE_GOLF_SCORECARDS (0x00940000) // Also called GOLF_ROUNDS? +#define TTBLUE_FILE_REST_PROTO_FILE (0x00890000) // Only file uiprod command is used + // on except notification files +#define TTBLUE_FILE_FIRMWARE_CHUNK (0x00fd0000) // Used when doing OTA updates? +#define TTBLUE_FILE_BRIDGEHEAD (0x00000000) // ?? +#define TTBLUE_FILE_MANIFEST1 (0x00850000) +#define TTBLUE_FILE_PREFERENCES_XML (0x00f20000) +#define TTBLUE_FILE_TTBIN_DATA (0x00910000) +#define TTBLUE_FILE_GPSQUICKFIX_DATA (0x00010100) + +#endif // __TTBLUE_H__ diff --git a/ttops.c b/ttops.c index cae03cd..47546f2 100644 --- a/ttops.c +++ b/ttops.c @@ -14,30 +14,13 @@ #include "util.h" #include "ttops.h" #include "version.h" +#include "ttblue.h" /****************************************************************************/ struct tt_handles v1_handles = { .ppcp=0x0b, .passcode=0x32, .magic=0x35, .cmd_status=0x25, .length=0x28, .transfer=0x2b, .check=0x2e }; struct tt_handles v2_handles = { .ppcp=0, .passcode=0x82, .magic=0x85, .cmd_status=0x72, .length=0x75, .transfer=0x78, .check=0x7b }; -struct tt_files v1_files = { - .hostname = 0x00020002, - .preference = 0x00f20000, - .manifest = 0x00850000, - .activity_start = 0x00910000, - .gps_status = 0x00020001, - .quickgps = 0x00010100 -}; - -struct tt_files v2_files = { - .hostname = 0x00020003, - .preference = 0x00f20000, - .manifest = 0x00850000, - .activity_start = 0x00910000, - .gps_status = 0x00020001, - .quickgps = 0x00010100 -}; - struct ble_dev_info v1_info[] = { { 0x001e, "maker" }, { 0x0016, "serial" }, @@ -98,7 +81,6 @@ tt_device_init(int protocol_version, int fd) { d->oldest_tested_firmware = VERSION_TUPLE(1,8,34); d->newest_tested_firmware = VERSION_TUPLE(1,8,52); d->tested_models = tested_models_v1; - d->files = &v1_files; break; case 2: d->h = &v2_handles; @@ -108,7 +90,6 @@ tt_device_init(int protocol_version, int fd) { // @drkingpo confirmed v1.2.0 works now (see issue #5) // @Grimler91 tested 1.7.62 and 1.7.64. d->tested_models = tested_models_v2; - d->files = &v2_files; break; default: return NULL; @@ -228,7 +209,7 @@ tt_read_file(TTDEV *d, uint32_t fileno, int debug, uint8_t **buf) if (fileno>>24) return -EINVAL; - uint8_t cmd[] = {1, (fileno>>16)&0xff, fileno&0xff, (fileno>>8)&0xff}; + uint8_t cmd[] = {MSG_READ, (fileno>>16)&0xff, fileno&0xff, (fileno>>8)&0xff}; att_wrreq(d->fd, d->h->cmd_status, cmd, sizeof cmd); if (EXPECT_uint32(d, d->h->cmd_status, 1) < 0) goto prealloc_fail; @@ -309,7 +290,7 @@ tt_write_file(TTDEV *d, uint32_t fileno, int debug, const uint8_t *buf, uint32_t if (fileno>>24) return -EINVAL; - uint8_t cmd[] = {0, (fileno>>16)&0xff, fileno&0xff, (fileno>>8)&0xff}; + uint8_t cmd[] = {MSG_WRITE, (fileno>>16)&0xff, fileno&0xff, (fileno>>8)&0xff}; att_wrreq(d->fd, d->h->cmd_status, cmd, sizeof cmd); if (EXPECT_uint32(d, d->h->cmd_status, 1) < 0) return -1; @@ -408,7 +389,7 @@ tt_delete_file(TTDEV *d, uint32_t fileno) if (fileno>>24) return -EINVAL; - uint8_t cmd[] = {4, (fileno>>16)&0xff, fileno&0xff, (fileno>>8)&0xff}; + uint8_t cmd[] = {MSG_DELETE, (fileno>>16)&0xff, fileno&0xff, (fileno>>8)&0xff}; att_wrreq(d->fd, d->h->cmd_status, cmd, sizeof cmd); if (EXPECT_uint32(d, d->h->cmd_status, 1) < 0) return -1; @@ -433,7 +414,7 @@ tt_list_sub_files(TTDEV *d, uint32_t fileno, uint16_t **outlist) if (fileno>>24) return -EINVAL; - uint8_t cmd[] = {3, (fileno>>16)&0xff, fileno&0xff, (fileno>>8)&0xff}; + uint8_t cmd[] = {MSG_LIST_FILES, (fileno>>16)&0xff, fileno&0xff, (fileno>>8)&0xff}; att_wrreq(d->fd, d->h->cmd_status, cmd, sizeof cmd); if (EXPECT_uint32(d, d->h->cmd_status, 1) < 0) return -1; diff --git a/ttops.h b/ttops.h index d0652c2..04c6ea8 100644 --- a/ttops.h +++ b/ttops.h @@ -6,8 +6,6 @@ struct tt_handles { uint16_t ppcp, passcode, magic, cmd_status, length, transfer, check; }; -struct tt_files { uint32_t hostname, preference, manifest, activity_start, gps_status, quickgps; }; - struct ble_dev_info { uint16_t handle; const char *name; From 2b2cc94301f7d52702e16bfa7b2ab10d13ce6058 Mon Sep 17 00:00:00 2001 From: Henrik Grimler Date: Fri, 7 Dec 2018 22:26:51 +0100 Subject: [PATCH 2/5] tt_reboot: use MSG_RESET_DEVICE instead of hard-coding 0x07 --- ttops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ttops.c b/ttops.c index 47546f2..6bf38e0 100644 --- a/ttops.c +++ b/ttops.c @@ -194,7 +194,7 @@ tt_reboot(TTDEV *d) { // overwhelm the device with a torrent of writes to the (read-only) status register // v2 version tested by @Grimler91; v1 version tested by @dlenski on TomTom Runner v1 - uint32_t bork = htobl(d->protocol_version == 2 ? 0x07 : 0); + uint32_t bork = htobl(d->protocol_version == 2 ? MSG_RESET_DEVICE : 0); for (int ii=1; ii<=1000; ii++) { if (att_wrreq(d->fd, d->h->cmd_status, &bork, sizeof bork) < 0) return ii; From f08f7acee51b7a1a40d743f0c9797e3b4b80259e Mon Sep 17 00:00:00 2001 From: Henrik Grimler Date: Tue, 4 Dec 2018 20:07:25 +0100 Subject: [PATCH 3/5] Change dev_code to string to allow for codes starting with 0. Add new var read_code and read -c argument into it and then strcpy into dev_code. (Mostly because I couldn't figure out how to read the popt arg into a char[]) --- ttblue.c | 19 ++++++++++--------- ttops.c | 6 +++--- ttops.h | 2 +- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/ttblue.c b/ttblue.c index 9f2273a..9ccc261 100644 --- a/ttblue.c +++ b/ttblue.c @@ -285,7 +285,8 @@ save_buf_to_file(const char *filename, const char *mode, const void *fbuf, int l int debug=1; int get_activities=0, set_time=0, update_gps=0, version=0, daemonize=0, new_pair=1; int sleep_success=3600, sleep_fail=10; -uint32_t dev_code; +char dev_code[6]; +char *read_code; char *activity_store=".", *dev_address=NULL, *interface=NULL, *postproc=NULL, *gqf_url=GQF_GPS_URL; struct poptOption options[] = { @@ -299,7 +300,7 @@ struct poptOption options[] = { { "qf-url", 0, POPT_ARG_STRING, &gqf_url, 0, "Alternate URL for QuickFix update (ephemeris) file." }, { "device", 'd', POPT_ARG_STRING, &dev_address, 0, "Bluetooth MAC address of the watch (E4:04:39:__:__:__); will use first TomTom device if unspecified", "MACADDR" }, { "interface", 'i', POPT_ARG_STRING, &interface, 0, "Bluetooth HCI interface to use", "hciX" }, - { "code", 'c', POPT_ARG_INT, &dev_code, 'c', "6-digit pairing code for the watch (if already paired)", "NUMBER" }, + { "code", 'c', POPT_ARG_STRING, &read_code, 'c', "6-digit pairing code for the watch (if already paired)", "NUMBER" }, { "version", 'v', POPT_ARG_NONE, &version, 0, "Show watch firmware version and identifiers" }, { "debug", 'D', POPT_ARG_NONE, 0, 'D', "Increase level of debugging output" }, { "quiet", 'q', POPT_ARG_VAL, &debug, 0, "Suppress debugging output" }, @@ -324,7 +325,6 @@ int main(int argc, const char **argv) // parse args int ch; - char dangling; poptContext optCon = poptGetContext(NULL, argc, argv, options, 0); while ((ch=poptGetNextOpt(optCon))>=0) { @@ -369,6 +369,10 @@ int main(int argc, const char **argv) char hostname[32]; gethostname(hostname, sizeof hostname); + if (read_code != NULL) { + strcpy(dev_code, read_code); + } + // prompt user to put device in pairing mode if (new_pair) { fputs(PAIRING_MODE_PROMPT, stderr); @@ -506,15 +510,12 @@ int main(int argc, const char **argv) // prompt for pairing code if (new_pair) { fputs(PAIRING_CODE_PROMPT, stderr); - if (!(scanf("%d%c", &dev_code, &dangling) && isspace(dangling))) { - fprintf(stderr, "Pairing code should be 6-digit number.\n"); - goto fatal; - } + fgets(dev_code, 7, stdin); } // authorize with the device - if (tt_authorize(ttd, dev_code) < 0) { - fprintf(stderr, "Device didn't accept pairing code %d.\n", dev_code); + if (tt_authorize(ttd, dev_code, new_pair) < 0) { + fprintf(stderr, "Device didn't accept pairing code %s.\n", dev_code); if (first) goto fatal; else goto fail; } diff --git a/ttops.c b/ttops.c index 6bf38e0..8ada889 100644 --- a/ttops.c +++ b/ttops.c @@ -158,12 +158,12 @@ tt_check_device_version(TTDEV *d, bool warning) /****************************************************************************/ int -tt_authorize(TTDEV *d, uint32_t code) +tt_authorize(TTDEV *d, char code[6], bool new_code) { // authorize with the device const uint16_t auth_one = btohs(0x0001); - uint32_t bcode = htobl(code); - const uint8_t *magic_bytes = BARRAY( 0x01, 0x19, 0, 0, 0x01, 0x17, 0, 0 ); + uint32_t bcode = htobl(atoi(code)); + const uint8_t *magic_bytes; switch (d->protocol_version) { case 1: diff --git a/ttops.h b/ttops.h index 04c6ea8..3147124 100644 --- a/ttops.h +++ b/ttops.h @@ -29,7 +29,7 @@ typedef struct ttdev { TTDEV *tt_device_init(int protocol_version, int fd); bool tt_device_done(TTDEV *d); struct ble_dev_info *tt_check_device_version(TTDEV *d, bool warning); -int tt_authorize(TTDEV *d, uint32_t code); +int tt_authorize(TTDEV *d, char code[6], bool new_code); int tt_read_file(TTDEV *d, uint32_t fileno, int debug, uint8_t **buf); int tt_write_file(TTDEV *d, uint32_t fileno, int debug, const uint8_t *buf, uint32_t length, uint32_t write_delay); int tt_delete_file(TTDEV *d, uint32_t fileno); From 786cbb8344518b11776f422a15e317a5a80c07e5 Mon Sep 17 00:00:00 2001 From: Henrik Grimler Date: Sun, 3 Mar 2019 17:59:52 +0100 Subject: [PATCH 4/5] re-add magic bytes --- ttops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ttops.c b/ttops.c index 8ada889..5e94eae 100644 --- a/ttops.c +++ b/ttops.c @@ -163,7 +163,7 @@ tt_authorize(TTDEV *d, char code[6], bool new_code) // authorize with the device const uint16_t auth_one = btohs(0x0001); uint32_t bcode = htobl(atoi(code)); - const uint8_t *magic_bytes; + const uint8_t *magic_bytes = BARRAY( 0x01, 0x19, 0, 0, 0x01, 0x17, 0, 0 ); switch (d->protocol_version) { case 1: From f2506fd2398a07592dac1adf58598773cb8804f5 Mon Sep 17 00:00:00 2001 From: Henrik Grimler Date: Thu, 16 May 2019 10:11:28 +0200 Subject: [PATCH 5/5] Fix broken option loop poptGetContext returns the int specified in the 5th position in the poptOption struct. --- ttblue.c | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/ttblue.c b/ttblue.c index 9ccc261..4105c7d 100644 --- a/ttblue.c +++ b/ttblue.c @@ -290,24 +290,24 @@ char *read_code; char *activity_store=".", *dev_address=NULL, *interface=NULL, *postproc=NULL, *gqf_url=GQF_GPS_URL; struct poptOption options[] = { - { "auto", 'a', POPT_ARG_NONE, NULL, 'a', "Same as --get-activities --update-gps --set-time --version" }, - { "get-activities", 0, POPT_ARG_NONE, &get_activities, 0, "Downloads and deletes .ttbin activity files from the watch" }, - { "set-time", 0, POPT_ARG_NONE, &set_time, 0, "Set time zone on the watch to match this computer" }, - { "activity-store", 's', POPT_ARG_STRING|POPT_ARGFLAG_SHOW_DEFAULT, &activity_store, 0, "Location to store .ttbin activity files", "PATH" }, - { "post", 'p', POPT_ARG_STRING, &postproc, 0, "Command to run (with .ttbin file as argument) for every activity file", "CMD" }, - { "update-gps", 0, POPT_ARG_NONE, NULL, 'G', "Download TomTom QuickFix update file and send it to the watch (if repeated, forces update even if not needed)" }, - { "glonass", 0, POPT_ARG_NONE, NULL, 'g', "Use TomTom's GLONASS version of QuickFix update file." }, - { "qf-url", 0, POPT_ARG_STRING, &gqf_url, 0, "Alternate URL for QuickFix update (ephemeris) file." }, - { "device", 'd', POPT_ARG_STRING, &dev_address, 0, "Bluetooth MAC address of the watch (E4:04:39:__:__:__); will use first TomTom device if unspecified", "MACADDR" }, - { "interface", 'i', POPT_ARG_STRING, &interface, 0, "Bluetooth HCI interface to use", "hciX" }, - { "code", 'c', POPT_ARG_STRING, &read_code, 'c', "6-digit pairing code for the watch (if already paired)", "NUMBER" }, - { "version", 'v', POPT_ARG_NONE, &version, 0, "Show watch firmware version and identifiers" }, - { "debug", 'D', POPT_ARG_NONE, 0, 'D', "Increase level of debugging output" }, - { "quiet", 'q', POPT_ARG_VAL, &debug, 0, "Suppress debugging output" }, - { "daemon", 0, POPT_ARG_NONE, &daemonize, 0, "Run as a daemon which will try to connect repeatedly" }, - { "wait-success", 'w', POPT_ARG_INT|POPT_ARGFLAG_SHOW_DEFAULT, &sleep_success, 0, "Wait time after successful connection to watch", "SECONDS" }, - { "wait-fail", 'W', POPT_ARG_INT|POPT_ARGFLAG_SHOW_DEFAULT, &sleep_fail, 10, "Wait time after failed connection to watch", "SECONDS" }, -// { "no-config", 'C', POPT_ARG_NONE, &config, 0, "Do not load or save settings from ~/.ttblue config file" }, + { "auto", 'a', POPT_ARG_NONE, NULL, 0, "Same as --get-activities --update-gps --set-time --version" }, + { "get-activities", 0, POPT_ARG_NONE, &get_activities, 1, "Downloads and deletes .ttbin activity files from the watch" }, + { "set-time", 0, POPT_ARG_NONE, &set_time, 2, "Set time zone on the watch to match this computer" }, + { "activity-store", 's', POPT_ARG_STRING|POPT_ARGFLAG_SHOW_DEFAULT, &activity_store, 3, "Location to store .ttbin activity files", "PATH" }, + { "post", 'p', POPT_ARG_STRING, &postproc, 4, "Command to run (with .ttbin file as argument) for every activity file", "CMD" }, + { "update-gps", 0, POPT_ARG_NONE, NULL, 5, "Download TomTom QuickFix update file and send it to the watch (if repeated, forces update even if not needed)" }, + { "glonass", 0, POPT_ARG_NONE, NULL, 6, "Use TomTom's GLONASS version of QuickFix update file." }, + { "qf-url", 0, POPT_ARG_STRING, &gqf_url, 7, "Alternate URL for QuickFix update (ephemeris) file." }, + { "device", 'd', POPT_ARG_STRING, &dev_address, 8, "Bluetooth MAC address of the watch (E4:04:39:__:__:__); will use first TomTom device if unspecified", "MACADDR" }, + { "interface", 'i', POPT_ARG_STRING, &interface, 9, "Bluetooth HCI interface to use", "hciX" }, + { "code", 'c', POPT_ARG_STRING, &read_code, 10, "6-digit pairing code for the watch (if already paired)", "NUMBER" }, + { "version", 'v', POPT_ARG_NONE, &version, 11, "Show watch firmware version and identifiers" }, + { "debug", 'D', POPT_ARG_NONE, 0, 12, "Increase level of debugging output" }, + { "quiet", 'q', POPT_ARG_VAL, &debug, 13, "Suppress debugging output" }, + { "daemon", 0, POPT_ARG_NONE, &daemonize, 14, "Run as a daemon which will try to connect repeatedly" }, + { "wait-success", 'w', POPT_ARG_INT|POPT_ARGFLAG_SHOW_DEFAULT, &sleep_success, 15, "Wait time after successful connection to watch", "SECONDS" }, + { "wait-fail", 'W', POPT_ARG_INT|POPT_ARGFLAG_SHOW_DEFAULT, &sleep_fail, 16, "Wait time after failed connection to watch", "SECONDS" }, +// { "no-config", 'C', POPT_ARG_NONE, &config, 17, "Do not load or save settings from ~/.ttblue config file" }, POPT_AUTOHELP POPT_TABLEEND }; @@ -329,11 +329,11 @@ int main(int argc, const char **argv) while ((ch=poptGetNextOpt(optCon))>=0) { switch (ch) { - case 'c': new_pair=false; break; - case 'D': debug++; break; - case 'a': get_activities = update_gps = set_time = version = true; break; - case 'G': update_gps++; break; - case 'g': gqf_url = GQF_GLONASS_URL; break; + case 10: new_pair=false; break; + case 12: debug++; break; + case 0 : get_activities = update_gps = set_time = version = true; break; + case 5 : update_gps++; break; + case 6 : gqf_url = GQF_GLONASS_URL; break; } } if (ch<-1) {