From 2fda09bd42eee020b89714dacbba448893c97cd7 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Fri, 2 Feb 2007 09:32:29 +0000 Subject: [PATCH] rewrote ucs-2 conversion to do endian conversiondireclty git-svn-id: https://svn.code.sf.net/p/gphoto/code/trunk/libgphoto2@9964 67ed7778-7388-44ab-90cf-0a291f65f57c --- camlibs/ptp2/ChangeLog | 6 +++ camlibs/ptp2/library.c | 28 ++++--------- camlibs/ptp2/ptp-pack.c | 91 ++++++++++++++++++++--------------------- 3 files changed, 58 insertions(+), 67 deletions(-) diff --git a/camlibs/ptp2/ChangeLog b/camlibs/ptp2/ChangeLog index b8cfdd42c..d8cf43aa3 100644 --- a/camlibs/ptp2/ChangeLog +++ b/camlibs/ptp2/ChangeLog @@ -1,3 +1,9 @@ +2007-02-02 Marcus Meissner + + * library.c: Rewritten UCS-2 handling to not + use strange hacks, but UCS-2LE directly. + (from Chuck Cranor) + 2007-01-29 Marcus Meissner * library.c: Added focuslock toggle option. diff --git a/camlibs/ptp2/library.c b/camlibs/ptp2/library.c index e29af01ce..57fcff590 100644 --- a/camlibs/ptp2/library.c +++ b/camlibs/ptp2/library.c @@ -51,23 +51,6 @@ # define N_(String) (String) #endif -/* - * On MacOS (Darwin) and *BSD we're not using glibc, but libiconv. - * glibc knows that UCS-2 is to be in the local machine endianness, - * whereas libiconv does not. So we construct this macro to get - * things right. Reportedly, glibc 2.1.3 has a bug so that UCS-2 - * is always bigendian though, we would need to work around that - * too... - */ -#ifndef __GLIBC__ -#define UCS_2_INTERNAL "UCS-2-INTERNAL" -#else -#if (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1 ) -#error "Too old glibc. This versions iconv() implementation cannot be trusted." -#endif -#define UCS_2_INTERNAL "UCS-2" -#endif - #include "ptp.h" #include "ptp-bugs.h" #include "ptp-private.h" @@ -3861,7 +3844,7 @@ camera_init (Camera *camera, GPContext *context) CameraAbilities a; int ret, i, retried = 0; PTPParams *params; - char *curloc; + char *curloc, *camloc; GPPortSettings settings; gp_port_get_settings (camera->port, &settings); @@ -3893,6 +3876,11 @@ camera_init (Camera *camera, GPContext *context) memset (camera->pl->params.data, 0, sizeof (PTPData)); ((PTPData *) camera->pl->params.data)->camera = camera; camera->pl->params.byteorder = PTP_DL_LE; + if (camera->pl->params.byteorder == PTP_DL_LE) + camloc = "UCS-2LE"; + else + camloc = "UCS-2BE"; + camera->pl->params.maxpacketsize = settings.usb.maxpacketsize; if (!camera->pl->params.maxpacketsize) camera->pl->params.maxpacketsize = 64; /* assume USB 1.0 */ @@ -3933,8 +3921,8 @@ camera_init (Camera *camera, GPContext *context) curloc = nl_langinfo (CODESET); if (!curloc) curloc="UTF-8"; - camera->pl->params.cd_ucs2_to_locale = iconv_open(curloc, UCS_2_INTERNAL); - camera->pl->params.cd_locale_to_ucs2 = iconv_open(UCS_2_INTERNAL, curloc); + camera->pl->params.cd_ucs2_to_locale = iconv_open(curloc, camloc); + camera->pl->params.cd_locale_to_ucs2 = iconv_open(camloc, curloc); if ((camera->pl->params.cd_ucs2_to_locale == (iconv_t) -1) || (camera->pl->params.cd_locale_to_ucs2 == (iconv_t) -1)) { gp_log (GP_LOG_ERROR, "iconv", "Failed to create iconv converter.\n"); diff --git a/camlibs/ptp2/ptp-pack.c b/camlibs/ptp2/ptp-pack.c index 6ec4f24a0..7efa66fb4 100644 --- a/camlibs/ptp2/ptp-pack.c +++ b/camlibs/ptp2/ptp-pack.c @@ -89,50 +89,46 @@ dtoh64ap (PTPParams *params, unsigned char *a) static inline char* ptp_unpack_string(PTPParams *params, unsigned char* data, uint16_t offset, uint8_t *len) { - int i; - uint8_t loclen; + uint8_t length; + uint16_t string[PTP_MAXSTRLEN+1]; + /* allow for UTF-8: max of 3 bytes per UCS-2 char, plus final null */ + char loclstr[PTP_MAXSTRLEN*3+1]; + size_t nconv, srclen, destlen; + char *src, *dest; - /* Cannot exceed 255 (PTP_MAXSTRLEN) since it is a single byte, duh ... */ - loclen = dtoh8a(&data[offset]); - /* This len is used to advance the buffer pointer */ - *len = loclen; - if (loclen) { - uint16_t string[PTP_MAXSTRLEN+1]; - char *stringp = (char *) string; - char loclstr[PTP_MAXSTRLEN*3+1]; /* UTF-8 encoding is max 3 bytes per UCS2 char. */ - char *locp = loclstr; - size_t nconv; - size_t convlen = loclen * 2; /* UCS-2 is 16 bit wide */ - size_t convmax = PTP_MAXSTRLEN*3; - - for (i=0;icd_ucs2_to_locale, &src, &srclen, + &dest, &destlen); + if (nconv == (size_t) -1) { /* do it the hard way */ + int i; + /* try the old way, in case iconv is broken */ + for (i=0;i127) + loclstr[i] = '?'; + else + loclstr[i] = dtoh16a(&data[offset+1+2*i]); } - /* be paranoid! Add a terminator. :( */ - string[loclen]=0x0000U; - loclstr[0]='\0'; - /* loclstr=ucs2_to_utf8(string); */ - /* Do the conversion. */ - nconv = iconv (params->cd_ucs2_to_locale, &stringp, &convlen, &locp, &convmax); - /* FIXME: handle size errors */ - loclstr[PTP_MAXSTRLEN*3] = '\0'; - if (nconv == (size_t) -1) { - int i; - /* try the old way, in case iconv is broken */ - for (i=0;i127) - loclstr[i] = '?'; - else - loclstr[i] = string[i]; - } - string[loclen] = 0; - } - return strdup(loclstr); + dest = loclstr+length; } - return NULL; + *dest = '\0'; + loclstr[sizeof(loclstr)-1] = '\0'; /* be safe? */ + return(strdup(loclstr)); } - static inline int ucs2strlen(uint16_t const * const unicstr) { @@ -147,7 +143,6 @@ ucs2strlen(uint16_t const * const unicstr) static inline void ptp_pack_string(PTPParams *params, char *string, unsigned char* data, uint16_t offset, uint8_t *len) { - int i; int packedlen; uint16_t ucs2str[PTP_MAXSTRLEN+1]; char *ucs2strp = (char *) ucs2str; @@ -157,11 +152,15 @@ ptp_pack_string(PTPParams *params, char *string, unsigned char* data, uint16_t o size_t convmax = PTP_MAXSTRLEN * 2; /* Includes the terminator */ /* Cannot exceed 255 (PTP_MAXSTRLEN) since it is a single byte, duh ... */ - ucs2str[0] = 0x0000U; - memset(ucs2strp, 0, PTP_MAXSTRLEN*2+2); - nconv = iconv (params->cd_locale_to_ucs2, &stringp, &convlen, &ucs2strp, &convmax); + memset(ucs2strp, 0, sizeof(ucs2str)); /* XXX: necessary? */ + nconv = iconv(params->cd_locale_to_ucs2, &stringp, &convlen, + &ucs2strp, &convmax); if (nconv == (size_t) -1) ucs2str[0] = 0x0000U; + /* + * XXX: isn't packedlen just ( (uint16_t *)ucs2strp - ucs2str )? + * why do we need ucs2strlen()? + */ packedlen = ucs2strlen(ucs2str); if (packedlen > PTP_MAXSTRLEN-1) { *len=0; @@ -170,10 +169,8 @@ ptp_pack_string(PTPParams *params, char *string, unsigned char* data, uint16_t o /* number of characters including terminating 0 (PTP standard confirmed) */ htod8a(&data[offset],packedlen+1); - for (i=0;i