[packages/libgphoto2] Version: 2.4.14.1 snapshot (fixes some crashes)

jajcus jajcus at pld-linux.org
Sun Sep 23 22:22:45 CEST 2012


commit 7b411445e53d670c6cfcee6a4f04815c8ffcf854
Author: Jacek Konieczny <jajcus at jajcus.net>
Date:   Sun Sep 23 22:22:18 2012 +0200

    Version: 2.4.14.1 snapshot (fixes some crashes)

 libgphoto2-svn.patch | 1033 ++++++++++++++++++++++++++++++++++++++++++++++++++
 libgphoto2.spec      |   13 +-
 2 files changed, 1042 insertions(+), 4 deletions(-)
---
diff --git a/libgphoto2.spec b/libgphoto2.spec
index 3d859bd..c11ccfb 100644
--- a/libgphoto2.spec
+++ b/libgphoto2.spec
@@ -11,15 +11,19 @@ Summary(es.UTF-8):	Foto GNU (gphoto) Release 2
 Summary(pl.UTF-8):	Biblioteki obsługi kamer cyfrowych
 Summary(pt_BR.UTF-8):	GNU Photo - programa GNU para câmeras digitais
 Name:		libgphoto2
-Version:	2.4.14
-Release:	2
+%define	base_version	2.4.14
+%define	snap		14116
+Version:	2.4.14.1
+Release:	0.svn%{snap}
 License:	LGPL v2+
 Group:		Libraries
-Source0:	http://downloads.sourceforge.net/gphoto/%{name}-%{version}.tar.bz2
+Source0:	http://downloads.sourceforge.net/gphoto/%{name}-%{base_version}.tar.bz2
 # Source0-md5:	c7fc6cafa6343f2457976dbe9f2d9d68
 Patch0:		%{name}-mode-owner-group.patch
 Patch1:		%{name}-IXANY.patch
 Patch2:		%{name}-increase_max_entries.patch
+# svn diff -r 14002:%{snap}
+Patch3:		%{name}-svn.patch
 URL:		http://www.gphoto.org/
 BuildRequires:	autoconf >= 2.59
 BuildRequires:	automake >= 1:1.9
@@ -164,12 +168,13 @@ Plik z informacjami o urządzeniach HAL-a do obsługi kamer cyfrowych
 w przestrzeni użytkownika.
 
 %prep
-%setup -q
+%setup -q -n %{name}-%{base_version}
 %patch0 -p1
 %ifarch alpha
 %patch1 -p1
 %endif
 %patch2 -p1
+%patch3 -p0
 
 %{__rm} po/stamp-po libgphoto2_port/po/stamp-po
 
diff --git a/libgphoto2-svn.patch b/libgphoto2-svn.patch
new file mode 100644
index 0000000..ddc444e
--- /dev/null
+++ b/libgphoto2-svn.patch
@@ -0,0 +1,1033 @@
+Index: configure.ac
+===================================================================
+--- configure.ac	(revision 14002)
++++ configure.ac	(revision 14116)
+@@ -5,7 +5,7 @@
+ dnl       So lastversion.X.trunk for instance. Bump X if necessary.
+ 
+ dnl ******* THE NEXT RELEASE VERSION MUST BE 2.4.15 at least or higher!
+-AC_INIT([libgphoto2 photo camera library], [2.4.14], [gphoto-devel at lists.sourceforge.net], [libgphoto2])
++AC_INIT([libgphoto2 photo camera library], [2.4.14.1], [gphoto-devel at lists.sourceforge.net], [libgphoto2])
+ AC_CONFIG_SRCDIR([libgphoto2/gphoto2-version.c])
+ AC_CONFIG_HEADERS([config.h])
+ AC_CONFIG_MACRO_DIR([auto-m4])
+Index: camlibs/ptp2/library.c
+===================================================================
+--- camlibs/ptp2/library.c	(revision 14002)
++++ camlibs/ptp2/library.c	(revision 14116)
+@@ -623,9 +623,14 @@
+ 	{"Sony:SLT-A55 (PTP mode)",   0x054c, 0x04a3, 0},
+ 	/* http://sourceforge.net/tracker/?func=detail&atid=358874&aid=3515558&group_id=8874 */
+ 	{"Sony:SLT-A35 (PTP mode)",   0x054c, 0x04a7, 0},
++	/* t.ludewig at gmail.com */
++	{"Sony:SLT-A65V (PTP mode)",  0x054c, 0x0574, 0},
+ 	/* Rudi */
+ 	{"Sony:DSC-HX100V (PTP mode)",0x054c, 0x0543, 0},
+ 
++	/* t.ludewig at gmail.com */
++	{"Sony:DSC-HX200V (PTP mode)",0x054c, 0x061f, 0},
++
+ 	/* Nikon Coolpix 2500: M. Meissner, 05 Oct 2003 */
+ 	{"Nikon:Coolpix 2500 (PTP mode)", 0x04b0, 0x0109, 0},
+ 	/* Nikon Coolpix 5700: A. Tanenbaum, 29 Oct 2002 */
+@@ -715,7 +720,7 @@
+ 	{"Nikon:Coolpix L110 (PTP mode)", 0x04b0, 0x017e, PTP_CAP},
+ 
+ 	/* miguel at rozsas.eng.br */
+-	{"Nikon:Coolpix P500 (PTP mode)", 0x04b0, 0x0184, 0},
++	{"Nikon:Coolpix P500 (PTP mode)", 0x04b0, 0x0184, PTP_CAP},
+ 	/* Graeme Wyatt <graeme.wyatt at nookawarra.com> */
+ 	{"Nikon:Coolpix L120 (PTP mode)", 0x04b0, 0x0185, PTP_CAP},
+ 	/* Kévin Ottens <ervin at ipsquad.net> */
+@@ -740,6 +745,10 @@
+ 	{"Nikon:Coolpix S8000 (PTP mode)",0x04b0, 0x021f, 0},
+ 	/* Aleksej Serdjukov <deletesoftware at yandex.ru> */
+ 	{"Nikon:Coolpix S5100 (PTP mode)",0x04b0, 0x0220, 0},
++	/* wlady.cs at gmail.com */
++	{"Nikon:Coolpix P300 (PTP mode)", 0x04b0, 0x0221, 0},
++	/* t.ludewig at gmail.com */
++	{"Nikon:Coolpix P510 (PTP mode)", 0x04b0, 0x0223, 0},
+ 	/* Nikon Coolpix 2000 */
+ 	{"Nikon:Coolpix 2000 (PTP mode)", 0x04b0, 0x0302, 0},
+ 	/* From IRC reporter. */
+@@ -810,6 +819,15 @@
+ 	/* IRC Reporter popolon */
+ 	{"Nikon:DSC D5100 (PTP mode)",    0x04b0, 0x0429, PTP_CAP|PTP_CAP_PREVIEW},
+ 
++	/* Roderick Stewart <roderick.stewart at gmail.com> */
++	{"Nikon:DSC D800E (PTP mode)",    0x04b0, 0x042e, PTP_CAP|PTP_CAP_PREVIEW},
++	
++	/* http://sourceforge.net/tracker/?func=detail&aid=3536904&group_id=8874&atid=108874 */
++	{"Nikon:V1",    		  0x04b0, 0x0601, PTP_CAP},
++	/* https://sourceforge.net/tracker/?func=detail&atid=358874&aid=3556403&group_id=8874 */
++	{"Nikon:J1",    		  0x04b0, 0x0602, PTP_CAP},
++
++
+ #if 0
+ 	/* Thomas Luzat <thomas.luzat at gmx.net> */
+ 	/* this was reported as not working, mass storage only:
+@@ -872,6 +890,9 @@
+ 	{"Olympus:X920",                  0x07b4, 0x0116, 0},
+ 	{"Olympus:X925",                  0x07b4, 0x0116, 0},
+ 
++	/* t.ludewig at gmail.com */
++	{"Olympus:SP-720UZ",		  0x07b4, 0x012f, 0},
++
+ 	/* IRC report */
+ 	{"Casio:EX-Z120",                 0x07cf, 0x1042, 0},
+ 	/* Andrej Semen (at suse) */
+@@ -1058,6 +1079,8 @@
+ 
+ 	/* Martin Lasarsch at SUSE. MTP_PROPLIST returns just 0 entries */
+ 	{"Canon:Digital IXUS 90 IS",		0x04a9, 0x3174, PTPBUG_DELETE_SENDS_EVENT},
++	/* Daniel Moyne <daniel.moyne at free.fr> */
++	{"Canon:Powershot SD790 IS",		0x04a9, 0x3174, PTPBUG_DELETE_SENDS_EVENT},
+ 
+ 	/* https://sourceforge.net/tracker/?func=detail&aid=2722422&group_id=8874&atid=358874 */
+ 	{"Canon:Digital IXUS 85 IS",		0x04a9, 0x3174, PTPBUG_DELETE_SENDS_EVENT},
+@@ -1177,9 +1200,18 @@
+ 	/* https://sourceforge.net/tracker/?func=detail&atid=358874&aid=3310995&group_id=8874 */
+ 	{"Canon:EOS 600D",			0x04a9, 0x3218, PTP_CAP|PTP_CAP_PREVIEW},
+ 
++	/* analemma88 at gmail.com */
++	{"Canon:PowerShot A800",		0x04a9, 0x3226, PTPBUG_DELETE_SENDS_EVENT},
++
+ 	/* Juha Pesonen <juha.e.pesonen at gmail.com> */
+ 	{"Canon:PowerShot SX230HS",		0x04a9, 0x3228, PTPBUG_DELETE_SENDS_EVENT},
+ 
++	/* t.ludewig at gmail.com */
++	{"Canon:PowerShot SX40HS",		0x04a9, 0x3238, PTPBUG_DELETE_SENDS_EVENT},
++
++	/* t.ludewig at gmail.com */
++	{"Canon:EOS 650D",			0x04a9, 0x323b, PTP_CAP|PTP_CAP_PREVIEW},
++
+ 	/* Konica-Minolta PTP cameras */
+ 	{"Konica-Minolta:DiMAGE A2 (PTP mode)",        0x132b, 0x0001, 0},
+ 	{"Konica-Minolta:DiMAGE Z2 (PictBridge mode)", 0x132b, 0x0007, 0},
+@@ -1244,10 +1276,17 @@
+ 	{"Fuji:FinePix F80EXR",			0x04cb, 0x020e, 0},
+ 	/* salsaman <salsaman at gmail.com> */
+ 	{"Fuji:FinePix Z700EXR",		0x04cb, 0x020d, 0},
++	/* https://sourceforge.net/tracker/index.php?func=detail&aid=3556692&group_id=8874&atid=108874 */
++	{"Fuji:FinePix S2950",			0x04cb, 0x0240, 0},
+ 	/* Luis Arias <kaaloo at gmail.com> */
+ 	{"Fuji:FinePix X10",			0x04cb, 0x0263, 0},
++	/* t.ludewig at gmail.com */
++	{"Fuji:FinePix S4300",			0x04cb, 0x0265, 0},
++	/* t.ludewig at gmail.com */
++	{"Fuji:FinePix X-S1",			0x04cb, 0x026e, 0},
++	/* t.ludewig at gmail.com */
++	{"Fuji:FinePix HS30EXR",		0x04cb, 0x0271, 0},
+ 
+-
+ 	{"Ricoh:Caplio R5 (PTP mode)",          0x05ca, 0x0110, 0},
+ 	{"Ricoh:Caplio GX (PTP mode)",          0x05ca, 0x0325, 0},
+ 	{"Sea & Sea:5000G (PTP mode)",		0x05ca, 0x0327, 0},
+@@ -1289,6 +1328,9 @@
+ 	{"Apple:iPod Touch 3rd Gen (PTP mode)",	0x05ac, 0x1299, 0},
+ 	{"Apple:iPad (PTP mode)",		0x05ac, 0x129a, 0},
+ 
++	/* Don Cohen <don-sourceforge-xxzw at isis.cs3-inc.com> */
++	{"Apple:iPhone 4S (PTP mode)",		0x05ac, 0x12a0, 0},
++
+ 	/* https://sourceforge.net/tracker/index.php?func=detail&aid=1869653&group_id=158745&atid=809061 */
+ 	{"Pioneer:DVR-LX60D",			0x08e4, 0x0142, 0},
+ 
+@@ -4555,12 +4597,14 @@
+ 		unsigned char *ximage = NULL;
+ 		unsigned int xlen = 0;
+ 
+-		/* If thumb size is 0 then there is no thumbnail at all... */
+-		if((size=oi->ThumbCompressedSize)==0) return (GP_ERROR_NOT_SUPPORTED);
++		size=oi->ThumbCompressedSize;
++		/* If thumb size is 0 and the OFC is not a image type (0x3800 / 0xb800)... */
++		if ((size==0) && ((oi->ObjectFormat & 0x7800) != 0x3800))
++			return GP_ERROR_NOT_SUPPORTED;
+ 		CPR (context, ptp_getthumb(params,
+ 			params->handles.Handler[object_id],
+ 			&ximage, &xlen));
+-		if (xlen != size)
++		if (size && (xlen != size))
+ 			gp_log (GP_LOG_ERROR, "get_file_func/GP_FILE_TYPE_PREVIEW", "size mismatch %d vs %d", size, xlen);
+ 		set_mimetype (camera, file, params->deviceinfo.VendorExtensionID, oi->ThumbFormat);
+ 		CR (gp_file_set_data_and_size (file, (char*)ximage, xlen));
+Index: camlibs/canon/canon.c
+===================================================================
+--- camlibs/canon/canon.c	(revision 14002)
++++ camlibs/canon/canon.c	(revision 14116)
+@@ -1333,8 +1333,7 @@
+                         if ( is_image ( new_name ) ) {
+                                 /* Yup, we'll assume that this is the new image. */
+                                 GP_DEBUG ( "  Found our new image file" );
+-                                strncpy ( path->name, new_name,
+-                                          strlen ( new_name ) );
++                                strcpy ( path->name, new_name );
+                                 strcpy ( path->folder, canon2gphotopath ( camera, path->folder ) );
+ 
+ 				/* FIXME: Marcus: make it less large effort... */
+Index: camlibs/ax203/ax203.h
+===================================================================
+--- camlibs/ax203/ax203.h	(revision 14002)
++++ camlibs/ax203/ax203.h	(revision 14116)
+@@ -49,6 +49,7 @@
+ #define AX203_EEPROM_CMD	0x00
+ #define AX203_GET_VERSION	0x01
+ #define AX203_GET_LCD_SIZE	0x02
++#define AX203_GET_CHECKSUM	0x05 /* Note only seen on 206 sofar */
+ 
+ #define AX3003_FRAME_CMD	0xCA
+ #define AX3003_SET_TIME		0x01
+@@ -102,6 +103,7 @@
+ 	int mem_size;
+ 	int has_4k_sectors;
+ 	int block_protection_removed;
++	int pp_64k;
+ 	/* Driver configuration settings */
+ 	int syncdatetime;
+ };
+Index: camlibs/ax203/README.ax203
+===================================================================
+--- camlibs/ax203/README.ax203	(revision 14002)
++++ camlibs/ax203/README.ax203	(revision 14116)
+@@ -113,6 +113,24 @@
+ to be removed, a lot more of the memory could be used to actually store
+ pictures.
+ 
++ax206 checksum command
++----------------------
+ 
++While working on support for the ax206's not quite raw flash access mode
++for eeproms with AAI, like the SST25VF080, I found out that at least the
++ax206 also has a command to read part of the eeprom and generate a 16 bit
++checksum for it. The layout of the scsi cmd buffer for this is as follows:
++byte       0: 0xcd (read from dev)
++byte  1 -  4: 0
++byte       5: 5
++byte       6: 5
++byte  7 -  8: size of area to checksum, byte 7 == MSB, 0 means 65536
++byte  9 - 10: 0
++byte 11 - 13: address to start checksum, byte 11 == MSB
++
++And then readback 64 bytes of scsi data, where the first 2 are the 16 bit
++checksum of all the bytes in the area with byte 0 being the MSB.
++
++
+ Hans de Goede <hdegoede at redhat.com>
+-3 May 2010
++16 Sep 2012
+Index: camlibs/ax203/ax203.c
+===================================================================
+--- camlibs/ax203/ax203.c	(revision 14002)
++++ camlibs/ax203/ax203.c	(revision 14116)
+@@ -1,6 +1,6 @@
+ /* Appotech ax203 picframe access library
+  *
+- *   Copyright (c) 2010 Hans de Goede <hdegoede at redhat.com>
++ *   Copyright (c) 2010-2012 Hans de Goede <hdegoede at redhat.com>
+  *
+  * 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
+@@ -43,6 +43,7 @@
+ 	uint32_t id;
+ 	int mem_size;
+ 	int has_4k_sectors;
++	int pp_64k;
+ } ax203_eeprom_info[] = {
+ 	{ "AMIC A25L040", 0x37133037,  524288, 1 },
+ 	{ "AMIC A25L080", 0x37143037, 1048576, 1 },
+@@ -85,9 +86,8 @@
+ 	{ "Spansion S25FL008A", 0x00130201, 1048576, 0 },
+ 	{ "Spansion S25FL016A", 0x00140201, 2097152, 0 },
+ 
+-	/* The SST25VF080 and SST25VF016 (id:0xbf8e25bf & 0xbf4125bf) PP
+-	   instruction can only program a single byte at a time. Thus they
+-	   are not supported */
++	{ "SST25VF080", 0xbf8e25bf, 1048576, 0, 1 },
++	{ "SST25VF016", 0xbf4125bf, 2097152, 0, 1 },
+ 
+ 	{ "ST M25P08", 0x7f142020, 1048576, 0 },
+ 	{ "ST M25P16", 0x7f152020, 2097152, 0 },
+@@ -123,7 +123,7 @@
+ static int
+ ax203_send_eeprom_cmd(Camera *camera, int to_dev,
+ 	char *eeprom_cmd, int eeprom_cmd_size,
+-	char *data, int data_size)
++	char *data, int data_size, char extra_arg)
+ {
+ 	char cmd_buffer[16];
+ 	int i;
+@@ -143,6 +143,8 @@
+ 	for (i = 0; i < eeprom_cmd_size; i++)
+ 		cmd_buffer[10 + i] = eeprom_cmd[i];
+ 
++	cmd_buffer[15] = extra_arg;
++
+ 	return ax203_send_cmd (camera, to_dev, cmd_buffer, sizeof(cmd_buffer),
+ 			       data, data_size);
+ }
+@@ -194,6 +196,31 @@
+ #endif
+ 
+ static int
++ax203_get_checksum(Camera *camera, int address, int size)
++{
++	int ret;
++	char cmd_buffer[16];
++	uint8_t buf[2];
++
++	memset (cmd_buffer, 0, sizeof (cmd_buffer));
++
++	cmd_buffer[0] = AX203_FROM_DEV;
++	cmd_buffer[5] = AX203_GET_CHECKSUM;
++	cmd_buffer[6] = AX203_GET_CHECKSUM;
++	cmd_buffer[7] = (size >> 8) & 0xff;
++	cmd_buffer[8] = size & 0xff;
++	cmd_buffer[11] = (address >> 16) & 0xff;
++	cmd_buffer[12] = (address >> 8) & 0xff;
++	cmd_buffer[13] = address & 0xff;
++
++	ret = ax203_send_cmd (camera, 0, cmd_buffer, sizeof(cmd_buffer),
++			      (char *)buf, 2);
++	if (ret < 0) return ret;
++
++	return be16atoh(buf);
++}
++
++static int
+ ax3003_get_frame_id(Camera *camera)
+ {
+ 	int ret;
+@@ -273,7 +300,7 @@
+ {
+ 	char cmd = SPI_EEPROM_RDID;
+ 
+-	return ax203_send_eeprom_cmd (camera, 0, &cmd, 1, buf, 4);
++	return ax203_send_eeprom_cmd (camera, 0, &cmd, 1, buf, 4, 0);
+ }
+ 
+ static int
+@@ -281,7 +308,7 @@
+ {
+ 	char cmd = SPI_EEPROM_RDP;
+ 
+-	return ax203_send_eeprom_cmd (camera, 1, &cmd, 1, NULL, 0);
++	return ax203_send_eeprom_cmd (camera, 1, &cmd, 1, NULL, 0, 0);
+ }
+ 
+ static int
+@@ -295,11 +322,12 @@
+ 	cmd[3] = (address) & 0xff;
+ 		    
+ 	return ax203_send_eeprom_cmd (camera, 0, cmd, sizeof(cmd), buf,
+-				      buf_size);
++				      buf_size, 0);
+ }
+ 
+ static int
+-ax203_eeprom_program_page(Camera *camera, int address, char *buf, int buf_size)
++ax203_eeprom_program_page(Camera *camera, int address, char *buf, int buf_size,
++	char extra_arg)
+ {
+ 	char cmd[4];
+ 
+@@ -309,7 +337,7 @@
+ 	cmd[3] = (address) & 0xff;
+ 		    
+ 	return ax203_send_eeprom_cmd (camera, 1, cmd, sizeof(cmd), buf,
+-				      buf_size);
++				      buf_size, extra_arg);
+ }
+ 
+ static int
+@@ -317,7 +345,7 @@
+ {
+ 	char cmd = SPI_EEPROM_WREN;
+ 
+-	return ax203_send_eeprom_cmd (camera, 1, &cmd, 1, NULL, 0);
++	return ax203_send_eeprom_cmd (camera, 1, &cmd, 1, NULL, 0, 0);
+ }
+ 
+ static int
+@@ -328,7 +356,7 @@
+ 	cmd[0] = SPI_EEPROM_WRSR;
+ 	cmd[1] = 0;
+ 
+-	return ax203_send_eeprom_cmd (camera, 1, cmd, sizeof(cmd), NULL, 0);
++	return ax203_send_eeprom_cmd (camera, 1, cmd, sizeof(cmd), NULL, 0, 0);
+ }
+ 
+ static int
+@@ -341,7 +369,7 @@
+ 	cmd[2] = (address >> 8) & 0xff;
+ 	cmd[3] = (address) & 0xff;
+ 		    
+-	return ax203_send_eeprom_cmd (camera, 1, cmd, sizeof(cmd), NULL, 0);
++	return ax203_send_eeprom_cmd (camera, 1, cmd, sizeof(cmd), NULL, 0, 0);
+ }
+ 
+ static int
+@@ -354,7 +382,7 @@
+ 	cmd[2] = (address >> 8) & 0xff;
+ 	cmd[3] = (address) & 0xff;
+ 		    
+-	return ax203_send_eeprom_cmd (camera, 1, cmd, sizeof(cmd), NULL, 0);
++	return ax203_send_eeprom_cmd (camera, 1, cmd, sizeof(cmd), NULL, 0, 0);
+ }
+ 
+ static int
+@@ -380,7 +408,8 @@
+ 	}
+ 
+ 	while (1) {
+-		CHECK (ax203_send_eeprom_cmd (camera, 0, &cmd, 1, buf, count))
++		CHECK (ax203_send_eeprom_cmd (camera, 0, &cmd, 1,
++					      buf, count, 0))
+ 		/* We only need to check the last read */
+ 		if (!(buf[count - 1] & 0x01)) /* Check write in progress bit */
+ 			break; /* No write in progress, done waiting */
+@@ -445,7 +474,7 @@
+ 		for (i = 0; i < SPI_EEPROM_SECTOR_SIZE; i += 256) {
+ 			CHECK (ax203_eeprom_write_enable (camera))
+ 			CHECK (ax203_eeprom_program_page (camera, base + i,
+-							  buf + i, 256))
++							  buf + i, 256, 0))
+ 			CHECK (ax203_eeprom_wait_ready (camera))
+ 		}
+ 	}
+@@ -1574,12 +1603,24 @@
+ 	return GP_OK;
+ }
+ 
++/* The ax3003 and the ax206 with AAI capable eeproms can program 64k at once,
++   this is probably done by special handling inside the firmware. */
+ static int
+-ax203_commit_block_ax3003(Camera *camera, int bss)
++ax203_commit_block_64k_at_once(Camera *camera, int bss)
+ {
+ 	int block_sector_size = SPI_EEPROM_BLOCK_SIZE / SPI_EEPROM_SECTOR_SIZE;
+ 	int i, address = bss * SPI_EEPROM_SECTOR_SIZE;
++	int checksum = 0;
++	char extra_arg = 0;
+ 
++	/* The ax206 (and we assume the same applies for ax203, untested!):
++	   1) Needs the last byte of the scsi cmd to be 2 to enable 64k pp
++	   2) Has an extra checksum function, which we might as well use. */
++	if (camera->pl->frame_version != AX3003_FIRMWARE_3_5_x) {
++		extra_arg = 2;
++		checksum = 1;
++	}
++
+ 	/* Make sure we have read the entire block before erasing it !! */
+ 	for (i = 0; i < block_sector_size; i++)
+ 		CHECK (ax203_check_sector_present (camera, bss + i))
+@@ -1594,14 +1635,31 @@
+ 	/* Erase the block */
+ 	CHECK (ax203_erase64k_sector (camera, bss))
+ 
+-	/* And program the block in one large 64k page write, the ax3003
+-	   probably emulates this in firmware, to avoid usb bus overhead. */
++	/* program the block in one large 64k page write */
+ 	CHECK (ax203_eeprom_write_enable (camera))
+ 	CHECK (ax203_eeprom_program_page (camera, address,
+ 					  camera->pl->mem + address,
+-					  SPI_EEPROM_BLOCK_SIZE))
++					  SPI_EEPROM_BLOCK_SIZE, extra_arg))
+ 	CHECK (ax203_eeprom_wait_ready (camera))
+ 
++	/* and ask the device to verify the write with a checksum */
++	if (checksum) {
++		checksum = 0;
++		for (i = address; i < (address + SPI_EEPROM_BLOCK_SIZE); i++)
++			checksum += ((uint8_t *)camera->pl->mem)[i];
++		checksum &= 0xffff;
++
++		i = ax203_get_checksum(camera, address, SPI_EEPROM_BLOCK_SIZE);
++		if (i < 0)
++			return i;
++		if (i != checksum) {
++			gp_log (GP_LOG_ERROR, "ax203",
++				"checksum mismatch after programming "
++				"expected %04x, got %04x\n", checksum, i);
++			return GP_ERROR_IO;
++		}
++	}
++
+ 	for (i = 0; i < block_sector_size; i++)
+ 		camera->pl->sector_dirty[bss + i] = 0;
+ 
+@@ -1630,8 +1688,8 @@
+ 		if (!dirty_sectors)
+ 			continue;
+ 
+-		if (camera->pl->frame_version == AX3003_FIRMWARE_3_5_x)
+-			CHECK (ax203_commit_block_ax3003 (camera, i))
++		if (camera->pl->pp_64k)
++			CHECK (ax203_commit_block_64k_at_once (camera, i))
+ 		/* There are 16 4k sectors per 64k block, when we need to
+ 		   program 12 or more sectors, programming the entire block
+ 		   becomes faster */
+@@ -1700,9 +1758,13 @@
+ 
+ 	camera->pl->mem_size       = ax203_eeprom_info[i].mem_size;
+ 	camera->pl->has_4k_sectors = ax203_eeprom_info[i].has_4k_sectors;
+-	GP_DEBUG ("%s EEPROM found, capacity: %d, has 4k sectors: %d",
+-		  ax203_eeprom_info[i].name, camera->pl->mem_size,
+-		  camera->pl->has_4k_sectors);
++	camera->pl->pp_64k         = ax203_eeprom_info[i].pp_64k;
++	if (camera->pl->frame_version == AX3003_FIRMWARE_3_5_x)
++		camera->pl->pp_64k = 1;
++	GP_DEBUG (
++		"%s EEPROM found, capacity: %d, has 4k sectors: %d, pp_64k %d",
++		ax203_eeprom_info[i].name, camera->pl->mem_size,
++		camera->pl->has_4k_sectors, camera->pl->pp_64k);
+ 
+ 	return ax203_init (camera);
+ }
+Index: NEWS
+===================================================================
+--- NEWS	(revision 14002)
++++ NEWS	(revision 14116)
+@@ -1,3 +1,8 @@
++libgphoto2 2.4.14.1
++
++* ptp2: some fixes
++
++------------------------------------------------------------------------
+ libgphoto2 2.4.14
+ 
+ packaging:
+Index: libgphoto2_port/libusb1/libusb1.c
+===================================================================
+--- libgphoto2_port/libusb1/libusb1.c	(revision 14002)
++++ libgphoto2_port/libusb1/libusb1.c	(revision 14116)
+@@ -71,6 +71,10 @@
+ 
+ 	int detached;
+ 
++	time_t				devslastchecked;
++	int				nrofdevs;
++	struct libusb_device_descriptor	*descs;
++	libusb_device			**devs;
+ };
+ 
+ GPPortType
+@@ -79,38 +83,34 @@
+ 	return (GP_PORT_USB);
+ }
+ 
+-static time_t gp_devslastchecked = 0;
+-static int gp_nrofdevs = 0;
+-static struct libusb_device_descriptor	*gp_descs;
+-static libusb_device			**gp_devs;
+ 
+ static ssize_t
+-load_devicelist (libusb_context *ctx) {
++load_devicelist (GPPortPrivateLibrary *pl) {
+ 	time_t	xtime;
+ 
+ 	time(&xtime);
+-	if (xtime != gp_devslastchecked) {
+-		if (gp_nrofdevs)
+-			libusb_free_device_list (gp_devs, 1);
+-		free (gp_descs);
+-		gp_nrofdevs = 0;
+-		gp_devs = NULL;
+-		gp_descs = NULL;
++	if (xtime != pl->devslastchecked) {
++		if (pl->nrofdevs)
++			libusb_free_device_list (pl->devs, 1);
++		free (pl->descs);
++		pl->nrofdevs = 0;
++		pl->devs = NULL;
++		pl->descs = NULL;
+ 	}
+-	if (!gp_nrofdevs) {
++	if (!pl->nrofdevs) {
+ 		int 	i;
+ 
+-		gp_nrofdevs = libusb_get_device_list (ctx, &gp_devs);
+-		gp_descs = malloc (sizeof(gp_descs[0])*gp_nrofdevs);
+-		for (i=0;i<gp_nrofdevs;i++) {
++		pl->nrofdevs = libusb_get_device_list (pl->ctx, &pl->devs);
++		pl->descs = malloc (sizeof(pl->descs[0])*pl->nrofdevs);
++		for (i=0;i<pl->nrofdevs;i++) {
+ 			int ret;
+-			ret = libusb_get_device_descriptor(gp_devs[i], &gp_descs[i]);
++			ret = libusb_get_device_descriptor(pl->devs[i], &pl->descs[i]);
+ 			if (ret)
+ 				gp_log (GP_LOG_ERROR, "libusb1", "libusb_get_device_descriptor(%d) returned %d", i, ret);
+ 		}
+ 	}
+-	time (&gp_devslastchecked);
+-	return gp_nrofdevs;
++	time (&pl->devslastchecked);
++	return pl->nrofdevs;
+ }
+ 
+ int
+@@ -119,6 +119,10 @@
+ 	GPPortInfo	info;
+ 	int		nrofdevices = 0;
+ 	int		d, i, i1, i2, unknownint;
++	libusb_context	*ctx;
++	libusb_device	**devs = NULL;
++	int		nrofdevs = 0;
++	struct libusb_device_descriptor	*descs;
+ 
+ 	/* generic matcher. This will catch passed XXX,YYY entries for instance. */
+ 	info.type = GP_PORT_USB;
+@@ -126,26 +130,33 @@
+ 	strcpy (info.path, "^usb:");
+ 	CHECK (gp_port_info_list_append (list, info));
+ 
+-	libusb_init (NULL);
+-	gp_nrofdevs = load_devicelist (NULL);
++	libusb_init (&ctx);
++	nrofdevs = libusb_get_device_list (ctx, &devs);
++	descs = malloc (sizeof(descs[0])*nrofdevs);
++	for (i=0;i<nrofdevs;i++) {
++		int ret;
++		ret = libusb_get_device_descriptor(devs[i], &descs[i]);
++		if (ret)
++			gp_log (GP_LOG_ERROR, "libusb1", "libusb_get_device_descriptor(%d) returned %d", i, ret);
++	}
+ 
+-	for (d = 0; d < gp_nrofdevs; d++) {
++	for (d = 0; d < nrofdevs; d++) {
+ 		/* Devices which are definitely not cameras. */
+-		if (	(gp_descs[d].bDeviceClass == LIBUSB_CLASS_HUB)		||
+-			(gp_descs[d].bDeviceClass == LIBUSB_CLASS_HID)		||
+-			(gp_descs[d].bDeviceClass == LIBUSB_CLASS_PRINTER)	||
+-			(gp_descs[d].bDeviceClass == LIBUSB_CLASS_COMM)	||
+-			(gp_descs[d].bDeviceClass == 0xe0)	/* wireless / bluetooth */
++		if (	(descs[d].bDeviceClass == LIBUSB_CLASS_HUB)		||
++			(descs[d].bDeviceClass == LIBUSB_CLASS_HID)		||
++			(descs[d].bDeviceClass == LIBUSB_CLASS_PRINTER)	||
++			(descs[d].bDeviceClass == LIBUSB_CLASS_COMM)	||
++			(descs[d].bDeviceClass == 0xe0)	/* wireless / bluetooth */
+ 		)
+ 			continue;
+ 		/* excepts HUBs, usually the interfaces have the classes, not
+ 		 * the device */
+ 		unknownint = 0;
+-		for (i = 0; i < gp_descs[d].bNumConfigurations; i++) {
++		for (i = 0; i < descs[d].bNumConfigurations; i++) {
+ 			struct libusb_config_descriptor *config;
+ 			int ret;
+ 
+-			ret = libusb_get_config_descriptor (gp_devs[d], i, &config);
++			ret = libusb_get_config_descriptor (devs[d], i, &config);
+ 			if (ret) {
+ 				unknownint++;
+ 				continue;
+@@ -185,22 +196,22 @@
+ 	/* Redo the same bus/device walk, but now add the ports with usb:x,y notation,
+ 	 * so we can address all USB devices.
+ 	 */
+-	for (d = 0; d < gp_nrofdevs; d++) {
++	for (d = 0; d < nrofdevs; d++) {
+ 		/* Devices which are definitely not cameras. */
+-		if (	(gp_descs[d].bDeviceClass == LIBUSB_CLASS_HUB)		||
+-			(gp_descs[d].bDeviceClass == LIBUSB_CLASS_HID)		||
+-			(gp_descs[d].bDeviceClass == LIBUSB_CLASS_PRINTER)	||
+-			(gp_descs[d].bDeviceClass == LIBUSB_CLASS_COMM)
++		if (	(descs[d].bDeviceClass == LIBUSB_CLASS_HUB)		||
++			(descs[d].bDeviceClass == LIBUSB_CLASS_HID)		||
++			(descs[d].bDeviceClass == LIBUSB_CLASS_PRINTER)	||
++			(descs[d].bDeviceClass == LIBUSB_CLASS_COMM)
+ 		)
+ 			continue;
+ 		/* excepts HUBs, usually the interfaces have the classes, not
+ 		 * the device */
+ 		unknownint = 0;
+-		for (i = 0; i < gp_descs[d].bNumConfigurations; i++) {
++		for (i = 0; i < descs[d].bNumConfigurations; i++) {
+ 			struct libusb_config_descriptor *config;
+ 			int ret;
+ 
+-			ret = libusb_get_config_descriptor (gp_devs[d], i, &config);
++			ret = libusb_get_config_descriptor (devs[d], i, &config);
+ 			if (ret) {
+ 				gp_log (GP_LOG_ERROR, "libusb1", "libusb_get_config_descriptor(%d) returned %d", d, ret);
+ 				unknownint++;
+@@ -226,8 +237,8 @@
+ 		info.type = GP_PORT_USB;
+ 		strcpy (info.name, "Universal Serial Bus");
+ 		snprintf (info.path,sizeof(info.path), "usb:%03d,%03d",
+-			libusb_get_bus_number (gp_devs[d]),
+-			libusb_get_device_address (gp_devs[d])
++			libusb_get_bus_number (devs[d]),
++			libusb_get_device_address (devs[d])
+ 		);
+ 		CHECK (gp_port_info_list_append (list, info));
+ 	}
+@@ -239,7 +250,7 @@
+ 		strcpy (info.path, "usb:");
+ 		CHECK (gp_port_info_list_append (list, info));
+ 	}
+-	libusb_exit (NULL);
++	libusb_exit (ctx); /* should free all stuff above */
+ 	return (GP_OK);
+ }
+ 
+@@ -269,11 +280,10 @@
+ {
+ 	if (port->pl) {
+ 		libusb_exit (port->pl->ctx);
++		free (port->pl->descs);
+ 		free (port->pl);
+ 		port->pl = NULL;
+ 	}
+-	if (gp_devs) libusb_free_device_list (gp_devs, 1);
+-	free (gp_descs);
+ 	return (GP_OK);
+ }
+ 
+@@ -744,6 +754,7 @@
+ {
+ 	char *s;
+ 	int d, busnr = 0, devnr = 0;
++	GPPortPrivateLibrary *pl = port->pl;
+ 
+ 	if (!port)
+ 		return (GP_ERROR_BAD_PARAMETERS);
+@@ -767,23 +778,23 @@
+ 		return GP_ERROR_BAD_PARAMETERS;
+ 	}
+ 
+-	gp_nrofdevs = load_devicelist (port->pl->ctx);
++	pl->nrofdevs = load_devicelist (port->pl);
+ 
+-	for (d = 0; d < gp_nrofdevs; d++) {
++	for (d = 0; d < pl->nrofdevs; d++) {
+ 		struct libusb_config_descriptor *confdesc;
+ 		int ret;
+ 		int config = -1, interface = -1, altsetting = -1;
+ 
+-		if ((gp_descs[d].idVendor != idvendor) ||
+-		    (gp_descs[d].idProduct != idproduct))
++		if ((pl->descs[d].idVendor != idvendor) ||
++		    (pl->descs[d].idProduct != idproduct))
+ 			continue;
+ 
+-		if (busnr && (busnr != libusb_get_bus_number (gp_devs[d])))
++		if (busnr && (busnr != libusb_get_bus_number (pl->devs[d])))
+ 			continue;
+-		if (devnr && (devnr != libusb_get_device_address (gp_devs[d])))
++		if (devnr && (devnr != libusb_get_device_address (pl->devs[d])))
+ 			continue;
+ 
+-		port->pl->d = gp_devs[d];
++		port->pl->d = pl->devs[d];
+ 
+ 		gp_log (GP_LOG_VERBOSE, "libusb1",
+ 			"Looking for USB device "
+@@ -791,9 +802,9 @@
+ 			idvendor, idproduct);
+ 
+ 		/* Use the first config, interface and altsetting we find */
+-		gp_port_usb_find_first_altsetting(gp_devs[d], &config, &interface, &altsetting);
++		gp_port_usb_find_first_altsetting(pl->devs[d], &config, &interface, &altsetting);
+ 
+-		ret = libusb_get_config_descriptor (gp_devs[d], config, &confdesc);
++		ret = libusb_get_config_descriptor (pl->devs[d], config, &confdesc);
+ 		if (ret)
+ 			continue;
+ 
+@@ -810,11 +821,11 @@
+ 		port->settings.usb.interface = confdesc->interface[interface].altsetting[altsetting].bInterfaceNumber;
+ 		port->settings.usb.altsetting = confdesc->interface[interface].altsetting[altsetting].bAlternateSetting;
+ 
+-		port->settings.usb.inep  = gp_port_usb_find_ep(gp_devs[d], config, interface, altsetting, LIBUSB_ENDPOINT_IN, LIBUSB_TRANSFER_TYPE_BULK);
+-		port->settings.usb.outep = gp_port_usb_find_ep(gp_devs[d], config, interface, altsetting, LIBUSB_ENDPOINT_OUT, LIBUSB_TRANSFER_TYPE_BULK);
+-		port->settings.usb.intep = gp_port_usb_find_ep(gp_devs[d], config, interface, altsetting, LIBUSB_ENDPOINT_IN, LIBUSB_TRANSFER_TYPE_INTERRUPT);
++		port->settings.usb.inep  = gp_port_usb_find_ep(pl->devs[d], config, interface, altsetting, LIBUSB_ENDPOINT_IN, LIBUSB_TRANSFER_TYPE_BULK);
++		port->settings.usb.outep = gp_port_usb_find_ep(pl->devs[d], config, interface, altsetting, LIBUSB_ENDPOINT_OUT, LIBUSB_TRANSFER_TYPE_BULK);
++		port->settings.usb.intep = gp_port_usb_find_ep(pl->devs[d], config, interface, altsetting, LIBUSB_ENDPOINT_IN, LIBUSB_TRANSFER_TYPE_INTERRUPT);
+ 
+-		port->settings.usb.maxpacketsize = libusb_get_max_packet_size (gp_devs[d], port->settings.usb.inep);
++		port->settings.usb.maxpacketsize = libusb_get_max_packet_size (pl->devs[d], port->settings.usb.inep);
+ 		gp_log (GP_LOG_VERBOSE, "libusb1",
+ 			"Detected defaults: config %d, "
+ 			"interface %d, altsetting %d, "
+@@ -998,6 +1009,8 @@
+ 	if (class == 666) /* Special hack for MTP devices with MS OS descriptors. */
+ 		return gp_port_usb_match_mtp_device (dev, configno, interfaceno, altsettingno);
+ 
++	ret = libusb_get_device_descriptor(dev, &desc);
++
+ 	if (desc.bDeviceClass == class &&
+ 	    (subclass == -1 ||
+ 	     desc.bDeviceSubClass == subclass) &&
+@@ -1005,7 +1018,6 @@
+ 	     desc.bDeviceProtocol == protocol))
+ 		return 1;
+ 
+-	ret = libusb_get_device_descriptor(dev, &desc);
+ 
+ 	for (i = 0; i < desc.bNumConfigurations; i++) {
+ 		struct libusb_config_descriptor *config;
+@@ -1045,6 +1057,7 @@
+ {
+ 	char *s;
+ 	int d, busnr = 0, devnr = 0;
++	GPPortPrivateLibrary *pl = port->pl;
+ 
+ 	if (!port)
+ 		return (GP_ERROR_BAD_PARAMETERS);
+@@ -1065,14 +1078,14 @@
+ 	if (!class)
+ 		return GP_ERROR_BAD_PARAMETERS;
+ 
+-	gp_nrofdevs = load_devicelist (port->pl->ctx);
+-	for (d = 0; d < gp_nrofdevs; d++) {
++	pl->nrofdevs = load_devicelist (port->pl);
++	for (d = 0; d < pl->nrofdevs; d++) {
+ 		struct libusb_config_descriptor *confdesc;
+ 		int i, ret, config = -1, interface = -1, altsetting = -1;
+ 
+-		if (busnr && (busnr != libusb_get_bus_number (gp_devs[d])))
++		if (busnr && (busnr != libusb_get_bus_number (pl->devs[d])))
+ 			continue;
+-		if (devnr && (devnr != libusb_get_device_address (gp_devs[d])))
++		if (devnr && (devnr != libusb_get_device_address (pl->devs[d])))
+ 			continue;
+ 
+ 		gp_log (GP_LOG_VERBOSE, "gphoto2-port-usb",
+@@ -1080,17 +1093,17 @@
+ 			"(class 0x%x, subclass, 0x%x, protocol 0x%x)...", 
+ 			class, subclass, protocol);
+ 
+-		ret = gp_port_usb_match_device_by_class(gp_devs[d], class, subclass, protocol, &config, &interface, &altsetting);
++		ret = gp_port_usb_match_device_by_class(pl->devs[d], class, subclass, protocol, &config, &interface, &altsetting);
+ 		if (!ret)
+ 			continue;
+ 
+-		port->pl->d = gp_devs[d];
++		port->pl->d = pl->devs[d];
+ 		gp_log (GP_LOG_VERBOSE, "libusb1",
+ 			"Found USB class device "
+ 			"(class 0x%x, subclass, 0x%x, protocol 0x%x)", 
+ 			class, subclass, protocol);
+ 
+-		ret = libusb_get_config_descriptor (gp_devs[d], config, &confdesc);
++		ret = libusb_get_config_descriptor (pl->devs[d], config, &confdesc);
+ 		if (ret) continue;
+ 
+ 		/* Set the defaults */
+@@ -1098,9 +1111,9 @@
+ 		port->settings.usb.interface = confdesc->interface[interface].altsetting[altsetting].bInterfaceNumber;
+ 		port->settings.usb.altsetting = confdesc->interface[interface].altsetting[altsetting].bAlternateSetting;
+ 
+-		port->settings.usb.inep  = gp_port_usb_find_ep(gp_devs[d], config, interface, altsetting, LIBUSB_ENDPOINT_IN, LIBUSB_TRANSFER_TYPE_BULK);
+-		port->settings.usb.outep = gp_port_usb_find_ep(gp_devs[d], config, interface, altsetting, LIBUSB_ENDPOINT_OUT, LIBUSB_TRANSFER_TYPE_BULK);
+-		port->settings.usb.intep = gp_port_usb_find_ep(gp_devs[d], config, interface, altsetting, LIBUSB_ENDPOINT_IN, LIBUSB_TRANSFER_TYPE_INTERRUPT);
++		port->settings.usb.inep  = gp_port_usb_find_ep(pl->devs[d], config, interface, altsetting, LIBUSB_ENDPOINT_IN, LIBUSB_TRANSFER_TYPE_BULK);
++		port->settings.usb.outep = gp_port_usb_find_ep(pl->devs[d], config, interface, altsetting, LIBUSB_ENDPOINT_OUT, LIBUSB_TRANSFER_TYPE_BULK);
++		port->settings.usb.intep = gp_port_usb_find_ep(pl->devs[d], config, interface, altsetting, LIBUSB_ENDPOINT_IN, LIBUSB_TRANSFER_TYPE_INTERRUPT);
+ 		port->settings.usb.maxpacketsize = 0;
+ 		gp_log (GP_LOG_DEBUG, "libusb1", "inep to look for is %02x", port->settings.usb.inep);
+ 		for (i=0;i<confdesc->interface[interface].altsetting[altsetting].bNumEndpoints;i++) {
+@@ -1117,8 +1130,8 @@
+ 			port->settings.usb.config,
+ 			port->settings.usb.interface,
+ 			port->settings.usb.altsetting,
+-			gp_descs[d].idVendor,
+-			gp_descs[d].idProduct,
++			pl->descs[d].idVendor,
++			pl->descs[d].idProduct,
+ 			port->settings.usb.inep,
+ 			port->settings.usb.outep,
+ 			port->settings.usb.intep
+Index: libgphoto2_port/usbscsi/linux.c
+===================================================================
+--- libgphoto2_port/usbscsi/linux.c	(revision 14002)
++++ libgphoto2_port/usbscsi/linux.c	(revision 14116)
+@@ -1,6 +1,6 @@
+ /* SCSI commands to USB Mass storage devices port library for Linux
+  * 
+- *   Copyright (c) 2010 Hans de Goede <hdegoede at redhat.com>
++ *   Copyright (c) 2010-2012 Hans de Goede <hdegoede at redhat.com>
+  *
+  * 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
+@@ -19,6 +19,7 @@
+ #include "config.h"
+ #include <gphoto2/gphoto2-port-library.h>
+ 
++#include <errno.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+@@ -29,6 +30,7 @@
+ #ifdef HAVE_LIMITS_H
+ # include <limits.h>
+ #endif
++#include <sys/file.h>
+ #include <sys/stat.h>
+ #include <sys/types.h>
+ #ifdef HAVE_SYS_PARAM_H
+@@ -40,9 +42,6 @@
+ #ifdef HAVE_SCSI_SG_H
+ # include <scsi/sg.h>
+ #endif
+-#ifdef HAVE_LOCKDEV
+-#  include <lockdev.h>
+-#endif
+ 
+ #include <gphoto2/gphoto2-port-result.h>
+ #include <gphoto2/gphoto2-port-log.h>
+@@ -80,62 +79,37 @@
+ }
+ 
+ static int
+-gp_port_usbscsi_lock (GPPort *port, const char *path)
++gp_port_usbscsi_lock (GPPort *port)
+ {
+-#ifdef HAVE_LOCKDEV
+-	int pid;
+-
+ 	gp_log (GP_LOG_DEBUG, "gphoto2-port-usbscsi",
+-		"Trying to lock '%s'...", path);
++		"Trying to lock '%s'...", port->settings.usbscsi.path);
+ 
+-	pid = dev_lock (path);
+-	if (pid) {
+-		if (port) {
+-			if (pid > 0)
+-				gp_port_set_error (port, _("Device '%s' is "
+-					"locked by pid %d"), path, pid);
+-			else
+-				gp_port_set_error (port, _("Device '%s' could "
+-					"not be locked (dev_lock returned "
+-					"%d)"), path, pid);
++	if (flock(port->pl->fd, LOCK_EX | LOCK_NB) != 0) {
++		switch (errno) {
++		case EWOULDBLOCK:
++			gp_port_set_error (port,
++				_("Device '%s' is locked by another app."),
++				port->settings.usbscsi.path);
++			return GP_ERROR_IO_LOCK;
++		default:
++			gp_port_set_error (port,
++				_("Failed to lock '%s' (%m)."),
++				port->settings.usbscsi.path);
++			return GP_ERROR_IO;
+ 		}
+-		return GP_ERROR_IO_LOCK;
+ 	}
+-#else
+-# ifdef __GCC__
+-#  warning No locking library found. 
+-#  warning You will run into problems if you use
+-#  warning gphoto2 with a usbscsi picframe in 
+-#  warning combination with Konqueror (KDE) or Nautilus (GNOME).
+-#  warning This will *not* concern USB cameras.
+-# endif
+-#endif
+ 
+ 	return GP_OK;
+ }
+ 
+ static int
+-gp_port_usbscsi_unlock (GPPort *port, const char *path)
++gp_port_usbscsi_unlock (GPPort *port)
+ {
+-#ifdef HAVE_LOCKDEV
+-	int pid;
+-
+-	pid = dev_unlock (path, 0);
+-	if (pid) {
+-		if (port) {
+-			if (pid > 0)
+-				gp_port_set_error (port, _("Device '%s' could "
+-					"not be unlocked as it is locked by "
+-					"pid %d."), path, pid);
+-			else
+-				gp_port_set_error (port, _("Device '%s' could "
+-					"not be unlocked (dev_unlock "
+-					"returned %d)"), path, pid);
+-		}
+-		return GP_ERROR_IO_LOCK;
++	if (flock(port->pl->fd, LOCK_UN) != 0) {
++		gp_port_set_error (port, _("Failed to unlock '%s' (%m)."),
++				   port->settings.usbscsi.path);
++		return GP_ERROR_IO;
+ 	}
+-#endif /* !HAVE_LOCKDEV */
+-
+ 	return GP_OK;
+ }
+ 
+@@ -269,34 +243,36 @@
+ 	const int max_tries = 5;
+ 	const char *path = port->settings.usbscsi.path;
+ 
+-	result = gp_port_usbscsi_lock (port, path);
+-	if (result != GP_OK) {
+-		for (i = 0; i < max_tries; i++) {
+-			result = gp_port_usbscsi_lock (port, path);
+-			if (result == GP_OK)
+-				break;
+-			gp_log (GP_LOG_DEBUG, "gphoto2-port-usbscsi",
+-				"Failed to get a lock, trying again...");
+-			sleep (1);
+-		}
+-		CHECK (result)
+-	}
+ 	port->pl->fd = open (path, O_RDWR);
+ 	if (port->pl->fd == -1) {
+-		gp_port_usbscsi_unlock (port, path);
+ 		gp_port_set_error (port, _("Failed to open '%s' (%m)."), path);
+ 		return GP_ERROR_IO;
+ 	}
+ 
+-	return GP_OK;
++	result = gp_port_usbscsi_lock (port);
++	for (i = 0; i < max_tries && result == GP_ERROR_IO_LOCK; i++) {
++		gp_log (GP_LOG_DEBUG, "gphoto2-port-usbscsi",
++			"Failed to get a lock, trying again...");
++		sleep (1);
++		result = gp_port_usbscsi_lock (port);
++	}
++	if (result != GP_OK) {
++		close (port->pl->fd);
++		port->pl->fd = -1;
++	}
++	return result;
+ }
+ 
+ static int
+ gp_port_usbscsi_close (GPPort *port)
+ {
++	int result;
++
+ 	if (!port || port->pl->fd == -1)
+ 		return GP_OK;
+ 
++	result = gp_port_usbscsi_unlock (port);
++
+ 	if (close (port->pl->fd) == -1) {
+ 		gp_port_set_error (port, _("Could not close "
+ 			"'%s' (%m)."), port->settings.usbscsi.path);
+@@ -304,10 +280,7 @@
+ 	}
+ 	port->pl->fd = -1;
+ 
+-	CHECK (gp_port_usbscsi_unlock (port,
+-					port->settings.usbscsi.path))
+-
+-	return GP_OK;
++	return result;
+ }
+ 
+ static int gp_port_usbscsi_send_scsi_cmd (GPPort *port, int to_dev, char *cmd,
+@@ -338,7 +311,7 @@
+ 	io_hdr.mx_sb_len = sense_size;
+ 	io_hdr.dxferp = (unsigned char *)data;
+ 	io_hdr.dxfer_len = data_size;
+-	io_hdr.timeout = 500;
++	io_hdr.timeout = 1500;
+ 
+ 	if (ioctl (port->pl->fd, SG_IO, &io_hdr) < 0)
+ 	{
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/libgphoto2.git/commitdiff/7b411445e53d670c6cfcee6a4f04815c8ffcf854




More information about the pld-cvs-commit mailing list