diff options
author | Marcus Meissner <marcus@jet.franken.de> | 2017-04-08 15:27:45 +0200 |
---|---|---|
committer | Marcus Meissner <marcus@jet.franken.de> | 2017-04-08 15:27:45 +0200 |
commit | ae116909d45e11d3eca6f6fd5d504495d6229cbd (patch) | |
tree | 4c86976c90cb72712229909699e4af6a8668068c | |
parent | fe35d7878bb6e77692bb76cfd7c62b3cbb1268ad (diff) | |
parent | 0baea37addf5c6870cb5c601839addc51a346ea9 (diff) | |
download | libgphoto2-ae116909d45e11d3eca6f6fd5d504495d6229cbd.tar.gz |
Merge branch 'pentax'
New Pentax K DSLR implementation
-rw-r--r-- | camlibs/pentax/Makefile-files | 2 | ||||
-rw-r--r-- | camlibs/pentax/exiftool_pentax_lens.txt | 212 | ||||
-rw-r--r-- | camlibs/pentax/library.c | 658 | ||||
-rw-r--r-- | camlibs/pentax/pslr.c | 2196 | ||||
-rw-r--r-- | camlibs/pentax/pslr.h | 302 | ||||
-rw-r--r-- | camlibs/pentax/pslr_enum.c | 303 | ||||
-rw-r--r-- | camlibs/pentax/pslr_enum.h | 214 | ||||
-rw-r--r-- | camlibs/pentax/pslr_lens.c | 51 | ||||
-rw-r--r-- | camlibs/pentax/pslr_lens.h | 34 | ||||
-rw-r--r-- | camlibs/pentax/pslr_model.c | 750 | ||||
-rw-r--r-- | camlibs/pentax/pslr_model.h | 167 | ||||
-rw-r--r-- | camlibs/pentax/pslr_scsi.h | 83 |
12 files changed, 3587 insertions, 1385 deletions
diff --git a/camlibs/pentax/Makefile-files b/camlibs/pentax/Makefile-files index c9a64005e..c8d944220 100644 --- a/camlibs/pentax/Makefile-files +++ b/camlibs/pentax/Makefile-files @@ -5,7 +5,7 @@ EXTRA_DIST += pentax/README.pentax pentax/ChangeLog camlibdoc_DATA += pentax/README.pentax EXTRA_LTLIBRARIES += pentax.la -pentax_la_SOURCES = pentax/pslr.c pentax/pslr.h pentax/library.c +pentax_la_SOURCES = pentax/pslr.c pentax/library.c pentax/pslr_enum.c pentax/pslr_lens.c pentax/pslr_model.c pentax/pslr_enum.h pentax/pslr.h pentax/pslr_lens.h pentax/pslr_model.h pentax/pslr_scsi.h pentax/exiftool_pentax_lens.txt pentax_la_CFLAGS = $(AM_CFLAGS) $(NO_UNUSED_CFLAGS) $(CFLAGS) -DLIBGPHOTO2 pentax_la_LDFLAGS = $(camlib_ldflags) pentax_la_DEPENDENCIES = $(camlib_dependencies) diff --git a/camlibs/pentax/exiftool_pentax_lens.txt b/camlibs/pentax/exiftool_pentax_lens.txt new file mode 100644 index 000000000..37d7cbf4e --- /dev/null +++ b/camlibs/pentax/exiftool_pentax_lens.txt @@ -0,0 +1,212 @@ +{0, 0, "M-42 or No Lens"}, +{1, 0, "K or M Lens"}, +{2, 0, "A Series Lens"}, +{3, 0, "Sigma"}, +{3, 17, "smc PENTAX-FA SOFT 85mm F2.8"}, +{3, 18, "smc PENTAX-F 1.7X AF ADAPTER"}, +{3, 19, "smc PENTAX-F 24-50mm F4"}, +{3, 20, "smc PENTAX-F 35-80mm F4-5.6"}, +{3, 21, "smc PENTAX-F 80-200mm F4.7-5.6"}, +{3, 22, "smc PENTAX-F FISH-EYE 17-28mm F3.5-4.5"}, +{3, 23, "smc PENTAX-F 100-300mm F4.5-5.6 or Sigma Lens"}, +{3, 24, "smc PENTAX-F 35-135mm F3.5-4.5"}, +{3, 25, "smc PENTAX-F 35-105mm F4-5.6 or Sigma or Tokina Lens"}, +{3, 26, "smc PENTAX-F* 250-600mm F5.6 ED[IF]"}, +{3, 27, "smc PENTAX-F 28-80mm F3.5-4.5 or Tokina Lens"}, +{3, 28, "smc PENTAX-F 35-70mm F3.5-4.5 or Tokina Lens"}, +{3, 29, "PENTAX-F 28-80mm F3.5-4.5 or Sigma or Tokina Lens"}, +{3, 30, "PENTAX-F 70-200mm F4-5.6"}, +{3, 31, "smc PENTAX-F 70-210mm F4-5.6 or Tokina or Takumar Lens"}, +{3, 32, "smc PENTAX-F 50mm F1.4"}, +{3, 33, "smc PENTAX-F 50mm F1.7"}, +{3, 34, "smc PENTAX-F 135mm F2.8 [IF]"}, +{3, 35, "smc PENTAX-F 28mm F2.8"}, +{3, 36, "Sigma 20mm F1.8 EX DG Aspherical RF"}, +{3, 38, "smc PENTAX-F* 300mm F4.5 ED[IF]"}, +{3, 39, "smc PENTAX-F* 600mm F4 ED[IF]"}, +{3, 40, "smc PENTAX-F Macro 100mm F2.8"}, +{3, 41, "smc PENTAX-F Macro 50mm F2.8 or Sigma Lens"}, +{3, 42, "Sigma 300mm F2.8 EX DG APO IF"}, +{3, 44, "Sigma or Tamron Lens (3 44)"}, +{3, 46, "Sigma or Samsung Lens (3 46)"}, +{3, 50, "smc PENTAX-FA 28-70mm F4 AL"}, +{3, 51, "Sigma 28mm F1.8 EX DG Aspherical Macro"}, +{3, 52, "smc PENTAX-FA 28-200mm F3.8-5.6 AL[IF] or Tamron Lens"}, +{3, 53, "smc PENTAX-FA 28-80mm F3.5-5.6 AL"}, +{3, 247, "smc PENTAX-DA FISH-EYE 10-17mm F3.5-4.5 ED[IF]"}, +{3, 248, "smc PENTAX-DA 12-24mm F4 ED AL[IF]"}, +{3, 250, "smc PENTAX-DA 50-200mm F4-5.6 ED"}, +{3, 251, "smc PENTAX-DA 40mm F2.8 Limited"}, +{3, 252, "smc PENTAX-DA 18-55mm F3.5-5.6 AL"}, +{3, 253, "smc PENTAX-DA 14mm F2.8 ED[IF]"}, +{3, 254, "smc PENTAX-DA 16-45mm F4 ED AL"}, +{3, 255, "Sigma Lens (3 255)"}, +{4, 1, "smc PENTAX-FA SOFT 28mm F2.8"}, +{4, 2, "smc PENTAX-FA 80-320mm F4.5-5.6"}, +{4, 3, "smc PENTAX-FA 43mm F1.9 Limited"}, +{4, 6, "smc PENTAX-FA 35-80mm F4-5.6"}, +{4, 10, "Irix 15mm F2.4"}, +{4, 12, "smc PENTAX-FA 50mm F1.4"}, +{4, 15, "smc PENTAX-FA 28-105mm F4-5.6 [IF]"}, +{4, 16, "Tamron AF 80-210mm F4-5.6 (178D)"}, +{4, 19, "Tamron SP AF 90mm F2.8 (172E)"}, +{4, 20, "smc PENTAX-FA 28-80mm F3.5-5.6"}, +{4, 21, "Cosina AF 100-300mm F5.6-6.7"}, +{4, 22, "Tokina 28-80mm F3.5-5.6"}, +{4, 23, "smc PENTAX-FA 20-35mm F4 AL"}, +{4, 24, "smc PENTAX-FA 77mm F1.8 Limited"}, +{4, 25, "Tamron SP AF 14mm F2.8"}, +{4, 26, "smc PENTAX-FA Macro 100mm F3.5 or Cosina Lens"}, +{4, 27, "Tamron AF 28-300mm F3.5-6.3 LD Aspherical[IF] Macro (185D/285D)"}, +{4, 28, "smc PENTAX-FA 35mm F2 AL"}, +{4, 29, "Tamron AF 28-200mm F3.8-5.6 LD Super II Macro (371D)"}, +{4, 34, "smc PENTAX-FA 24-90mm F3.5-4.5 AL[IF]"}, +{4, 35, "smc PENTAX-FA 100-300mm F4.7-5.8"}, +{4, 36, "Tamron AF 70-300mm F4-5.6 LD Macro 1:2"}, +{4, 37, "Tamron SP AF 24-135mm F3.5-5.6 AD AL (190D)"}, +{4, 38, "smc PENTAX-FA 28-105mm F3.2-4.5 AL[IF]"}, +{4, 39, "smc PENTAX-FA 31mm F1.8 AL Limited"}, +{4, 41, "Tamron AF 28-200mm Super Zoom F3.8-5.6 Aspherical XR [IF] Macro (A03)"}, +{4, 43, "smc PENTAX-FA 28-90mm F3.5-5.6"}, +{4, 44, "smc PENTAX-FA J 75-300mm F4.5-5.8 AL"}, +{4, 45, "Tamron Lens (4 45)"}, +{4, 46, "smc PENTAX-FA J 28-80mm F3.5-5.6 AL"}, +{4, 47, "smc PENTAX-FA J 18-35mm F4-5.6 AL"}, +{4, 49, "Tamron SP AF 28-75mm F2.8 XR Di LD Aspherical [IF] Macro"}, +{4, 51, "smc PENTAX-D FA 50mm F2.8 Macro"}, +{4, 52, "smc PENTAX-D FA 100mm F2.8 Macro"}, +{4, 55, "Samsung/Schneider D-XENOGON 35mm F2"}, +{4, 56, "Samsung/Schneider D-XENON 100mm F2.8 Macro"}, +{4, 75, "Tamron SP AF 70-200mm F2.8 Di LD [IF] Macro (A001)"}, +{4, 214, "smc PENTAX-DA 35mm F2.4 AL"}, +{4, 229, "smc PENTAX-DA 18-55mm F3.5-5.6 AL II"}, +{4, 230, "Tamron SP AF 17-50mm F2.8 XR Di II"}, +{4, 231, "smc PENTAX-DA 18-250mm F3.5-6.3 ED AL [IF]"}, +{4, 237, "Samsung/Schneider D-XENOGON 10-17mm F3.5-4.5"}, +{4, 239, "Samsung/Schneider D-XENON 12-24mm F4 ED AL [IF]"}, +{4, 242, "smc PENTAX-DA* 16-50mm F2.8 ED AL [IF] SDM (SDM unused)"}, +{4, 243, "smc PENTAX-DA 70mm F2.4 Limited"}, +{4, 244, "smc PENTAX-DA 21mm F3.2 AL Limited"}, +{4, 245, "Samsung/Schneider D-XENON 50-200mm F4-5.6"}, +{4, 246, "Samsung/Schneider D-XENON 18-55mm F3.5-5.6"}, +{4, 247, "smc PENTAX-DA FISH-EYE 10-17mm F3.5-4.5 ED[IF]"}, +{4, 248, "smc PENTAX-DA 12-24mm F4 ED AL [IF]"}, +{4, 249, "Tamron XR DiII 18-200mm F3.5-6.3 (A14)"}, +{4, 250, "smc PENTAX-DA 50-200mm F4-5.6 ED"}, +{4, 251, "smc PENTAX-DA 40mm F2.8 Limited"}, +{4, 252, "smc PENTAX-DA 18-55mm F3.5-5.6 AL"}, +{4, 253, "smc PENTAX-DA 14mm F2.8 ED[IF]"}, +{4, 254, "smc PENTAX-DA 16-45mm F4 ED AL"}, +{5, 1, "smc PENTAX-FA* 24mm F2 AL[IF]"}, +{5, 2, "smc PENTAX-FA 28mm F2.8 AL"}, +{5, 3, "smc PENTAX-FA 50mm F1.7"}, +{5, 4, "smc PENTAX-FA 50mm F1.4"}, +{5, 5, "smc PENTAX-FA* 600mm F4 ED[IF]"}, +{5, 6, "smc PENTAX-FA* 300mm F4.5 ED[IF]"}, +{5, 7, "smc PENTAX-FA 135mm F2.8 [IF]"}, +{5, 8, "smc PENTAX-FA Macro 50mm F2.8"}, +{5, 9, "smc PENTAX-FA Macro 100mm F2.8"}, +{5, 10, "smc PENTAX-FA* 85mm F1.4 [IF]"}, +{5, 11, "smc PENTAX-FA* 200mm F2.8 ED[IF]"}, +{5, 12, "smc PENTAX-FA 28-80mm F3.5-4.7"}, +{5, 13, "smc PENTAX-FA 70-200mm F4-5.6"}, +{5, 14, "smc PENTAX-FA* 250-600mm F5.6 ED[IF]"}, +{5, 15, "smc PENTAX-FA 28-105mm F4-5.6"}, +{5, 16, "smc PENTAX-FA 100-300mm F4.5-5.6"}, +{5, 98, "smc PENTAX-FA 100-300mm F4.5-5.6"}, +{6, 1, "smc PENTAX-FA* 85mm F1.4 [IF]"}, +{6, 2, "smc PENTAX-FA* 200mm F2.8 ED[IF]"}, +{6, 3, "smc PENTAX-FA* 300mm F2.8 ED[IF]"}, +{6, 4, "smc PENTAX-FA* 28-70mm F2.8 AL"}, +{6, 5, "smc PENTAX-FA* 80-200mm F2.8 ED[IF]"}, +{6, 6, "smc PENTAX-FA* 28-70mm F2.8 AL"}, +{6, 7, "smc PENTAX-FA* 80-200mm F2.8 ED[IF]"}, +{6, 8, "smc PENTAX-FA 28-70mm F4AL"}, +{6, 9, "smc PENTAX-FA 20mm F2.8"}, +{6, 10, "smc PENTAX-FA* 400mm F5.6 ED[IF]"}, +{6, 13, "smc PENTAX-FA* 400mm F5.6 ED[IF]"}, +{6, 14, "smc PENTAX-FA* Macro 200mm F4 ED[IF]"}, +{7, 0, "smc PENTAX-DA 21mm F3.2 AL Limited"}, +{7, 58, "smc PENTAX-D FA Macro 100mm F2.8 WR"}, +{7, 75, "Tamron SP AF 70-200mm F2.8 Di LD [IF] Macro (A001)"}, +{7, 201, "smc Pentax-DA L 50-200mm F4-5.6 ED WR"}, +{7, 202, "smc PENTAX-DA L 18-55mm F3.5-5.6 AL WR"}, +{7, 203, "HD PENTAX-DA 55-300mm F4-5.8 ED WR"}, +{7, 204, "HD PENTAX-DA 15mm F4 ED AL Limited"}, +{7, 205, "HD PENTAX-DA 35mm F2.8 Macro Limited"}, +{7, 206, "HD PENTAX-DA 70mm F2.4 Limited"}, +{7, 207, "HD PENTAX-DA 21mm F3.2 ED AL Limited"}, +{7, 208, "HD PENTAX-DA 40mm F2.8 Limited"}, +{7, 212, "smc PENTAX-DA 50mm F1.8"}, +{7, 213, "smc PENTAX-DA 40mm F2.8 XS"}, +{7, 214, "smc PENTAX-DA 35mm F2.4 AL"}, +{7, 216, "smc PENTAX-DA L 55-300mm F4-5.8 ED"}, +{7, 217, "smc PENTAX-DA 50-200mm F4-5.6 ED WR"}, +{7, 218, "smc PENTAX-DA 18-55mm F3.5-5.6 AL WR"}, +{7, 220, "Tamron SP AF 10-24mm F3.5-4.5 Di II LD Aspherical [IF]"}, +{7, 221, "smc PENTAX-DA L 50-200mm F4-5.6 ED"}, +{7, 222, "smc PENTAX-DA L 18-55mm F3.5-5.6"}, +{7, 223, "Samsung/Schneider D-XENON 18-55mm F3.5-5.6 II"}, +{7, 224, "smc PENTAX-DA 15mm F4 ED AL Limited"}, +{7, 225, "Samsung/Schneider D-XENON 18-250mm F3.5-6.3"}, +{7, 226, "smc PENTAX-DA* 55mm F1.4 SDM (SDM unused)"}, +{7, 227, "smc PENTAX-DA* 60-250mm F4 [IF] SDM (SDM unused)"}, +{7, 228, "Samsung 16-45mm F4 ED"}, +{7, 229, "smc PENTAX-DA 18-55mm F3.5-5.6 AL II"}, +{7, 230, "Tamron AF 17-50mm F2.8 XR Di-II LD (Model A16)"}, +{7, 231, "smc PENTAX-DA 18-250mm F3.5-6.3 ED AL [IF]"}, +{7, 233, "smc PENTAX-DA 35mm F2.8 Macro Limited"}, +{7, 234, "smc PENTAX-DA* 300mm F4 ED [IF] SDM (SDM unused)"}, +{7, 235, "smc PENTAX-DA* 200mm F2.8 ED [IF] SDM (SDM unused)"}, +{7, 236, "smc PENTAX-DA 55-300mm F4-5.8 ED"}, +{7, 238, "Tamron AF 18-250mm F3.5-6.3 Di II LD Aspherical [IF] Macro"}, +{7, 241, "smc PENTAX-DA* 50-135mm F2.8 ED [IF] SDM (SDM unused)"}, +{7, 242, "smc PENTAX-DA* 16-50mm F2.8 ED AL [IF] SDM (SDM unused)"}, +{7, 243, "smc PENTAX-DA 70mm F2.4 Limited"}, +{7, 244, "smc PENTAX-DA 21mm F3.2 AL Limited"}, +{8, 0, "Sigma 50-150mm F2.8 II APO EX DC HSM"}, +{8, 3, "Sigma AF 18-125mm F3.5-5.6 DC"}, +{8, 4, "Sigma 50mm F1.4 EX DG HSM"}, +{8, 7, "Sigma 24-70mm F2.8 IF EX DG HSM"}, +{8, 8, "Sigma 18-250mm F3.5-6.3 DC OS HSM"}, +{8, 11, "Sigma 10-20mm F3.5 EX DC HSM"}, +{8, 12, "Sigma 70-300mm F4-5.6 DG OS"}, +{8, 13, "Sigma 120-400mm F4.5-5.6 APO DG OS HSM"}, +{8, 14, "Sigma 17-70mm F2.8-4.0 DC Macro OS HSM"}, +{8, 15, "Sigma 150-500mm F5-6.3 APO DG OS HSM"}, +{8, 16, "Sigma 70-200mm F2.8 EX DG Macro HSM II"}, +{8, 17, "Sigma 50-500mm F4.5-6.3 DG OS HSM"}, +{8, 18, "Sigma 8-16mm F4.5-5.6 DC HSM"}, +{8, 21, "Sigma 17-50mm F2.8 EX DC OS HSM"}, +{8, 22, "Sigma 85mm F1.4 EX DG HSM"}, +{8, 23, "Sigma 70-200mm F2.8 APO EX DG OS HSM"}, +{8, 25, "Sigma 17-50mm F2.8 EX DC HSM"}, +{8, 27, "Sigma 18-200mm F3.5-6.3 II DC HSM"}, +{8, 28, "Sigma 18-250mm F3.5-6.3 DC Macro HSM"}, +{8, 29, "Sigma 35mm F1.4 DG HSM"}, +{8, 30, "Sigma 17-70mm F2.8-4 DC Macro HSM | C"}, +{8, 31, "Sigma 18-35mm F1.8 DC HSM"}, +{8, 32, "Sigma 30mm F1.4 DC HSM | A"}, +{8, 34, "Sigma 18-300mm F3.5-6.3 DC Macro HSM"}, +{8, 59, "HD PENTAX-D FA 150-450mm F4.5-5.6 ED DC AW"}, +{8, 60, "HD PENTAX-D FA* 70-200mm F2.8 ED DC AW"}, +{8, 61, "HD PENTAX-D FA 28-105mm F3.5-5.6 ED DC WR"}, +{8, 62, "HD PENTAX-D FA 24-70mm F2.8 ED SDM WR"}, +{8, 63, "HD PENTAX-D FA 15-30mm F2.8 ED SDM WR"}, +{8, 197, "HD PENTAX-DA 55-300mm F4.5-6.3 ED PLM WR RE"}, +{8, 198, "smc PENTAX-DA L 18-50mm F4-5.6 DC WR RE"}, +{8, 199, "HD PENTAX-DA 18-50mm F4-5.6 DC WR RE"}, +{8, 200, "HD PENTAX-DA 16-85mm F3.5-5.6 ED DC WR"}, +{8, 209, "HD PENTAX-DA 20-40mm F2.8-4 ED Limited DC WR"}, +{8, 210, "smc PENTAX-DA 18-270mm F3.5-6.3 ED SDM"}, +{8, 211, "HD PENTAX-DA 560mm F5.6 ED AW"}, +{8, 215, "smc PENTAX-DA 18-135mm F3.5-5.6 ED AL [IF] DC WR"}, +{8, 226, "smc PENTAX-DA* 55mm F1.4 SDM"}, +{8, 227, "smc PENTAX-DA* 60-250mm F4 [IF] SDM"}, +{8, 232, "smc PENTAX-DA 17-70mm F4 AL [IF] SDM"}, +{8, 234, "smc PENTAX-DA* 300mm F4 ED [IF] SDM"}, +{8, 235, "smc PENTAX-DA* 200mm F2.8 ED [IF] SDM"}, +{8, 241, "smc PENTAX-DA* 50-135mm F2.8 ED [IF] SDM"}, +{8, 242, "smc PENTAX-DA* 16-50mm F2.8 ED AL [IF] SDM"}, +{8, 255, "Sigma Lens (8 255)"}, +{9, 0, "645 Manual Lens"}, diff --git a/camlibs/pentax/library.c b/camlibs/pentax/library.c index 10e6c36cd..926306fb5 100644 --- a/camlibs/pentax/library.c +++ b/camlibs/pentax/library.c @@ -1,6 +1,6 @@ -/* Pentax K series library + /* Pentax K series library * - * Copyright (c) 2011 Marcus Meissner <meissner@suse.de> + * Copyright (c) 2011,2017 Marcus Meissner <meissner@suse.de> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -18,7 +18,7 @@ * Boston, MA 02110-1301 USA */ -#define _BSD_SOURCE +#define _DEFAULT_SOURCE #include "config.h" @@ -27,6 +27,7 @@ #include <string.h> #include <stdlib.h> #include <stdio.h> +#include <unistd.h> #include <sys/time.h> #include <stdbool.h> @@ -50,6 +51,14 @@ # define N_(String) (String) #endif +bool debug = true; + +struct _CameraPrivateLibrary { + ipslr_handle_t pslr; + char *lastfn; + int capcnt; +}; + int camera_id (CameraText *id) { @@ -65,12 +74,12 @@ camera_abilities (CameraAbilitiesList *list) memset (&a, 0, sizeof(a)); strcpy (a.model, "Pentax:K20D"); - a.status = GP_DRIVER_STATUS_EXPERIMENTAL; + a.status = GP_DRIVER_STATUS_TESTING; a.port = GP_PORT_USB_SCSI; a.speed[0] = 0; a.usb_vendor = 0x0a17; a.usb_product = 0x0091; - a.operations = GP_OPERATION_CAPTURE_IMAGE | GP_OPERATION_CONFIG; + a.operations = GP_OPERATION_CAPTURE_IMAGE | GP_OPERATION_CONFIG | GP_OPERATION_TRIGGER_CAPTURE; a.folder_operations = GP_FOLDER_OPERATION_NONE; a.file_operations = GP_FILE_OPERATION_DELETE; if (GP_OK != (ret = gp_abilities_list_append (list, a))) @@ -101,6 +110,12 @@ camera_abilities (CameraAbilitiesList *list) if (GP_OK != (ret = gp_abilities_list_append (list, a))) return ret; + strcpy (a.model, "Pentax:K50D"); + // same usb vendor like Pentax K5D + a.usb_product = 0x0160; + if (GP_OK != (ret = gp_abilities_list_append (list, a))) + return ret; + strcpy (a.model, "Pentax:K30"); // same usb vendor like Pentax K5D a.usb_product = 0x0132; @@ -116,13 +131,51 @@ camera_abilities (CameraAbilitiesList *list) } +int scsi_write(GPPort *port, uint8_t *cmd, uint32_t cmdLen, + uint8_t *buf, uint32_t bufLen) { + int ret; + char sense_buffer[32]; + + ret = gp_port_send_scsi_cmd (port, 1, (char*)cmd, cmdLen, + sense_buffer, sizeof(sense_buffer), (char*)buf, bufLen); + if (ret == GP_OK) return PSLR_OK; + return PSLR_SCSI_ERROR; +} + +int scsi_read(GPPort *port, uint8_t *cmd, uint32_t cmdLen, + uint8_t *buf, uint32_t bufLen) +{ + int ret; + char sense_buffer[32]; + + ret = gp_port_send_scsi_cmd (port, 0, (char*)cmd, cmdLen, + sense_buffer, sizeof(sense_buffer), (char*)buf, bufLen); + if (ret == GP_OK) return bufLen; + return -PSLR_SCSI_ERROR; +} + +void close_drive(GPPort **port) { + /* is going to be closed by other means */ + return; +} + + + static int camera_summary (Camera *camera, CameraText *summary, GPContext *context) { + char *statusinfo; + pslr_status status; + + pslr_get_status (&camera->pl->pslr, &status); + + statusinfo = collect_status_info( &camera->pl->pslr, status ); + sprintf (summary->text, _( "Pentax K DSLR capture driver.\n" - "Based on pkremote by Pontus Lidman.\n" - )); + "Using code from pktriggercord by Andras Salamon.\n" + "Collected Status Information:\n%s" + ), statusinfo); return GP_OK; } @@ -159,29 +212,13 @@ static CameraFilesystemFuncs fsfuncs = { }; static int -save_buffer(pslr_handle_t camhandle, int bufno, CameraFile *file, pslr_status *status) +save_buffer(pslr_handle_t camhandle, int bufno, pslr_buffer_type buftype, uint32_t jpegres, CameraFile *file) { - int imagetype; - int image_resolution; - uint8_t buf[65536]; - uint32_t current; + uint8_t buf[65536]; + uint32_t current; - switch (status->image_format) { - case PSLR_IMAGE_FORMAT_JPEG: - imagetype = status->jpeg_quality + 1; - image_resolution = status->jpeg_resolution; - break; - case PSLR_IMAGE_FORMAT_RAW: - imagetype = 0; - image_resolution = 0; - break; - default: - gp_log (GP_LOG_ERROR, "pentax", "Sorry, only JPEG and PEF RAW files are supported\n"); - return GP_ERROR; - } - - GP_DEBUG("get buffer %d type %d res %d\n", bufno, imagetype, image_resolution); - if ( pslr_buffer_open(camhandle, bufno, imagetype, status->jpeg_resolution) != PSLR_OK) + gp_log(GP_LOG_DEBUG, "pentax", "save_buffer: get buffer %d type %d res %d\n", bufno, buftype, jpegres); + if ( pslr_buffer_open(camhandle, bufno, buftype, jpegres) != PSLR_OK) return GP_ERROR; current = 0; @@ -191,8 +228,7 @@ save_buffer(pslr_handle_t camhandle, int bufno, CameraFile *file, pslr_status *s if (bytes == 0) break; // PEF file got from K100D Super have broken header, WTF? - if (current == 0 && status->image_format == PSLR_IMAGE_FORMAT_RAW && - status->raw_format == PSLR_RAW_FORMAT_PEF) { + if (current == 0 && (buftype == PSLR_BUF_PEF)) { const unsigned char correct_header[92] = { 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, @@ -220,81 +256,161 @@ save_buffer(pslr_handle_t camhandle, int bufno, CameraFile *file, pslr_status *s return current; } -static int capcnt = 0; +static int +_timeout_passed(struct timeval *start, int timeout) { + struct timeval curtime; + + gettimeofday (&curtime, NULL); + return ((curtime.tv_sec - start->tv_sec)*1000)+((curtime.tv_usec - start->tv_usec)/1000) >= timeout; +} static int camera_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path, GPContext *context) { - pslr_handle_t p = camera->pl; + pslr_handle_t p = &camera->pl->pslr; pslr_status status; int ret, length; CameraFile *file = NULL; CameraFileInfo info; + int bufno, i; + const char *mimes[2]; + int buftypes[2], jpegres[2], nrofdownloads = 1; + char *fns[2], *lastfn = NULL; + struct timeval event_start; + + gp_log (GP_LOG_DEBUG, "pentax", "camera_capture"); pslr_get_status (p, &status); pslr_shutter (p); strcpy (path->folder, "/"); - const char *mime; - if (status.image_format == PSLR_IMAGE_FORMAT_JPEG) { - sprintf (path->name, "capt%04d.jpg", capcnt++); - mime = GP_MIME_JPEG; - } else if (status.image_format == PSLR_IMAGE_FORMAT_RAW && - status.raw_format == PSLR_RAW_FORMAT_PEF) { - sprintf (path->name, "capt%04d.pef", capcnt++); - mime = GP_MIME_RAW; - } else { + gp_log (GP_LOG_ERROR, "pentax", "image format image=0x%x, raw=0x%x", status.image_format, status.raw_format); + switch (status.image_format) { + case PSLR_IMAGE_FORMAT_JPEG: + sprintf (path->name, "capt%04d.jpg", camera->pl->capcnt++); + mimes[0] = GP_MIME_JPEG; + buftypes[0] = status.jpeg_quality + 1; + jpegres[0] = status.jpeg_resolution; + fns[0] = strdup(path->name); + break; + case PSLR_IMAGE_FORMAT_RAW_PLUS: /* FIXME: the same as _RAW ? */ + buftypes[1] = status.jpeg_quality + 1; + jpegres[1] = status.jpeg_resolution; + mimes[1] = GP_MIME_JPEG; + sprintf (path->name, "capt%04d.jpg", camera->pl->capcnt); + fns[1] = strdup(path->name); + lastfn = strdup (fns[1]); + nrofdownloads = 2; + /* FALLTHROUGH */ + case PSLR_IMAGE_FORMAT_RAW: + jpegres[0] = 0; + switch (status.raw_format) { + case PSLR_RAW_FORMAT_PEF: + sprintf (path->name, "capt%04d.pef", camera->pl->capcnt++); + fns[0] = strdup (path->name); + mimes[0] = GP_MIME_RAW; + buftypes[0] = PSLR_BUF_PEF; + break; + case PSLR_RAW_FORMAT_DNG: + sprintf (path->name, "capt%04d.dng", camera->pl->capcnt++); + fns[0] = strdup (path->name); + mimes[0] = "image/x-adobe-dng"; + buftypes[0] = PSLR_BUF_DNG; + break; + default: + gp_log (GP_LOG_ERROR, "pentax", "unknown format image=0x%x, raw=0x%x", status.image_format, status.raw_format); + return GP_ERROR; + } + break; + default: + gp_log (GP_LOG_ERROR, "pentax", "unknown format image=0x%x (raw=0x%x)", status.image_format, status.raw_format); return GP_ERROR; } + /* get status again, also waits until not busy */ + pslr_get_status (p, &status); - ret = gp_file_new(&file); - if (ret!=GP_OK) return ret; - gp_file_set_mtime (file, time(NULL)); - gp_file_set_mime_type (file, mime); - + gettimeofday (&event_start, 0); while (1) { - length = save_buffer( p, (int)0, file, &status); - if (length == GP_ERROR_NOT_SUPPORTED) return length; - if (length >= GP_OK) + if (status.bufmask != 0) + break; + if (_timeout_passed (&event_start, 30*1000)) break; - usleep(100000); + usleep(100*1000); /* 100 ms */ + pslr_get_status (p, &status); } - pslr_delete_buffer(p, (int)0 ); - - gp_log (GP_LOG_DEBUG, "pentax", "append image to fs"); - ret = gp_filesystem_append(camera->fs, path->folder, path->name, context); - if (ret != GP_OK) { - gp_file_free (file); - return ret; + if (status.bufmask == 0) { + gp_log (GP_LOG_ERROR, "pentax", "no buffer available for download after 30 seconds."); + free (lastfn); + return GP_ERROR; } - gp_log (GP_LOG_DEBUG, "pentax", "adding filedata to fs"); - ret = gp_filesystem_set_file_noop(camera->fs, path->folder, path->name, GP_FILE_TYPE_NORMAL, file, context); - if (ret != GP_OK) { - gp_file_free (file); - return ret; + for (bufno=0;bufno<16;bufno++) + if (status.bufmask & (1 << bufno)) + break; + /* we will have found one if bufmask != 0 */ + + for (i = 0; i<nrofdownloads; i++ ) { + ret = gp_file_new(&file); + if (ret!=GP_OK) return ret; + gp_file_set_mtime (file, time(NULL)); + gp_file_set_mime_type (file, mimes[i]); + + while (1) { + length = save_buffer( p, bufno, buftypes[i], jpegres[i], file); + if (length == GP_ERROR_NOT_SUPPORTED) return length; + if (length >= GP_OK) + break; + usleep(100000); + } + + gp_log (GP_LOG_DEBUG, "pentax", "append image to fs"); + ret = gp_filesystem_append(camera->fs, path->folder, fns[i], context); + if (ret != GP_OK) { + gp_file_free (file); + return ret; + } + gp_log (GP_LOG_DEBUG, "pentax", "adding filedata to fs"); + ret = gp_filesystem_set_file_noop(camera->fs, path->folder, fns[i], GP_FILE_TYPE_NORMAL, file, context); + if (ret != GP_OK) { + gp_file_free (file); + return ret; + } + /* We have now handed over the file, disclaim responsibility by unref. */ + gp_file_unref (file); + /* we also get the fs info for free, so just set it */ + info.file.fields = GP_FILE_INFO_TYPE | + GP_FILE_INFO_SIZE | GP_FILE_INFO_MTIME; + strcpy (info.file.type, GP_MIME_JPEG); + info.file.size = length; + info.file.mtime = time(NULL); + + info.preview.fields = 0; + gp_log (GP_LOG_DEBUG, "pentax", "setting fileinfo in fs"); + ret = gp_filesystem_set_info_noop(camera->fs, path->folder, fns[i], info, context); + free (fns[i]); } - /* We have now handed over the file, disclaim responsibility by unref. */ - gp_file_unref (file); - /* we also get the fs info for free, so just set it */ - info.file.fields = GP_FILE_INFO_TYPE | - GP_FILE_INFO_SIZE | GP_FILE_INFO_MTIME; - strcpy (info.file.type, GP_MIME_JPEG); - info.file.size = length; - info.file.mtime = time(NULL); - - info.preview.fields = 0; - gp_log (GP_LOG_DEBUG, "pentax", "setting fileinfo in fs"); - ret = gp_filesystem_set_info_noop(camera->fs, path->folder, path->name, info, context); + camera->pl->lastfn = lastfn; + + pslr_delete_buffer(p, bufno ); + pslr_get_status (&camera->pl->pslr, &status); /* wait until busy is gone */ + return ret; } static int -_timeout_passed(struct timeval *start, int timeout) { - struct timeval curtime; +camera_trigger_capture (Camera *camera, GPContext *context) +{ + pslr_handle_t p = &camera->pl->pslr; + pslr_status status; - gettimeofday (&curtime, NULL); - return ((curtime.tv_sec - start->tv_sec)*1000)+((curtime.tv_usec - start->tv_usec)/1000) >= timeout; + gp_log (GP_LOG_DEBUG, "pentax", "camera_trigger_capture"); + + pslr_get_status (p, &status); + pslr_shutter (p); + /* get status again, also waits until not busy */ + pslr_get_status (p, &status); + + return GP_OK; } @@ -304,82 +420,137 @@ camera_wait_for_event (Camera *camera, int timeout, GPContext *context) { struct timeval event_start; CameraFilePath *path; - pslr_handle_t p = camera->pl; + pslr_handle_t p = &camera->pl->pslr; int ret, length; CameraFile *file = NULL; CameraFileInfo info; + gp_log (GP_LOG_DEBUG, "pentax", "camera_wait_for_event %d ms", timeout); + *eventtype = GP_EVENT_TIMEOUT; *eventdata = NULL; + if (camera->pl->lastfn) { + path = malloc(sizeof(CameraFilePath)); + strcpy (path->folder, "/"); + strcpy (path->name, camera->pl->lastfn); + free (camera->pl->lastfn); + camera->pl->lastfn = NULL; + *eventtype = GP_EVENT_FILE_ADDED; + *eventdata = path; + return GP_OK; + } + gettimeofday (&event_start, 0); while (1) { pslr_status status; - int bufno; + int i, bufno; + const char *mimes[2]; + int buftypes[2], jpegres[2], nrofdownloads = 1; + char *fns[2]; - if (PSLR_OK != pslr_get_status (camera->pl, &status)) + if (PSLR_OK != pslr_get_status (&camera->pl->pslr, &status)) break; if (status.bufmask == 0) goto next; + gp_log (GP_LOG_ERROR, "pentax", "wait_for_event: new image found! mask 0x%x", status.bufmask); /* New image on camera! */ for (bufno=0;bufno<16;bufno++) if (status.bufmask & (1<<bufno)) break; if (bufno == 16) goto next; - const char *mime; path = malloc(sizeof(CameraFilePath)); strcpy (path->folder, "/"); - if (status.image_format == PSLR_IMAGE_FORMAT_JPEG) { - sprintf (path->name, "capt%04d.jpg", capcnt++); - mime = GP_MIME_JPEG; - } else if (status.image_format == PSLR_IMAGE_FORMAT_RAW && - status.raw_format == PSLR_RAW_FORMAT_PEF) { - sprintf (path->name, "capt%04d.pef", capcnt++); - mime = GP_MIME_RAW; - } else { + gp_log (GP_LOG_ERROR, "pentax", "wait_for_event: imageformat %d / rawformat %d", status.image_format, status.raw_format); + switch (status.image_format) { + case PSLR_IMAGE_FORMAT_JPEG: + sprintf (path->name, "capt%04d.jpg", camera->pl->capcnt++); + mimes[0] = GP_MIME_JPEG; + buftypes[0] = status.jpeg_quality + 1; + jpegres[0] = status.jpeg_resolution; + fns[0] = strdup (path->name); + break; + case PSLR_IMAGE_FORMAT_RAW_PLUS: /* FIXME: the same as _RAW ? */ + mimes[1] = GP_MIME_JPEG; + buftypes[1] = status.jpeg_quality + 1; + jpegres[1] = status.jpeg_resolution; + nrofdownloads = 2; + sprintf (path->name, "capt%04d.jpg", camera->pl->capcnt); + fns[1] = strdup (path->name); + /* we pass back the secondary file via the private struct, and return the first */ + camera->pl->lastfn = strdup (fns[1]); + /* FALLTHROUGH */ + case PSLR_IMAGE_FORMAT_RAW: + jpegres[0] = 0; + switch (status.raw_format) { + case PSLR_RAW_FORMAT_PEF: + sprintf (path->name, "capt%04d.pef", camera->pl->capcnt++); + fns[0] = strdup (path->name); + mimes[0] = GP_MIME_RAW; + buftypes[0] = PSLR_BUF_PEF; + break; + case PSLR_RAW_FORMAT_DNG: + sprintf (path->name, "capt%04d.dng", camera->pl->capcnt++); + fns[0] = strdup (path->name); + mimes[0] = "image/x-adobe-dng"; + buftypes[0] = PSLR_BUF_DNG; + break; + default: + gp_log (GP_LOG_ERROR, "pentax", "unknown format image=0x%x, raw=0x%x", status.image_format, status.raw_format); + return GP_ERROR; + } + break; + default: + gp_log (GP_LOG_ERROR, "pentax", "unknown format image=0x%x (raw=0x%x)", status.image_format, status.raw_format); return GP_ERROR; } - ret = gp_file_new(&file); - if (ret!=GP_OK) return ret; - gp_file_set_mtime (file, time(NULL)); - gp_file_set_mime_type (file, mime); + for (i = 0; i < nrofdownloads; i++) { + ret = gp_file_new(&file); + if (ret!=GP_OK) return ret; + gp_file_set_mtime (file, time(NULL)); + gp_file_set_mime_type (file, mimes[i]); + + while (1) { + length = save_buffer( p, bufno, buftypes[i], jpegres[i], file); + if (length == GP_ERROR_NOT_SUPPORTED) return length; + if (length >= GP_OK) + break; + usleep(100000); + } - while (1) { - length = save_buffer( p, bufno, file, &status); - if (length == GP_ERROR_NOT_SUPPORTED) return length; - if (length >= GP_OK) - break; - usleep(100000); - } - pslr_delete_buffer(p, bufno ); - gp_log (GP_LOG_DEBUG, "pentax", "append image to fs"); - ret = gp_filesystem_append(camera->fs, path->folder, path->name, context); - if (ret != GP_OK) { - gp_file_free (file); - return ret; - } - gp_log (GP_LOG_DEBUG, "pentax", "adding filedata to fs"); - ret = gp_filesystem_set_file_noop(camera->fs, path->folder, path->name, GP_FILE_TYPE_NORMAL, file, context); - if (ret != GP_OK) { - gp_file_free (file); - return ret; + gp_log (GP_LOG_DEBUG, "pentax", "append image to fs"); + ret = gp_filesystem_append(camera->fs, path->folder, fns[i], context); + if (ret != GP_OK) { + gp_file_free (file); + return ret; + } + gp_log (GP_LOG_DEBUG, "pentax", "adding filedata to fs"); + ret = gp_filesystem_set_file_noop(camera->fs, path->folder, fns[i], GP_FILE_TYPE_NORMAL, file, context); + if (ret != GP_OK) { + gp_file_free (file); + return ret; + } + /* We have now handed over the file, disclaim responsibility by unref. */ + gp_file_unref (file); + /* we also get the fs info for free, so just set it */ + info.file.fields = GP_FILE_INFO_TYPE | + GP_FILE_INFO_SIZE | GP_FILE_INFO_MTIME; + strcpy (info.file.type, GP_MIME_JPEG); + info.file.size = length; + info.file.mtime = time(NULL); + + info.preview.fields = 0; + gp_log (GP_LOG_DEBUG, "pentax", "setting fileinfo in fs"); + ret = gp_filesystem_set_info_noop(camera->fs, path->folder, fns[i], info, context); + free (fns[i]); } - /* We have now handed over the file, disclaim responsibility by unref. */ - gp_file_unref (file); - /* we also get the fs info for free, so just set it */ - info.file.fields = GP_FILE_INFO_TYPE | - GP_FILE_INFO_SIZE | GP_FILE_INFO_MTIME; - strcpy (info.file.type, GP_MIME_JPEG); - info.file.size = length; - info.file.mtime = time(NULL); + pslr_delete_buffer (p, bufno); + pslr_get_status (&camera->pl->pslr, &status); /* wait until busy is gone */ - info.preview.fields = 0; - gp_log (GP_LOG_DEBUG, "pentax", "setting fileinfo in fs"); - ret = gp_filesystem_set_info_noop(camera->fs, path->folder, path->name, info, context); *eventtype = GP_EVENT_FILE_ADDED; *eventdata = path; return GP_OK; @@ -399,16 +570,17 @@ camera_get_config (Camera *camera, CameraWidget **window, GPContext *context) const char *model; pslr_status status; char buf[20]; - const char **available_resolutions; - int i; + int *available_resolutions; + int i, ival; + float fval; - pslr_get_status (camera->pl, &status); + pslr_get_status (&camera->pl->pslr, &status); - model = pslr_camera_name (camera->pl); + model = pslr_camera_name (&camera->pl->pslr); - available_resolutions = pslr_camera_resolution_steps (camera->pl); + available_resolutions = pslr_get_model_jpeg_resolutions (&camera->pl->pslr); - GP_DEBUG ("*** camera_get_config"); + gp_log (GP_LOG_DEBUG, "pentax", "*** camera_get_config"); gp_widget_new (GP_WIDGET_WINDOW, _("Camera and Driver Configuration"), window); gp_widget_set_name (*window, "main"); @@ -425,12 +597,10 @@ camera_get_config (Camera *camera, CameraWidget **window, GPContext *context) gp_widget_new (GP_WIDGET_RADIO, _("Image format"), &t); gp_widget_set_name (t, "img_format"); - if (pslr_is_image_format_supported(camera->pl, PSLR_IMAGE_FORMAT_JPEG)) - gp_widget_add_choice (t, "JPEG"); - if (pslr_is_image_format_supported(camera->pl, PSLR_IMAGE_FORMAT_RAW)) - gp_widget_add_choice (t, "RAW"); - if (pslr_is_image_format_supported(camera->pl, PSLR_IMAGE_FORMAT_RAW_PLUS)) - gp_widget_add_choice (t, "RAW+"); + /* it seems the upstream code seems to have it always available? */ + gp_widget_add_choice (t, "JPEG"); + gp_widget_add_choice (t, "RAW"); + gp_widget_add_choice (t, "RAW+"); switch (status.image_format) { case PSLR_IMAGE_FORMAT_JPEG: gp_widget_set_value (t, "JPEG"); break; case PSLR_IMAGE_FORMAT_RAW: gp_widget_set_value (t, "RAW"); break; @@ -442,31 +612,35 @@ camera_get_config (Camera *camera, CameraWidget **window, GPContext *context) } gp_widget_append (section, t); - if (pslr_is_image_format_supported(camera->pl, PSLR_IMAGE_FORMAT_JPEG)) { - gp_widget_new (GP_WIDGET_RADIO, _("Image Size"), &t); - gp_widget_set_name (t, "imgsize"); - for (i = 0; i < PSLR_MAX_RESOLUTIONS && available_resolutions[i]; i++) - { - gp_widget_add_choice (t, available_resolutions[i]); - } + gp_widget_new (GP_WIDGET_RADIO, _("Image Size"), &t); + gp_widget_set_name (t, "imgsize"); + for (i = 0; i < MAX_RESOLUTION_SIZE && available_resolutions[i]; i++) + { + char buf[20]; - if (status.jpeg_resolution > 0 && status.jpeg_resolution < PSLR_MAX_RESOLUTIONS) - gp_widget_set_value (t, available_resolutions[status.jpeg_resolution]); - else - gp_widget_set_value (t, _("Unknown")); + sprintf(buf,"%d", available_resolutions[i]); + gp_widget_add_choice (t, buf); + } - gp_widget_append (section, t); + if (status.jpeg_resolution > 0 && status.jpeg_resolution < MAX_RESOLUTION_SIZE) { + char buf[20]; - gp_widget_new (GP_WIDGET_RADIO, _("Image Quality"), &t); - gp_widget_set_name (t, "imgquality"); - gp_widget_add_choice (t, "4"); - gp_widget_add_choice (t, "3"); - gp_widget_add_choice (t, "2"); - gp_widget_add_choice (t, "1"); - sprintf (buf,"%d",status.jpeg_quality); + sprintf(buf, "%d", status.jpeg_resolution); gp_widget_set_value (t, buf); - gp_widget_append (section, t); - } + } else + gp_widget_set_value (t, _("Unknown")); + + gp_widget_append (section, t); + + gp_widget_new (GP_WIDGET_RADIO, _("Image Quality"), &t); + gp_widget_set_name (t, "imgquality"); + gp_widget_add_choice (t, "4"); + gp_widget_add_choice (t, "3"); + gp_widget_add_choice (t, "2"); + gp_widget_add_choice (t, "1"); + sprintf (buf,"%d",status.jpeg_quality); + gp_widget_set_value (t, buf); + gp_widget_append (section, t); gp_widget_new (GP_WIDGET_RADIO, _("ISO"), &t); gp_widget_set_name (t, "iso"); @@ -540,11 +714,11 @@ camera_get_config (Camera *camera, CameraWidget **window, GPContext *context) gp_widget_set_readonly (t, 1); gp_widget_append (section, t); - gp_widget_new (GP_WIDGET_TEXT, _("EC"), &t); - gp_widget_set_name (t, "ec"); - sprintf(buf,"%d/%d",status.ec.nom,status.ec.denom); - gp_widget_set_value (t, buf); - gp_widget_set_readonly (t, 1); + gp_widget_new (GP_WIDGET_RANGE, _("Exposure Compensation"), &t); + gp_widget_set_name (t, "exposurecompensation"); + fval = 1.0*status.ec.nom/status.ec.denom; + gp_widget_set_range (t, -3.0, 3.0, (status.custom_ev_steps == PSLR_CUSTOM_EV_STEPS_1_2)? 0.5:0.333333); + gp_widget_set_value (t, &fval); gp_widget_append (section, t); gp_widget_new (GP_WIDGET_RADIO, _("Shooting Mode"), &t); @@ -559,15 +733,15 @@ camera_get_config (Camera *camera, CameraWidget **window, GPContext *context) gp_widget_add_choice (t, _("B")); gp_widget_add_choice (t, _("X")); switch (status.exposure_mode) { - case PSLR_EXPOSURE_MODE_GREEN: gp_widget_set_value (t, _("GREEN"));break; - case PSLR_EXPOSURE_MODE_M: gp_widget_set_value (t, _("M"));break; - case PSLR_EXPOSURE_MODE_P: gp_widget_set_value (t, _("P"));break; - case PSLR_EXPOSURE_MODE_AV: gp_widget_set_value (t, _("AV"));break; - case PSLR_EXPOSURE_MODE_TV: gp_widget_set_value (t, _("TV"));break; - case PSLR_EXPOSURE_MODE_SV: gp_widget_set_value (t, _("SV"));break; - case PSLR_EXPOSURE_MODE_TAV: gp_widget_set_value (t, _("TAV"));break; - case PSLR_EXPOSURE_MODE_X: gp_widget_set_value (t, _("X"));break; - case PSLR_EXPOSURE_MODE_B: gp_widget_set_value (t, _("B"));break; + case PSLR_GUI_EXPOSURE_MODE_GREEN: gp_widget_set_value (t, _("GREEN"));break; + case PSLR_GUI_EXPOSURE_MODE_M: gp_widget_set_value (t, _("M"));break; + case PSLR_GUI_EXPOSURE_MODE_P: gp_widget_set_value (t, _("P"));break; + case PSLR_GUI_EXPOSURE_MODE_AV: gp_widget_set_value (t, _("AV"));break; + case PSLR_GUI_EXPOSURE_MODE_TV: gp_widget_set_value (t, _("TV"));break; + case PSLR_GUI_EXPOSURE_MODE_SV: gp_widget_set_value (t, _("SV"));break; + case PSLR_GUI_EXPOSURE_MODE_TAV: gp_widget_set_value (t, _("TAV"));break; + case PSLR_GUI_EXPOSURE_MODE_X: gp_widget_set_value (t, _("X"));break; + case PSLR_GUI_EXPOSURE_MODE_B: gp_widget_set_value (t, _("B"));break; default: sprintf(buf, _("Unknown mode %d"), status.exposure_mode); gp_widget_set_value (t, buf); @@ -575,6 +749,12 @@ camera_get_config (Camera *camera, CameraWidget **window, GPContext *context) } gp_widget_append (section, t); + gp_widget_new (GP_WIDGET_TOGGLE, _("Bulb"), &t); + gp_widget_set_name (t, "bulb"); + ival = 2; + gp_widget_set_value (t, &ival); + gp_widget_append (section, t); + return GP_OK; } @@ -586,55 +766,58 @@ camera_set_config (Camera *camera, CameraWidget *window, GPContext *context) pslr_status status; int ret; - pslr_get_status(camera->pl, &status); + pslr_get_status(&camera->pl->pslr, &status); - GP_DEBUG ("*** camera_set_config"); + gp_log (GP_LOG_DEBUG, "pentax", "*** camera_set_config"); ret = gp_widget_get_child_by_label (window, _("Image Size"), &w); if ((ret == GP_OK) && (gp_widget_changed (w))) { int i, resolution = -1; - const char **valid_resolutions; + int *valid_resolutions; gp_widget_set_changed (w, 0); - valid_resolutions = pslr_camera_resolution_steps (camera->pl); + valid_resolutions = pslr_get_model_jpeg_resolutions (&camera->pl->pslr); gp_widget_get_value (w, &sval); - for (i = 0; i < PSLR_MAX_RESOLUTIONS; i++) + for (i = 0; i < MAX_RESOLUTION_SIZE; i++) { - if (!strcmp(sval,valid_resolutions[i])) + int foo; + + sscanf(sval, "%d", &foo); + if (foo != valid_resolutions[i]) resolution = i; } if (resolution == -1) { gp_log (GP_LOG_ERROR, "pentax", "Could not decode image size %s", sval); } else { - pslr_set_jpeg_resolution(camera->pl, resolution); - pslr_get_status(camera->pl, &status); + pslr_set_jpeg_resolution(&camera->pl->pslr, resolution); + pslr_get_status(&camera->pl->pslr, &status); } } ret = gp_widget_get_child_by_label (window, _("Shooting Mode"), &w); if ((ret == GP_OK) && gp_widget_changed (w)) { - pslr_exposure_mode_t exposuremode; + pslr_gui_exposure_mode_t exposuremode; gp_widget_set_changed (w, 0); gp_widget_get_value (w, &sval); - exposuremode = PSLR_EXPOSURE_MODE_MAX; - if (!strcmp(sval,_("GREEN"))) exposuremode = PSLR_EXPOSURE_MODE_GREEN; - if (!strcmp(sval,_("M"))) exposuremode = PSLR_EXPOSURE_MODE_M; - if (!strcmp(sval,_("B"))) exposuremode = PSLR_EXPOSURE_MODE_B; - if (!strcmp(sval,_("P"))) exposuremode = PSLR_EXPOSURE_MODE_P; - if (!strcmp(sval,_("SV"))) exposuremode = PSLR_EXPOSURE_MODE_SV; - if (!strcmp(sval,_("TV"))) exposuremode = PSLR_EXPOSURE_MODE_TV; - if (!strcmp(sval,_("AV"))) exposuremode = PSLR_EXPOSURE_MODE_AV; - if (!strcmp(sval,_("TAV"))) exposuremode = PSLR_EXPOSURE_MODE_TAV; - if (!strcmp(sval,_("X"))) exposuremode = PSLR_EXPOSURE_MODE_TAV; - if (exposuremode != PSLR_EXPOSURE_MODE_MAX) { - pslr_set_exposure_mode(camera->pl, exposuremode); - pslr_get_status(camera->pl, &status); + exposuremode = PSLR_GUI_EXPOSURE_MODE_MAX; + if (!strcmp(sval,_("GREEN"))) exposuremode = PSLR_GUI_EXPOSURE_MODE_GREEN; + if (!strcmp(sval,_("M"))) exposuremode = PSLR_GUI_EXPOSURE_MODE_M; + if (!strcmp(sval,_("B"))) exposuremode = PSLR_GUI_EXPOSURE_MODE_B; + if (!strcmp(sval,_("P"))) exposuremode = PSLR_GUI_EXPOSURE_MODE_P; + if (!strcmp(sval,_("SV"))) exposuremode = PSLR_GUI_EXPOSURE_MODE_SV; + if (!strcmp(sval,_("TV"))) exposuremode = PSLR_GUI_EXPOSURE_MODE_TV; + if (!strcmp(sval,_("AV"))) exposuremode = PSLR_GUI_EXPOSURE_MODE_AV; + if (!strcmp(sval,_("TAV"))) exposuremode = PSLR_GUI_EXPOSURE_MODE_TAV; + if (!strcmp(sval,_("X"))) exposuremode = PSLR_GUI_EXPOSURE_MODE_TAV; + if (exposuremode != PSLR_GUI_EXPOSURE_MODE_MAX) { + pslr_set_exposure_mode(&camera->pl->pslr, exposuremode); + pslr_get_status(&camera->pl->pslr, &status); } else { - } gp_log (GP_LOG_ERROR, "pentax", "Could not decode exposuremode %s", sval); + } } ret = gp_widget_get_child_by_label (window, _("ISO"), &w); @@ -644,13 +827,27 @@ camera_set_config (Camera *camera, CameraWidget *window, GPContext *context) gp_widget_set_changed (w, 0); gp_widget_get_value (w, &sval); if (sscanf(sval, "%d", &iso)) { - pslr_set_iso(camera->pl, iso); - pslr_get_status(camera->pl, &status); + /* pslr_set_iso(&camera->pl->pslr, iso); */ + pslr_set_iso(&camera->pl->pslr, iso, 0, 0); /* FIXME: check if 0 is ok */ + pslr_get_status(&camera->pl->pslr, &status); // FIXME: K-30 iso doesn't get updated immediately } else gp_log (GP_LOG_ERROR, "pentax", "Could not decode iso %s", sval); } + gp_widget_get_child_by_label (window, _("Exposure Compensation"), &w); + if (gp_widget_changed (w)) { + float fval; + pslr_rational_t rational; + + gp_widget_get_value (w, &fval); + rational.denom = 10; + rational.nom = (int)(10 * fval); + + pslr_set_ec (&camera->pl->pslr, rational); + + } + gp_widget_get_child_by_label (window, _("Image Quality"), &w); if (gp_widget_changed (w)) { int qual; @@ -661,8 +858,8 @@ camera_set_config (Camera *camera, CameraWidget *window, GPContext *context) gp_widget_set_changed (w, 0); gp_widget_get_value (w, &sval); if (sscanf(sval, "%d", &qual)) { - pslr_set_jpeg_quality (camera->pl, qual); - pslr_get_status (camera->pl, &status); + pslr_set_jpeg_stars (&camera->pl->pslr, qual); + pslr_get_status (&camera->pl->pslr, &status); } else gp_log (GP_LOG_ERROR, "pentax", "Could not decode image quality %s", sval); } @@ -674,14 +871,14 @@ camera_set_config (Camera *camera, CameraWidget *window, GPContext *context) gp_widget_set_changed (w, 0); gp_widget_get_value (w, &sval); if (sscanf(sval, "%d/%d", &speed.nom, &speed.denom)) { - pslr_set_shutter(camera->pl, speed); - pslr_get_status(camera->pl, &status); + pslr_set_shutter(&camera->pl->pslr, speed); + pslr_get_status(&camera->pl->pslr, &status); } else { char c; if (sscanf(sval, "%d%c", &speed.nom, &c) && (c=='s')) { speed.denom = 1; - pslr_set_shutter(camera->pl, speed); - pslr_get_status(camera->pl, &status); + pslr_set_shutter(&camera->pl->pslr, speed); + pslr_get_status(&camera->pl->pslr, &status); } else { gp_log (GP_LOG_ERROR, "pentax", "Could not decode shutterspeed %s", sval); } @@ -705,8 +902,8 @@ camera_set_config (Camera *camera, CameraWidget *window, GPContext *context) aperture.nom = apt1; aperture.denom = 1; } - pslr_set_aperture(camera->pl, aperture); - pslr_get_status(camera->pl, &status); + pslr_set_aperture(&camera->pl->pslr, aperture); + pslr_get_status(&camera->pl->pslr, &status); } else if (sscanf(sval, "%d", &apt1)) { if (apt1<11) { aperture.nom = apt1*10; @@ -715,39 +912,74 @@ camera_set_config (Camera *camera, CameraWidget *window, GPContext *context) aperture.nom = apt1; aperture.denom = 1; } - pslr_set_aperture(camera->pl, aperture); - pslr_get_status(camera->pl, &status); + pslr_set_aperture(&camera->pl->pslr, aperture); + pslr_get_status(&camera->pl->pslr, &status); } else { gp_log (GP_LOG_ERROR, "pentax", "Could not decode aperture %s", sval); } } + ret = gp_widget_get_child_by_label (window, _("Bulb"), &w); + if ((ret == GP_OK) && gp_widget_changed (w)) { + int bulb; + + if (status.exposure_mode != PSLR_GUI_EXPOSURE_MODE_B) { + gp_context_error (context, _("You need to switch the shooting mode or the camera to 'B' for bulb exposure.")); + return GP_ERROR; + } + + gp_widget_set_changed (w, 0); + gp_widget_get_value (w, &bulb); + pslr_bulb (&camera->pl->pslr, bulb); + + if (bulb) /* also press the shutter */ + pslr_shutter (&camera->pl->pslr); + } + return GP_OK; } static int camera_exit (Camera *camera, GPContext *context) { - pslr_disconnect (camera->pl); + pslr_disconnect (&camera->pl->pslr); free (camera->pl); return GP_OK; } +char ** +get_drives(int *driveNum) { + /* should not be called */ + return NULL; +} + +pslr_result get_drive_info(char* driveName, FDTYPE* hDevice, + char* vendorId, int vendorIdSizeMax, + char* productId, int productIdSizeMax) { + /* should not be called */ + return PSLR_NO_MEMORY; +} + + int camera_init (Camera *camera, GPContext *context) { - const char *model; - camera->pl = pslr_init (camera->port); - if (camera->pl == NULL) return GP_ERROR_NO_MEMORY; - pslr_connect (camera->pl); + CameraPrivateLibrary *cpl; + + cpl = calloc (sizeof (CameraPrivateLibrary), 1); + /* pslr = pslr_init (model, device); ... but it basically just opens the fd */ + cpl->pslr.fd = camera->port; + + camera->pl = cpl; + + pslr_connect (&cpl->pslr); camera->functions->exit = camera_exit; camera->functions->summary = camera_summary; camera->functions->get_config = camera_get_config; camera->functions->set_config = camera_set_config; camera->functions->capture = camera_capture; + camera->functions->trigger_capture = camera_trigger_capture; camera->functions->wait_for_event = camera_wait_for_event; - model = pslr_camera_name (camera->pl); - gp_log (GP_LOG_DEBUG, "pentax", "reported camera model is %s\n", model); return gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera); } diff --git a/camlibs/pentax/pslr.c b/camlibs/pentax/pslr.c index 782364be7..8e768bd60 100644 --- a/camlibs/pentax/pslr.c +++ b/camlibs/pentax/pslr.c @@ -1,23 +1,37 @@ /* + pkTriggerCord + Copyright (C) 2011-2017 Andras Salamon <andras.salamon@melda.info> + Remote control of Pentax DSLR cameras. + + Support for K200D added by Jens Dreyer <jens.dreyer@udo.edu> 04/2011 + Support for K-r added by Vincenc Podobnik <vincenc.podobnik@gmail.com> 06/2011 + Support for K-30 added by Camilo Polymeris <cpolymeris@gmail.com> 09/2012 + Support for K-01 added by Ethan Queen <ethanqueen@gmail.com> 01/2013 + Support for K-3 added by Tao Wang <twang2218@gmail.com> 01/2016 + + based on: + PK-Remote Remote control of Pentax DSLR cameras. Copyright (C) 2008 Pontus Lidman <pontus@lysator.liu.se> + PK-Remote for Windows + Copyright (C) 2010 Tomasz Kos + This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + GNU Lesser General Public License for more details. You should have received a copy of the GNU General Public License + and GNU Lesser General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#define _BSD_SOURCE + */ #include <stdint.h> #include <stdio.h> @@ -27,39 +41,22 @@ #include <fcntl.h> #include <stdlib.h> #include <signal.h> +#include <unistd.h> #include <stdbool.h> - -#ifndef LIBGPHOTO2 -#include <sys/ioctl.h> -#include <linux/../scsi/sg.h> -#endif - #include <stdarg.h> #include <dirent.h> - -#ifdef LIBGPHOTO2 -#include <gphoto2/gphoto2-library.h> -#include <gphoto2/gphoto2-result.h> -#include <gphoto2/gphoto2-port.h> -#include <gphoto2/gphoto2-setting.h> -#endif +#include <math.h> #include "pslr.h" +#include "pslr_scsi.h" +#include "pslr_lens.h" -#define MAX_SEGMENTS 20 -#define MAX_RESOLUTIONS 4 -#define POLL_INTERVAL 100000 /* Number of us to wait when polling */ +#define POLL_INTERVAL 50000 /* Number of us to wait when polling */ #define BLKSZ 65536 /* Block size for downloads; if too big, we get * memory allocation error from sg driver */ #define BLOCK_RETRY 3 /* Number of retries, since we can occasionally * get SCSI errors when downloading data */ -#ifdef DEBUG -#define DPRINT(x...) printf(x) -#else -#define DPRINT(x...) do { } while (0) -#endif - #define CHECK(x) do { \ int __r; \ __r = (x); \ @@ -69,63 +66,15 @@ } \ } while (0) -#define CHECK_CLN(x,rval,label) do { \ - int __r; \ - __r = (x); \ - if (__r != PSLR_OK) { \ - fprintf(stderr, "%s:%d:%s failed: %d\n", __FILE__, __LINE__, #x, __r); \ - rval = __r; \ - goto label; \ - } \ - } while (0) - -#define PSLR_SUPPORTED_IMAGE_FORMAT_JPEG (1 << PSLR_IMAGE_FORMAT_JPEG) -#define PSLR_SUPPORTED_IMAGE_FORMAT_RAW (1 << PSLR_IMAGE_FORMAT_RAW) -#define PSLR_SUPPORTED_IMAGE_FORMAT_RAW_PLUS (1 << PSLR_IMAGE_FORMAT_RAW_PLUS) - -typedef enum { - PSLR_BUFFER_SEGMENT_LAST = 2, - PSLR_BUFFER_SEGMENT_INNER = 3, - PSLR_BUFFER_SEGMENT_OFFS = 4, -} pslr_segment_type_t; - -typedef struct { - uint32_t a; - uint32_t type; - uint32_t addr; - uint32_t length; -} pslr_buffer_segment_info; +void sleep_sec(double sec) { + int i; + for (i=0; i<floor(sec); ++i) { + usleep(999999); // 1000000 is not working for Windows + } + usleep(1000000*(sec-floor(sec))); +} -typedef struct { - uint32_t offset; - uint32_t addr; - uint32_t length; -} ipslr_segment_t; - -typedef struct { - uint32_t id1; - uint32_t id2; - const char *name; - const char *resolution_steps[MAX_RESOLUTIONS]; - int supported_formats; -} ipslr_model_info_t; - -typedef struct { -#ifdef LIBGPHOTO2 - GPPort *port; -#else - int fd; -#endif - pslr_status status; - uint32_t id1; - uint32_t id2; - ipslr_model_info_t *model; - char devname[256]; - ipslr_segment_t segments[MAX_SEGMENTS]; - uint32_t buffer_len; - uint32_t segment_count; - uint32_t offset; -} ipslr_handle_t; +ipslr_handle_t pslr; static int ipslr_set_mode(ipslr_handle_t *p, uint32_t mode); static int ipslr_cmd_00_09(ipslr_handle_t *p, uint32_t mode); @@ -133,161 +82,366 @@ static int ipslr_cmd_10_0a(ipslr_handle_t *p, uint32_t mode); static int ipslr_cmd_00_05(ipslr_handle_t *p); static int ipslr_status(ipslr_handle_t *p, uint8_t *buf); static int ipslr_status_full(ipslr_handle_t *p, pslr_status *status); -static int ipslr_press_shutter(ipslr_handle_t *p); -static int ipslr_select_buffer(ipslr_handle_t *p, int bufno, int buftype, int bufres); +static int ipslr_press_shutter(ipslr_handle_t *p, bool fullpress); +static int ipslr_select_buffer(ipslr_handle_t *p, int bufno, pslr_buffer_type buftype, int bufres); static int ipslr_buffer_segment_info(ipslr_handle_t *p, pslr_buffer_segment_info *pInfo); -static int ipslr_read_buffer(pslr_handle_t h, int bufno, int buftype, int bufres, - uint8_t **ppData, uint32_t *pLen); static int ipslr_next_segment(ipslr_handle_t *p); static int ipslr_download(ipslr_handle_t *p, uint32_t addr, uint32_t length, uint8_t *buf); static int ipslr_identify(ipslr_handle_t *p); -static int ipslr_write_args(ipslr_handle_t *p, int n, ...); +static int _ipslr_write_args(uint8_t cmd_2, ipslr_handle_t *p, int n, ...); +#define ipslr_write_args(p,n,...) _ipslr_write_args(0,(p),(n),__VA_ARGS__) +#define ipslr_write_args_special(p,n,...) _ipslr_write_args(4,(p),(n),__VA_ARGS__) -/*static int ipslr_cmd_00_04(ipslr_handle_t *p, uint32_t mode);*/ - -static int command(ipslr_handle_t *, int a, int b, int c); -static int get_status(ipslr_handle_t *); -static int get_result(ipslr_handle_t *); -static int read_result(ipslr_handle_t *, uint8_t *buf, uint32_t n); +static int command(FDTYPE fd, int a, int b, int c); +static int get_status(FDTYPE fd); +static int get_result(FDTYPE fd); +static int read_result(FDTYPE fd, uint8_t *buf, uint32_t n); void hexdump(uint8_t *buf, uint32_t bufLen); -static int scsi_write(ipslr_handle_t *, uint8_t *cmd, uint32_t cmdLen, - uint8_t *buf, uint32_t bufLen); -static int scsi_read(ipslr_handle_t *, uint8_t *cmd, uint32_t cmdLen, - uint8_t *buf, uint32_t bufLen); +static pslr_progress_callback_t progress_callback = NULL; +user_file_format_t file_formats[3] = { + { USER_FILE_FORMAT_PEF, "PEF", "pef"}, + { USER_FILE_FORMAT_DNG, "DNG", "dng"}, + { USER_FILE_FORMAT_JPEG, "JPEG", "jpg"}, +}; -static uint32_t get_uint32(uint8_t *buf); -static bool is_k10d(ipslr_handle_t *p); -static bool is_k20d(ipslr_handle_t *p); -static bool is_k30(ipslr_handle_t *p); -static bool is_k100ds(ipslr_handle_t *p); -static bool is_istds(ipslr_handle_t *p); +const char* valid_vendors[3] = {"PENTAX", "SAMSUNG", "RICOHIMG"}; +const char* valid_models[3] = {"DIGITAL_CAMERA", "DSC", "Digital Camera"}; -static pslr_progress_callback_t progress_callback = NULL; +// x18 subcommands to change camera properties +// X18_n: unknown effect +typedef enum { + X18_00, + X18_EXPOSURE_MODE, + X18_02, + X18_AE_METERING_MODE, + X18_FLASH_MODE, + X18_AF_MODE, + X18_AF_POINT_SEL, + X18_AF_POINT, + X18_08, + X18_09, + X18_0A, + X18_0B, + X18_0C, + X18_0D, + X18_0E, + X18_0F, + X18_WHITE_BALANCE, + X18_WHITE_BALANCE_ADJ, + X18_IMAGE_FORMAT, + X18_JPEG_STARS, + X18_JPEG_RESOLUTION, + X18_ISO, + X18_SHUTTER, + X18_APERTURE, + X18_EC, + X18_19, + X18_FLASH_EXPOSURE_COMPENSATION, + X18_JPEG_IMAGE_TONE, + X18_DRIVE_MODE, + X18_1D, + X18_1E, + X18_RAW_FORMAT, + X18_JPEG_SATURATION, + X18_JPEG_SHARPNESS, + X18_JPEG_CONTRAST, + X18_COLOR_SPACE, + X18_24, + X18_JPEG_HUE +} x18_subcommands_t; + +// x10 subcommands for buttons +// X10_n: unknown effect +typedef enum { + X10_00, + X10_01, + X10_02, + X10_03, + X10_04, + X10_SHUTTER, + X10_AE_LOCK, + X10_GREEN, + X10_AE_UNLOCK, + X10_09, + X10_CONNECT, + X10_0B, + X10_CONTINUOUS, + X10_BULB, + X10_0E, + X10_0F, + X10_10, + X10_DUST +} x10_subcommands_t; + +/* ************** Enabling/disabling debug mode *************/ +/* Done by reverse engineering the USB communication between PK Tether and */ +/* Pentax K-10D camera. The debug on/off should work without breaking the */ +/* camera, but you are invoking this subroutines without any warranties */ +/* Written by: Samo Penic, 2014 */ + +#define DEBUG_OFF 0 +#define DEBUG_ON 1 + +/* a different write_args function needs to be done with slightly changed */ +/* command sequence. Original function was ipslr_write_args(). */ + +int pslr_get_buffer_status(pslr_handle_t *h, uint32_t *x, uint32_t *y) { + ipslr_handle_t *p = (ipslr_handle_t *) h; + DPRINT("[C]\t\tipslr_get_buffer_status()\n"); + uint8_t buf[800]; + int n; -static ipslr_model_info_t camera_models[] = { - { PSLR_ID1_K30, PSLR_ID2_K30, "K30", { "16", "12", "8", "5" }, PSLR_SUPPORTED_IMAGE_FORMAT_JPEG }, - { PSLR_ID1_K20D, PSLR_ID2_K20D, "K20D", { "14", "10", "6", "2" }, PSLR_SUPPORTED_IMAGE_FORMAT_JPEG }, - { PSLR_ID1_K10D, PSLR_ID2_K10D, "K10D", { "10", "6", "2" }, PSLR_SUPPORTED_IMAGE_FORMAT_JPEG }, - { PSLR_ID1_K110D, PSLR_ID2_K110D, "K110D", { "6", "4", "2" }, PSLR_SUPPORTED_IMAGE_FORMAT_JPEG }, - { PSLR_ID1_K100D, PSLR_ID2_K100D, "K100D", { "6", "4", "2" }, PSLR_SUPPORTED_IMAGE_FORMAT_JPEG }, - { PSLR_ID1_K100DS, PSLR_ID2_K100DS, "K100DS", {}, PSLR_SUPPORTED_IMAGE_FORMAT_RAW }, - { PSLR_ID1_IST_DS2, PSLR_ID2_IST_DS2, "*ist DS2", { "6", "4", "2" }, PSLR_SUPPORTED_IMAGE_FORMAT_JPEG }, - { PSLR_ID1_IST_DL, PSLR_ID2_IST_DL, "*ist DL", { "6", "4", "2" }, PSLR_SUPPORTED_IMAGE_FORMAT_JPEG }, - { PSLR_ID1_IST_DS, PSLR_ID2_IST_DS, "*ist DS", { "6", "4", "2" }, PSLR_SUPPORTED_IMAGE_FORMAT_JPEG }, - { PSLR_ID1_IST_D, PSLR_ID2_IST_D, "*ist D", { "6", "4", "2" }, PSLR_SUPPORTED_IMAGE_FORMAT_JPEG }, - { PSLR_ID1_GX10, PSLR_ID2_GX10, "GX10", { "10", "6", "2" }, PSLR_SUPPORTED_IMAGE_FORMAT_JPEG }, - { PSLR_ID1_GX20, PSLR_ID2_GX20, "GX20", { "14", "10", "6", "2" }, PSLR_SUPPORTED_IMAGE_FORMAT_JPEG }, -}; + CHECK(command(p->fd, 0x02, 0x00, 0)); + n = get_result(p->fd); + DPRINT("[C]\t\tipslr_get_buffer_status() bytes: %d\n",n); + if (n!= 8) { + return PSLR_READ_ERROR; + } + CHECK(read_result(p->fd, buf, n)); + int i; + for (i=0; i<n; ++i) { + DPRINT("[C]\t\tbuf[%d]=%02x\n",i,buf[i]); + } + return PSLR_OK; +} -#ifndef LIBGPHOTO2 -static ipslr_handle_t pslr; +/* Commands in form 23 XX YY. I know it is stupid, but ipslr_cmd functions */ +/* are sooooo handy. */ +static int ipslr_cmd_23_XX(ipslr_handle_t *p, char XX, char YY, uint32_t mode) { + DPRINT("[C]\t\tipslr_cmd_23_XX(%x, %x, mode=%x)\n", XX, YY, mode); + CHECK(ipslr_write_args(p, 1, mode)); + CHECK(command(p->fd, 0x23, XX, YY)); + CHECK(get_status(p->fd)); + return PSLR_OK; +} -pslr_handle_t pslr_init() -{ - gp_system_dir d; - char nmbuf[256]; - char infobuf[64]; - gp_system_dirent ent; - int fd; +/* First of two exceptions. Command 0x23 0x06 0x14 behaves differently than */ +/* generic 23 XX YY commands */ +static int ipslr_cmd_23_06(ipslr_handle_t *p, char debug_on_off) { + DPRINT("[C]\t\tipslr_cmd_23_06(debug=%d)\n", debug_on_off); + CHECK(ipslr_write_args(p, 1, 3)); + if (debug_on_off==0) { + CHECK(ipslr_write_args_special(p, 4,0,0,0,0)); + } else { + CHECK(ipslr_write_args_special(p, 4,1,1,0,0)); + } + CHECK(command(p->fd, 0x23, 0x06, 0x14)); + CHECK(get_status(p->fd)); + return PSLR_OK; +} - memset(&pslr.devname, 0, sizeof(pslr.devname)); +/* Second exception. Command 0x23 0x04 0x08 behaves differently than generic */ +/* 23 XX YY commands */ +static int ipslr_cmd_23_04(ipslr_handle_t *p) { + DPRINT("[C]\t\tipslr_cmd_23_04()\n"); + CHECK(ipslr_write_args(p, 1, 3)); // posebni ARGS-i + CHECK(ipslr_write_args_special(p, 1, 1)); // posebni ARGS-i + CHECK(command(p->fd, 0x23, 0x04, 0x08)); + CHECK(get_status(p->fd)); + return PSLR_OK; +} - d = gp_system_opendir("/sys/class/scsi_generic"); +/* Function called to enable/disable debug mode. If debug_mode argument is 0 */ +/* function disables debug mode, else debug mode is enabled */ +int debug_onoff(ipslr_handle_t *p, char debug_mode) { + DPRINT("[C]\tdebug_onoff(%d)\n", debug_mode); + uint8_t buf[16]; /* buffer for storing statuses and read_results */ - if (!d) - return NULL; + ipslr_cmd_00_09(p,1); - while (1) { - ent = gp_system_readdir(d); - if (!ent) - break; - if (strcmp(ent->d_name, ".")==0 || strcmp(ent->d_name, "..") == 0) - continue; - snprintf(nmbuf, sizeof(nmbuf), "/sys/class/scsi_generic/%s/device/vendor", ent->d_name); - fd = open(nmbuf, O_RDONLY); - if (fd == -1) { - continue; - } - read(fd, infobuf, sizeof(infobuf)); - close(fd); + ipslr_cmd_23_XX(p,0x07,0x04,3); + read_result(p->fd,buf,0x10); - if ((strncmp(infobuf, "PENTAX", 6) != 0) && (strncmp(infobuf, "SAMSUNG", 7) != 0)) + ipslr_cmd_23_XX(p,0x05,0x04,3); + read_result(p->fd,buf,0x04); + ipslr_status(p,buf); - continue; + if (debug_mode==0) { + ipslr_cmd_23_06(p,DEBUG_OFF); + } else { + ipslr_cmd_23_06(p,DEBUG_ON); + } + ipslr_status(p,buf); - snprintf(nmbuf, sizeof(nmbuf), "/sys/class/scsi_generic/%s/device/model", ent->d_name); - fd = open(nmbuf, O_RDONLY); - if (fd == -1) { - continue; - } - read(fd, infobuf, sizeof(infobuf)); - close(fd); - if (!(strncmp(infobuf, "DIGITAL_CAMERA", 14) == 0 - || strncmp(infobuf, "DSC_K20D", 8) == 0) - || strncmp(infobuf, "DSC_K-30", 8) == 0) { - continue; - } + ipslr_cmd_23_04(p); - /* Found PENTAX DIGITAL_CAMERA */ - snprintf(pslr.devname, sizeof(pslr.devname), "/dev/%s", ent->d_name); - pslr.devname[sizeof(pslr.devname)-1] = '\0'; + ipslr_cmd_23_XX(p,0x00,0x04, 0); - /* Only support first connected camera at this time. */ - break; + ipslr_cmd_00_09(p,2); + ipslr_status(p,buf); + return PSLR_OK; +} + +/* ************* End enabling/disabling debug mode ************ */ + +user_file_format_t *get_file_format_t( user_file_format uff ) { + unsigned int i; + for (i = 0; i<sizeof(file_formats) / sizeof(file_formats[0]); i++) { + if (file_formats[i].uff == uff) { + return &file_formats[i]; + } } + return NULL; +} - gp_system_closedir(d); - if (pslr.devname[0] == '\0') - return NULL; +int pslr_set_user_file_format(pslr_handle_t h, user_file_format uff) { + switch ( uff ) { + case USER_FILE_FORMAT_PEF: + pslr_set_image_format(h, PSLR_IMAGE_FORMAT_RAW); + pslr_set_raw_format(h, PSLR_RAW_FORMAT_PEF); + break; + case USER_FILE_FORMAT_DNG: + pslr_set_image_format(h, PSLR_IMAGE_FORMAT_RAW); + pslr_set_raw_format(h, PSLR_RAW_FORMAT_DNG); + break; + case USER_FILE_FORMAT_JPEG: + pslr_set_image_format(h, PSLR_IMAGE_FORMAT_JPEG); + break; + case USER_FILE_FORMAT_MAX: + return PSLR_PARAM; + } + return PSLR_OK; +} - pslr.fd = open(pslr.devname, O_RDWR); - if (pslr.fd == -1) { - return NULL; +user_file_format get_user_file_format( pslr_status *st ) { + int rawfmt = st->raw_format; + int imgfmt = st->image_format; + if (imgfmt == PSLR_IMAGE_FORMAT_JPEG) { + return USER_FILE_FORMAT_JPEG; + } else { + if (rawfmt == PSLR_RAW_FORMAT_PEF) { + return USER_FILE_FORMAT_PEF; + } else { + return USER_FILE_FORMAT_DNG; + } } +} - return &pslr; +// most of the cameras require this exposure mode conversion step +pslr_gui_exposure_mode_t exposure_mode_conversion( pslr_exposure_mode_t exp ) { + switch ( exp ) { + + case PSLR_EXPOSURE_MODE_GREEN: + return PSLR_GUI_EXPOSURE_MODE_GREEN; + case PSLR_EXPOSURE_MODE_P: + return PSLR_GUI_EXPOSURE_MODE_P; + case PSLR_EXPOSURE_MODE_SV: + return PSLR_GUI_EXPOSURE_MODE_SV; + case PSLR_EXPOSURE_MODE_TV: + return PSLR_GUI_EXPOSURE_MODE_TV; + case PSLR_EXPOSURE_MODE_AV: + case PSLR_EXPOSURE_MODE_AV_OFFAUTO: + return PSLR_GUI_EXPOSURE_MODE_AV; + case PSLR_EXPOSURE_MODE_TAV: + return PSLR_GUI_EXPOSURE_MODE_TAV; + case PSLR_EXPOSURE_MODE_M: + case PSLR_EXPOSURE_MODE_M_OFFAUTO: + return PSLR_GUI_EXPOSURE_MODE_M; + case PSLR_EXPOSURE_MODE_B: + case PSLR_EXPOSURE_MODE_B_OFFAUTO: + return PSLR_GUI_EXPOSURE_MODE_B; + case PSLR_EXPOSURE_MODE_X: + return PSLR_GUI_EXPOSURE_MODE_X; + case PSLR_EXPOSURE_MODE_MAX: + return PSLR_GUI_EXPOSURE_MODE_MAX; + } + return 0; } -#else -pslr_handle_t -pslr_init(GPPort *port) -{ - ipslr_handle_t *p = calloc(sizeof(ipslr_handle_t),1); - if (p) - p->port = port; - return p; + +pslr_handle_t pslr_init( char *model, char *device ) { + FDTYPE fd; + char vendorId[20]; + char productId[20]; + int driveNum; + char **drives; + const char *camera_name; + + DPRINT("[C]\tplsr_init()\n"); + + if ( device == NULL ) { + drives = get_drives(&driveNum); + } else { + driveNum = 1; + drives = malloc( driveNum * sizeof(char*) ); + drives[0] = malloc( strlen( device )+1 ); + strncpy( drives[0], device, strlen( device ) ); + drives[0][strlen(device)]='\0'; + } + DPRINT("driveNum:%d\n",driveNum); + int i; + for ( i=0; i<driveNum; ++i ) { + pslr_result result = get_drive_info( drives[i], &fd, vendorId, sizeof(vendorId), productId, sizeof(productId)); + + DPRINT("\tChecking drive: %s %s %s\n", drives[i], vendorId, productId); + if ( find_in_array( valid_vendors, sizeof(valid_vendors)/sizeof(valid_vendors[0]),vendorId) != -1 + && find_in_array( valid_models, sizeof(valid_models)/sizeof(valid_models[0]), productId) != -1 ) { + if ( result == PSLR_OK ) { + DPRINT("\tFound camera %s %s\n", vendorId, productId); + pslr.fd = fd; + if ( model != NULL ) { + // user specified the camera model + camera_name = pslr_camera_name( &pslr ); + DPRINT("\tName of the camera: %s\n", camera_name); + if ( str_comparison_i( camera_name, model, strlen( camera_name) ) == 0 ) { + return &pslr; + } else { + DPRINT("\tIgnoring camera %s %s\n", vendorId, productId); + pslr_shutdown ( &pslr ); + pslr.id = 0; + pslr.model = NULL; + } + } else { + return &pslr; + } + } else { + DPRINT("\tCannot get drive info of Pentax camera. Please do not forget to install the program using 'make install'\n"); + // found the camera but communication is not possible + close_drive( &fd ); + continue; + } + } else { + close_drive( &fd ); + continue; + } + } + DPRINT("\tcamera not found\n"); + return NULL; } -#endif -int pslr_connect(pslr_handle_t h) -{ +int pslr_connect(pslr_handle_t h) { + DPRINT("[C]\tpslr_connect()\n"); ipslr_handle_t *p = (ipslr_handle_t *) h; uint8_t statusbuf[28]; CHECK(ipslr_status(p, statusbuf)); CHECK(ipslr_set_mode(p, 1)); CHECK(ipslr_status(p, statusbuf)); CHECK(ipslr_identify(p)); + if ( !p->model ) { + DPRINT("\nUnknown Pentax camera.\n"); + return -1; + } CHECK(ipslr_status_full(p, &p->status)); - DPRINT("init bufmask=0x%x\n", p->status.bufmask); - if (is_k10d(p) || is_k20d(p) || is_k30(p) || is_k100ds(p)) + DPRINT("\tinit bufmask=0x%x\n", p->status.bufmask); + if ( !p->model->old_scsi_command ) { CHECK(ipslr_cmd_00_09(p, 2)); + } CHECK(ipslr_status_full(p, &p->status)); CHECK(ipslr_cmd_10_0a(p, 1)); - if (!is_k30(p) && is_istds(p)) { + if ( p->model->old_scsi_command ) { CHECK(ipslr_cmd_00_05(p)); } - CHECK(ipslr_status_full(p, &p->status)); return 0; } -int pslr_disconnect(pslr_handle_t h) -{ +int pslr_disconnect(pslr_handle_t h) { + DPRINT("[C]\tpslr_disconnect()\n"); ipslr_handle_t *p = (ipslr_handle_t *) h; uint8_t statusbuf[28]; CHECK(ipslr_cmd_10_0a(p, 0)); @@ -296,266 +450,462 @@ int pslr_disconnect(pslr_handle_t h) return PSLR_OK; } -int pslr_shutdown(pslr_handle_t h) -{ +int pslr_shutdown(pslr_handle_t h) { + DPRINT("[C]\tpslr_shutdown()\n"); ipslr_handle_t *p = (ipslr_handle_t *) h; -#ifdef LIBGPHOTO2 - /* FIXME: close camera? */ - gp_port_close (p->port); -#else - close(p->fd); -#endif + close_drive(&p->fd); return PSLR_OK; } -int pslr_shutter(pslr_handle_t h) -{ +int pslr_shutter(pslr_handle_t h) { + DPRINT("[C]\tpslr_shutter()\n"); ipslr_handle_t *p = (ipslr_handle_t *) h; - ipslr_press_shutter(p); - return PSLR_OK; + return ipslr_press_shutter(p, true); } -int pslr_focus(pslr_handle_t h) -{ +int pslr_focus(pslr_handle_t h) { + DPRINT("[C]\tpslr_focus()\n"); ipslr_handle_t *p = (ipslr_handle_t *) h; - CHECK(ipslr_write_args(p, 1, 1)); - CHECK(command(p, 0x10, 0x05, 0x04)); - CHECK(get_status(p)); - return PSLR_OK; + return ipslr_press_shutter(p, false); } -int pslr_get_status(pslr_handle_t h, pslr_status *ps) -{ +int pslr_get_status(pslr_handle_t h, pslr_status *ps) { + DPRINT("[C]\tpslr_get_status()\n"); ipslr_handle_t *p = (ipslr_handle_t *) h; + memset( ps, 0, sizeof( pslr_status )); CHECK(ipslr_status_full(p, &p->status)); - memcpy(ps, &p->status, sizeof(pslr_status)); + memcpy(ps, &p->status, sizeof (pslr_status)); + +// uint32_t x, y; +// pslr_get_buffer_status(h, &x, &y); + return PSLR_OK; } -int pslr_get_buffer(pslr_handle_t h, int bufno, int type, int resolution, - uint8_t **ppData, uint32_t *pLen) -{ - CHECK(ipslr_read_buffer(h, bufno, type, resolution, ppData, pLen)); +char *format_rational( pslr_rational_t rational, char * fmt ) { + char *ret = malloc(32); + if ( rational.denom == 0 ) { + snprintf( ret, 32, "unknown" ); + } else { + snprintf( ret, 32, fmt, 1.0 * rational.nom / rational.denom ); + } + return ret; +} + +char *get_white_balance_single_adjust_str( uint32_t adjust, char negativeChar, char positiveChar ) { + char *ret = malloc(4); + if ( adjust < 7 ) { + snprintf( ret, 4, "%c%d", negativeChar, 7-adjust); + } else if ( adjust > 7 ) { + snprintf( ret, 4, "%c%d", positiveChar, adjust-7); + } else { + ret = ""; + } + return ret; +} + +char *get_white_balance_adjust_str( uint32_t adjust_mg, uint32_t adjust_ba ) { + char *ret = malloc(8); + if ( adjust_mg != 7 || adjust_ba != 7 ) { + snprintf(ret, 8, "%s%s", get_white_balance_single_adjust_str(adjust_mg, 'M', 'G'),get_white_balance_single_adjust_str(adjust_ba, 'B', 'A')); + } else { + ret = "0"; + } + return ret; +} + +char *collect_status_info( pslr_handle_t h, pslr_status status ) { + char *strbuffer = malloc(8192); + sprintf(strbuffer,"%-32s: %d\n", "current iso", status.current_iso); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %d/%d\n", "current shutter speed", status.current_shutter_speed.nom, status.current_shutter_speed.denom); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %d/%d\n", "camera max shutter speed", status.max_shutter_speed.nom, status.max_shutter_speed.denom); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %s\n", "current aperture", format_rational( status.current_aperture, "%.1f")); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %s\n", "lens max aperture", format_rational( status.lens_max_aperture, "%.1f")); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %s\n", "lens min aperture", format_rational( status.lens_min_aperture, "%.1f")); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %d/%d\n", "set shutter speed", status.set_shutter_speed.nom, status.set_shutter_speed.denom); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %s\n", "set aperture", format_rational( status.set_aperture, "%.1f")); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %d\n", "fixed iso", status.fixed_iso); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %d-%d\n", "auto iso", status.auto_iso_min,status.auto_iso_max); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %d\n", "jpeg quality", status.jpeg_quality); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %dM\n", "jpeg resolution", pslr_get_jpeg_resolution( h, status.jpeg_resolution)); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %s\n", "jpeg image tone", get_pslr_jpeg_image_tone_str(status.jpeg_image_tone)); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %d\n", "jpeg saturation", status.jpeg_saturation); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %d\n", "jpeg contrast", status.jpeg_contrast); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %d\n", "jpeg sharpness", status.jpeg_sharpness); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %d\n", "jpeg hue", status.jpeg_hue); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %s mm\n", "zoom", format_rational(status.zoom, "%.2f")); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %d\n", "focus", status.focus); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %s\n", "color space", get_pslr_color_space_str(status.color_space)); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %s\n", "image format", get_pslr_image_format_str(status.image_format)); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %s\n", "raw format", get_pslr_raw_format_str(status.raw_format)); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %d\n", "light meter flags", status.light_meter_flags); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %s\n", "ec", format_rational( status.ec, "%.2f" ) ); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %s\n", "custom ev steps", get_pslr_custom_ev_steps_str(status.custom_ev_steps)); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %d\n", "custom sensitivity steps", status.custom_sensitivity_steps); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %d\n", "exposure mode", status.exposure_mode); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %s\n", "scene mode", get_pslr_scene_mode_str(status.scene_mode)); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %d\n", "user mode flag", status.user_mode_flag); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %s\n", "ae metering mode", get_pslr_ae_metering_str(status.ae_metering_mode)); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %s\n", "af mode", get_pslr_af_mode_str(status.af_mode)); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %s\n", "af point select", get_pslr_af_point_sel_str(status.af_point_select)); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %d\n", "selected af point", status.selected_af_point); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %d\n", "focused af point", status.focused_af_point); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %s\n", "drive mode", get_pslr_drive_mode_str(status.drive_mode)); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %s\n", "auto bracket mode", status.auto_bracket_mode > 0 ? "on" : "off"); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %d\n", "auto bracket picture count", status.auto_bracket_picture_count); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %d\n", "auto bracket picture counter", status.auto_bracket_picture_counter); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %s\n", "auto bracket ev", format_rational(status.auto_bracket_ev, "%.2f")); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %s\n", "shake reduction", status.shake_reduction > 0 ? "on" : "off"); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %s\n", "white balance mode", get_pslr_white_balance_mode_str(status.white_balance_mode)); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %s\n", "white balance adjust", get_white_balance_adjust_str(status.white_balance_adjust_mg, status.white_balance_adjust_ba)); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %s\n", "flash mode", get_pslr_flash_mode_str(status.flash_mode)); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %.2f\n", "flash exposure compensation", (1.0 * status.flash_exposure_compensation/256)); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %.2f\n", "manual mode ev", (1.0 * status.manual_mode_ev / 10)); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %s\n", "lens", get_lens_name(status.lens_id1, status.lens_id2)); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %.2fV %.2fV %.2fV %.2fV\n", "battery", 0.01 * status.battery_1, 0.01 * status.battery_2, 0.01 * status.battery_3, 0.01 * status.battery_4); + sprintf(strbuffer+strlen(strbuffer),"%-32s: %s\n", "buffer mask", int_to_binary(status.bufmask)); + return strbuffer; +} + +int pslr_get_status_buffer(pslr_handle_t h, uint8_t *st_buf) { + DPRINT("[C]\tpslr_get_status_buffer()\n"); + ipslr_handle_t *p = (ipslr_handle_t *) h; + memset( st_buf, 0, MAX_STATUS_BUF_SIZE); +// CHECK(ipslr_status_full(p, &p->status)); +// ipslr_status_full(p, &p->status); + memcpy(st_buf, p->status_buffer, MAX_STATUS_BUF_SIZE); + return PSLR_OK; +} + +int pslr_get_buffer(pslr_handle_t h, int bufno, pslr_buffer_type type, int resolution, + uint8_t **ppData, uint32_t *pLen) { + DPRINT("[C]\tpslr_get_buffer()\n"); + uint8_t *buf = 0; + int ret; + ret = pslr_buffer_open(h, bufno, type, resolution); + if ( ret != PSLR_OK ) { + return ret; + } + + uint32_t size = pslr_buffer_get_size(h); + buf = malloc(size); + if (!buf) { + return PSLR_NO_MEMORY; + } + + uint32_t bytes = pslr_buffer_read(h, buf, size); + + if ( bytes != size ) { + return PSLR_READ_ERROR; + } + pslr_buffer_close(h); + if (ppData) { + *ppData = buf; + } + if (pLen) { + *pLen = size; + } + return PSLR_OK; } -int pslr_set_progress_callback(pslr_handle_t h, pslr_progress_callback_t cb, uintptr_t user_data) -{ +int pslr_set_progress_callback(pslr_handle_t h, pslr_progress_callback_t cb, uintptr_t user_data) { progress_callback = cb; return PSLR_OK; } -int pslr_set_shutter(pslr_handle_t h, pslr_rational_t value) -{ - ipslr_handle_t *p = (ipslr_handle_t *) h; - CHECK(ipslr_write_args(p, 2, value.nom, value.denom)); - CHECK(command(p, 0x18, 0x16, 0x08)); - CHECK(get_status(p)); +int ipslr_handle_command_x18( ipslr_handle_t *p, bool cmd9_wrap, int subcommand, int argnum, ...) { + DPRINT("[C]\t\tipslr_handle_command_x18(0x%x, %d)\n", subcommand, argnum); + if ( cmd9_wrap ) { + CHECK(ipslr_cmd_00_09(p, 1)); + } + // max 4 args + va_list ap; + int args[4]; + int i; + for ( i = 0; i < 4; ++i ) { + args[i] = 0; + } + va_start(ap, argnum); + for (i = 0; i < argnum; i++) { + args[i] = va_arg(ap, int); + } + va_end(ap); + CHECK(ipslr_write_args(p, argnum, args[0], args[1], args[2], args[3])); + CHECK(command(p->fd, 0x18, subcommand, 4 * argnum)); + CHECK(get_status(p->fd)); + if ( cmd9_wrap ) { + CHECK(ipslr_cmd_00_09(p, 2)); + } return PSLR_OK; } -int pslr_set_aperture(pslr_handle_t h, pslr_rational_t value) -{ +int pslr_test( pslr_handle_t h, bool cmd9_wrap, int subcommand, int argnum, int arg1, int arg2, int arg3, int arg4) { + DPRINT("[C]\tpslr_test(wrap=%d, subcommand=0x%x, %x, %x, %x, %x)\n", cmd9_wrap, subcommand, arg1, arg2, arg3, arg4); ipslr_handle_t *p = (ipslr_handle_t *) h; - CHECK(ipslr_write_args(p, 3, value.nom, value.denom, 0)); - CHECK(command(p, 0x18, 0x17, 0x0c)); - CHECK(get_status(p)); - return PSLR_OK; + return ipslr_handle_command_x18( p, cmd9_wrap, subcommand, argnum, arg1, arg2, arg3, arg4); } -int pslr_set_iso(pslr_handle_t h, uint32_t value) -{ +int pslr_set_shutter(pslr_handle_t h, pslr_rational_t value) { + DPRINT("[C]\tpslr_set_shutter(%x %x)\n", value.nom, value.denom); ipslr_handle_t *p = (ipslr_handle_t *) h; - /* TODO: if cmd 00 09 fails? */ - CHECK(ipslr_cmd_00_09(p, 1)); - CHECK(ipslr_write_args(p, 3, value, 0, 0)); - CHECK(command(p, 0x18, 0x15, 0x0c)); - CHECK(get_status(p)); - CHECK(ipslr_cmd_00_09(p, 2)); - return PSLR_OK; + return ipslr_handle_command_x18( p, true, X18_SHUTTER, 2, value.nom, value.denom, 0); } -int pslr_set_ec(pslr_handle_t h, pslr_rational_t value) -{ +int pslr_set_aperture(pslr_handle_t h, pslr_rational_t value) { + DPRINT("[C]\tpslr_set_aperture(%x %x)\n", value.nom, value.denom); ipslr_handle_t *p = (ipslr_handle_t *) h; - /* TODO: if cmd 00 09 fails? */ - CHECK(ipslr_cmd_00_09(p, 1)); - CHECK(ipslr_write_args(p, 3, value.nom, value.denom)); - CHECK(command(p, 0x18, 0x18, 0x08)); - CHECK(get_status(p)); - CHECK(ipslr_cmd_00_09(p, 2)); - return PSLR_OK; + return ipslr_handle_command_x18( p, false, X18_APERTURE, 3, value.nom, value.denom, 0); +} + +int pslr_set_iso(pslr_handle_t h, uint32_t value, uint32_t auto_min_value, uint32_t auto_max_value) { + DPRINT("[C]\tpslr_set_iso(0x%X, auto_min=%X, auto_max=%X)\n", value, auto_min_value, auto_max_value); + ipslr_handle_t *p = (ipslr_handle_t *) h; + return ipslr_handle_command_x18( p, true, X18_ISO, 3, value, auto_min_value, auto_max_value); } -int pslr_set_jpeg_quality(pslr_handle_t h, pslr_jpeg_quality_t quality) -{ +int pslr_set_ec(pslr_handle_t h, pslr_rational_t value) { + DPRINT("[C]\tpslr_set_ec(0x%X 0x%X)\n", value.nom, value.denom); + ipslr_handle_t *p = (ipslr_handle_t *) h; + return ipslr_handle_command_x18( p, true, X18_EC, 2, value.nom, value.denom, 0); +} + +int pslr_set_white_balance(pslr_handle_t h, pslr_white_balance_mode_t wb_mode) { + DPRINT("[C]\tpslr_set_white_balance(0x%X)\n", wb_mode); + ipslr_handle_t *p = (ipslr_handle_t *) h; + return ipslr_handle_command_x18( p, true, X18_WHITE_BALANCE, 1, wb_mode); +} + +int pslr_set_white_balance_adjustment(pslr_handle_t h, pslr_white_balance_mode_t wb_mode, uint32_t wbadj_mg, uint32_t wbadj_ba) { + DPRINT("[C]\tpslr_set_white_balance_adjustment(mode=0x%X, tint=0x%X, temp=0x%X)\n", wb_mode, wbadj_mg, wbadj_ba); + ipslr_handle_t *p = (ipslr_handle_t *) h; + return ipslr_handle_command_x18( p, true, X18_WHITE_BALANCE_ADJ, 3, wb_mode, wbadj_mg, wbadj_ba); +} + + +int pslr_set_flash_mode(pslr_handle_t h, pslr_flash_mode_t value) { + DPRINT("[C]\tpslr_set_flash_mode(%X)\n", value); + ipslr_handle_t *p = (ipslr_handle_t *) h; + return ipslr_handle_command_x18( p, true, X18_FLASH_MODE, 1, value, 0, 0); +} + +int pslr_set_flash_exposure_compensation(pslr_handle_t h, pslr_rational_t value) { + DPRINT("[C]\tpslr_set_flash_exposure_compensation(%X %X)\n", value.nom, value.denom); + ipslr_handle_t *p = (ipslr_handle_t *) h; + return ipslr_handle_command_x18( p, true, X18_FLASH_EXPOSURE_COMPENSATION, 2, value.nom, value.denom, 0); +} + +int pslr_set_drive_mode(pslr_handle_t h, pslr_drive_mode_t drive_mode) { + DPRINT("[C]\tpslr_set_drive_mode(%X)\n", drive_mode); + ipslr_handle_t *p = (ipslr_handle_t *) h; + return ipslr_handle_command_x18( p, true, X18_DRIVE_MODE, 1, drive_mode, 0, 0); +} + +int pslr_set_ae_metering_mode(pslr_handle_t h, pslr_ae_metering_t ae_metering_mode) { + DPRINT("[C]\tpslr_set_ae_metering_mode(%X)\n", ae_metering_mode); + ipslr_handle_t *p = (ipslr_handle_t *) h; + return ipslr_handle_command_x18( p, true, X18_AE_METERING_MODE, 1, ae_metering_mode, 0, 0); +} + +int pslr_set_af_mode(pslr_handle_t h, pslr_af_mode_t af_mode) { + DPRINT("[C]\tpslr_set_af_mode(%X)\n", af_mode); + ipslr_handle_t *p = (ipslr_handle_t *) h; + return ipslr_handle_command_x18( p, true, X18_AF_MODE, 1, af_mode, 0, 0); +} + +int pslr_set_af_point_sel(pslr_handle_t h, pslr_af_point_sel_t af_point_sel) { + DPRINT("[C]\tpslr_set_af_point_sel(%X)\n", af_point_sel); + ipslr_handle_t *p = (ipslr_handle_t *) h; + return ipslr_handle_command_x18( p, true, X18_AF_POINT_SEL, 1, af_point_sel, 0, 0); +} + +int pslr_set_jpeg_stars(pslr_handle_t h, int jpeg_stars ) { + DPRINT("[C]\tpslr_set_jpeg_stars(%X)\n", jpeg_stars); int hwqual; ipslr_handle_t *p = (ipslr_handle_t *) h; - if (quality >= PSLR_JPEG_QUALITY_MAX) + if ( jpeg_stars > p->model->max_jpeg_stars ) { return PSLR_PARAM; - if (is_k20d(p)) - { - hwqual = quality; - } - else if (is_k30(p)) - { - // max_qual - hwqual = number of stars (on the lcd) - hwqual = abs(quality-3); } - else - { - hwqual = quality-1; - } - CHECK(ipslr_cmd_00_09(p, 1)); - CHECK(ipslr_write_args(p, 2, 1, hwqual)); - CHECK(command(p, 0x18, 0x13, 0x08)); - CHECK(get_status(p)); - CHECK(ipslr_cmd_00_09(p, 2)); - return PSLR_OK; + hwqual = get_hw_jpeg_quality( p->model, jpeg_stars ); + return ipslr_handle_command_x18( p, true, X18_JPEG_STARS, 2, 1, hwqual, 0); } -int pslr_set_jpeg_resolution(pslr_handle_t h, int resolution) -{ +int _get_user_jpeg_resolution( ipslr_model_info_t *model, int hwres ) { + return model->jpeg_resolutions[hwres]; +} + +int pslr_get_jpeg_resolution(pslr_handle_t h, int hwres) { ipslr_handle_t *p = (ipslr_handle_t *) h; - if (resolution >= PSLR_MAX_RESOLUTIONS) - return PSLR_PARAM; + return _get_user_jpeg_resolution( p->model, hwres ); +} - CHECK(ipslr_cmd_00_09(p, 1)); - CHECK(ipslr_write_args(p, 2, 1, resolution)); - CHECK(command(p, 0x18, 0x14, 0x08)); - CHECK(get_status(p)); - CHECK(ipslr_cmd_00_09(p, 2)); - return PSLR_OK; +int _get_hw_jpeg_resolution( ipslr_model_info_t *model, int megapixel) { + int resindex = 0; + while ( resindex < MAX_RESOLUTION_SIZE && model->jpeg_resolutions[resindex] > megapixel ) { + ++resindex; + } + return resindex < MAX_RESOLUTION_SIZE ? resindex : MAX_RESOLUTION_SIZE-1; } -int pslr_set_jpeg_image_mode(pslr_handle_t h, pslr_jpeg_image_mode_t image_mode) -{ +int pslr_set_jpeg_resolution(pslr_handle_t h, int megapixel) { + DPRINT("[C]\tpslr_set_jpeg_resolution(%X)\n", megapixel); ipslr_handle_t *p = (ipslr_handle_t *) h; - if (image_mode < 0 || image_mode > PSLR_JPEG_IMAGE_MODE_MAX) + int hwres = _get_hw_jpeg_resolution( p->model, megapixel ); + return ipslr_handle_command_x18( p, true, X18_JPEG_RESOLUTION, 2, 1, hwres, 0); +} + +int pslr_set_jpeg_image_tone(pslr_handle_t h, pslr_jpeg_image_tone_t image_tone) { + DPRINT("[C]\tpslr_set_jpeg_image_tone(%X)\n", image_tone); + ipslr_handle_t *p = (ipslr_handle_t *) h; + if (image_tone < 0 || image_tone > PSLR_JPEG_IMAGE_TONE_MAX) { return PSLR_PARAM; + } + return ipslr_handle_command_x18( p, true, X18_JPEG_IMAGE_TONE, 1, image_tone, 0, 0); +} - CHECK(ipslr_cmd_00_09(p, 1)); - CHECK(ipslr_write_args(p, 1, image_mode)); - CHECK(command(p, 0x18, 0x1b, 0x04)); - CHECK(get_status(p)); - CHECK(ipslr_cmd_00_09(p, 2)); - return PSLR_OK; +int pslr_set_jpeg_sharpness(pslr_handle_t h, int32_t sharpness) { + DPRINT("[C]\tpslr_set_jpeg_sharpness(%X)\n", sharpness); + ipslr_handle_t *p = (ipslr_handle_t *) h; + int hw_sharpness = sharpness + (pslr_get_model_jpeg_property_levels( h )-1) / 2; + if (hw_sharpness < 0 || hw_sharpness >= p->model->jpeg_property_levels) { + return PSLR_PARAM; + } + return ipslr_handle_command_x18( p, false, X18_JPEG_SHARPNESS, 2, 0, hw_sharpness, 0); } -int pslr_set_jpeg_sharpness(pslr_handle_t h, int32_t sharpness) -{ +int pslr_set_jpeg_contrast(pslr_handle_t h, int32_t contrast) { + DPRINT("[C]\tpslr_set_jpeg_contrast(%X)\n", contrast); ipslr_handle_t *p = (ipslr_handle_t *) h; - if (sharpness < 0 || sharpness > 6) + int hw_contrast = contrast + (pslr_get_model_jpeg_property_levels( h )-1) / 2; + if (hw_contrast < 0 || hw_contrast >= p->model->jpeg_property_levels) { return PSLR_PARAM; - CHECK(ipslr_write_args(p, 2, 0, sharpness)); - CHECK(command(p, 0x18, 0x21, 0x08)); - CHECK(get_status(p)); - return PSLR_OK; + } + return ipslr_handle_command_x18( p, false, X18_JPEG_CONTRAST, 2, 0, hw_contrast, 0); } -int pslr_set_jpeg_contrast(pslr_handle_t h, int32_t contrast) -{ +int pslr_set_jpeg_hue(pslr_handle_t h, int32_t hue) { + DPRINT("[C]\tpslr_set_jpeg_hue(%X)\n", hue); ipslr_handle_t *p = (ipslr_handle_t *) h; - if (contrast < 0 || contrast > 6) + int hw_hue = hue + (pslr_get_model_jpeg_property_levels( h )-1) / 2; + DPRINT("hw_hue: %d\n", hw_hue); + if (hw_hue < 0 || hw_hue >= p->model->jpeg_property_levels) { return PSLR_PARAM; - CHECK(ipslr_write_args(p, 2, 0, contrast)); - CHECK(command(p, 0x18, 0x22, 0x08)); - CHECK(get_status(p)); - return PSLR_OK; + } + DPRINT("before return\n"); + return ipslr_handle_command_x18( p, false, X18_JPEG_HUE, 2, 0, hw_hue, 0); } -int pslr_set_jpeg_saturation(pslr_handle_t h, int32_t saturation) -{ +int pslr_set_jpeg_saturation(pslr_handle_t h, int32_t saturation) { + DPRINT("[C]\tpslr_set_jpeg_saturation(%X)\n", saturation); ipslr_handle_t *p = (ipslr_handle_t *) h; - if (saturation < 0 || saturation > 6) + int hw_saturation = saturation + (pslr_get_model_jpeg_property_levels( h )-1) / 2; + if (hw_saturation < 0 || hw_saturation >= p->model->jpeg_property_levels) { return PSLR_PARAM; - CHECK(ipslr_write_args(p, 2, 0, saturation)); - CHECK(command(p, 0x18, 0x20, 0x08)); - CHECK(get_status(p)); - return PSLR_OK; + } + return ipslr_handle_command_x18( p, false, X18_JPEG_SATURATION, 2, 0, hw_saturation, 0); } -int pslr_set_image_format(pslr_handle_t h, pslr_image_format_t format) -{ +int pslr_set_image_format(pslr_handle_t h, pslr_image_format_t format) { + DPRINT("[C]\tpslr_set_image_format(%X)\n", format); ipslr_handle_t *p = (ipslr_handle_t *) h; - if (format < 0 || format > PSLR_IMAGE_FORMAT_MAX) + if (format < 0 || format > PSLR_IMAGE_FORMAT_MAX) { return PSLR_PARAM; - CHECK(ipslr_cmd_00_09(p, 1)); - CHECK(ipslr_write_args(p, 2, 1, format)); - CHECK(command(p, 0x18, 0x12, 0x08)); - CHECK(get_status(p)); - CHECK(ipslr_cmd_00_09(p, 2)); - return PSLR_OK; + } + return ipslr_handle_command_x18( p, true, X18_IMAGE_FORMAT, 2, 1, format, 0); } -int pslr_is_image_format_supported(pslr_handle_t h, pslr_image_format_t format) -{ +int pslr_set_raw_format(pslr_handle_t h, pslr_raw_format_t format) { + DPRINT("[C]\tpslr_set_raw_format(%X)\n", format); ipslr_handle_t *p = (ipslr_handle_t *) h; - if (format < 0 || format >= PSLR_IMAGE_FORMAT_MAX || !p->model) - return false; - return (1 << format) & p->model->supported_formats; + if (format < 0 || format > PSLR_RAW_FORMAT_MAX) { + return PSLR_PARAM; + } + return ipslr_handle_command_x18( p, true, X18_RAW_FORMAT, 2, 1, format, 0); } -int pslr_set_raw_format(pslr_handle_t h, pslr_raw_format_t format) -{ +int pslr_set_color_space(pslr_handle_t h, pslr_color_space_t color_space) { + DPRINT("[C]\tpslr_set_raw_format(%X)\n", color_space); ipslr_handle_t *p = (ipslr_handle_t *) h; - if (format < 0 || format > PSLR_RAW_FORMAT_MAX) + if (color_space < 0 || color_space > PSLR_COLOR_SPACE_MAX) { return PSLR_PARAM; - CHECK(ipslr_cmd_00_09(p, 1)); - CHECK(ipslr_write_args(p, 2, 1, format)); - CHECK(command(p, 0x18, 0x1f, 0x08)); - CHECK(get_status(p)); - CHECK(ipslr_cmd_00_09(p, 2)); - return PSLR_OK; + } + return ipslr_handle_command_x18( p, true, X18_COLOR_SPACE, 1, color_space, 0, 0); } -int pslr_delete_buffer(pslr_handle_t h, int bufno) -{ + +int pslr_delete_buffer(pslr_handle_t h, int bufno) { + DPRINT("[C]\tpslr_delete_buffer(%X)\n", bufno); ipslr_handle_t *p = (ipslr_handle_t *) h; - if (bufno < 0 || bufno > 9) + if (bufno < 0 || bufno > 9) { return PSLR_PARAM; + } CHECK(ipslr_write_args(p, 1, bufno)); - CHECK(command(p, 0x02, 0x03, 0x04)); - CHECK(get_status(p)); - return PSLR_OK; + CHECK(command(p->fd, 0x02, 0x03, 0x04)); + CHECK(get_status(p->fd)); + return PSLR_OK; } -int pslr_green_button(pslr_handle_t h) -{ +int pslr_green_button(pslr_handle_t h) { + DPRINT("[C]\tpslr_green_button()\n"); ipslr_handle_t *p = (ipslr_handle_t *) h; - CHECK(command(p, 0x10, 0x07, 0x00)); - CHECK(get_status(p)); + CHECK(command(p->fd, 0x10, X10_GREEN, 0x00)); + CHECK(get_status(p->fd)); return PSLR_OK; } -int pslr_ae_lock(pslr_handle_t h, bool lock) -{ +int pslr_dust_removal(pslr_handle_t h) { + DPRINT("[C]\tpslr_dust_removal()\n"); ipslr_handle_t *p = (ipslr_handle_t *) h; - if (lock) - CHECK(command(p, 0x10, 0x06, 0x00)); - else - CHECK(command(p, 0x10, 0x08, 0x00)); - CHECK(get_status(p)); + CHECK(command(p->fd, 0x10, X10_DUST, 0x00)); + CHECK(get_status(p->fd)); return PSLR_OK; } -int pslr_set_exposure_mode(pslr_handle_t h, pslr_exposure_mode_t mode) -{ +int pslr_bulb(pslr_handle_t h, bool on ) { + DPRINT("[C]\tpslr_bulb(%d)\n", on); ipslr_handle_t *p = (ipslr_handle_t *) h; + CHECK(ipslr_write_args(p, 1, on ? 1 : 0)); + CHECK(command(p->fd, 0x10, X10_BULB, 0x04)); + CHECK(get_status(p->fd)); + return PSLR_OK; +} - if (mode < 0 || mode >= PSLR_EXPOSURE_MODE_MAX) - return PSLR_PARAM; +int pslr_button_test(pslr_handle_t h, int bno, int arg) { + DPRINT("[C]\tpslr_button_test(%X, %X)\n", bno, arg); + int r; + ipslr_handle_t *p = (ipslr_handle_t *) h; + CHECK(ipslr_write_args(p, 1, arg)); + CHECK(command(p->fd, 0x10, bno, 4)); + r = get_status(p->fd); + DPRINT("\tbutton result code: 0x%x\n", r); + return PSLR_OK; +} - CHECK(ipslr_cmd_00_09(p, 1)); - CHECK(ipslr_write_args(p, 2, 1, mode)); - CHECK(command(p, 0x18, 0x01, 0x08)); - CHECK(get_status(p)); - CHECK(ipslr_cmd_00_09(p, 2)); + +int pslr_ae_lock(pslr_handle_t h, bool lock) { + DPRINT("[C]\tpslr_ae_lock(%X)\n", lock); + ipslr_handle_t *p = (ipslr_handle_t *) h; + if (lock) { + CHECK(command(p->fd, 0x10, X10_AE_LOCK, 0x00)); + } else { + CHECK(command(p->fd, 0x10, X10_AE_UNLOCK, 0x00)); + } + CHECK(get_status(p->fd)); return PSLR_OK; } -int pslr_buffer_open(pslr_handle_t h, int bufno, int buftype, int bufres) -{ +int pslr_set_exposure_mode(pslr_handle_t h, pslr_exposure_mode_t mode) { + DPRINT("[C]\tpslr_set_exposure_mode(%X)\n", mode); + ipslr_handle_t *p = (ipslr_handle_t *) h; + + if (mode < 0 || mode >= PSLR_EXPOSURE_MODE_MAX) { + return PSLR_PARAM; + } + return ipslr_handle_command_x18( p, true, X18_EXPOSURE_MODE, 2, 1, mode, 0); +} + +int pslr_buffer_open(pslr_handle_t h, int bufno, pslr_buffer_type buftype, int bufres) { + DPRINT("[C]\tpslr_buffer_open(#%X, type=%X, res=%X)\n", bufno, buftype, bufres); pslr_buffer_segment_info info; uint16_t bufs; uint32_t buf_total = 0; @@ -566,77 +916,83 @@ int pslr_buffer_open(pslr_handle_t h, int bufno, int buftype, int bufres) ipslr_handle_t *p = (ipslr_handle_t *) h; - memset(&info, 0, sizeof(info)); + memset(&info, 0, sizeof (info)); CHECK(ipslr_status_full(p, &p->status)); bufs = p->status.bufmask; - if ((bufs & (1<<bufno)) == 0) { - DPRINT("No buffer data (%d)\n", bufno); + DPRINT("\tp->status.bufmask = %x\n", p->status.bufmask); + + if ( p->model->parser_function && (bufs & (1 << bufno)) == 0) { + // do not check this for limited support cameras + DPRINT("\tNo buffer data (%d)\n", bufno); return PSLR_READ_ERROR; } while (retry < 3) { /* If we get response 0x82 from the camera, there is a * desynch. We can recover by stepping through segment infos - * until we get the last one (type = 2). Retry up to 3 times. */ + * until we get the last one (b = 2). Retry up to 3 times. */ ret = ipslr_select_buffer(p, bufno, buftype, bufres); - if (ret == PSLR_OK) + if (ret == PSLR_OK) { break; + } retry++; retry2 = 0; + /* Try up to 9 times to reach segment info type 2 (last + * segment) */ do { CHECK(ipslr_buffer_segment_info(p, &info)); CHECK(ipslr_next_segment(p)); - DPRINT("Recover: type=%d\n", info.type); - } while (++retry2 < 100 && info.type != PSLR_BUFFER_SEGMENT_LAST); + DPRINT("\tRecover: b=%d\n", info.b); + } while (++retry2 < 10 && info.b != 2); } - if (retry == 3) + if (retry == 3) { return ret; + } i = 0; j = 0; do { CHECK(ipslr_buffer_segment_info(p, &info)); - DPRINT("%d: addr: 0x%x len: %d type=%d\n", i, info.addr, info.length, info.type); - if (info.type == PSLR_BUFFER_SEGMENT_OFFS) + DPRINT("\t%d: Addr: 0x%X Len: %d(0x%08X) B=%d\n", i, info.addr, info.length, info.length, info.b); + if (info.b == 4) { p->segments[j].offset = info.length; - else if (info.type == PSLR_BUFFER_SEGMENT_INNER) { + } else if (info.b == 3) { if (j == MAX_SEGMENTS) { - DPRINT("Too many segments.\n"); + DPRINT("\tToo many segments.\n"); return PSLR_NO_MEMORY; } p->segments[j].addr = info.addr; p->segments[j].length = info.length; j++; - } else { - DPRINT("Unknown segment type %d\n", info.type); } CHECK(ipslr_next_segment(p)); buf_total += info.length; i++; - } while (i < 100 && info.type != PSLR_BUFFER_SEGMENT_LAST); + } while (i < 9 && info.b != 2); p->segment_count = j; - p->buffer_len = buf_total; p->offset = 0; return PSLR_OK; } -uint32_t pslr_buffer_read(pslr_handle_t h, uint8_t *buf, uint32_t size) -{ +uint32_t pslr_buffer_read(pslr_handle_t h, uint8_t *buf, uint32_t size) { ipslr_handle_t *p = (ipslr_handle_t *) h; - unsigned int i; + int i; uint32_t pos = 0; uint32_t seg_offs; uint32_t addr; uint32_t blksz; int ret; + DPRINT("[C]\tpslr_buffer_read(%d)\n", size); + /* Find current segment */ - for (i=0; i<p->segment_count; i++) { - if (p->offset < pos + p->segments[i].length) + for (i = 0; i < p->segment_count; i++) { + if (p->offset < pos + p->segments[i].length) { break; + } pos += p->segments[i].length; } @@ -645,469 +1001,307 @@ uint32_t pslr_buffer_read(pslr_handle_t h, uint8_t *buf, uint32_t size) /* Compute block size */ blksz = size; - if (blksz > p->segments[i].length - seg_offs) + if (blksz > p->segments[i].length - seg_offs) { blksz = p->segments[i].length - seg_offs; - if (blksz > BLKSZ) + } + if (blksz > BLKSZ) { blksz = BLKSZ; + } + +// DPRINT("File offset %d segment: %d offset %d address 0x%x read size %d\n", p->offset, +// i, seg_offs, addr, blksz); - /*printf("File offset %d segment: %d offset %d address 0x%x read size %d\n", p->offset, - * i, seg_offs, addr, blksz); */ - ret = ipslr_download(p, addr, blksz, buf); - if (ret != PSLR_OK) + if (ret != PSLR_OK) { return 0; + } p->offset += blksz; return blksz; } -uint32_t pslr_buffer_get_size(pslr_handle_t h) -{ +uint32_t pslr_buffer_get_size(pslr_handle_t h) { ipslr_handle_t *p = (ipslr_handle_t *) h; - unsigned int i; + int i; uint32_t len = 0; - for (i=0; i<p->segment_count; i++) { + for (i = 0; i < p->segment_count; i++) { len += p->segments[i].length; } + DPRINT("\tbuffer get size:%d\n",len); return len; } -void pslr_buffer_close(pslr_handle_t h) -{ +void pslr_buffer_close(pslr_handle_t h) { ipslr_handle_t *p = (ipslr_handle_t *) h; - memset(&p->segments[0], 0, sizeof(p->segments)); + memset(&p->segments[0], 0, sizeof (p->segments)); p->offset = 0; p->segment_count = 0; } -int pslr_select_af_point(pslr_handle_t h, uint32_t point) -{ +int pslr_select_af_point(pslr_handle_t h, uint32_t point) { ipslr_handle_t *p = (ipslr_handle_t *) h; - CHECK(ipslr_cmd_00_09(p, 1)); - CHECK(ipslr_write_args(p, 1, point)); - CHECK(command(p, 0x18, 0x07, 0x04)); - CHECK(get_status(p)); - CHECK(ipslr_cmd_00_09(p, 2)); - return PSLR_OK; + return ipslr_handle_command_x18( p, true, X18_AF_POINT, 1, point, 0, 0); +} + +int pslr_get_model_max_jpeg_stars(pslr_handle_t h) { + ipslr_handle_t *p = (ipslr_handle_t *) h; + return p->model->max_jpeg_stars; +} + +int pslr_get_model_buffer_size(pslr_handle_t h) { + ipslr_handle_t *p = (ipslr_handle_t *) h; + return p->model->buffer_size; +} + +int pslr_get_model_jpeg_property_levels(pslr_handle_t h) { + ipslr_handle_t *p = (ipslr_handle_t *) h; + return p->model->jpeg_property_levels; } -const char *pslr_camera_name(pslr_handle_t h) -{ +int *pslr_get_model_jpeg_resolutions(pslr_handle_t h) { + ipslr_handle_t *p = (ipslr_handle_t *) h; + return p->model->jpeg_resolutions; +} + +bool pslr_get_model_only_limited(pslr_handle_t h) { + ipslr_handle_t *p = (ipslr_handle_t *) h; + return p->model->buffer_size == 0 && !p->model->parser_function; +} + +bool pslr_get_model_has_jpeg_hue(pslr_handle_t h) { + ipslr_handle_t *p = (ipslr_handle_t *) h; + return p->model->has_jpeg_hue; +} + +bool pslr_get_model_need_exposure_conversion(pslr_handle_t h) { + ipslr_handle_t *p = (ipslr_handle_t *) h; + return p->model->need_exposure_mode_conversion; +} + +int pslr_get_model_fastest_shutter_speed(pslr_handle_t h) { + ipslr_handle_t *p = (ipslr_handle_t *) h; + return p->model->fastest_shutter_speed; +} + +int pslr_get_model_base_iso_min(pslr_handle_t h) { + ipslr_handle_t *p = (ipslr_handle_t *) h; + return p->model->base_iso_min; +} + +int pslr_get_model_base_iso_max(pslr_handle_t h) { + ipslr_handle_t *p = (ipslr_handle_t *) h; + return p->model->base_iso_max; +} + +int pslr_get_model_extended_iso_min(pslr_handle_t h) { + ipslr_handle_t *p = (ipslr_handle_t *) h; + return p->model->extended_iso_min; +} + +int pslr_get_model_extended_iso_max(pslr_handle_t h) { + ipslr_handle_t *p = (ipslr_handle_t *) h; + return p->model->extended_iso_max; +} + +pslr_jpeg_image_tone_t pslr_get_model_max_supported_image_tone(pslr_handle_t h) { + ipslr_handle_t *p = (ipslr_handle_t *) h; + return p->model->max_supported_image_tone; +} + +int pslr_get_model_af_point_num(pslr_handle_t h) { + ipslr_handle_t *p = (ipslr_handle_t *) h; + return p->model->af_point_num; +} + +const char *pslr_camera_name(pslr_handle_t h) { + DPRINT("[C]\tpslr_camera_name()\n"); ipslr_handle_t *p = (ipslr_handle_t *) h; int ret; - if (p->id1 == 0) { + if (p->id == 0) { ret = ipslr_identify(p); - if (ret != PSLR_OK) + if (ret != PSLR_OK) { return NULL; + } } - if (p->model) + if (p->model) { return p->model->name; - else { + } else { static char unk_name[256]; - snprintf(unk_name, sizeof(unk_name), "ID#%x:%x", p->id1, p->id2); - unk_name[sizeof(unk_name)-1] = '\0'; + snprintf(unk_name, sizeof (unk_name), "ID#%x", p->id); + unk_name[sizeof (unk_name) - 1] = '\0'; return unk_name; } } -const char **pslr_camera_resolution_steps(pslr_handle_t h) -{ +pslr_buffer_type pslr_get_jpeg_buffer_type(pslr_handle_t h, int jpeg_stars) { ipslr_handle_t *p = (ipslr_handle_t *) h; - if (p->model) - return p->model->resolution_steps; - return NULL; + return 2 + get_hw_jpeg_quality( p->model, jpeg_stars ); } /* ----------------------------------------------------------------------- */ -static int ipslr_set_mode(ipslr_handle_t *p, uint32_t mode) -{ +static int ipslr_set_mode(ipslr_handle_t *p, uint32_t mode) { + DPRINT("[C]\t\tipslr_set_mode(0x%x)\n", mode); CHECK(ipslr_write_args(p, 1, mode)); - CHECK(command(p, 0, 0, 4)); - CHECK(get_status(p)); + CHECK(command(p->fd, 0, 0, 4)); + CHECK(get_status(p->fd)); return PSLR_OK; } -static int ipslr_cmd_00_09(ipslr_handle_t *p, uint32_t mode) -{ +static int ipslr_cmd_00_09(ipslr_handle_t *p, uint32_t mode) { + DPRINT("[C]\t\tipslr_cmd_00_09(0x%x)\n", mode); CHECK(ipslr_write_args(p, 1, mode)); - CHECK(command(p, 0, 9, 4)); - CHECK(get_status(p)); + CHECK(command(p->fd, 0, 9, 4)); + CHECK(get_status(p->fd)); return PSLR_OK; } -static int ipslr_cmd_10_0a(ipslr_handle_t *p, uint32_t mode) -{ +static int ipslr_cmd_10_0a(ipslr_handle_t *p, uint32_t mode) { + DPRINT("[C]\t\tipslr_cmd_10_0a(0x%x)\n", mode); CHECK(ipslr_write_args(p, 1, mode)); - CHECK(command(p, 0x10, 0x0a, 4)); - CHECK(get_status(p)); + CHECK(command(p->fd, 0x10, X10_CONNECT, 4)); + CHECK(get_status(p->fd)); return PSLR_OK; } -static int ipslr_cmd_00_05(ipslr_handle_t *p) -{ +static int ipslr_cmd_00_05(ipslr_handle_t *p) { + DPRINT("[C]\t\tipslr_cmd_00_05()\n"); int n; uint8_t buf[0xb8]; - CHECK(command(p, 0x00, 0x05, 0x00)); - n = get_result(p); + CHECK(command(p->fd, 0x00, 0x05, 0x00)); + n = get_result(p->fd); if (n != 0xb8) { - DPRINT("only got %d bytes\n", n); + DPRINT("\tonly got %d bytes\n", n); return PSLR_READ_ERROR; } - CHECK(read_result(p, buf, n)); + CHECK(read_result(p->fd, buf, n)); return PSLR_OK; } -static int ipslr_status(ipslr_handle_t *p, uint8_t *buf) -{ +static int ipslr_status(ipslr_handle_t *p, uint8_t *buf) { int n; - CHECK(command(p, 0, 1, 0)); - n = get_result(p); + DPRINT("[C]\t\tipslr_status()\n"); + CHECK(command(p->fd, 0, 1, 0)); + n = get_result(p->fd); if (n == 16 || n == 28) { - return read_result(p, buf, n); + return read_result(p->fd, buf, n); } else { return PSLR_READ_ERROR; } } -#define MAX_STATUS_BUF_SIZE 452 -#ifdef DEBUG -static uint8_t lastbuf[MAX_STATUS_BUF_SIZE]; -static int first = 1; - -static void ipslr_status_diff(uint8_t *buf) -{ - int n; - int diffs; - if (first) - { - hexdump(buf, MAX_STATUS_BUF_SIZE); - memcpy(lastbuf, buf, MAX_STATUS_BUF_SIZE); - first = 0; - } - - diffs = 0; - for (n = 0; n < MAX_STATUS_BUF_SIZE; n++) - { - if (lastbuf[n] != buf[n]) - { - DPRINT("buf[%03X] last %02Xh %3d new %02Xh %3d\n", n, lastbuf[n], lastbuf[n], buf[n], buf[n]); - diffs++; - } - } - if (diffs) - { - DPRINT("---------------------------\n"); - memcpy(lastbuf, buf, MAX_STATUS_BUF_SIZE); - } -} -#endif - -static int ipslr_status_full(ipslr_handle_t *p, pslr_status *status) -{ +static int ipslr_status_full(ipslr_handle_t *p, pslr_status *status) { int n; - uint8_t buf[MAX_STATUS_BUF_SIZE]; - CHECK(command(p, 0, 8, 0)); - n = get_result(p); - - if (p->model && is_k10d(p)) { - /* K10D status block */ - if (n != 392) { - DPRINT("only got %d bytes\n", n); - return PSLR_READ_ERROR; - } - - CHECK(read_result(p, buf, n)); - memset(status, 0, sizeof(*status)); - status->bufmask = buf[0x16] << 8 | buf[0x17]; - status->current_iso = get_uint32(&buf[0x11c]); - status->current_shutter_speed.nom = get_uint32(&buf[0xf4]); - status->current_shutter_speed.denom = get_uint32(&buf[0xf8]); - status->current_aperture.nom = get_uint32(&buf[0xfc]); - status->current_aperture.denom = get_uint32(&buf[0x100]); - status->lens_min_aperture.nom = get_uint32(&buf[0x12c]); - status->lens_min_aperture.denom = get_uint32(&buf[0x130]); - status->lens_max_aperture.nom = get_uint32(&buf[0x134]); - status->lens_max_aperture.denom = get_uint32(&buf[0x138]); - status->current_zoom.nom = get_uint32(&buf[0x16c]); - status->current_zoom.denom = get_uint32(&buf[0x170]); - status->set_aperture.nom = get_uint32(&buf[0x34]); - status->set_aperture.denom = get_uint32(&buf[0x38]); - status->set_shutter_speed.nom = get_uint32(&buf[0x2c]); - status->set_shutter_speed.denom = get_uint32(&buf[0x30]); - status->set_iso = get_uint32(&buf[0x60]); - status->jpeg_resolution = get_uint32(&buf[0x7c]); - status->jpeg_contrast = get_uint32(&buf[0x94]); - status->jpeg_sharpness = get_uint32(&buf[0x90]); - status->jpeg_saturation = get_uint32(&buf[0x8c]); - status->jpeg_quality = 1+get_uint32(&buf[0x80]); - status->jpeg_image_mode = get_uint32(&buf[0x88]); - status->zoom.nom = get_uint32(&buf[0x16c]); - status->zoom.denom = get_uint32(&buf[0x170]); - status->focus = get_uint32(&buf[0x174]); - status->raw_format = get_uint32(&buf[0x84]); - status->image_format = get_uint32(&buf[0x78]); - status->light_meter_flags = get_uint32(&buf[0x124]); - status->ec.nom = get_uint32(&buf[0x3c]); - status->ec.denom = get_uint32(&buf[0x40]); - status->custom_ev_steps = get_uint32(&buf[0x9c]); - status->custom_sensitivity_steps = get_uint32(&buf[0xa0]); - status->exposure_mode = get_uint32(&buf[0xe0]); - status->user_mode_flag = get_uint32(&buf[0x1c]); - status->af_point_select = get_uint32(&buf[0xbc]); - status->selected_af_point = get_uint32(&buf[0xc0]); - status->focused_af_point = get_uint32(&buf[0x150]); - return PSLR_OK; - } - - if (p->model && is_k20d(p)) { - /* K20D status block */ - if (n != 412) { - DPRINT("only got %d bytes\n", n); - return PSLR_READ_ERROR; - } - - CHECK(read_result(p, buf, n)); -#ifdef DEBUG - ipslr_status_diff(buf); -#endif - memset(status, 0, sizeof(*status)); - status->bufmask = buf[0x16] << 8 | buf[0x17]; - status->current_iso = get_uint32(&buf[0x130]); /*d*/ - status->current_shutter_speed.nom = get_uint32(&buf[0x108]); /*d*/ - status->current_shutter_speed.denom = get_uint32(&buf[0x10C]); /*d*/ - status->current_aperture.nom = get_uint32(&buf[0x110]); /*d*/ - status->current_aperture.denom = get_uint32(&buf[0x114]); /*d*/ - status->lens_min_aperture.nom = get_uint32(&buf[0x140]); /*d*/ - status->lens_min_aperture.denom = get_uint32(&buf[0x144]); /*d*/ - status->lens_max_aperture.nom = get_uint32(&buf[0x148]); /*d*/ - status->lens_max_aperture.denom = get_uint32(&buf[0x14B]); /*d*/ - status->current_zoom.nom = get_uint32(&buf[0x180]); /*d*/ - status->current_zoom.denom = get_uint32(&buf[0x184]); /*d*/ - status->set_aperture.nom = get_uint32(&buf[0x34]); /*d*/ - status->set_aperture.denom = get_uint32(&buf[0x38]); /*d*/ - status->set_shutter_speed.nom = get_uint32(&buf[0x2c]); /*d*/ - status->set_shutter_speed.denom = get_uint32(&buf[0x30]); /*d*/ - status->set_iso = get_uint32(&buf[0x60]); /*d*/ - status->jpeg_resolution = get_uint32(&buf[0x7c]); /*d*/ - status->jpeg_contrast = get_uint32(&buf[0x94]); /* commands do now work for it?*/ - status->jpeg_sharpness = get_uint32(&buf[0x90]); /* commands do now work for it?*/ - status->jpeg_saturation = get_uint32(&buf[0x8c]); /* commands do now work for it?*/ - status->jpeg_quality = get_uint32(&buf[0x80]); /*d*/ - status->jpeg_image_mode = get_uint32(&buf[0x88]); /*d*/ - status->zoom.nom = get_uint32(&buf[0x180]); /*d*/ - status->zoom.denom = get_uint32(&buf[0x184]); /*d*/ - status->focus = get_uint32(&buf[0x188]); /*d current focus ring position?*/ - status->raw_format = get_uint32(&buf[0x84]); /*d*/ - status->image_format = get_uint32(&buf[0x78]); /*d*/ - status->light_meter_flags = get_uint32(&buf[0x138]); /*d*/ - status->ec.nom = get_uint32(&buf[0x3c]); /*d*/ - status->ec.denom = get_uint32(&buf[0x40]); /*d*/ - status->custom_ev_steps = get_uint32(&buf[0x9c]); - status->custom_sensitivity_steps = get_uint32(&buf[0xa0]); - status->exposure_mode = get_uint32(&buf[0xe0]); /*d*/ - status->user_mode_flag = get_uint32(&buf[0x1c]); /*d*/ - status->af_point_select = get_uint32(&buf[0xbc]); /* not sure*/ - status->selected_af_point = get_uint32(&buf[0xc0]); /*d*/ - status->focused_af_point = get_uint32(&buf[0x160]); /*d, unsure about it, a lot is changing when the camera focuses*/ - /* 0x158 current ev? - / 0xB8 0 - MF, 1 - AF.S, 2 - AF.C - / 0xB4, 0xC4 - metering mode, 0 - matrix, 1 - center weighted, 2 - spot - / 0x160 and 0x164 change when AF - / 0xC0 changes when selecting focus point manually or from GUI - / 0xBC focus point selection 0 - auto, 1 - manual, 2 - center - */ - return PSLR_OK; + DPRINT("[C]\t\tipslr_status_full()\n"); + CHECK(command(p->fd, 0, 8, 0)); + n = get_result(p->fd); + DPRINT("\tread %d bytes\n", n); + int expected_bufsize = p->model != NULL ? p->model->buffer_size : 0; + if ( p->model == NULL ) { + DPRINT("\tp model null\n"); } + DPRINT("\texpected_bufsize: %d\n",expected_bufsize); - if (p->model && is_k30(p)) { // might work with k01 too - if (n != 452) { - DPRINT("only got %d bytes\n", n); - return PSLR_READ_ERROR; - } - CHECK(read_result(p, buf, n)); -#ifdef DEBUG - ipslr_status_diff(buf); -#endif - memset(status, 0, sizeof(*status)); - status->bufmask = get_uint32(&buf[0x1E]); - status->current_iso = get_uint32(&buf[0x134]); - status->current_shutter_speed.nom = get_uint32(&buf[0x10C]); - status->current_shutter_speed.denom = get_uint32(&buf[0x110]); - status->current_aperture.nom = get_uint32(&buf[0x114]); - status->current_aperture.denom = get_uint32(&buf[0x118]); - status->lens_min_aperture.nom = get_uint32(&buf[0x144]); - status->lens_min_aperture.denom = get_uint32(&buf[0x148]); - status->lens_max_aperture.nom = get_uint32(&buf[0x14C]); - status->lens_max_aperture.denom = get_uint32(&buf[0x150]); - status->current_zoom.nom = get_uint32(&buf[0x1A0]); - status->current_zoom.denom = get_uint32(&buf[0x1A4]); - status->set_aperture.nom = get_uint32(&buf[0x3C]); - status->set_aperture.denom = get_uint32(&buf[0x40]); - status->set_shutter_speed.nom = get_uint32(&buf[0x34]); - status->set_shutter_speed.denom = get_uint32(&buf[0x38]); - status->set_iso = get_uint32(&buf[0x14]); - status->jpeg_resolution = get_uint32(&buf[0x84]); - status->jpeg_contrast = get_uint32(&buf[0x9C]); - status->jpeg_sharpness = get_uint32(&buf[0x98]); - status->jpeg_saturation = get_uint32(&buf[0x94]); - status->jpeg_quality = 3-get_uint32(&buf[0x88]); // Maximum quality is 3 - status->jpeg_image_mode = get_uint32(&buf[0x80]); - status->zoom.nom = get_uint32(&buf[0x1A0]); - status->zoom.denom = get_uint32(&buf[0x1A4]); - status->focus = get_uint32(&buf[0x1A8]); - status->raw_format = get_uint32(&buf[0x8C]); - status->image_format = get_uint32(&buf[0x80]); - status->light_meter_flags = get_uint32(&buf[0x13C]); - status->ec.nom = get_uint32(&buf[0x44]); - status->ec.denom = get_uint32(&buf[0x48]); - status->custom_ev_steps = get_uint32(&buf[0x15C]); - status->custom_sensitivity_steps = get_uint32(&buf[0xa8]); - status->exposure_mode = get_uint32(&buf[0xb4]); - status->user_mode_flag = get_uint32(&buf[0x24]); - status->af_point_select = get_uint32(&buf[0xc4]); - status->selected_af_point = get_uint32(&buf[0xc0]); - status->focused_af_point = get_uint32(&buf[0x168]); - return PSLR_OK; - } - - if (p->model && is_k100ds(p)) { - /* K100DS (Super) status block */ - if (n != 264) { - DPRINT("only got %d bytes\n", n); - return PSLR_READ_ERROR; - } - - CHECK(read_result(p, buf, n)); - memset(status, 0, sizeof(*status)); - - status->bufmask = get_uint32(&buf[0x10]); - status->image_format = PSLR_IMAGE_FORMAT_RAW; - status->raw_format = PSLR_RAW_FORMAT_PEF; + CHECK(read_result(p->fd, p->status_buffer, n > MAX_STATUS_BUF_SIZE ? MAX_STATUS_BUF_SIZE: n)); + if ( expected_bufsize == 0 || !p->model->parser_function ) { + // limited support only return PSLR_OK; - } - - if (p->model && is_istds(p)) { - /* *ist DS status block */ - if (n != 0x108) { - DPRINT("only got %d bytes\n", n); - return PSLR_READ_ERROR; + } else if ( expected_bufsize > 0 && expected_bufsize != n ) { + DPRINT("\tWaiting for %d bytes but got %d\n", expected_bufsize, n); + return PSLR_READ_ERROR; + } else { + // everything OK + (*p->model->parser_function)(p, status); + if ( p->model->need_exposure_mode_conversion ) { + status->exposure_mode = exposure_mode_conversion( status->exposure_mode ); } - CHECK(read_result(p, buf, n)); -#ifdef DEBUG - ipslr_status_diff(buf); -#endif - memset(status, 0, sizeof(*status)); - status->bufmask = get_uint32(&buf[0x10]); - status->set_shutter_speed.nom = get_uint32(&buf[0x80]); - status->set_shutter_speed.denom = get_uint32(&buf[0x84]); - status->set_aperture.nom = get_uint32(&buf[0x88]); - status->set_aperture.denom = get_uint32(&buf[0x8c]); - status->lens_min_aperture.nom = get_uint32(&buf[0xb8]); - status->lens_min_aperture.denom = get_uint32(&buf[0xbc]); - status->lens_max_aperture.nom = get_uint32(&buf[0xc0]); - status->lens_max_aperture.denom = get_uint32(&buf[0xc4]); - return PSLR_OK; } - /* Unknown camera */ - return PSLR_OK; } -static int ipslr_press_shutter(ipslr_handle_t *p) -{ +// fullpress: take picture +// halfpress: autofocus +static int ipslr_press_shutter(ipslr_handle_t *p, bool fullpress) { + DPRINT("[C]\t\tipslr_press_shutter(fullpress = %s)\n", (fullpress ? "true" : "false")); + int r; CHECK(ipslr_status_full(p, &p->status)); - DPRINT("before: mask=0x%x\n", p->status.bufmask); - CHECK(ipslr_write_args(p, 1, 2)); - CHECK(command(p, 0x10, 0x05, 0x04)); - get_status(p); - DPRINT("shutter result code: 0x%x\n", p->status); + DPRINT("\t\tbefore: mask=0x%x\n", p->status.bufmask); + CHECK(ipslr_write_args(p, 1, fullpress ? 2 : 1)); + CHECK(command(p->fd, 0x10, X10_SHUTTER, 0x04)); + r = get_status(p->fd); + DPRINT("\t\tshutter result code: 0x%x\n", r); return PSLR_OK; } -static int ipslr_read_buffer(pslr_handle_t h, int bufno, int buftype, int bufres, - uint8_t **ppData, uint32_t *pLen) -{ - uint8_t *buf = 0; - uint8_t *buf_ptr; - uint32_t bytes; - - if (!ppData || !pLen) - return PSLR_PARAM; - - ipslr_handle_t *p = (ipslr_handle_t *) h; - - CHECK(pslr_buffer_open(h, bufno, buftype, bufres)); - - buf = malloc(p->buffer_len); - if (!buf) - return PSLR_NO_MEMORY; - buf_ptr = buf; - - do { - bytes = pslr_buffer_read(h, buf_ptr, p->buffer_len - (buf_ptr - buf)); - buf_ptr += bytes; - } while(bytes); - pslr_buffer_close(h); - *ppData = buf; - *pLen = buf_ptr - buf; - - return PSLR_OK; -} - -static int ipslr_select_buffer(ipslr_handle_t *p, int bufno, int buftype, int bufres) -{ +static int ipslr_select_buffer(ipslr_handle_t *p, int bufno, pslr_buffer_type buftype, int bufres) { int r; - DPRINT("Select buffer %d,%d,%d,0\n", bufno, buftype,bufres); - if (is_k20d(p)) { + DPRINT("\t\tSelect buffer %d,%d,%d,0\n", bufno, buftype, bufres); + if ( !p->model->old_scsi_command ) { CHECK(ipslr_write_args(p, 4, bufno, buftype, bufres, 0)); - CHECK(command(p, 0x02, 0x01, 0x10)); - } else if (is_k10d(p)) { - CHECK(ipslr_write_args(p, 4, bufno, buftype, bufres-1, 0)); - CHECK(command(p, 0x02, 0x01, 0x10)); + CHECK(command(p->fd, 0x02, 0x01, 0x10)); } else { /* older cameras: 3-arg select buffer */ CHECK(ipslr_write_args(p, 4, bufno, buftype, bufres)); - CHECK(command(p, 0x02, 0x01, 0x0c)); + CHECK(command(p->fd, 0x02, 0x01, 0x0c)); } - r = get_status(p); - if (r != 0) + r = get_status(p->fd); + if (r != 0) { return PSLR_COMMAND_ERROR; + } return PSLR_OK; } -static int ipslr_next_segment(ipslr_handle_t *p) -{ +static int ipslr_next_segment(ipslr_handle_t *p) { + DPRINT("[C]\t\tipslr_next_segment()\n"); int r; CHECK(ipslr_write_args(p, 1, 0)); - CHECK(command(p, 0x04, 0x01, 0x04)); - usleep(10000); /* needed !! 100 too short, 1000 not short enough for PEF */ - r = get_status(p); - if (r == 0) + CHECK(command(p->fd, 0x04, 0x01, 0x04)); + usleep(100000); // needed !! 100 too short, 1000 not short enough for PEF + r = get_status(p->fd); + if (r == 0) { return PSLR_OK; + } return PSLR_COMMAND_ERROR; } -static int ipslr_buffer_segment_info(ipslr_handle_t *p, pslr_buffer_segment_info *pInfo) -{ +static int ipslr_buffer_segment_info(ipslr_handle_t *p, pslr_buffer_segment_info *pInfo) { + DPRINT("[C]\t\tipslr_buffer_segment_info()\n"); uint8_t buf[16]; uint32_t n; + int num_try = 20; - CHECK(command(p, 0x04, 0x00, 0x00)); - n = get_result(p); - if (n != 16) - return PSLR_READ_ERROR; - CHECK(read_result(p, buf, 16)); - pInfo->a = get_uint32(&buf[0]); - pInfo->type = get_uint32(&buf[4]); - pInfo->addr = get_uint32(&buf[8]); - pInfo->length = get_uint32(&buf[12]); + pInfo->b = 0; + while ( pInfo->b == 0 && --num_try > 0 ) { + CHECK(command(p->fd, 0x04, 0x00, 0x00)); + n = get_result(p->fd); + if (n != 16) { + return PSLR_READ_ERROR; + } + CHECK(read_result(p->fd, buf, 16)); + + // use the right function based on the endian. + get_uint32_func get_uint32_func_ptr; + if (p->model->is_little_endian) { + get_uint32_func_ptr = get_uint32_le; + } else { + get_uint32_func_ptr = get_uint32_be; + } + + pInfo->a = (*get_uint32_func_ptr)(&buf[0]); + pInfo->b = (*get_uint32_func_ptr)(&buf[4]); + pInfo->addr = (*get_uint32_func_ptr)(&buf[8]); + pInfo->length = (*get_uint32_func_ptr)(&buf[12]); + if ( pInfo-> b == 0 ) { + DPRINT("\tWaiting for segment info addr: 0x%x len: %d B=%d\n", pInfo->addr, pInfo->length, pInfo->b); + sleep_sec( 0.1 ); + } + } return PSLR_OK; } -static int ipslr_download(ipslr_handle_t *p, uint32_t addr, uint32_t length, uint8_t *buf) -{ - uint8_t downloadCmd[8] = { 0xf0, 0x24, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00 }; +static int ipslr_download(ipslr_handle_t *p, uint32_t addr, uint32_t length, uint8_t *buf) { + DPRINT("[C]\t\tipslr_download(address = 0x%X, length = %d)\n", addr, length); + uint8_t downloadCmd[8] = {0xf0, 0x24, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00}; uint32_t block; int n; int retry; @@ -1115,18 +1309,19 @@ static int ipslr_download(ipslr_handle_t *p, uint32_t addr, uint32_t length, uin retry = 0; while (length > 0) { - if (length > BLKSZ) + if (length > BLKSZ) { block = BLKSZ; - else + } else { block = length; + } - /*DPRINT("Get 0x%x bytes from 0x%x\n", block, addr); */ + //DPRINT("Get 0x%x bytes from 0x%x\n", block, addr); CHECK(ipslr_write_args(p, 2, addr, block)); - CHECK(command(p, 0x06, 0x00, 0x08)); - get_status(p); + CHECK(command(p->fd, 0x06, 0x00, 0x08)); + get_status(p->fd); - n = scsi_read(p, downloadCmd, sizeof(downloadCmd), buf, block); - get_status(p); + n = scsi_read(p->fd, downloadCmd, sizeof (downloadCmd), buf, block); + get_status(p->fd); if (n < 0) { if (retry < BLOCK_RETRY) { @@ -1140,74 +1335,187 @@ static int ipslr_download(ipslr_handle_t *p, uint32_t addr, uint32_t length, uin addr += n; retry = 0; if (progress_callback) { - progress_callback(length_start-length, length_start); + progress_callback(length_start - length, length_start); } } return PSLR_OK; } - -static int ipslr_identify(ipslr_handle_t *p) -{ +static int ipslr_identify(ipslr_handle_t *p) { + DPRINT("[C]\t\tipslr_identify()\n"); uint8_t idbuf[8]; int n; - unsigned int i; - CHECK(command(p, 0, 4, 0)); - n = get_result(p); - if (n != 8) + CHECK(command(p->fd, 0, 4, 0)); + n = get_result(p->fd); + if (n != 8) { return PSLR_READ_ERROR; - CHECK(read_result(p, idbuf, 8)); - p->id1 = get_uint32(&idbuf[0]); - p->id2 = get_uint32(&idbuf[4]); - p->model = NULL; - for (i=0; i<sizeof(camera_models)/sizeof(camera_models[0]); i++) { - if (camera_models[i].id1 == p->id1) { - p->model = &camera_models[i]; - break; + } + CHECK(read_result(p->fd, idbuf, 8)); + // Check the camera endian, which affect ID + if (idbuf[0] == 0) { + p->id = get_uint32_be(&idbuf[0]); + } else { + p->id = get_uint32_le(&idbuf[0]); + } + DPRINT("\tid of the camera: %x\n", p->id); + p->model = find_model_by_id( p->id ); + return PSLR_OK; +} + +int pslr_read_datetime(pslr_handle_t *h, int *year, int *month, int *day, int *hour, int *min, int *sec) { + ipslr_handle_t *p = (ipslr_handle_t *) h; + DPRINT("[C]\t\tipslr_read_datetime()\n"); + uint8_t idbuf[800]; + int n; + + CHECK(command(p->fd, 0x20, 0x06, 0)); + n = get_result(p->fd); + DPRINT("[C]\t\tipslr_read_datetime() bytes: %d\n",n); + if (n!= 24) { + return PSLR_READ_ERROR; + } + CHECK(read_result(p->fd, idbuf, n)); + get_uint32_func get_uint32_func_ptr; + + if (p->model->is_little_endian) { + get_uint32_func_ptr = get_uint32_le; + } else { + get_uint32_func_ptr = get_uint32_be; + } + *year = (*get_uint32_func_ptr)(idbuf); + *month = (*get_uint32_func_ptr)(idbuf+4); + *day = (*get_uint32_func_ptr)(idbuf+8); + *hour = (*get_uint32_func_ptr)(idbuf+12); + *min = (*get_uint32_func_ptr)(idbuf+16); + *sec = (*get_uint32_func_ptr)(idbuf+20); + return PSLR_OK; +} + +int pslr_read_dspinfo(pslr_handle_t *h, char* firmware) { + ipslr_handle_t *p = (ipslr_handle_t *) h; + DPRINT("[C]\t\tipslr_read_dspinfo()\n"); + uint8_t buf[4]; + int n; + + CHECK(command(p->fd, 0x01, 0x01, 0)); + n = get_result(p->fd); + DPRINT("[C]\t\tipslr_read_dspinfo() bytes: %d\n",n); + if (n!= 4) { + return PSLR_READ_ERROR; + } + CHECK(read_result(p->fd, buf, n)); + if (p->model->is_little_endian) { + snprintf( firmware, 16, "%d.%02d.%02d.%02d", buf[3], buf[2], buf[1], buf[0]); + } else { + snprintf( firmware, 16, "%d.%02d.%02d.%02d", buf[0], buf[1], buf[2], buf[3]); + } + return PSLR_OK; +} + +int pslr_read_setting(pslr_handle_t *h, int offset, uint32_t *value) { + ipslr_handle_t *p = (ipslr_handle_t *) h; + DPRINT("[C]\t\tipslr_read_setting(%d)\n", offset); + uint8_t buf[4]; + int n; + + CHECK(ipslr_write_args(p, 1, offset)); + CHECK(command(p->fd, 0x20, 0x09, 4)); + n = get_result(p->fd); + DPRINT("[C]\t\tipslr_read_setting() bytes: %d\n",n); + if (n!= 4) { + return PSLR_READ_ERROR; + } + CHECK(read_result(p->fd, buf, n)); + get_uint32_func get_uint32_func_ptr; + if (p->model->is_little_endian) { + get_uint32_func_ptr = get_uint32_le; + } else { + get_uint32_func_ptr = get_uint32_be; + } + *value = (*get_uint32_func_ptr)(buf); + return PSLR_OK; +} + +int pslr_write_setting(pslr_handle_t *h, int offset, uint32_t value) { + ipslr_handle_t *p = (ipslr_handle_t *) h; + DPRINT("[C]\t\tipslr_write_setting(%d)=%d\n", offset, value); + CHECK(ipslr_cmd_00_09(p, 1)); + CHECK(ipslr_write_args(p, 2, offset, value)); + CHECK(command(p->fd, 0x20, 0x08, 8)); + CHECK(ipslr_cmd_00_09(p, 2)); + return PSLR_OK; +} + +int pslr_read_settings(pslr_handle_t *h, int offset, int length, uint8_t *buf) { + int index=offset; + uint32_t value; + int ret; + while (index<offset+length) { + if ( (ret = pslr_read_setting(h, index, &value)) != PSLR_OK ) { + return ret; } + buf[index] = value; + ++index; } return PSLR_OK; } -static int ipslr_write_args(ipslr_handle_t *p, int n, ...) -{ +static int _ipslr_write_args(uint8_t cmd_2, ipslr_handle_t *p, int n, ...) { va_list ap; - uint8_t cmd[8] = { 0xf0, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - uint8_t buf[4*n]; + uint8_t cmd[8] = {0xf0, 0x4f, cmd_2, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t buf[4 * n]; + FDTYPE fd = p->fd; int res; int i; uint32_t data; + // print debug info va_start(ap, n); - if (is_k10d(p) || is_k20d(p)) { + DPRINT("[C]\t\t\t_ipslr_write_args(cmd_2 = 0x%x, {", cmd_2); + for (i = 0; i < n; i++) { + if (i > 0) { + DPRINT(", "); + } + DPRINT("0x%X", va_arg(ap, uint32_t)); + } + DPRINT("})\n"); + va_end(ap); + + va_start(ap, n); + if ( p->model && !p->model->old_scsi_command ) { /* All at once */ - for (i=0; i<n; i++) { + for (i = 0; i < n; i++) { data = va_arg(ap, uint32_t); - buf[4*i+0] = data >> 24; - buf[4*i+1] = data >> 16; - buf[4*i+2] = data >> 8; - buf[4*i+3] = data; + + if (p->model == NULL || !p->model->is_little_endian) { + set_uint32_be(data, &buf[4*i]); + } else { + set_uint32_le(data, &buf[4*i]); + } } - cmd[4] = 4*n; - res = scsi_write(p, cmd, sizeof(cmd), buf, 4*n); + cmd[4] = 4 * n; + + + res = scsi_write(fd, cmd, sizeof (cmd), buf, 4 * n); if (res != PSLR_OK) { - va_end(ap); return res; - } + } } else { /* Arguments one by one */ - for (i=0; i<n; i++) { + for (i = 0; i < n; i++) { data = va_arg(ap, uint32_t); - buf[0] = data >> 24; - buf[1] = data >> 16; - buf[2] = data >> 8; - buf[3] = data; + + if (p->model == NULL || !p->model->is_little_endian) { + set_uint32_be(data, &buf[0]); + } else { + set_uint32_le(data, &buf[0]); + } + cmd[4] = 4; - cmd[2] = i*4; - res = scsi_write(p, cmd, sizeof(cmd), buf, 4); + cmd[2] = i * 4; + res = scsi_write(fd, cmd, sizeof (cmd), buf, 4); if (res != PSLR_OK) { - va_end(ap); return res; } } @@ -1218,25 +1526,25 @@ static int ipslr_write_args(ipslr_handle_t *p, int n, ...) /* ----------------------------------------------------------------------- */ -static int command(ipslr_handle_t *p, int a, int b, int c) -{ - uint8_t cmd[8] = { 0xf0, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static int command(FDTYPE fd, int a, int b, int c) { + DPRINT("[C]\t\t\tcommand(fd=%x, %x, %x, %x)\n", fd, a, b, c); + uint8_t cmd[8] = {0xf0, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; cmd[2] = a; cmd[3] = b; cmd[4] = c; - CHECK(scsi_write(p, cmd, sizeof(cmd), 0, 0)); + + CHECK(scsi_write(fd, cmd, sizeof (cmd), 0, 0)); return PSLR_OK; } -static int read_status(ipslr_handle_t *p, uint8_t *buf) -{ - uint8_t cmd[8] = { 0xf0, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static int read_status(FDTYPE fd, uint8_t *buf) { + uint8_t cmd[8] = {0xf0, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; int n; - n = scsi_read(p, cmd, 8, buf, 8); + n = scsi_read(fd, cmd, 8, buf, 8); if (n != 8) { - DPRINT("Only got %d bytes\n", n); + DPRINT("\tOnly got %d bytes\n", n); /* The *ist DS doesn't know to return the correct number of read bytes for this command, so return PSLR_OK instead of PSLR_READ_ERROR */ @@ -1245,263 +1553,107 @@ static int read_status(ipslr_handle_t *p, uint8_t *buf) return PSLR_OK; } -static int get_status(ipslr_handle_t *p) -{ +static int get_status(FDTYPE fd) { + DPRINT("[C]\t\t\tget_status(0x%x)\n", fd); + uint8_t statusbuf[8]; + memset(statusbuf,0,8); + while (1) { - /*usleep(POLL_INTERVAL); */ - CHECK(read_status(p, statusbuf)); - /*DPRINT("get_status->\n"); */ - /*hexdump(statusbuf, 8); */ - if (!(statusbuf[7] & 0x01) || (statusbuf[7] & 0xfe)) + CHECK(read_status(fd, statusbuf)); + DPRINT("[R]\t\t\t\t => ERROR: 0x%02X\n", statusbuf[7]); + if (statusbuf[7] != 0x01) { break; - /*DPRINT("Waiting for ready - "); */ - /*hexdump(statusbuf, 8); */ + } usleep(POLL_INTERVAL); } - if ((statusbuf[7] & 0xff) != 0) { - DPRINT("ERROR: 0x%x\n", statusbuf[7]); + if (statusbuf[7] != 0) { + DPRINT("\tERROR: 0x%x\n", statusbuf[7]); } return statusbuf[7]; } -static int get_result(ipslr_handle_t *p) -{ +static int get_result(FDTYPE fd) { + DPRINT("[C]\t\t\tget_result(0x%x)\n", fd); uint8_t statusbuf[8]; while (1) { - /*DPRINT("read out status\n");*/ - CHECK(read_status(p, statusbuf)); - /*hexdump(statusbuf, 8);*/ - if (statusbuf[6] == 0x01) + //DPRINT("read out status\n"); + CHECK(read_status(fd, statusbuf)); + //hexdump_debug(statusbuf, 8); + if (statusbuf[6] == 0x01) { break; - /*DPRINT("Waiting for result\n");*/ - /*hexdump(statusbuf, 8);*/ + } + //DPRINT("Waiting for result\n"); + //hexdump_debug(statusbuf, 8); usleep(POLL_INTERVAL); } if ((statusbuf[7] & 0xff) != 0) { - DPRINT("ERROR: 0x%x\n", statusbuf[7]); + DPRINT("\tERROR: 0x%x\n", statusbuf[7]); return -1; + } else { + DPRINT("[R]\t\t\t\t => [%02X %02X %02X %02X]\n", + statusbuf[0], statusbuf[1], statusbuf[2], statusbuf[3]); } - return statusbuf[0] | statusbuf[1] << 8 | statusbuf[2] << 16 | statusbuf[3]; + return statusbuf[0] | statusbuf[1] << 8 | statusbuf[2] << 16 | statusbuf[3] << 24; } -static int read_result(ipslr_handle_t *p, uint8_t *buf, uint32_t n) -{ - uint8_t cmd[8] = { 0xf0, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - unsigned int r; - cmd[4] = n; - cmd[5] = n >> 8; - cmd[6] = n >> 16; - cmd[7] = n >> 24; - r = scsi_read(p, cmd, sizeof(cmd), buf, n); - if (r != n) +static int read_result(FDTYPE fd, uint8_t *buf, uint32_t n) { + DPRINT("[C]\t\t\tread_result(0x%x, size=%d)\n", fd, n); + uint8_t cmd[8] = {0xf0, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + int r; + int i; + set_uint32_le(n, &cmd[4]); + r = scsi_read(fd, cmd, sizeof (cmd), buf, n); + if (r != n) { return PSLR_READ_ERROR; - return PSLR_OK; -} - -void hexdump(uint8_t *buf, uint32_t bufLen) -{ - unsigned int i; - - for (i=0; i<bufLen; i++) { - if (i%16 == 0) - DPRINT("0x%04x | ", i); - DPRINT("%02x ", buf[i]); - if (i%8 == 7) - DPRINT(" "); - if (i%16 == 15) - DPRINT("\n"); - } - if (i%16 != 15) - DPRINT("\n"); -} - - -/* ----------------------------------------------------------------------- */ -#ifdef LIBGPHOTO2 -static int scsi_write(ipslr_handle_t *p, uint8_t *cmd, uint32_t cmdLen, - uint8_t *buf, uint32_t bufLen) { - int ret; - char sense_buffer[32]; - - ret = gp_port_send_scsi_cmd (p->port, 1, (char*)cmd, cmdLen, - sense_buffer, sizeof(sense_buffer), (char*)buf, bufLen); - if (ret == GP_OK) return PSLR_OK; - return PSLR_SCSI_ERROR; -} -static int scsi_read(ipslr_handle_t *p, uint8_t *cmd, uint32_t cmdLen, - uint8_t *buf, uint32_t bufLen) -{ - int ret; - char sense_buffer[32]; - - ret = gp_port_send_scsi_cmd (p->port, 0, (char*)cmd, cmdLen, - sense_buffer, sizeof(sense_buffer), (char*)buf, bufLen); - if (ret == GP_OK) return bufLen; - return -PSLR_SCSI_ERROR; -} - -#else -static void print_scsi_error(sg_io_hdr_t *pIo, uint8_t *sense_buffer) -{ - int k; - - if (pIo->sb_len_wr > 0) { - DPRINT("SCSI error: sense data: "); - for (k = 0; k < pIo->sb_len_wr; ++k) { - if ((k > 0) && (0 == (k % 10))) - DPRINT("\n "); - DPRINT("0x%02x ", sense_buffer[k]); + } else { + // Print first 32 bytes of the result. + DPRINT("[R]\t\t\t\t => ["); + for (i = 0; i < n && i < 32; ++i) { + if (i > 0) { + if (i % 16 == 0) { + DPRINT("\n\t\t\t\t "); + } else if ((i%4) == 0 ) { + DPRINT(" "); + } + DPRINT(" "); + } + DPRINT("%02X", buf[i]); } - DPRINT("\n"); + if (n > 32) { + DPRINT(" ... (%d bytes more)", (n-32)); + } + DPRINT("]\n"); } - if (pIo->masked_status) - DPRINT("SCSI status=0x%x\n", pIo->status); - if (pIo->host_status) - DPRINT("host_status=0x%x\n", pIo->host_status); - if (pIo->driver_status) - DPRINT("driver_status=0x%x\n", pIo->driver_status); + return PSLR_OK; } -static int scsi_write(ipslr_handle_t *p, uint8_t *cmd, uint32_t cmdLen, - uint8_t *buf, uint32_t bufLen) -{ - - sg_io_hdr_t io; - int sg_fd = p->fd; - uint8_t sense[32]; - int r; - - memset(&io, 0, sizeof(io)); - - io.interface_id = 'S'; - io.cmd_len = cmdLen; - /* io.iovec_count = 0; */ /* memset takes care of this */ - io.mx_sb_len = sizeof(sense); - io.dxfer_direction = SG_DXFER_TO_DEV; - io.dxfer_len = bufLen; - io.dxferp = buf; - io.cmdp = cmd; - io.sbp = sense; - io.timeout = 20000; /* 20000 millisecs == 20 seconds */ - /* io.flags = 0; */ /* take defaults: indirect IO, etc */ - /* io.pack_id = 0; */ - /* io.usr_ptr = NULL; */ - - r = ioctl(sg_fd, SG_IO, &io); - - if (r == -1) { - perror("ioctl"); - return PSLR_DEVICE_ERROR; - } - - if ((io.info & SG_INFO_OK_MASK) != SG_INFO_OK) { - print_scsi_error(&io, sense); - return PSLR_SCSI_ERROR; - } else { - return PSLR_OK; - } +char *copyright() { + char *ret = malloc(sizeof(char)*1024); + sprintf(ret, "Copyright (C) 2011-2017 Andras Salamon\n\ +\n\ +Based on:\n\ +pslr-shoot (C) 2009 Ramiro Barreiro\n\ +PK-Remote (C) 2008 Pontus Lidman \n\n"); + return ret; } -static int scsi_read(ipslr_handle_t *p, uint8_t *cmd, uint32_t cmdLen, - uint8_t *buf, uint32_t bufLen) -{ - sg_io_hdr_t io; - int sg_fd = p->fd; - uint8_t sense[32]; - int r; +/* ----------------------------------------------------------------------- + write_debug +----------------------------------------------------------------------- */ +void write_debug( const char* message, ... ) { - memset(&io, 0, sizeof(io)); - - io.interface_id = 'S'; - io.cmd_len = cmdLen; - /* io.iovec_count = 0; */ /* memset takes care of this */ - io.mx_sb_len = sizeof(sense); - io.dxfer_direction = SG_DXFER_FROM_DEV; - io.dxfer_len = bufLen; - io.dxferp = buf; - io.cmdp = cmd; - io.sbp = sense; - io.timeout = 20000; /* 20000 millisecs == 20 seconds */ - /* io.flags = 0; */ /* take defaults: indirect IO, etc */ - /* io.pack_id = 0; */ - /* io.usr_ptr = NULL; */ - - r = ioctl(sg_fd, SG_IO, &io); - if (r == -1) { - perror("ioctl"); - return -PSLR_DEVICE_ERROR; - } - - if ((io.info & SG_INFO_OK_MASK) != SG_INFO_OK) { - print_scsi_error(&io, sense); - return -PSLR_SCSI_ERROR; - } else { - /* Older Pentax DSLR will report all bytes remaining, so make - * a special case for this (treat it as all bytes read). */ - if (io.resid == bufLen) - return bufLen; - else - return bufLen - io.resid; + // Be sure debug is really on as DPRINT doesn't know + // + if ( !debug ) { + return; } -} -#endif /* LIBGPHOTO2 */ -/* ----------------------------------------------------------------------- */ - -static uint32_t get_uint32(uint8_t *buf) -{ - uint32_t res; - res = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; - return res; -} - -/* ----------------------------------------------------------------------- */ - -static bool is_k10d(ipslr_handle_t *p) -{ - if (p->model && p->model->id1 == PSLR_ID1_K10D - && p->model->id2 == PSLR_ID2_K10D) - return true; - - if (p->model && p->model->id1 == PSLR_ID1_GX10 - && p->model->id2 == PSLR_ID2_GX10) - return true; - - return false; -} - -static bool is_k20d(ipslr_handle_t *p) -{ - if (p->model && p->model->id1 == PSLR_ID1_K20D - && p->model->id2 == PSLR_ID2_K20D) - return true; - if (p->model && p->model->id1 == PSLR_ID1_GX20 - && p->model->id2 == PSLR_ID2_GX20) - return true; - return false; -} - -static bool is_k30(ipslr_handle_t *p) -{ - if (p->model && p->model->id1 == PSLR_ID1_K30 - && p->model->id2 == PSLR_ID2_K30) - return true; - return false; -} - -static bool is_k100ds(ipslr_handle_t *p) -{ - if (p->model && p->model->id1 == PSLR_ID1_K100DS - && p->model->id2 == PSLR_ID2_K100DS) - return true; - - return false; -} -static bool is_istds(ipslr_handle_t *p) -{ - if (p->model && p->model->id1 == PSLR_ID1_IST_DS - && p->model->id2 == PSLR_ID2_IST_DS) - return true; - return false; + // Write to stderr + // + va_list argp; + va_start(argp, message); + vfprintf( stderr, message, argp ); + va_end(argp); + return; } diff --git a/camlibs/pentax/pslr.h b/camlibs/pentax/pslr.h index 02e0f444b..829b7c91c 100644 --- a/camlibs/pentax/pslr.h +++ b/camlibs/pentax/pslr.h @@ -1,23 +1,44 @@ /* + pkTriggerCord + Copyright (C) 2011-2017 Andras Salamon <andras.salamon@melda.info> + Remote control of Pentax DSLR cameras. + + Support for K200D added by Jens Dreyer <jens.dreyer@udo.edu> 04/2011 + Support for K-r added by Vincenc Podobnik <vincenc.podobnik@gmail.com> 06/2011 + Support for K-30 added by Camilo Polymeris <cpolymeris@gmail.com> 09/2012 + Support for K-01 added by Ethan Queen <ethanqueen@gmail.com> 01/2013 + Support for K-3 added by Tao Wang <twang2218@gmail.com> 01/2016 + + based on: + PK-Remote Remote control of Pentax DSLR cameras. Copyright (C) 2008 Pontus Lidman <pontus@lysator.liu.se> + PK-Remote for Windows + Copyright (C) 2010 Tomasz Kos + This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + GNU Lesser General Public License for more details. You should have received a copy of the GNU General Public License + and GNU Lesser General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ + */ + +#ifndef PSLR_H +#define PSLR_H -#define PSLR_MAX_RESOLUTIONS 4 +#include "pslr_enum.h" +#include "pslr_scsi.h" +#include "pslr_model.h" #define PSLR_LIGHT_METER_AE_LOCK 0x8 @@ -33,81 +54,33 @@ #define PSLR_AF_POINT_BOT_MID 0x200 #define PSLR_AF_POINT_BOT_RIGHT 0x400 -#define PSLR_ID1_K30 0x12f52 -#define PSLR_ID2_K30 0x20c -#define PSLR_ID1_K20D 0x12cd2 -#define PSLR_ID2_K20D 0x1ba -#define PSLR_ID1_K10D 0x12c1e -#define PSLR_ID2_K10D 0x1a5 -#define PSLR_ID1_K110D 0x12b9d -#define PSLR_ID2_K110D 0x1ac -#define PSLR_ID1_K100D 0x12b9c -#define PSLR_ID2_K100D 0x189 -#define PSLR_ID1_K100DS 0x12ba2 -#define PSLR_ID2_K100DS 0x189 -#define PSLR_ID1_IST_D 0x12994 -#define PSLR_ID2_IST_D 0x141 -#define PSLR_ID1_IST_DS 0x12aa2 -#define PSLR_ID2_IST_DS 0x177 -#define PSLR_ID1_IST_DS2 0x12b60 -#define PSLR_ID2_IST_DS2 0x19a -#define PSLR_ID1_IST_DL 0x12b1a -#define PSLR_ID2_IST_DL 0x188 -#define PSLR_ID1_GX10 0x12c20 -#define PSLR_ID2_GX10 0x1ad -#define PSLR_ID1_GX20 0x12cd4 -#define PSLR_ID2_GX20 0x1c6 - -typedef enum { - PSLR_OK = 0, - PSLR_DEVICE_ERROR, - PSLR_SCSI_ERROR, - PSLR_COMMAND_ERROR, - PSLR_READ_ERROR, - PSLR_NO_MEMORY, - PSLR_PARAM, /* Invalid parameters to API */ - PSLR_ERROR_MAX -} pslr_result; - typedef enum { - PSLR_BUF_THUMBNAIL, - PSLR_BUF_PREVIEW, - PSLR_BUF_JPEG, - PSLR_BUF_PEF + PSLR_BUF_PEF, + PSLR_BUF_DNG, + PSLR_BUF_JPEG_4, // only for cameras supporting 4* mode ? + PSLR_BUF_JPEG_3, + PSLR_BUF_JPEG_2, + PSLR_BUF_JPEG_1, + PSLR_BUF_PREVIEW = 8, + PSLR_BUF_THUMBNAIL = 9 // 7 works also } pslr_buffer_type; typedef enum { - PSLR_JPEG_QUALITY_4, /* K20D only */ - PSLR_JPEG_QUALITY_3, - PSLR_JPEG_QUALITY_2, - PSLR_JPEG_QUALITY_1, - PSLR_JPEG_QUALITY_MAX -} pslr_jpeg_quality_t; - -typedef enum { - PSLR_JPEG_IMAGE_MODE_NATURAL, - PSLR_JPEG_IMAGE_MODE_BRIGHT, - PSLR_JPEG_IMAGE_MODE_MAX -} pslr_jpeg_image_mode_t; + USER_FILE_FORMAT_PEF, + USER_FILE_FORMAT_DNG, + USER_FILE_FORMAT_JPEG, + USER_FILE_FORMAT_MAX +} user_file_format; -typedef enum { - PSLR_RAW_FORMAT_PEF, - PSLR_RAW_FORMAT_DNG, - PSLR_RAW_FORMAT_MAX -} pslr_raw_format_t; +typedef struct { + user_file_format uff; + const char *file_format_name; + const char *extension; +} user_file_format_t; -typedef enum { - PSLR_IMAGE_FORMAT_JPEG, - PSLR_IMAGE_FORMAT_RAW, - PSLR_IMAGE_FORMAT_RAW_PLUS, - PSLR_IMAGE_FORMAT_MAX -} pslr_image_format_t; +extern user_file_format_t file_formats[3]; -typedef enum { - PSLR_CUSTOM_EV_STEPS_1_2, - PSLR_CUSTOM_EV_STEPS_1_3, - PSLR_CUSTOM_EV_STEPS_MAX -} pslr_custom_ev_steps_t; +user_file_format_t *get_file_format_t( user_file_format uff ); typedef enum { PSLR_CUSTOM_SENSITIVITY_STEPS_1EV, @@ -115,84 +88,55 @@ typedef enum { PSLR_CUSTOM_SENSITIVITY_STEPS_MAX } pslr_custom_sensitivity_steps_t; +// OFF-AUTO: Off-Auto-Aperture typedef enum { - PSLR_EXPOSURE_MODE_GREEN, - PSLR_EXPOSURE_MODE_P, - PSLR_EXPOSURE_MODE_SV, - PSLR_EXPOSURE_MODE_TV, - PSLR_EXPOSURE_MODE_AV, - PSLR_EXPOSURE_MODE_TAV, - PSLR_EXPOSURE_MODE_M, - PSLR_EXPOSURE_MODE_B, - PSLR_EXPOSURE_MODE_X, - PSLR_EXPOSURE_MODE_MAX + PSLR_EXPOSURE_MODE_P = 0 , + PSLR_EXPOSURE_MODE_GREEN = 1, +// PSLR_EXPOSURE_MODE_HYP = 2, +// PSLR_EXPOSURE_MODE_AUTO_PICT = 1, +// PSLR_EXPOSURE_MODE_GREEN = 3, maybe 1 is AUTO_PICT + PSLR_EXPOSURE_MODE_TV = 4, + PSLR_EXPOSURE_MODE_AV = 5, +// PSLR_EXPOSURE_MODE_TV_SHIFT = 6, //? +// PSLR_EXPOSURE_MODE_AV_SHIFT = 7, //? + PSLR_EXPOSURE_MODE_M = 8, + PSLR_EXPOSURE_MODE_B = 9, + PSLR_EXPOSURE_MODE_AV_OFFAUTO = 10, + PSLR_EXPOSURE_MODE_M_OFFAUTO = 11, + PSLR_EXPOSURE_MODE_B_OFFAUTO = 12, + PSLR_EXPOSURE_MODE_TAV = 13, // ? + PSLR_EXPOSURE_MODE_SV = 15, + PSLR_EXPOSURE_MODE_X = 16, // ? + PSLR_EXPOSURE_MODE_MAX = 17 } pslr_exposure_mode_t; typedef enum { - PSLR_AF_POINT_SEL_AUTO, - PSLR_AF_POINT_SEL_SEL, - PSLR_AF_POINT_SEL_CENTER, - PSLR_AF_POINT_SEL_MAX -} pslr_af_point_sel_t; - -typedef struct { - int32_t nom; - int32_t denom; -} pslr_rational_t; + PSLR_GUI_EXPOSURE_MODE_GREEN, + PSLR_GUI_EXPOSURE_MODE_P, + PSLR_GUI_EXPOSURE_MODE_SV, + PSLR_GUI_EXPOSURE_MODE_TV, + PSLR_GUI_EXPOSURE_MODE_AV, + PSLR_GUI_EXPOSURE_MODE_TAV, + PSLR_GUI_EXPOSURE_MODE_M, + PSLR_GUI_EXPOSURE_MODE_B, + PSLR_GUI_EXPOSURE_MODE_X, + PSLR_GUI_EXPOSURE_MODE_MAX +} pslr_gui_exposure_mode_t; typedef void *pslr_handle_t; -typedef enum { - PSLR_STREAM_RAW, - PSLR_STREAM_JPEG -} pslr_stream_t; - -typedef void *pslr_buffer_handle_t; - -typedef struct { - uint16_t power; -} pslr_status_brief; - typedef struct { - pslr_status_brief brief; - uint16_t bufmask; /* 0x16 */ - uint32_t current_iso; /* 0x11c */ - pslr_rational_t current_shutter_speed; /* 0xf4 */ - pslr_rational_t current_aperture; /* 0xfc */ - pslr_rational_t lens_max_aperture; /* 0x12c */ - pslr_rational_t lens_min_aperture; /* 0x134 */ - pslr_rational_t current_zoom; /* 0x16c */ - pslr_rational_t set_shutter_speed; /* 0x2c */ - pslr_rational_t set_aperture; /* 0x34 */ - uint32_t set_iso; /* 0x60 */ - uint32_t jpeg_resolution; /* 0x7c */ - uint32_t jpeg_saturation; /* 0x8c */ - uint32_t jpeg_quality; /* 0x80 */ - uint32_t jpeg_contrast; /* 0x94 */ - uint32_t jpeg_sharpness; /* 0x90 */ - uint32_t jpeg_image_mode; /* 0x88 */ - pslr_rational_t zoom; /* 0x16c */ - uint32_t focus; /* 0x174 */ - uint32_t image_format; /* 0x78 */ - uint32_t raw_format; /* 0x84 */ - uint32_t light_meter_flags; /* 0x124 */ - pslr_rational_t ec; /* 0x3c */ - uint32_t custom_ev_steps; /* 0x9c */ - uint32_t custom_sensitivity_steps; /* 0xa0 */ - uint32_t exposure_mode; /* 0xe0 */ - uint32_t user_mode_flag; /* 0x1c */ - uint32_t af_point_select; /* 0xbc */ - uint32_t selected_af_point; /* 0xc0 */ - uint32_t focused_af_point; /* 0x150 */ -} pslr_status; + uint32_t a; + uint32_t b; + uint32_t addr; + uint32_t length; +} pslr_buffer_segment_info; typedef void (*pslr_progress_callback_t)(uint32_t current, uint32_t total); -#ifdef LIBGPHOTO2 -pslr_handle_t pslr_init(GPPort *port); -#else -pslr_handle_t pslr_init(void); -#endif +void sleep_sec(double sec); + +pslr_handle_t pslr_init(char *model, char *device); int pslr_connect(pslr_handle_t h); int pslr_disconnect(pslr_handle_t h); int pslr_shutdown(pslr_handle_t h); @@ -202,41 +146,101 @@ int pslr_shutter(pslr_handle_t h); int pslr_focus(pslr_handle_t h); int pslr_get_status(pslr_handle_t h, pslr_status *sbuf); -int pslr_get_buffer(pslr_handle_t h, int bufno, int type, int resolution, +int pslr_get_status_buffer(pslr_handle_t h, uint8_t *st_buf); + +char *collect_status_info( pslr_handle_t h, pslr_status status ); + +int pslr_get_buffer(pslr_handle_t h, int bufno, pslr_buffer_type type, int resolution, uint8_t **pdata, uint32_t *pdatalen); -int pslr_set_progress_callback(pslr_handle_t h, pslr_progress_callback_t cb, +int pslr_set_progress_callback(pslr_handle_t h, pslr_progress_callback_t cb, uintptr_t user_data); int pslr_set_shutter(pslr_handle_t h, pslr_rational_t value); int pslr_set_aperture(pslr_handle_t h, pslr_rational_t value); -int pslr_set_iso(pslr_handle_t h, uint32_t value); +int pslr_set_iso(pslr_handle_t h, uint32_t value, uint32_t auto_min_value, uint32_t auto_max_value); int pslr_set_ec(pslr_handle_t h, pslr_rational_t value); -int pslr_set_jpeg_quality(pslr_handle_t h, pslr_jpeg_quality_t quality); -int pslr_set_jpeg_resolution(pslr_handle_t h, int resolution); -int pslr_set_jpeg_image_mode(pslr_handle_t h, pslr_jpeg_image_mode_t image_mode); +int pslr_set_white_balance(pslr_handle_t h, pslr_white_balance_mode_t wb_mode); +int pslr_set_white_balance_adjustment(pslr_handle_t h, pslr_white_balance_mode_t wb_mode, uint32_t wbadj_mg, uint32_t wbadj_ba); +int pslr_set_flash_mode(pslr_handle_t h, pslr_flash_mode_t value); +int pslr_set_flash_exposure_compensation(pslr_handle_t h, pslr_rational_t value); +int pslr_set_drive_mode(pslr_handle_t h, pslr_drive_mode_t drive_mode); +int pslr_set_af_mode(pslr_handle_t h, pslr_af_mode_t af_mode); +int pslr_set_af_point_sel(pslr_handle_t h, pslr_af_point_sel_t af_point_sel); +int pslr_set_ae_metering_mode(pslr_handle_t h, pslr_ae_metering_t ae_metering_mode); +int pslr_set_color_space(pslr_handle_t h, pslr_color_space_t color_space); + +int pslr_set_jpeg_stars(pslr_handle_t h, int jpeg_stars); +int pslr_set_jpeg_resolution(pslr_handle_t h, int megapixel); +int pslr_set_jpeg_image_tone(pslr_handle_t h, pslr_jpeg_image_tone_t image_mode); int pslr_set_jpeg_sharpness(pslr_handle_t h, int32_t sharpness); int pslr_set_jpeg_contrast(pslr_handle_t h, int32_t contrast); int pslr_set_jpeg_saturation(pslr_handle_t h, int32_t saturation); +int pslr_set_jpeg_hue(pslr_handle_t h, int32_t hue); int pslr_set_image_format(pslr_handle_t h, pslr_image_format_t format); -int pslr_is_image_format_supported(pslr_handle_t h, pslr_image_format_t format); int pslr_set_raw_format(pslr_handle_t h, pslr_raw_format_t format); +int pslr_set_user_file_format(pslr_handle_t h, user_file_format uff); +user_file_format get_user_file_format( pslr_status *st ); int pslr_delete_buffer(pslr_handle_t h, int bufno); int pslr_green_button(pslr_handle_t h); + +int pslr_button_test(pslr_handle_t h, int bno, int arg); + int pslr_ae_lock(pslr_handle_t h, bool lock); -int pslr_buffer_open(pslr_handle_t h, int bufno, int type, int resolution); +int pslr_dust_removal(pslr_handle_t h); + +int pslr_bulb(pslr_handle_t h, bool on ); + +int pslr_buffer_open(pslr_handle_t h, int bufno, pslr_buffer_type type, int resolution); uint32_t pslr_buffer_read(pslr_handle_t h, uint8_t *buf, uint32_t size); -void pslr_buffer_close(pslr_buffer_handle_t h); +void pslr_buffer_close(pslr_handle_t h); uint32_t pslr_buffer_get_size(pslr_handle_t h); int pslr_set_exposure_mode(pslr_handle_t h, pslr_exposure_mode_t mode); int pslr_select_af_point(pslr_handle_t h, uint32_t point); const char *pslr_camera_name(pslr_handle_t h); -const char **pslr_camera_resolution_steps(pslr_handle_t h); +int pslr_get_model_max_jpeg_stars(pslr_handle_t h); +int pslr_get_model_jpeg_property_levels(pslr_handle_t h); +int pslr_get_model_buffer_size(pslr_handle_t h); +int pslr_get_model_fastest_shutter_speed(pslr_handle_t h); +int pslr_get_model_base_iso_min(pslr_handle_t h); +int pslr_get_model_base_iso_max(pslr_handle_t h); +int pslr_get_model_extended_iso_min(pslr_handle_t h); +int pslr_get_model_extended_iso_max(pslr_handle_t h); +int *pslr_get_model_jpeg_resolutions(pslr_handle_t h); +bool pslr_get_model_only_limited(pslr_handle_t h); +bool pslr_get_model_has_jpeg_hue(pslr_handle_t h); +bool pslr_get_model_need_exposure_conversion(pslr_handle_t h); +pslr_jpeg_image_tone_t pslr_get_model_max_supported_image_tone(pslr_handle_t h); + +int pslr_get_model_af_point_num(pslr_handle_t h); + +pslr_buffer_type pslr_get_jpeg_buffer_type(pslr_handle_t h, int quality); +int pslr_get_jpeg_resolution(pslr_handle_t h, int hwres); + +int pslr_read_datetime(pslr_handle_t *h, int *year, int *month, int *day, int *hour, int *min, int *sec); + +int pslr_read_dspinfo(pslr_handle_t *h, char *firmware); + +int pslr_read_setting(pslr_handle_t *h, int offset, uint32_t *value); +int pslr_write_setting(pslr_handle_t *h, int offset, uint32_t value); +int pslr_read_settings(pslr_handle_t *h, int offset, int length, uint8_t *buf); + +pslr_gui_exposure_mode_t exposure_mode_conversion( pslr_exposure_mode_t exp ); +char *format_rational( pslr_rational_t rational, char * fmt ); + +int pslr_test( pslr_handle_t h, bool cmd9_wrap, int subcommand, int argnum, int arg1, int arg2, int arg3, int arg4); + +char *copyright(); + +void write_debug( const char* message, ... ); + +int debug_onoff(ipslr_handle_t *p, char debug_mode); +#endif diff --git a/camlibs/pentax/pslr_enum.c b/camlibs/pentax/pslr_enum.c new file mode 100644 index 000000000..083e0d4ec --- /dev/null +++ b/camlibs/pentax/pslr_enum.c @@ -0,0 +1,303 @@ +/* + pkTriggerCord + Copyright (C) 2011-2017 Andras Salamon <andras.salamon@melda.info> + Remote control of Pentax DSLR cameras. + + Support for K200D added by Jens Dreyer <jens.dreyer@udo.edu> 04/2011 + Support for K-r added by Vincenc Podobnik <vincenc.podobnik@gmail.com> 06/2011 + Support for K-30 added by Camilo Polymeris <cpolymeris@gmail.com> 09/2012 + Support for K-01 added by Ethan Queen <ethanqueen@gmail.com> 01/2013 + Support for K-3 added by Tao Wang <twang2218@gmail.com> 01/2016 + + based on: + + PK-Remote + Remote control of Pentax DSLR cameras. + Copyright (C) 2008 Pontus Lidman <pontus@lysator.liu.se> + + PK-Remote for Windows + Copyright (C) 2010 Tomasz Kos + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + and GNU Lesser General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include "pslr_enum.h" + +#include <string.h> +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> + +const char* pslr_color_space_str[PSLR_COLOR_SPACE_MAX] = { + "sRGB", + "AdobeRGB" +}; + +const char* pslr_af_mode_str[PSLR_AF_MODE_MAX] = { + "MF", + "AF.S", + "AF.C", + "AF.A" +}; + +const char* pslr_ae_metering_str[PSLR_AE_METERING_MAX] = { + "Multi", + "Center", + "Spot" +}; + +const char* pslr_flash_mode_str[PSLR_FLASH_MODE_MAX] = { + "Manual", + "Manual-RedEye", + "Slow", + "Slow-RedEye", + "TrailingCurtain", + "Auto", + "Auto-RedEye", + "TrailingCurtain", // maybe in manual mode?? + "Wireless" +}; + +const char* pslr_drive_mode_str[PSLR_DRIVE_MODE_MAX] = { + "Single", // Bracketing also returns Single + "Continuous-HI", + "SelfTimer-12", + "SelfTimer-2", + "Remote", + "Remote-3", + "Continuous-LO" +}; + +const char* pslr_af_point_sel_str[PSLR_AF_POINT_SEL_MAX] = { + "Auto-5", + "Select", + "Spot", + "Auto-11" +}; + +const char* pslr_jpeg_image_tone_str[PSLR_JPEG_IMAGE_TONE_MAX] = { + "Natural", + "Bright", + "Portrait", + "Landscape", + "Vibrant", + "Monochrome", + "Muted", + "ReversalFilm", + "BleachBypass", + "Radiant", + "CrossProcessing", + "Flat", + "Auto" +}; + +const char* pslr_white_balance_mode_str[PSLR_WHITE_BALANCE_MODE_MAX] = { + "Auto", + "Daylight", + "Shade", + "Cloudy", + "Fluorescent_D", + "Fluorescent_N", + "Fluorescent_W", + "Tungsten", + "Flash", + "Manual", // sometimes called Manual1 + "Manual2", + "Manual3", + "Kelvin1", + "Kelvin2", + "Kelvin3", + "Fluorescent_L", + "CTE", + "MultiAuto" +}; + +const char* pslr_custom_ev_steps_str[PSLR_CUSTOM_EV_STEPS_MAX] = { + "1/2", + "1/3" +}; + +const char* pslr_image_format_str[PSLR_IMAGE_FORMAT_MAX] = { + "JPEG", + "RAW", + "RAW+" +}; + +const char* pslr_raw_format_str[PSLR_RAW_FORMAT_MAX] = { + "PEF", + "DNG" +}; + +const char* pslr_scene_mode_str[PSLR_SCENE_MODE_MAX] = { + "NONE", + "HISPEED", + "DOF", + "MTF", + "STANDARD", + "PORTRAIT", + "LANDSCAPE", + "MACRO", + "SPORT", + "NIGHTSCENEPORTRAIT", + "NOFLASH",//10 + "NIGHTSCENE", + "SURFANDSNOW", + "TEXT", + "SUNSET", + "KIDS", + "PET", + "CANDLELIGHT", + "MUSEUM", + "19", // ? + "FOOD", + "STAGE", + "NIGHTSNAP", + "SWALLOWDOF", + "24", // ? + "NIGHTSCENEHDR", + "BLUESKY", + "FOREST", + "28", // ? + "BLACKLIGHTSILHOUETTE" +}; + + +// case insenstive comparison +// strnicmp +int str_comparison_i (const char *s1, const char *s2, int n) { + if ( s1 == NULL ) { + return s2 == NULL ? 0 : -(*s2); + } + if (s2 == NULL) { + return *s1; + } + + char c1='\0', c2='\0'; + int length=0; + while ( length<n && (c1 = tolower (*s1)) == (c2 = tolower (*s2))) { + if (*s1 == '\0') { + break; + } + ++s1; + ++s2; + ++length; + } + return c1 - c2; +} + +int find_in_array( const char** array, int length, char* str ) { + int i; + int found_index=-1; + size_t found_index_length=0; + size_t string_length; + for ( i = 0; i<length; ++i ) { + string_length = strlen(array[i]); + if ( (str_comparison_i( array[i], str, string_length ) == 0) && (string_length > found_index_length) ) { + found_index_length = string_length; + found_index = i; + } + } + return found_index; +} + +const char *get_pslr_str( const char** array, int length, int value ) { + if (value >=0 && value < length) { + return array[value]; + } else { + char *ret = malloc(128); + sprintf (ret, "Unknown value: %d", value); + return ret; + } +} + + +pslr_color_space_t get_pslr_color_space( char *str ) { + return find_in_array( pslr_color_space_str, sizeof(pslr_color_space_str)/sizeof(pslr_color_space_str[0]),str); +} + +const char *get_pslr_color_space_str( pslr_color_space_t value ) { + return get_pslr_str( pslr_color_space_str, sizeof(pslr_color_space_str)/sizeof(pslr_color_space_str[0]),value); +} + +pslr_af_mode_t get_pslr_af_mode( char *str ) { + return find_in_array( pslr_af_mode_str, sizeof(pslr_af_mode_str)/sizeof(pslr_af_mode_str[0]),str); +} + +const char *get_pslr_af_mode_str( pslr_af_mode_t value ) { + return get_pslr_str( pslr_af_mode_str, sizeof(pslr_af_mode_str)/sizeof(pslr_af_mode_str[0]),value); +} + +pslr_ae_metering_t get_pslr_ae_metering( char *str ) { + return find_in_array( pslr_ae_metering_str, sizeof(pslr_ae_metering_str)/sizeof(pslr_ae_metering_str[0]),str); +} + +const char *get_pslr_ae_metering_str( pslr_ae_metering_t value ) { + return get_pslr_str( pslr_ae_metering_str, sizeof(pslr_ae_metering_str)/sizeof(pslr_ae_metering_str[0]),value); +} + +pslr_flash_mode_t get_pslr_flash_mode( char *str ) { + return find_in_array( pslr_flash_mode_str, sizeof(pslr_flash_mode_str)/sizeof(pslr_flash_mode_str[0]),str); +} + +const char *get_pslr_flash_mode_str( pslr_flash_mode_t value ) { + return get_pslr_str( pslr_flash_mode_str, sizeof(pslr_flash_mode_str)/sizeof(pslr_flash_mode_str[0]),value); +} + +pslr_drive_mode_t get_pslr_drive_mode( char *str ) { + return find_in_array( pslr_drive_mode_str, sizeof(pslr_drive_mode_str)/sizeof(pslr_drive_mode_str[0]),str); +} + +const char *get_pslr_drive_mode_str( pslr_drive_mode_t value ) { + return get_pslr_str( pslr_drive_mode_str, sizeof(pslr_drive_mode_str)/sizeof(pslr_drive_mode_str[0]),value); +} + +pslr_af_point_sel_t get_pslr_af_point_sel( char *str ) { + return find_in_array( pslr_af_point_sel_str, sizeof(pslr_af_point_sel_str)/sizeof(pslr_af_point_sel_str[0]),str); +} + +const char *get_pslr_af_point_sel_str( pslr_af_point_sel_t value ) { + return get_pslr_str( pslr_af_point_sel_str, sizeof(pslr_af_point_sel_str)/sizeof(pslr_af_point_sel_str[0]),value); +} + +pslr_jpeg_image_tone_t get_pslr_jpeg_image_tone( char *str ) { + return find_in_array( pslr_jpeg_image_tone_str, sizeof(pslr_jpeg_image_tone_str)/sizeof(pslr_jpeg_image_tone_str[0]),str); +} + +const char *get_pslr_jpeg_image_tone_str( pslr_jpeg_image_tone_t value ) { + return get_pslr_str( pslr_jpeg_image_tone_str, sizeof(pslr_jpeg_image_tone_str)/sizeof(pslr_jpeg_image_tone_str[0]),value); +} + +pslr_white_balance_mode_t get_pslr_white_balance_mode( char *str ) { + return find_in_array( pslr_white_balance_mode_str, sizeof(pslr_white_balance_mode_str)/sizeof(pslr_white_balance_mode_str[0]),str); +} + +const char *get_pslr_white_balance_mode_str( pslr_white_balance_mode_t value ) { + return get_pslr_str( pslr_white_balance_mode_str, sizeof(pslr_white_balance_mode_str)/sizeof(pslr_white_balance_mode_str[0]),value); +} + +const char *get_pslr_custom_ev_steps_str( pslr_custom_ev_steps_t value ) { + return get_pslr_str( pslr_custom_ev_steps_str, sizeof(pslr_custom_ev_steps_str)/sizeof(pslr_custom_ev_steps_str[0]),value); +} + +const char *get_pslr_image_format_str( pslr_image_format_t value ) { + return get_pslr_str( pslr_image_format_str, sizeof(pslr_image_format_str)/sizeof(pslr_image_format_str[0]),value); +} + +const char *get_pslr_raw_format_str( pslr_raw_format_t value ) { + return get_pslr_str( pslr_raw_format_str, sizeof(pslr_raw_format_str)/sizeof(pslr_raw_format_str[0]),value); +} + +const char *get_pslr_scene_mode_str( pslr_scene_mode_t value ) { + return get_pslr_str( pslr_scene_mode_str, sizeof(pslr_scene_mode_str)/sizeof(pslr_scene_mode_str[0]),value); +} diff --git a/camlibs/pentax/pslr_enum.h b/camlibs/pentax/pslr_enum.h new file mode 100644 index 000000000..9d8c5eb87 --- /dev/null +++ b/camlibs/pentax/pslr_enum.h @@ -0,0 +1,214 @@ +/* + pkTriggerCord + Copyright (C) 2011-2017 Andras Salamon <andras.salamon@melda.info> + Remote control of Pentax DSLR cameras. + + based on: + + PK-Remote + Remote control of Pentax DSLR cameras. + Copyright (C) 2008 Pontus Lidman <pontus@lysator.liu.se> + + PK-Remote for Windows + Copyright (C) 2010 Tomasz Kos + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + and GNU Lesser General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#ifndef PSLR_ENUM_H +#define PSLR_ENUM_H + +typedef enum { + PSLR_COLOR_SPACE_SRGB, + PSLR_COLOR_SPACE_ADOBERGB, + PSLR_COLOR_SPACE_MAX +} pslr_color_space_t; + +typedef enum { + PSLR_AF_MODE_MF, + PSLR_AF_MODE_AF_S, + PSLR_AF_MODE_AF_C, + PSLR_AF_MODE_AF_A, + PSLR_AF_MODE_MAX +} pslr_af_mode_t; + +typedef enum { + PSLR_AE_METERING_MULTI, + PSLR_AE_METERING_CENTER, + PSLR_AE_METERING_SPOT, + PSLR_AE_METERING_MAX +} pslr_ae_metering_t; + +typedef enum { + PSLR_FLASH_MODE_MANUAL = 0, + PSLR_FLASH_MODE_MANUAL_REDEYE = 1, + PSLR_FLASH_MODE_SLOW = 2, + PSLR_FLASH_MODE_SLOW_REDEYE = 3, + PSLR_FLASH_MODE_TRAILING_CURTAIN = 4, + PSLR_FLASH_MODE_AUTO = 5, + PSLR_FLASH_MODE_AUTO_REDEYE = 6, + // 7 not used + PSLR_FLASH_MODE_WIRELESS = 8, + PSLR_FLASH_MODE_MAX = 9 +} pslr_flash_mode_t; + +typedef enum { + PSLR_DRIVE_MODE_SINGLE, + PSLR_DRIVE_MODE_CONTINUOUS_HI, + PSLR_DRIVE_MODE_SELF_TIMER_12, + PSLR_DRIVE_MODE_SELF_TIMER_2, + PSLR_DRIVE_MODE_REMOTE, + PSLR_DRIVE_MODE_REMOTE_3, + PSLR_DRIVE_MODE_CONTINUOUS_LO, + PSLR_DRIVE_MODE_MAX +} pslr_drive_mode_t; + +typedef enum { + PSLR_AF_POINT_SEL_AUTO_5, + PSLR_AF_POINT_SEL_SELECT, + PSLR_AF_POINT_SEL_SPOT, + PSLR_AF_POINT_SEL_AUTO_11, // maybe not for all cameras + PSLR_AF_POINT_SEL_MAX +} pslr_af_point_sel_t; + +typedef enum { + PSLR_JPEG_IMAGE_TONE_NONE = -1, + PSLR_JPEG_IMAGE_TONE_NATURAL, + PSLR_JPEG_IMAGE_TONE_BRIGHT, + PSLR_JPEG_IMAGE_TONE_PORTRAIT, + PSLR_JPEG_IMAGE_TONE_LANDSCAPE, + PSLR_JPEG_IMAGE_TONE_VIBRANT, + PSLR_JPEG_IMAGE_TONE_MONOCHROME, + PSLR_JPEG_IMAGE_TONE_MUTED, + PSLR_JPEG_IMAGE_TONE_REVERSAL_FILM, + PSLR_JPEG_IMAGE_TONE_BLEACH_BYPASS, + PSLR_JPEG_IMAGE_TONE_RADIANT, + PSLR_JPEG_IMAGE_TONE_CROSS_PROCESSING, + PSLR_JPEG_IMAGE_TONE_FLAT, + PSLR_JPEG_IMAGE_TONE_AUTO, + PSLR_JPEG_IMAGE_TONE_MAX +} pslr_jpeg_image_tone_t; + +typedef enum { + PSLR_WHITE_BALANCE_MODE_AUTO, + PSLR_WHITE_BALANCE_MODE_DAYLIGHT, + PSLR_WHITE_BALANCE_MODE_SHADE, + PSLR_WHITE_BALANCE_MODE_CLOUDY, + PSLR_WHITE_BALANCE_MODE_FLUORESCENT_DAYLIGHT_COLOR, + PSLR_WHITE_BALANCE_MODE_FLUORESCENT_DAYLIGHT_WHITE, + PSLR_WHITE_BALANCE_MODE_FLUORESCENT_COOL_WHITE, + PSLR_WHITE_BALANCE_MODE_TUNGSTEN, + PSLR_WHITE_BALANCE_MODE_FLASH, + PSLR_WHITE_BALANCE_MODE_MANUAL, + PSLR_WHITE_BALANCE_MODE_MANUAL_2, + PSLR_WHITE_BALANCE_MODE_MANUAL_3, + PSLR_WHITE_BALANCE_MODE_KELVIN_1, + PSLR_WHITE_BALANCE_MODE_KELVIN_2, + PSLR_WHITE_BALANCE_MODE_KELVIN_3, + PSLR_WHITE_BALANCE_MODE_FLUORESCENT_WARM_WHITE, + PSLR_WHITE_BALANCE_MODE_CTE, + PSLR_WHITE_BALANCE_MODE_MULTI_AUTO, + PSLR_WHITE_BALANCE_MODE_MAX +} pslr_white_balance_mode_t; + +typedef enum { + PSLR_CUSTOM_EV_STEPS_1_2, + PSLR_CUSTOM_EV_STEPS_1_3, + PSLR_CUSTOM_EV_STEPS_MAX +} pslr_custom_ev_steps_t; + +typedef enum { + PSLR_IMAGE_FORMAT_JPEG, + PSLR_IMAGE_FORMAT_RAW, + PSLR_IMAGE_FORMAT_RAW_PLUS, + PSLR_IMAGE_FORMAT_MAX +} pslr_image_format_t; + +typedef enum { + PSLR_RAW_FORMAT_PEF, + PSLR_RAW_FORMAT_DNG, + PSLR_RAW_FORMAT_MAX +} pslr_raw_format_t; + +typedef enum { + PSLR_SCENE_MODE_NONE, + PSLR_SCENE_MODE_HISPEED, + PSLR_SCENE_MODE_DOF, + PSLR_SCENE_MODE_MTF, + PSLR_SCENE_MODE_STANDARD, + PSLR_SCENE_MODE_PORTRAIT, + PSLR_SCENE_MODE_LANDSCAPE, + PSLR_SCENE_MODE_MACRO, + PSLR_SCENE_MODE_SPORT, + PSLR_SCENE_MODE_NIGHTSCENEPORTRAIT, + PSLR_SCENE_MODE_NOFLASH, + PSLR_SCENE_MODE_NIGHTSCENE, + PSLR_SCENE_MODE_SURFANDSNOW, + PSLR_SCENE_MODE_TEXT, + PSLR_SCENE_MODE_SUNSET, + PSLR_SCENE_MODE_KIDS, + PSLR_SCENE_MODE_PET, + PSLR_SCENE_MODE_CANDLELIGHT, + PSLR_SCENE_MODE_MUSEUM, + PSLR_SCENE_MODE_19, + PSLR_SCENE_MODE_FOOD, + PSLR_SCENE_MODE_STAGE, + PSLR_SCENE_MODE_NIGHTSNAP, + PSLR_SCENE_MODE_SWALLOWDOF, + PSLR_SCENE_MODE_24, + PSLR_SCENE_MODE_NIGHTSCENEHDR, + PSLR_SCENE_MODE_BLUESKY, + PSLR_SCENE_MODE_FOREST, + PSLR_SCENE_MODE_28, + PSLR_SCENE_MODE_BLACKLIGHTSILHOUETTE, + PSLR_SCENE_MODE_MAX +} pslr_scene_mode_t; + +int str_comparison_i (const char *s1, const char *s2, int n); +int find_in_array( const char** array, int length, char* str ); + +pslr_color_space_t get_pslr_color_space( char *str ); +const char *get_pslr_color_space_str( pslr_color_space_t value ); + +pslr_af_mode_t get_pslr_af_mode( char *str ); +const char *get_pslr_af_mode_str( pslr_af_mode_t value ); + +pslr_ae_metering_t get_pslr_ae_metering( char *str ); +const char *get_pslr_ae_metering_str( pslr_ae_metering_t value ); + +pslr_flash_mode_t get_pslr_flash_mode( char *str ); +const char *get_pslr_flash_mode_str( pslr_flash_mode_t value ); + +pslr_drive_mode_t get_pslr_drive_mode( char *str ); +const char *get_pslr_drive_mode_str( pslr_drive_mode_t value ); + +pslr_af_point_sel_t get_pslr_af_point_sel( char *str ); +const char *get_pslr_af_point_sel_str( pslr_af_point_sel_t value ); + +pslr_jpeg_image_tone_t get_pslr_jpeg_image_tone( char *str ); +const char *get_pslr_jpeg_image_tone_str( pslr_jpeg_image_tone_t value ); + +pslr_white_balance_mode_t get_pslr_white_balance_mode( char *str ); +const char *get_pslr_white_balance_mode_str( pslr_white_balance_mode_t value ); + +//pslr_custom_ev_steps_t get_pslr_custom_ev_steps( char *str ); +const char *get_pslr_custom_ev_steps_str( pslr_custom_ev_steps_t value ); + +const char *get_pslr_image_format_str( pslr_image_format_t value ); + +const char *get_pslr_raw_format_str( pslr_raw_format_t value ); + +const char *get_pslr_scene_mode_str( pslr_scene_mode_t value ); + +#endif diff --git a/camlibs/pentax/pslr_lens.c b/camlibs/pentax/pslr_lens.c new file mode 100644 index 000000000..70538bb30 --- /dev/null +++ b/camlibs/pentax/pslr_lens.c @@ -0,0 +1,51 @@ +/* + pkTriggerCord + Copyright (C) 2011-2017 Andras Salamon <andras.salamon@melda.info> + Remote control of Pentax DSLR cameras. + + based on: + + PK-Remote + Remote control of Pentax DSLR cameras. + Copyright (C) 2008 Pontus Lidman <pontus@lysator.liu.se> + + Pentax lens database comes from ExifTool ( http://www.sno.phy.queensu.ca/~phil/exiftool/ ) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + and GNU Lesser General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "pslr_lens.h" + +#include <stdio.h> + +static const struct { + uint32_t id1; + uint32_t id2; + const char *name; +} lens_id[] = { +#include "exiftool_pentax_lens.txt" +}; + +const char *get_lens_name( uint32_t id1, uint32_t id2) { + int lens_num = sizeof(lens_id)/sizeof(lens_id[0]); + int i; + for ( i=0; i<lens_num; ++i ) { + if ( lens_id[i].id1 == id1 && + lens_id[i].id2 == id2 ) { + return lens_id[i].name; + } + } + return ""; +} diff --git a/camlibs/pentax/pslr_lens.h b/camlibs/pentax/pslr_lens.h new file mode 100644 index 000000000..b4b14df22 --- /dev/null +++ b/camlibs/pentax/pslr_lens.h @@ -0,0 +1,34 @@ +/* + pkTriggerCord + Copyright (C) 2011-2017 Andras Salamon <andras.salamon@melda.info> + Remote control of Pentax DSLR cameras. + + based on: + + PK-Remote + Remote control of Pentax DSLR cameras. + Copyright (C) 2008 Pontus Lidman <pontus@lysator.liu.se> + + Pentax lens database comes from ExifTool ( http://www.sno.phy.queensu.ca/~phil/exiftool/ ) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + and GNU Lesser General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#ifndef PSLR_LENS_H +#define PSLR_LENS_H + +#include <stdint.h> + +const char *get_lens_name( uint32_t id1, uint32_t id2); +#endif diff --git a/camlibs/pentax/pslr_model.c b/camlibs/pentax/pslr_model.c new file mode 100644 index 000000000..4cadbb89c --- /dev/null +++ b/camlibs/pentax/pslr_model.c @@ -0,0 +1,750 @@ +/* + pkTriggerCord + Copyright (C) 2011-2017 Andras Salamon <andras.salamon@melda.info> + Remote control of Pentax DSLR cameras. + + Support for K200D added by Jens Dreyer <jens.dreyer@udo.edu> 04/2011 + Support for K-r added by Vincenc Podobnik <vincenc.podobnik@gmail.com> 06/2011 + Support for K-30 added by Camilo Polymeris <cpolymeris@gmail.com> 09/2012 + Support for K-01 added by Ethan Queen <ethanqueen@gmail.com> 01/2013 + Support for K-3 added by Tao Wang <twang2218@gmail.com> 01/2016 + + based on: + + PK-Remote + Remote control of Pentax DSLR cameras. + Copyright (C) 2008 Pontus Lidman <pontus@lysator.liu.se> + + PK-Remote for Windows + Copyright (C) 2010 Tomasz Kos + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + and GNU Lesser General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> + +#include "pslr_model.h" + +static uint8_t lastbuf[MAX_STATUS_BUF_SIZE]; +static int first = 1; + +static void ipslr_status_diff(uint8_t *buf) { + int n; + int diffs; + if (first) { + hexdump(buf, MAX_STATUS_BUF_SIZE); + memcpy(lastbuf, buf, MAX_STATUS_BUF_SIZE); + first = 0; + } + + diffs = 0; + for (n = 0; n < MAX_STATUS_BUF_SIZE; n++) { + if (lastbuf[n] != buf[n]) { + DPRINT("\t\tbuf[%03X] last %02Xh %3d new %02Xh %3d\n", n, lastbuf[n], lastbuf[n], buf[n], buf[n]); + diffs++; + } + } + if (diffs) { + DPRINT("---------------------------\n"); + memcpy(lastbuf, buf, MAX_STATUS_BUF_SIZE); + } +} + +uint16_t get_uint16_be(uint8_t *buf) { + uint16_t res; + res = buf[0] << 8 | buf[1]; + return res; +} + +uint32_t get_uint32_be(uint8_t *buf) { + uint32_t res; + res = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; + return res; +} + +int32_t get_int32_be(uint8_t *buf) { + int32_t res; + res = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; + return res; +} + +uint16_t get_uint16_le(uint8_t *buf) { + uint16_t res; + res = buf[1] << 8 | buf[0]; + return res; +} + +uint32_t get_uint32_le(uint8_t *buf) { + uint32_t res; + res = buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0]; + return res; +} + +int32_t get_int32_le(uint8_t *buf) { + int32_t res; + res = buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0]; + return res; +} + +void set_uint32_le(uint32_t v, uint8_t *buf) { + buf[0] = v; + buf[1] = v >> 8; + buf[2] = v >> 16; + buf[3] = v >> 24; +} + +void set_uint32_be(uint32_t v, uint8_t *buf) { + buf[0] = v >> 24; + buf[1] = v >> 16; + buf[2] = v >> 8; + buf[3] = v; +} + +char *shexdump(uint8_t *buf, uint32_t bufLen) { + char *ret = malloc(4*bufLen); + uint32_t i; + sprintf(ret,"%s",""); + for (i = 0; i < bufLen; i++) { + if (i % 16 == 0) { + sprintf(ret+strlen(ret),"0x%04x | ", i); + } + sprintf(ret+strlen(ret), "%02x ", buf[i]); + if (i % 8 == 7) { + sprintf(ret+strlen(ret), " "); + } + if (i % 16 == 15) { + sprintf(ret+strlen(ret), "\n"); + } + } + if (i % 16 != 15) { + sprintf(ret+strlen(ret), "\n"); + } + return ret; +} + +void hexdump(uint8_t *buf, uint32_t bufLen) { + char *dmp = shexdump(buf, bufLen); + DPRINT("%s",dmp); + free(dmp); +} + +void hexdump_debug(uint8_t *buf, uint32_t bufLen) { + char *dmp = shexdump(buf, bufLen); + DPRINT("%s",dmp); + free(dmp); +} + + +// based on http://stackoverflow.com/a/657202/21348 + +const char* int_to_binary( uint16_t x ) { + static char b[sizeof(uint16_t)*8+1] = {0}; + int y; + long long z; + for (z=(1LL<<sizeof(uint16_t)*8)-1,y=0; z>0; z>>=1,y++) { + b[y] = ( ((x & z) == z) ? '1' : '0'); + } + b[y] = 0; + return b; +} + + +int _get_user_jpeg_stars( ipslr_model_info_t *model, int hwqual ) { + if ( model->id == 0x12f71 ) { + // K5IIs hack + // TODO: test it + if ( hwqual == model->max_jpeg_stars -1 ) { + return model->max_jpeg_stars; + } else { + return model->max_jpeg_stars - 1 - hwqual; + } + } else { + return model->max_jpeg_stars - hwqual; + } +} + +int get_hw_jpeg_quality( ipslr_model_info_t *model, int user_jpeg_stars) { + if ( model->id == 0x12f71 ) { + // K5IIs hack + // TODO: test it + if ( user_jpeg_stars == model->max_jpeg_stars ) { + return model->max_jpeg_stars-1; + } else { + return model->max_jpeg_stars - 1 - user_jpeg_stars; + } + } else { + return model->max_jpeg_stars - user_jpeg_stars; + } +} + + +void ipslr_status_parse_k10d(ipslr_handle_t *p, pslr_status *status) { + uint8_t *buf = p->status_buffer; + if ( debug ) { + ipslr_status_diff(buf); + } + memset(status, 0, sizeof (*status)); + status->bufmask = get_uint16_be(&buf[0x16]); + status->user_mode_flag = get_uint32_be(&buf[0x1c]); + status->set_shutter_speed.nom = get_uint32_be(&buf[0x2c]); + status->set_shutter_speed.denom = get_uint32_be(&buf[0x30]); + status->set_aperture.nom = get_uint32_be(&buf[0x34]); + status->set_aperture.denom = get_uint32_be(&buf[0x38]); + status->ec.nom = get_uint32_be(&buf[0x3c]); + status->ec.denom = get_uint32_be(&buf[0x40]); + status->fixed_iso = get_uint32_be(&buf[0x60]); + status->image_format = get_uint32_be(&buf[0x78]); + status->jpeg_resolution = get_uint32_be(&buf[0x7c]); + status->jpeg_quality = _get_user_jpeg_stars( p->model, get_uint32_be(&buf[0x80])); + status->raw_format = get_uint32_be(&buf[0x84]); + status->jpeg_image_tone = get_uint32_be(&buf[0x88]); + status->jpeg_saturation = get_uint32_be(&buf[0x8c]); + status->jpeg_sharpness = get_uint32_be(&buf[0x90]); + status->jpeg_contrast = get_uint32_be(&buf[0x94]); + status->custom_ev_steps = get_uint32_be(&buf[0x9c]); + status->custom_sensitivity_steps = get_uint32_be(&buf[0xa0]); + status->af_point_select = get_uint32_be(&buf[0xbc]); + status->selected_af_point = get_uint32_be(&buf[0xc0]); + status->exposure_mode = get_uint32_be(&buf[0xac]); + status->current_shutter_speed.nom = get_uint32_be(&buf[0xf4]); + status->current_shutter_speed.denom = get_uint32_be(&buf[0xf8]); + status->current_aperture.nom = get_uint32_be(&buf[0xfc]); + status->current_aperture.denom = get_uint32_be(&buf[0x100]); + status->current_iso = get_uint32_be(&buf[0x11c]); + status->light_meter_flags = get_uint32_be(&buf[0x124]); + status->lens_min_aperture.nom = get_uint32_be(&buf[0x12c]); + status->lens_min_aperture.denom = get_uint32_be(&buf[0x130]); + status->lens_max_aperture.nom = get_uint32_be(&buf[0x134]); + status->lens_max_aperture.denom = get_uint32_be(&buf[0x138]); + status->focused_af_point = get_uint32_be(&buf[0x150]); + status->zoom.nom = get_uint32_be(&buf[0x16c]); + status->zoom.denom = get_uint32_be(&buf[0x170]); + status->focus = get_int32_be(&buf[0x174]); +} + +void ipslr_status_parse_k20d(ipslr_handle_t *p, pslr_status *status) { + + uint8_t *buf = p->status_buffer; + if ( debug ) { + ipslr_status_diff(buf); + } + memset(status, 0, sizeof (*status)); + status->bufmask = get_uint16_be( &buf[0x16]); + status->user_mode_flag = get_uint32_be(&buf[0x1c]); + status->set_shutter_speed.nom = get_uint32_be(&buf[0x2c]); + status->set_shutter_speed.denom = get_uint32_be(&buf[0x30]); + status->set_aperture.nom = get_uint32_be(&buf[0x34]); + status->set_aperture.denom = get_uint32_be(&buf[0x38]); + status->ec.nom = get_uint32_be(&buf[0x3c]); + status->ec.denom = get_uint32_be(&buf[0x40]); + status->fixed_iso = get_uint32_be(&buf[0x60]); + status->image_format = get_uint32_be(&buf[0x78]); + status->jpeg_resolution = get_uint32_be(&buf[0x7c]); + status->jpeg_quality = _get_user_jpeg_stars( p->model, get_uint32_be(&buf[0x80])); + status->raw_format = get_uint32_be(&buf[0x84]); + status->jpeg_image_tone = get_uint32_be(&buf[0x88]); + status->jpeg_saturation = get_uint32_be(&buf[0x8c]); // commands do now work for it? + status->jpeg_sharpness = get_uint32_be(&buf[0x90]); // commands do now work for it? + status->jpeg_contrast = get_uint32_be(&buf[0x94]); // commands do now work for it? + status->custom_ev_steps = get_uint32_be(&buf[0x9c]); + status->custom_sensitivity_steps = get_uint32_be(&buf[0xa0]); + status->ae_metering_mode = get_uint32_be(&buf[0xb4]); // same as c4 + status->af_mode = get_uint32_be(&buf[0xb8]); + status->af_point_select = get_uint32_be(&buf[0xbc]); // not sure + status->selected_af_point = get_uint32_be(&buf[0xc0]); + status->exposure_mode = get_uint32_be(&buf[0xac]); + status->current_shutter_speed.nom = get_uint32_be(&buf[0x108]); + status->current_shutter_speed.denom = get_uint32_be(&buf[0x10C]); + status->current_aperture.nom = get_uint32_be(&buf[0x110]); + status->current_aperture.denom = get_uint32_be(&buf[0x114]); + status->current_iso = get_uint32_be(&buf[0x130]); + status->light_meter_flags = get_uint32_be(&buf[0x138]); + status->lens_min_aperture.nom = get_uint32_be(&buf[0x140]); + status->lens_min_aperture.denom = get_uint32_be(&buf[0x144]); + status->lens_max_aperture.nom = get_uint32_be(&buf[0x148]); + status->lens_max_aperture.denom = get_uint32_be(&buf[0x14B]); + status->focused_af_point = get_uint32_be(&buf[0x160]); // unsure about it, a lot is changing when the camera focuses + status->zoom.nom = get_uint32_be(&buf[0x180]); + status->zoom.denom = get_uint32_be(&buf[0x184]); + status->focus = get_int32_be(&buf[0x188]); // current focus ring position? + // 0x158 current ev? + // 0x160 and 0x164 change when AF +} + +void ipslr_status_parse_istds(ipslr_handle_t *p, pslr_status *status) { + + uint8_t *buf = p->status_buffer; + /* *ist DS status block */ + memset(status, 0, sizeof (*status)); + status->bufmask = get_uint16_be(&buf[0x12]); + status->set_shutter_speed.nom = get_uint32_be(&buf[0x80]); + status->set_shutter_speed.denom = get_uint32_be(&buf[0x84]); + status->set_aperture.nom = get_uint32_be(&buf[0x88]); + status->set_aperture.denom = get_uint32_be(&buf[0x8c]); + status->lens_min_aperture.nom = get_uint32_be(&buf[0xb8]); + status->lens_min_aperture.denom = get_uint32_be(&buf[0xbc]); + status->lens_max_aperture.nom = get_uint32_be(&buf[0xc0]); + status->lens_max_aperture.denom = get_uint32_be(&buf[0xc4]); + + // no DNG support so raw format is PEF + status->raw_format = PSLR_RAW_FORMAT_PEF; +} + +// some of the cameras share most of the status fields +// this method is used for K-x, K-7, K-5, K-r +// +// some cameras also have this data block, but it's shifted a bit +void ipslr_status_parse_common(ipslr_handle_t *p, pslr_status *status, int shift) { + + uint8_t *buf = p->status_buffer; + get_uint32_func get_uint32_func_ptr; + get_int32_func get_int32_func_ptr; + get_uint16_func get_uint16_func_ptr; + + if (p->model->is_little_endian) { + get_uint32_func_ptr = get_uint32_le; + get_int32_func_ptr = get_int32_le; + get_uint16_func_ptr = get_uint16_le; + } else { + get_uint32_func_ptr = get_uint32_be; + get_int32_func_ptr = get_int32_be; + get_uint16_func_ptr = get_uint16_be; + } + + // 0x0C: 0x85 0xA5 + // 0x0F: beginning 0 sometime changes to 1 + // 0x14: LCD panel 2: turned off 3: on? + status->bufmask = (*get_uint16_func_ptr)( &buf[0x1E + shift]); + status->user_mode_flag = (*get_uint32_func_ptr)(&buf[0x24 + shift]); + status->flash_mode = (*get_uint32_func_ptr)(&buf[0x28 + shift]); + status->flash_exposure_compensation = (*get_int32_func_ptr)(&buf[0x2C + shift]); + status->set_shutter_speed.nom = (*get_uint32_func_ptr)(&buf[0x34 + shift]); + status->set_shutter_speed.denom = (*get_uint32_func_ptr)(&buf[0x38 + shift]); + status->set_aperture.nom = (*get_uint32_func_ptr)(&buf[0x3C + shift]); + status->set_aperture.denom = (*get_uint32_func_ptr)(&buf[0x40 + shift]); + status->ec.nom = (*get_uint32_func_ptr)(&buf[0x44 + shift]); + status->ec.denom = (*get_uint32_func_ptr)(&buf[0x48 + shift]); + status->auto_bracket_mode = (*get_uint32_func_ptr)(&buf[0x4C + shift]); + status->auto_bracket_ev.nom = (*get_uint32_func_ptr)(&buf[0x50 + shift]); + status->auto_bracket_ev.denom = (*get_uint32_func_ptr)(&buf[0x54 + shift]); + status->auto_bracket_picture_count = (*get_uint32_func_ptr)(&buf[0x58 + shift]); + status->drive_mode = (*get_uint32_func_ptr)(&buf[0x5C + shift]); + status->fixed_iso = (*get_uint32_func_ptr)(&buf[0x68 + shift]); + status->auto_iso_min = (*get_uint32_func_ptr)(&buf[0x6C + shift]); + status->auto_iso_max = (*get_uint32_func_ptr)(&buf[0x70 + shift]); + status->white_balance_mode = (*get_uint32_func_ptr)(&buf[0x74 + shift]); + status->white_balance_adjust_mg = (*get_uint32_func_ptr)(&buf[0x78 + shift]); // 0: M7 7: 0 14: G7 + status->white_balance_adjust_ba = (*get_uint32_func_ptr)(&buf[0x7C + shift]); // 0: B7 7: 0 14: A7 + status->image_format = (*get_uint32_func_ptr)(&buf[0x80 + shift]); + status->jpeg_resolution = (*get_uint32_func_ptr)(&buf[0x84 + shift]); + status->jpeg_quality = _get_user_jpeg_stars( p->model, (*get_uint32_func_ptr)(&buf[0x88 + shift])); + status->raw_format = (*get_uint32_func_ptr)(&buf[0x8C + shift]); + status->jpeg_image_tone = (*get_uint32_func_ptr)(&buf[0x90 + shift]); + status->jpeg_saturation = (*get_uint32_func_ptr)(&buf[0x94 + shift]); + status->jpeg_sharpness = (*get_uint32_func_ptr)(&buf[0x98 + shift]); + status->jpeg_contrast = (*get_uint32_func_ptr)(&buf[0x9C + shift]); + status->color_space = (*get_uint32_func_ptr)(&buf[0xA0 + shift]); + status->custom_ev_steps = (*get_uint32_func_ptr)(&buf[0xA4 + shift]); + status->custom_sensitivity_steps = (*get_uint32_func_ptr)(&buf[0xa8 + shift]); + status->exposure_mode = (*get_uint32_func_ptr)(&buf[0xb4 + shift]); + status->scene_mode = (*get_uint32_func_ptr)(&buf[0xb8 + shift]); + status->ae_metering_mode = (*get_uint32_func_ptr)(&buf[0xbc + shift]); // same as cc + status->af_mode = (*get_uint32_func_ptr)(&buf[0xC0 + shift]); + status->af_point_select = (*get_uint32_func_ptr)(&buf[0xc4 + shift]); + status->selected_af_point = (*get_uint32_func_ptr)(&buf[0xc8 + shift]); + status->shake_reduction = (*get_uint32_func_ptr)(&buf[0xE0 + shift]); + status->auto_bracket_picture_counter = (*get_uint32_func_ptr)(&buf[0xE4 + shift]); + status->jpeg_hue = (*get_uint32_func_ptr)(&buf[0xFC + shift]); + status->current_shutter_speed.nom = (*get_uint32_func_ptr)(&buf[0x10C + shift]); + status->current_shutter_speed.denom = (*get_uint32_func_ptr)(&buf[0x110 + shift]); + status->current_aperture.nom = (*get_uint32_func_ptr)(&buf[0x114 + shift]); + status->current_aperture.denom = (*get_uint32_func_ptr)(&buf[0x118 + shift]); + status->max_shutter_speed.nom = (*get_uint32_func_ptr)(&buf[0x12C + shift]); + status->max_shutter_speed.denom = (*get_uint32_func_ptr)(&buf[0x130 + shift]); + status->current_iso = (*get_uint32_func_ptr)(&buf[0x134 + shift]); + status->light_meter_flags = (*get_uint32_func_ptr)(&buf[0x13C + shift]); + status->lens_min_aperture.nom = (*get_uint32_func_ptr)(&buf[0x144 + shift]); + status->lens_min_aperture.denom = (*get_uint32_func_ptr)(&buf[0x148 + shift]); + status->lens_max_aperture.nom = (*get_uint32_func_ptr)(&buf[0x14C + shift]); + status->lens_max_aperture.denom = (*get_uint32_func_ptr)(&buf[0x150 + shift]); + status->manual_mode_ev = (*get_int32_func_ptr)(&buf[0x15C + shift]); + status->focused_af_point = (*get_uint32_func_ptr)(&buf[0x168 + shift]); //d, unsure about it, a lot is changing when the camera focuses + // probably voltage*100 + // battery_1 > battery2 ( noload vs load voltage?) + status->battery_1 = (*get_uint32_func_ptr)( &buf[0x170 + shift] ); + status->battery_2 = (*get_uint32_func_ptr)( &buf[0x174 + shift] ); + status->battery_3 = (*get_uint32_func_ptr)( &buf[0x180 + shift] ); + status->battery_4 = (*get_uint32_func_ptr)( &buf[0x184 + shift] ); + +} + +void ipslr_status_parse_kx(ipslr_handle_t *p, pslr_status *status) { + + uint8_t *buf = p->status_buffer; + if ( debug ) { + ipslr_status_diff(buf); + } + + memset(status, 0, sizeof (*status)); + ipslr_status_parse_common( p, status, 0); + status->zoom.nom = get_uint32_be(&buf[0x198]); + status->zoom.denom = get_uint32_be(&buf[0x19C]); + status->focus = get_int32_be(&buf[0x1A0]); + status->lens_id1 = (get_uint32_be( &buf[0x188])) & 0x0F; + status->lens_id2 = get_uint32_be( &buf[0x194]); +} + +// Vince: K-r support 2011-06-22 +// +void ipslr_status_parse_kr(ipslr_handle_t *p, pslr_status *status) { + uint8_t *buf = p->status_buffer; + if ( debug ) { + ipslr_status_diff(buf); + } + + memset(status, 0, sizeof (*status)); + ipslr_status_parse_common( p, status, 0 ); + status->zoom.nom = get_uint32_be(&buf[0x19C]); + status->zoom.denom = get_uint32_be(&buf[0x1A0]); + status->focus = get_int32_be(&buf[0x1A4]); + status->lens_id1 = (get_uint32_be( &buf[0x18C])) & 0x0F; + status->lens_id2 = get_uint32_be( &buf[0x198]); +} + +void ipslr_status_parse_k5(ipslr_handle_t *p, pslr_status *status) { + uint8_t *buf = p->status_buffer; + if ( debug ) { + ipslr_status_diff(buf); + } + + memset(status, 0, sizeof (*status)); + ipslr_status_parse_common( p, status, 0 ); + status->zoom.nom = get_uint32_be(&buf[0x1A0]); + status->zoom.denom = get_uint32_be(&buf[0x1A4]); + status->focus = get_int32_be(&buf[0x1A8]); // ? + status->lens_id1 = (get_uint32_be( &buf[0x190])) & 0x0F; + status->lens_id2 = get_uint32_be( &buf[0x19C]); + +// TODO: check these fields +//status.focused = getInt32(statusBuf, 0x164); +} + +void ipslr_status_parse_k30(ipslr_handle_t *p, pslr_status *status) { + uint8_t *buf = p->status_buffer; + if ( debug ) { + ipslr_status_diff(buf); + } + + memset(status, 0, sizeof (*status)); + ipslr_status_parse_common( p, status, 0 ); + //~ status->jpeg_contrast -= 4; + //~ status->jpeg_hue -= 4; + //~ status->jpeg_sharpness -= 4; + //~ status->jpeg_saturation -= 4; + status->zoom.nom = get_uint32_be(&buf[0x1A0]); + status->zoom.denom = 100; + status->focus = get_int32_be(&buf[0x1A8]); // ? + status->lens_id1 = (get_uint32_be( &buf[0x190])) & 0x0F; + status->lens_id2 = get_uint32_be( &buf[0x19C]); +} + +// status check seems to be the same as K30 +void ipslr_status_parse_k01(ipslr_handle_t *p, pslr_status *status) { + uint8_t *buf = p->status_buffer; + if ( debug ) { + ipslr_status_diff(buf); + } + + memset(status, 0, sizeof (*status)); + ipslr_status_parse_common( p, status, 0 ); + //~ status->jpeg_contrast -= 4; + //~ status->jpeg_hue -= 4; + //~ status->jpeg_sharpness -= 4; + //~ status->jpeg_saturation -= 4; + status->zoom.nom = get_uint32_be(&buf[0x1A0]); // - good for K01 + status->zoom.denom = 100; // good for K-01 + status->focus = get_int32_be(&buf[0x1A8]); // ? - good for K01 + status->lens_id1 = (get_uint32_be( &buf[0x190])) & 0x0F; // - good for K01 + status->lens_id2 = get_uint32_be( &buf[0x19C]); // - good for K01 +} + +void ipslr_status_parse_k50(ipslr_handle_t *p, pslr_status *status) { + uint8_t *buf = p->status_buffer; + if ( debug ) { + ipslr_status_diff(buf); + } + + memset(status, 0, sizeof (*status)); + ipslr_status_parse_common( p, status, 0 ); + status->zoom.nom = get_uint32_be(&buf[0x1A0]); + status->zoom.denom = get_uint32_be(&buf[0x1A4]); + // status->focus = get_int32_be(&buf[0x1A8]); // ? + status->lens_id1 = (get_uint32_be( &buf[0x190])) & 0x0F; + status->lens_id2 = get_uint32_be( &buf[0x19C]); +} + +void ipslr_status_parse_k500(ipslr_handle_t *p, pslr_status *status) { + uint8_t *buf = p->status_buffer; + if ( debug ) { + ipslr_status_diff(buf); + } + + memset(status, 0, sizeof (*status)); + ipslr_status_parse_common( p, status, 0 ); + status->zoom.nom = get_uint32_be(&buf[0x1A0]); + status->zoom.denom = get_uint32_be(&buf[0x1A4]); + // status->focus = get_int32_be(&buf[0x1A8]); // ? + status->lens_id1 = (get_uint32_be( &buf[0x190])) & 0x0F; + status->lens_id2 = get_uint32_be( &buf[0x19C]); + // cannot read max_shutter_speed from status buffer, hardwire the values here + status->max_shutter_speed.nom = 1; + status->max_shutter_speed.denom = 6000; +} + +void ipslr_status_parse_km(ipslr_handle_t *p, pslr_status *status) { + uint8_t *buf = p->status_buffer; + if ( debug ) { + ipslr_status_diff(buf); + } + + memset(status, 0, sizeof (*status)); + ipslr_status_parse_common( p, status, -4); + status->zoom.nom = get_uint32_be(&buf[0x180]); + status->zoom.denom = get_uint32_be(&buf[0x184]); + status->lens_id1 = (get_uint32_be( &buf[0x170])) & 0x0F; + status->lens_id2 = get_uint32_be( &buf[0x17c]); +// TODO +// status.focused = getInt32(statusBuf, 0x164); +} + +// K-3 returns data in little-endian +void ipslr_status_parse_k3(ipslr_handle_t *p, pslr_status *status) { + uint8_t *buf = p->status_buffer; + if ( debug ) { + ipslr_status_diff(buf); + } + + memset(status, 0, sizeof (*status)); + ipslr_status_parse_common( p, status, 0 ); + status->bufmask = get_uint16_le( &buf[0x1C]); + status->zoom.nom = get_uint32_le(&buf[0x1A0]); + status->zoom.denom = get_uint32_le(&buf[0x1A4]); + status->focus = get_int32_le(&buf[0x1A8]); + status->lens_id1 = (get_uint32_le( &buf[0x190])) & 0x0F; + status->lens_id2 = get_uint32_le( &buf[0x19C]); +} + +void ipslr_status_parse_ks1(ipslr_handle_t *p, pslr_status *status) { + uint8_t *buf = p->status_buffer; + if ( debug ) { + ipslr_status_diff(buf); + } + + memset(status, 0, sizeof (*status)); + ipslr_status_parse_common( p, status, 0 ); + status->bufmask = get_uint16_le( &buf[0x0C]); + status->zoom.nom = get_uint32_le(&buf[0x1A0]); + status->zoom.denom = get_uint32_le(&buf[0x1A4]); + status->focus = get_int32_le(&buf[0x1A8]); + status->lens_id1 = (get_uint32_le( &buf[0x190])) & 0x0F; + status->lens_id2 = get_uint32_le( &buf[0x19C]); +} + + +void ipslr_status_parse_k1(ipslr_handle_t *p, pslr_status *status) { + uint8_t *buf = p->status_buffer; + if ( debug ) { + ipslr_status_diff(buf); + } + + memset(status, 0, sizeof (*status)); + ipslr_status_parse_common( p, status, 0 ); +// parse_common returns invalid values for the following fields. Fixing the fields: + + status->jpeg_hue = get_uint32_le(&buf[0x100]); + status->current_shutter_speed.nom = get_uint32_le(&buf[0x110]); + status->current_shutter_speed.denom = get_uint32_le(&buf[0x114]); + status->current_aperture.nom = get_uint32_le(&buf[0x118]); + status->current_aperture.denom = get_uint32_le(&buf[0x11c]); + status->max_shutter_speed.nom = get_uint32_le(&buf[0x130]); + status->max_shutter_speed.denom = get_uint32_le(&buf[0x134]); + status->current_iso = get_uint32_le(&buf[0x138]); + status->light_meter_flags = get_uint32_le(&buf[0x140]); // ? + status->lens_min_aperture.nom = get_uint32_le(&buf[0x148]); + status->lens_min_aperture.denom = get_uint32_le(&buf[0x14c]); + status->lens_max_aperture.nom = get_uint32_le(&buf[0x150]); + status->lens_max_aperture.denom = get_uint32_le(&buf[0x154]); + status->manual_mode_ev = get_uint32_le(&buf[0x160]); // ? + status->focused_af_point = get_uint32_le(&buf[0x16c]); // ? + // battery fields? + + // selected_af_point is invalid + status->selected_af_point = 0; + + status->bufmask = get_uint16_le( &buf[0x0C]); + status->zoom.nom = get_uint32_le(&buf[0x1A4]); + status->zoom.denom = get_uint32_le(&buf[0x1A8]); +// status->focus = get_int32_le(&buf[0x1A8]); + status->lens_id1 = (get_uint32_le( &buf[0x194])) & 0x0F; + status->lens_id2 = get_uint32_le( &buf[0x1A0]); +} + +void ipslr_status_parse_k70(ipslr_handle_t *p, pslr_status *status) { + uint8_t *buf = p->status_buffer; + if ( debug ) { + ipslr_status_diff(buf); + } + + memset(status, 0, sizeof (*status)); + ipslr_status_parse_common( p, status, 0 ); +// parse_common returns invalid values for the following fields. Fixing the fields: + + status->auto_bracket_picture_counter = get_uint32_le(&buf[0xE8]); + status->jpeg_hue = get_uint32_le(&buf[0x100]); + status->current_shutter_speed.nom = get_uint32_le(&buf[0x110]); + status->current_shutter_speed.denom = get_uint32_le(&buf[0x114]); + status->current_aperture.nom = get_uint32_le(&buf[0x118]); + status->current_aperture.denom = get_uint32_le(&buf[0x11c]); + status->max_shutter_speed.nom = get_uint32_le(&buf[0x130]); + status->max_shutter_speed.denom = get_uint32_le(&buf[0x134]); + status->current_iso = get_uint32_le(&buf[0x138]); + status->light_meter_flags = get_uint32_le(&buf[0x140]); // ? + status->lens_min_aperture.nom = get_uint32_le(&buf[0x148]); + status->lens_min_aperture.denom = get_uint32_le(&buf[0x14c]); + status->lens_max_aperture.nom = get_uint32_le(&buf[0x150]); + status->lens_max_aperture.denom = get_uint32_le(&buf[0x154]); + status->manual_mode_ev = get_uint32_le(&buf[0x160]); // ? + status->focused_af_point = get_uint32_le(&buf[0x16c]); // ? + + status->battery_1 = get_uint32_le(&buf[0x174]); + status->battery_2 = get_uint32_le(&buf[0x178]); + status->battery_3 = 0; + status->battery_4 = 0; + + // selected_af_point is invalid + status->selected_af_point = 0; + + status->bufmask = get_uint16_le( &buf[0x0C]); + status->zoom.nom = get_uint32_le(&buf[0x1A4]); + status->zoom.denom = get_uint32_le(&buf[0x1A8]); +// status->focus = get_int32_le(&buf[0x1A8]); + status->lens_id1 = (get_uint32_le( &buf[0x194])) & 0x0F; + status->lens_id2 = get_uint32_le( &buf[0x1A0]); + status->shake_reduction = get_uint32_le(&buf[0xe4]); +} + +void ipslr_status_parse_k200d(ipslr_handle_t *p, pslr_status *status) { + uint8_t *buf = p->status_buffer; + if ( debug ) { + ipslr_status_diff(buf); + } + + memset(status, 0, sizeof (*status)); + status->bufmask = get_uint16_be(&buf[0x16]); + status->user_mode_flag = get_uint32_be(&buf[0x1c]); + status->set_shutter_speed.nom = get_uint32_be(&buf[0x2c]); + status->set_shutter_speed.denom = get_uint32_be(&buf[0x30]); + status->current_aperture.nom = get_uint32_be(&buf[0x034]); + status->current_aperture.denom = get_uint32_be(&buf[0x038]); + status->set_aperture.nom = get_uint32_be(&buf[0x34]); + status->set_aperture.denom = get_uint32_be(&buf[0x38]); + status->ec.nom = get_uint32_be(&buf[0x3c]); + status->ec.denom = get_uint32_be(&buf[0x40]); + status->current_iso = get_uint32_be(&buf[0x060]); + status->fixed_iso = get_uint32_be(&buf[0x60]); + status->auto_iso_min = get_uint32_be(&buf[0x64]); + status->auto_iso_max = get_uint32_be(&buf[0x68]); + status->image_format = get_uint32_be(&buf[0x78]); + status->jpeg_resolution = get_uint32_be(&buf[0x7c]); + status->jpeg_quality = _get_user_jpeg_stars( p->model, get_uint32_be(&buf[0x80])); + status->raw_format = get_uint32_be(&buf[0x84]); + status->jpeg_image_tone = get_uint32_be(&buf[0x88]); + status->jpeg_saturation = get_uint32_be(&buf[0x8c]); + status->jpeg_sharpness = get_uint32_be(&buf[0x90]); + status->jpeg_contrast = get_uint32_be(&buf[0x94]); + //status->custom_ev_steps = get_uint32_be(&buf[0x9c]); + //status->custom_sensitivity_steps = get_uint32_be(&buf[0xa0]); + status->exposure_mode = get_uint32_be(&buf[0xac]); + status->af_mode = get_uint32_be(&buf[0xb8]); + status->af_point_select = get_uint32_be(&buf[0xbc]); + status->selected_af_point = get_uint32_be(&buf[0xc0]); + status->drive_mode = get_uint32_be(&buf[0xcc]); + status->shake_reduction = get_uint32_be(&buf[0xda]); + status->jpeg_hue = get_uint32_be(&buf[0xf4]); + status->current_shutter_speed.nom = get_uint32_be(&buf[0x0104]); + status->current_shutter_speed.denom = get_uint32_be(&buf[0x108]); + status->light_meter_flags = get_uint32_be(&buf[0x124]); + status->lens_min_aperture.nom = get_uint32_be(&buf[0x13c]); + status->lens_min_aperture.denom = get_uint32_be(&buf[0x140]); + status->lens_max_aperture.nom = get_uint32_be(&buf[0x144]); + status->lens_max_aperture.denom = get_uint32_be(&buf[0x148]); + status->focused_af_point = get_uint32_be(&buf[0x150]); + status->zoom.nom = get_uint32_be(&buf[0x17c]); + status->zoom.denom = get_uint32_be(&buf[0x180]); + status->focus = get_int32_be(&buf[0x184]); + // Drive mode: 0=Single shot, 1= Continous Hi, 2= Continous Low or Self timer 12s, 3=Self timer 2s + // 4= remote, 5= remote 3s delay +} + +ipslr_model_info_t camera_models[] = { + { 0x12aa2, "*ist DS", 1, 1, 0, 264, 3, {6, 4, 2}, 5, 4000, 200, 3200, 200, 3200, PSLR_JPEG_IMAGE_TONE_BRIGHT, 0, 11, ipslr_status_parse_istds }, + { 0x12cd2, "K20D", 0, 1, 0, 412, 4, {14, 10, 6, 2}, 7, 4000, 100, 3200, 100, 6400, PSLR_JPEG_IMAGE_TONE_MONOCHROME, 1, 11, ipslr_status_parse_k20d }, + { 0x12c1e, "K10D", 0, 1, 0, 392, 3, {10, 6, 2}, 7, 4000, 100, 1600, 100, 1600, PSLR_JPEG_IMAGE_TONE_BRIGHT, 0, 11, ipslr_status_parse_k10d }, + { 0x12c20, "GX10", 0, 1, 0, 392, 3, {10, 6, 2}, 7, 4000, 100, 1600, 100, 1600, PSLR_JPEG_IMAGE_TONE_BRIGHT, 0, 11, ipslr_status_parse_k10d }, + { 0x12cd4, "GX20", 0, 1, 0, 412, 4, {14, 10, 6, 2}, 7, 4000, 100, 3200, 100, 6400, PSLR_JPEG_IMAGE_TONE_MONOCHROME, 1, 11, ipslr_status_parse_k20d }, + { 0x12dfe, "K-x", 0, 1, 0, 436, 3, {12, 10, 6, 2}, 9, 6000, 200, 6400, 100, 12800, PSLR_JPEG_IMAGE_TONE_MONOCHROME, 1, 11, ipslr_status_parse_kx }, //muted: bug + { 0x12cfa, "K200D", 0, 1, 0, 408, 3, {10, 6, 2}, 9, 4000, 100, 1600, 100, 1600, PSLR_JPEG_IMAGE_TONE_MONOCHROME, 1, 11, ipslr_status_parse_k200d }, + { 0x12db8, "K-7", 0, 1, 0, 436, 4, {14, 10, 6, 2}, 9, 8000, 100, 3200, 100, 6400, PSLR_JPEG_IMAGE_TONE_MUTED, 1, 11, ipslr_status_parse_kx }, + { 0x12e6c, "K-r", 0, 1, 0, 440, 3, {12, 10, 6, 2}, 9, 6000, 200,12800, 100, 25600, PSLR_JPEG_IMAGE_TONE_BLEACH_BYPASS, 1, 11, ipslr_status_parse_kr }, + { 0x12e76, "K-5", 0, 1, 0, 444, 4, {16, 10, 6, 2}, 9, 8000, 100,12800, 80, 51200, PSLR_JPEG_IMAGE_TONE_BLEACH_BYPASS, 1, 11, ipslr_status_parse_k5 }, + { 0x12d72, "K-2000", 0, 1, 0, 412, 3, {10, 6, 2}, 9, 4000, 100, 3200, 100, 3200, PSLR_JPEG_IMAGE_TONE_MONOCHROME, 1, 11, ipslr_status_parse_km }, + { 0x12d73, "K-m", 0, 1, 0, 412, 3, {10, 6, 2}, 9, 4000, 100, 3200, 100, 3200, PSLR_JPEG_IMAGE_TONE_MONOCHROME, 1, 11, ipslr_status_parse_km }, + { 0x12f52, "K-30", 0, 0, 0, 452, 3, {16, 12, 8, 5}, 9, 6000, 100,12800, 100, 25600, PSLR_JPEG_IMAGE_TONE_BLEACH_BYPASS, 1, 11, ipslr_status_parse_k30 }, + { 0x12ef8, "K-01", 0, 1, 0, 452, 3, {16, 12, 8, 5}, 9, 4000, 100,12800, 100, 25600, PSLR_JPEG_IMAGE_TONE_BLEACH_BYPASS, 1, 11, ipslr_status_parse_k01 }, + { 0x12f70, "K-5II", 0, 1, 0, 444, 4, {16, 10, 6, 2}, 9, 8000, 100, 12800, 80, 51200, PSLR_JPEG_IMAGE_TONE_BLEACH_BYPASS, 1, 11, ipslr_status_parse_k5 }, + { 0x12f71, "K-5IIs", 0, 1, 0, 444, 4, {16, 10, 6, 2}, 9, 8000, 100, 12800, 80, 51200, PSLR_JPEG_IMAGE_TONE_BLEACH_BYPASS, 1, 11, ipslr_status_parse_k5 }, + { 0x12fb6, "K-50", 0, 1, 0, 452, 4, {16, 12, 8, 5}, 9, 6000, 100, 51200, 100, 51200, PSLR_JPEG_IMAGE_TONE_BLEACH_BYPASS, 1, 11, ipslr_status_parse_k50 }, + { 0x12fc0, "K-3" , 0, 1, 1, 452, 4, {24, 14, 6, 2}, 9, 8000, 100, 51200, 100, 51200, PSLR_JPEG_IMAGE_TONE_BLEACH_BYPASS, 1, 27, ipslr_status_parse_k3 }, + { 0x1309c, "K-3II" , 0, 1, 1, 452, 4, {24, 14, 6, 2}, 9, 8000, 100, 51200, 100, 51200, PSLR_JPEG_IMAGE_TONE_BLEACH_BYPASS, 1, 27, ipslr_status_parse_k3 }, + { 0x12fca, "K-500", 0, 1, 0, 452, 3, {16, 12, 8, 5}, 9, 6000, 100, 51200, 100, 51200, PSLR_JPEG_IMAGE_TONE_CROSS_PROCESSING, 1, 11, ipslr_status_parse_k500 }, + // only limited support from here + { 0x12994, "*ist D", 1, 1, 0, 0, 3, {6, 4, 2}, 3, 4000, 200, 3200, 200, 3200, PSLR_JPEG_IMAGE_TONE_NONE , 0, 11, NULL}, // buffersize: 264 + { 0x12b60, "*ist DS2", 1, 1, 0, 0, 3, {6, 4, 2}, 5, 4000, 200, 3200, 200, 3200, PSLR_JPEG_IMAGE_TONE_BRIGHT, 0, 11, NULL}, + { 0x12b1a, "*ist DL", 1, 1, 0, 0, 3, {6, 4, 2}, 5, 4000, 200, 3200, 200, 3200, PSLR_JPEG_IMAGE_TONE_BRIGHT, 0, 11, NULL}, + { 0x12b80, "GX-1L", 1, 1, 0, 0, 3, {6, 4, 2}, 5, 4000, 200, 3200, 200, 3200, PSLR_JPEG_IMAGE_TONE_BRIGHT, 0, 11, NULL}, + { 0x12b9d, "K110D", 0, 1, 0, 0, 3, {6, 4, 2}, 5, 4000, 200, 3200, 200, 3200, PSLR_JPEG_IMAGE_TONE_BRIGHT, 0, 11, NULL}, + { 0x12b9c, "K100D", 1, 1, 0, 0, 3, {6, 4, 2}, 5, 4000, 200, 3200, 200, 3200, PSLR_JPEG_IMAGE_TONE_BRIGHT, 0, 11, NULL}, + { 0x12ba2, "K100D Super", 1, 1, 0, 0, 3, {6, 4, 2}, 5, 4000, 200, 3200, 200, 3200, PSLR_JPEG_IMAGE_TONE_BRIGHT, 0, 11, NULL}, + { 0x1301a, "K-S1", 0, 1, 1, 452, 3, {20, 12, 6, 2}, 9, 6000, 100, 51200, 100, 51200, PSLR_JPEG_IMAGE_TONE_CROSS_PROCESSING, 1, 11, ipslr_status_parse_ks1 }, + { 0x13024, "K-S2", 0, 1, 1, 452, 3, {20, 12, 6, 2}, 9, 6000, 100, 51200, 100, 51200, PSLR_JPEG_IMAGE_TONE_CROSS_PROCESSING, 1, 11, ipslr_status_parse_k3 }, + { 0x13092, "K-1", 0, 1, 1, 456, 3, {36, 22, 12, 2}, 9, 8000, 100, 204800, 100, 204800, PSLR_JPEG_IMAGE_TONE_FLAT, 1, 33, ipslr_status_parse_k1 }, + { 0x13222, "K-70", 0, 1, 1, 456, 3, {24, 14, 6, 2}, 9, 6000, 100, 102400, 100, 102400, PSLR_JPEG_IMAGE_TONE_AUTO, 1, 11, ipslr_status_parse_k70 } +}; + +ipslr_model_info_t *find_model_by_id( uint32_t id ) { + int i; + for ( i = 0; i<sizeof (camera_models) / sizeof (camera_models[0]); i++) { + if ( camera_models[i].id == id ) { + // DPRINT("found %d\n",i); + return &camera_models[i]; + } + } + // DPRINT("not found\n"); + return NULL; +} diff --git a/camlibs/pentax/pslr_model.h b/camlibs/pentax/pslr_model.h new file mode 100644 index 000000000..1524d7303 --- /dev/null +++ b/camlibs/pentax/pslr_model.h @@ -0,0 +1,167 @@ +/* + pkTriggerCord + Copyright (C) 2011-2017 Andras Salamon <andras.salamon@melda.info> + Remote control of Pentax DSLR cameras. + + Support for K200D added by Jens Dreyer <jens.dreyer@udo.edu> 04/2011 + Support for K-r added by Vincenc Podobnik <vincenc.podobnik@gmail.com> 06/2011 + Support for K-30 added by Camilo Polymeris <cpolymeris@gmail.com> 09/2012 + Support for K-01 added by Ethan Queen <ethanqueen@gmail.com> 01/2013 + Support for K-3 added by Tao Wang <twang2218@gmail.com> 01/2016 + + based on: + + PK-Remote + Remote control of Pentax DSLR cameras. + Copyright (C) 2008 Pontus Lidman <pontus@lysator.liu.se> + + PK-Remote for Windows + Copyright (C) 2010 Tomasz Kos + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + and GNU Lesser General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#ifndef PSLR_MODEL_H +#define PSLR_MODEL_H + +#include "pslr_enum.h" +#include "pslr_scsi.h" + +#define MAX_RESOLUTION_SIZE 4 +#define MAX_STATUS_BUF_SIZE 456 +#define MAX_SEGMENTS 4 + +typedef struct ipslr_handle ipslr_handle_t; + +typedef struct { + int32_t nom; + int32_t denom; +} pslr_rational_t; + +typedef struct { + uint16_t bufmask; + uint32_t current_iso; + pslr_rational_t current_shutter_speed; + pslr_rational_t current_aperture; + pslr_rational_t lens_max_aperture; + pslr_rational_t lens_min_aperture; + pslr_rational_t set_shutter_speed; + pslr_rational_t set_aperture; + pslr_rational_t max_shutter_speed; + uint32_t auto_bracket_mode; // 1: on, 0: off + pslr_rational_t auto_bracket_ev; + uint32_t auto_bracket_picture_count; + uint32_t auto_bracket_picture_counter; + uint32_t fixed_iso; + uint32_t jpeg_resolution; + uint32_t jpeg_saturation; + uint32_t jpeg_quality; + uint32_t jpeg_contrast; + uint32_t jpeg_sharpness; + uint32_t jpeg_image_tone; + uint32_t jpeg_hue; + pslr_rational_t zoom; + int32_t focus; + uint32_t image_format; + uint32_t raw_format; + uint32_t light_meter_flags; + pslr_rational_t ec; + uint32_t custom_ev_steps; + uint32_t custom_sensitivity_steps; + uint32_t exposure_mode; + uint32_t scene_mode; + uint32_t user_mode_flag; + uint32_t ae_metering_mode; + uint32_t af_mode; + uint32_t af_point_select; + uint32_t selected_af_point; + uint32_t focused_af_point; + uint32_t auto_iso_min; + uint32_t auto_iso_max; + uint32_t drive_mode; + uint32_t shake_reduction; + uint32_t white_balance_mode; + uint32_t white_balance_adjust_mg; + uint32_t white_balance_adjust_ba; + uint32_t flash_mode; + int32_t flash_exposure_compensation; // 1/256 + int32_t manual_mode_ev; // 1/10 + uint32_t color_space; + uint32_t lens_id1; + uint32_t lens_id2; + uint32_t battery_1; + uint32_t battery_2; + uint32_t battery_3; + uint32_t battery_4; +} pslr_status; + +typedef void (*ipslr_status_parse_t)(ipslr_handle_t *p, pslr_status *status); + +typedef struct { + uint32_t id; // Pentax model ID + const char *name; // name + bool old_scsi_command; // 1 for *ist cameras, 0 for the newer cameras + bool need_exposure_mode_conversion; // is exposure_mode_conversion required + bool is_little_endian; // whether the return value should be parsed as little-endian + int buffer_size; // buffer size in bytes + int max_jpeg_stars; // maximum jpeg stars + int jpeg_resolutions[MAX_RESOLUTION_SIZE]; // jpeg resolution table + int jpeg_property_levels; // 5 [-2, 2] or 7 [-3,3] or 9 [-4,4] + int fastest_shutter_speed; // fastest shutter speed denominator + int base_iso_min; // base iso minimum + int base_iso_max; // base iso maximum + int extended_iso_min; // extended iso minimum + int extended_iso_max; // extended iso maximum + pslr_jpeg_image_tone_t max_supported_image_tone; // last supported jpeg image tone + bool has_jpeg_hue; // camera has jpeg hue setting + int af_point_num; // number of AF points + ipslr_status_parse_t parser_function; // parse function for status buffer +} ipslr_model_info_t; + +typedef struct { + uint32_t offset; + uint32_t addr; + uint32_t length; +} ipslr_segment_t; + +struct ipslr_handle { + FDTYPE fd; + pslr_status status; + uint32_t id; + ipslr_model_info_t *model; + ipslr_segment_t segments[MAX_SEGMENTS]; + uint32_t segment_count; + uint32_t offset; + uint8_t status_buffer[MAX_STATUS_BUF_SIZE]; +}; + +ipslr_model_info_t *find_model_by_id( uint32_t id ); + +int get_hw_jpeg_quality( ipslr_model_info_t *model, int user_jpeg_stars); + +uint32_t get_uint32_be(uint8_t *buf); +uint32_t get_uint32_le(uint8_t *buf); +void set_uint32_be(uint32_t v, uint8_t *buf); +void set_uint32_le(uint32_t v, uint8_t *buf); + +typedef uint32_t (*get_uint32_func)(uint8_t *buf); +typedef uint16_t (*get_uint16_func)(uint8_t *buf); +typedef int32_t (*get_int32_func)(uint8_t *buf); + +char *shexdump(uint8_t *buf, uint32_t bufLen); +void hexdump(uint8_t *buf, uint32_t bufLen); +void hexdump_debug(uint8_t *buf, uint32_t bufLen); +const char* int_to_binary( uint16_t x ); + +#endif diff --git a/camlibs/pentax/pslr_scsi.h b/camlibs/pentax/pslr_scsi.h new file mode 100644 index 000000000..ca09b312a --- /dev/null +++ b/camlibs/pentax/pslr_scsi.h @@ -0,0 +1,83 @@ +/* + pkTriggerCord + Copyright (C) 2011-2017 Andras Salamon <andras.salamon@melda.info> + Remote control of Pentax DSLR cameras. + + based on: + + PK-Remote + Remote control of Pentax DSLR cameras. + Copyright (C) 2008 Pontus Lidman <pontus@lysator.liu.se> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + and GNU Lesser General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef PSLR_SCSI_H +#define PSLR_SCSI_H + +#include <stdint.h> +#include <string.h> +#include <stdbool.h> +#include <stdio.h> + +extern bool debug; +extern void write_debug( const char* message, ... ); + +#ifdef ANDROID +#include <android/log.h> +#define DPRINT(...) __android_log_print(ANDROID_LOG_DEBUG, "PkTriggerCord", __VA_ARGS__) +#else +#ifdef LIBGPHOTO2 +#include <gphoto2/gphoto2-library.h> +#define DPRINT(x...) gp_log (GP_LOG_DEBUG, "pentax", x) +#else +#define DPRINT(x...) write_debug(x) +#endif +#endif + +typedef enum { + PSLR_OK = 0, + PSLR_DEVICE_ERROR, + PSLR_SCSI_ERROR, + PSLR_COMMAND_ERROR, + PSLR_READ_ERROR, + PSLR_NO_MEMORY, + PSLR_PARAM, /* Invalid parameters to API */ + PSLR_ERROR_MAX +} pslr_result; + +/* This also could be used to specify FDTYPE HANDLE for Win32, but this seems tricky with includes */ +#ifdef LIBGPHOTO2 +typedef struct _GPPort GPPort; +#define FDTYPE GPPort* +#else +/* classic UNIX style handle */ +#define FDTYPE int +#endif + +int scsi_read(FDTYPE sg_fd, uint8_t *cmd, uint32_t cmdLen, + uint8_t *buf, uint32_t bufLen); + +int scsi_write(FDTYPE sg_fd, uint8_t *cmd, uint32_t cmdLen, + uint8_t *buf, uint32_t bufLen); + +char **get_drives(int *driveNum); + +pslr_result get_drive_info(char* driveName, FDTYPE* hDevice, + char* vendorId, int vendorIdSizeMax, + char* productId, int productIdSizeMax); + +void close_drive(FDTYPE *hDevice); +#endif |