Core: Add a libusb_strerror() function
authorHans de Goede <hdegoede@redhat.com>
Fri, 7 Jun 2013 18:07:16 +0000 (19:07 +0100)
committerPete Batard <pete@akeo.ie>
Sun, 9 Jun 2013 23:16:36 +0000 (00:16 +0100)
This patch adds the much requested libusb_strerror() function, taking into
account all issues people raised wrt previous attempts.

Criteria / Decisions underlying this implementation:
- Must support translated messages
- Must not use gettext as that does not work well in combination with Windows
 (when building with Visual C, or for Windows CE)
- API compatible with FreeBSD and various patched libusb-s floating around
- KISS:
 - Do not add any (other) library dependencies
 - Do not try to deal with message encodings (iconv), simply always return UTF-8
   making encoding the problem of the application using libusb_strerror.
 - Defaults to English, so apps which don't want translated messages,
   don't need to do anything special
 - Defaults to English (with pure ASCII messages), so apps which don't
   call libusb_setlocale() don't need to worry about encoding

20 files changed:
examples/xusb.c
libusb/Makefile.am
libusb/libusb-1.0.def
libusb/libusb.h
libusb/libusbi.h
libusb/strerror.c [new file with mode: 0644]
libusb/version_nano.h
msvc/libusb_dll_2005.vcproj
msvc/libusb_dll_2010.vcxproj
msvc/libusb_dll_2010.vcxproj.filters
msvc/libusb_dll_2012.vcxproj
msvc/libusb_dll_2012.vcxproj.filters
msvc/libusb_dll_wince.vcproj
msvc/libusb_sources
msvc/libusb_static_2005.vcproj
msvc/libusb_static_2010.vcxproj
msvc/libusb_static_2010.vcxproj.filters
msvc/libusb_static_2012.vcxproj
msvc/libusb_static_2012.vcxproj.filters
msvc/libusb_static_wince.vcproj

index 4e2f6a5..c4740b6 100644 (file)
@@ -64,7 +64,7 @@ static int perr(char const *format, ...)
        return r;
 }
 
-#define ERR_EXIT(errcode) do { perr("   %s\n", libusb_error_name((enum libusb_error)errcode)); return -1; } while (0)
+#define ERR_EXIT(errcode) do { perr("   %s\n", libusb_strerror((enum libusb_error)errcode)); return -1; } while (0)
 #define CALL_CHECK(fcall) do { r=fcall; if (r < 0) ERR_EXIT(r); } while (0);
 #define B(x) (((x)!=0)?1:0)
 #define be_to_int32(buf) (((buf)[0]<<24)|((buf)[1]<<16)|((buf)[2]<<8)|(buf)[3])
@@ -354,7 +354,7 @@ static int send_mass_storage_command(libusb_device_handle *handle, uint8_t endpo
                i++;
        } while ((r == LIBUSB_ERROR_PIPE) && (i<RETRY_MAX));
        if (r != LIBUSB_SUCCESS) {
-               perr("   send_mass_storage_command: %s\n", libusb_error_name(r));
+               perr("   send_mass_storage_command: %s\n", libusb_strerror((enum libusb_error)r));
                return -1;
        }
 
@@ -378,7 +378,7 @@ static int get_mass_storage_status(libusb_device_handle *handle, uint8_t endpoin
                i++;
        } while ((r == LIBUSB_ERROR_PIPE) && (i<RETRY_MAX));
        if (r != LIBUSB_SUCCESS) {
-               perr("   get_mass_storage_status: %s\n", libusb_error_name(r));
+               perr("   get_mass_storage_status: %s\n", libusb_strerror((enum libusb_error)r));
                return -1;
        }
        if (size != 13) {
@@ -460,7 +460,7 @@ static int test_mass_storage(libusb_device_handle *handle, uint8_t endpoint_in,
        if (r == 0) {
                lun = 0;
        } else if (r < 0) {
-               perr("   Failed: %s", libusb_error_name((enum libusb_error)r));
+               perr("   Failed: %s", libusb_strerror((enum libusb_error)r));
        }
        printf("   Max LUN = %d\n", lun);
 
@@ -638,7 +638,7 @@ static int test_hid(libusb_device_handle *handle, uint8_t endpoint_in)
                                libusb_clear_halt(handle, 0);
                                break;
                        default:
-                               printf("   Error: %s\n", libusb_error_name(r));
+                               printf("   Error: %s\n", libusb_strerror((enum libusb_error)r));
                                break;
                        }
                }
@@ -669,7 +669,7 @@ static int test_hid(libusb_device_handle *handle, uint8_t endpoint_in)
                                libusb_clear_halt(handle, 0);
                                break;
                        default:
-                               printf("   Error: %s\n", libusb_error_name(r));
+                               printf("   Error: %s\n", libusb_strerror((enum libusb_error)r));
                                break;
                        }
                }
@@ -680,7 +680,7 @@ static int test_hid(libusb_device_handle *handle, uint8_t endpoint_in)
                if (r >= 0) {
                        display_buffer_hex(report_buffer, size);
                } else {
-                       printf("   %s\n", libusb_error_name(r));
+                       printf("   %s\n", libusb_strerror((enum libusb_error)r));
                }
 
                free(report_buffer);
@@ -715,7 +715,7 @@ static void read_ms_winsub_feature_descriptors(libusb_device_handle *handle, uin
                r = libusb_control_transfer(handle, (uint8_t)(LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_VENDOR|os_fd[i].recipient),
                        bRequest, (uint16_t)(((iface_number)<< 8)|0x00), os_fd[i].index, os_desc, os_fd[i].header_size, 1000);
                if (r < os_fd[i].header_size) {
-                       perr("   Failed: %s", (r<0)?libusb_error_name((enum libusb_error)r):"header size is too small");
+                       perr("   Failed: %s", (r<0)?libusb_strerror((enum libusb_error)r):"header size is too small");
                        return;
                }
                le_type_punning_IS_fine = (void*)os_desc;
@@ -728,7 +728,7 @@ static void read_ms_winsub_feature_descriptors(libusb_device_handle *handle, uin
                r = libusb_control_transfer(handle, (uint8_t)(LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_VENDOR|os_fd[i].recipient),
                        bRequest, (uint16_t)(((iface_number)<< 8)|0x00), os_fd[i].index, os_desc, (uint16_t)length, 1000);
                if (r < 0) {
-                       perr("   Failed: %s", libusb_error_name((enum libusb_error)r));
+                       perr("   Failed: %s", libusb_strerror((enum libusb_error)r));
                        return;
                } else {
                        display_buffer_hex(os_desc, r);
@@ -977,6 +977,7 @@ int main(int argc, char** argv)
        size_t i, arglen;
        unsigned tmp_vid, tmp_pid;
        uint16_t endian_test = 0xBE00;
+       char* error_lang = NULL;
 
        // Default to generic, expecting VID:PID
        VID = 0;
@@ -1009,6 +1010,13 @@ int main(int argc, char** argv)
                                        binary_name = argv[++j];
                                        binary_dump = true;
                                        break;
+                               case 'l':
+                                       if ((j+1 >= argc) || (argv[j+1][0] == '-') || (argv[j+1][0] == '/')) {
+                                               printf("   Option -l requires an ISO 639-1 language parameter");
+                                               return 1;
+                                       }
+                                       error_lang = argv[++j];
+                                       break;
                                case 'j':
                                        // OLIMEX ARM-USB-TINY JTAG, 2 channel composite device - 2 interfaces
                                        if (!VID && !PID) {
@@ -1066,7 +1074,7 @@ int main(int argc, char** argv)
        }
 
        if ((show_help) || (argc == 1) || (argc > 7)) {
-               printf("usage: %s [-h] [-d] [-i] [-k] [-b file] [-j] [-x] [-s] [-p] [vid:pid]\n", argv[0]);
+               printf("usage: %s [-h] [-d] [-i] [-k] [-b file] [-l lang] [-j] [-x] [-s] [-p] [vid:pid]\n", argv[0]);
                printf("   -h      : display usage\n");
                printf("   -d      : enable debug output\n");
                printf("   -i      : print topology and speed info\n");
@@ -1076,6 +1084,7 @@ int main(int argc, char** argv)
                printf("   -p      : test Sony PS3 SixAxis controller\n");
                printf("   -s      : test Microsoft Sidewinder Precision Pro (HID)\n");
                printf("   -x      : test Microsoft XBox Controller Type S\n");
+               printf("   -l lang : language to report errors in (ISO 639-1)\n");
                printf("If only the vid:pid is provided, xusb attempts to run the most appropriate test\n");
                return 0;
        }
@@ -1087,6 +1096,11 @@ int main(int argc, char** argv)
                return r;
 
        libusb_set_debug(NULL, debug_mode?LIBUSB_LOG_LEVEL_DEBUG:LIBUSB_LOG_LEVEL_INFO);
+       if (error_lang != NULL) {
+               r = libusb_setlocale(error_lang);
+               if (r < 0)
+                       printf("Invalid or unsupported locale '%s': %s\n", error_lang, libusb_strerror((enum libusb_error)r));
+       }
 
        test_device(VID, PID);
 
index cd6db9c..7f9c1f9 100644 (file)
@@ -59,9 +59,10 @@ endif
 
 libusb_1_0_la_CFLAGS = $(AM_CFLAGS)
 libusb_1_0_la_LDFLAGS = $(LTLDFLAGS)
-libusb_1_0_la_SOURCES = libusbi.h core.c descriptor.c io.c sync.c $(OS_SRC) \
+libusb_1_0_la_SOURCES = libusbi.h core.c descriptor.c io.c strerror.c sync.c \
        os/linux_usbfs.h os/darwin_usb.h os/windows_usb.h os/windows_common.h \
-       hotplug.h hotplug.c $(THREADS_SRC) os/poll_posix.h os/poll_windows.h
+       hotplug.h hotplug.c $(THREADS_SRC) $(OS_SRC) \
+       os/poll_posix.h os/poll_windows.h
 
 hdrdir = $(includedir)/libusb-1.0
 hdr_HEADERS = libusb.h
index 7166d47..e6c46fd 100644 (file)
@@ -78,6 +78,8 @@ EXPORTS
   libusb_get_pollfds@4 = libusb_get_pollfds
   libusb_get_port_number
   libusb_get_port_number@4 = libusb_get_port_number
+  libusb_get_port_numbers
+  libusb_get_port_numbers@12 = libusb_get_port_numbers
   libusb_get_port_path
   libusb_get_port_path@16 = libusb_get_port_path
   libusb_get_ss_endpoint_companion_descriptor
@@ -136,6 +138,10 @@ EXPORTS
   libusb_set_interface_alt_setting@12 = libusb_set_interface_alt_setting
   libusb_set_pollfd_notifiers
   libusb_set_pollfd_notifiers@16 = libusb_set_pollfd_notifiers
+  libusb_setlocale
+  libusb_setlocale@4 = libusb_setlocale
+  libusb_strerror
+  libusb_strerror@4 = libusb_strerror
   libusb_submit_transfer
   libusb_submit_transfer@4 = libusb_submit_transfer
   libusb_try_lock_events
@@ -148,5 +154,3 @@ EXPORTS
   libusb_unref_device@4 = libusb_unref_device
   libusb_wait_for_event
   libusb_wait_for_event@8 = libusb_wait_for_event
-  libusb_get_port_numbers
-  libusb_get_port_numbers@12 = libusb_get_port_numbers
index d733c46..a56a687 100644 (file)
@@ -1044,8 +1044,9 @@ enum libusb_bos_type {
 /** \ingroup misc
  * Error codes. Most libusbx functions return 0 on success or one of these
  * codes on failure.
- * You can call \ref libusb_error_name() to retrieve a string representation
- * of an error code.
+ * You can call libusb_error_name() to retrieve a string representation of an
+ * error code or libusb_strerror() to get an end-user suitable description of
+ * an error code.
  */
 enum libusb_error {
        /** Success (no error) */
@@ -1087,13 +1088,16 @@ enum libusb_error {
        /** Operation not supported or unimplemented on this platform */
        LIBUSB_ERROR_NOT_SUPPORTED = -12,
 
-       /* NB! Remember to update libusb_error_name()
-          when adding new error codes here. */
+       /* NB: Remember to update LIBUSB_ERROR_COUNT below as well as the
+          message strings in strerror.c when adding new error codes here. */
 
        /** Other error */
        LIBUSB_ERROR_OTHER = -99,
 };
 
+/* Total number of error codes in enum libusb_error */
+#define LIBUSB_ERROR_COUNT 14
+
 /** \ingroup asyncio
  * Transfer status codes */
 enum libusb_transfer_status {
@@ -1299,6 +1303,8 @@ void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level);
 const struct libusb_version * LIBUSB_CALL libusb_get_version(void);
 int LIBUSB_CALL libusb_has_capability(uint32_t capability);
 const char * LIBUSB_CALL libusb_error_name(int errcode);
+int LIBUSB_CALL libusb_setlocale(const char *locale);
+const char * LIBUSB_CALL libusb_strerror(enum libusb_error errcode);
 
 ssize_t LIBUSB_CALL libusb_get_device_list(libusb_context *ctx,
        libusb_device ***list);
index eabf33d..d5e5c59 100644 (file)
 /* The following is used to silence warnings for unused variables */
 #define UNUSED(var)                    do { (void)(var); } while(0)
 
+#if !defined(ARRAYSIZE)
+#define ARRAYSIZE(array) (sizeof(array)/sizeof(array[0]))
+#endif
+
 struct list_head {
        struct list_head *prev, *next;
 };
diff --git a/libusb/strerror.c b/libusb/strerror.c
new file mode 100644 (file)
index 0000000..dfb4863
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * libusb strerror code
+ * Copyright © 2013 Hans de Goede <hdegoede@redhat.com>
+ *
+ * This library 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 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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 Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "config.h"
+
+#include <locale.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libusb.h"
+#include "libusbi.h"
+
+#if defined(_MSC_VER)
+#define strncasecmp _strnicmp
+#endif
+
+static int usbi_locale = 0;
+
+/** \ingroup misc
+ * How to add a new \ref libusb_strerror() translation:
+ * <ol>
+ * <li> Download the latest \c strerror.c from:<br>
+ *      https://raw.github.com/libusbx/libusbx/master/libusb/sterror.c </li>
+ * <li> Open the file in an UTF-8 capable editor </li>
+ * <li> Add the 2 letter <a href="http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes">ISO 639-1</a>
+ *      code for your locale at the end of \c usbi_locale_supported[]<br>
+ *    Eg. for Chinese, you would add "zh" so that:
+ *    \code... usbi_locale_supported[] = { "en", "nl", "fr" };\endcode
+ *    becomes:
+ *    \code... usbi_locale_supported[] = { "en", "nl", "fr", "zh" };\endcode </li>
+ * <li> Copy the <tt>{ / * English (en) * / ... }</tt> section and add it at the end of \c usbi_localized_errors<br>
+ *    Eg. for Chinese, the last section of \c usbi_localized_errors could look like:
+ *    \code
+ *     }, { / * Chinese (zh) * /
+ *         "Success",
+ *         ...
+ *         "Other error",
+ *     }
+ * };\endcode </li>
+ * <li> Translate each of the English messages from the section you copied into your language </li>
+ * <li> Save the file (in UTF-8 format) and send it to \c libusbx-devel@lists.sourceforge.net </li>
+ * </ol>
+ */
+
+static const char* usbi_locale_supported[] = { "en", "nl", "fr" };
+static const char* usbi_localized_errors[ARRAYSIZE(usbi_locale_supported)][LIBUSB_ERROR_COUNT] = {
+       { /* English (en) */
+               "Success",
+               "Input/Output Error",
+               "Invalid parameter",
+               "Access denied (insufficient permissions)",
+               "No such device (it may have been disconnected)",
+               "Entity not found",
+               "Resource busy",
+               "Operation timed out",
+               "Overflow",
+               "Pipe error",
+               "System call interrupted (perhaps due to signal)",
+               "Insufficient memory",
+               "Operation not supported or unimplemented on this platform",
+               "Other error",
+       }, { /* Dutch (nl) */
+               "Gelukt",
+               "Invoer-/uitvoerfout",
+               "Ongeldig argument",
+               "Toegang geweigerd (onvoldoende toegangsrechten)",
+               "Apparaat bestaat niet (verbinding met apparaat verbroken?)",
+               "Niet gevonden",
+               "Apparaat of hulpbron is bezig",
+               "Bewerking verlopen",
+               "Waarde is te groot",
+               "Gebroken pijp",
+               "Onderbroken systeemaanroep",
+               "Onvoldoende geheugen beschikbaar",
+               "Bewerking wordt niet ondersteund",
+               "Andere fout",
+       }, { /* French (fr) */
+               "Succès",
+               "Erreur d'entrée/sortie",
+               "Paramètre invalide",
+               "Accès refusé (permissions insuffisantes)",
+               "Périphérique introuvable (peut-être déconnecté)",
+               "Elément introuvable",
+               "Resource déjà occupée",
+               "Operation expirée",
+               "Débordement",
+               "Erreur de pipe",
+               "Appel système abandonné (peut-être à cause d’un signal)",
+               "Mémoire insuffisante",
+               "Opération non supportée or non implémentée sur cette plateforme",
+               "Autre erreur"
+       }
+};
+
+/** \ingroup misc
+ * Set the language, and only the language, not the encoding! used for
+ * translatable libusb messages.
+ *
+ * This takes a locale string in the default setlocale format: lang[-region]
+ * or lang[_country_region][.codeset]. Only the lang part of the string is
+ * used, and only 2 letter ISO 639-1 codes are accepted for it, such as "de".
+ * The optional region, country_region or codeset parts are ignored. This
+ * means that functions which return translatable strings will NOT honor the
+ * specified encoding. 
+ * All strings returned are encoded as UTF-8 strings.
+ *
+ * If libusb_setlocale() is not called, all messages will be in English.
+ *
+ * The following functions return translatable strings: libusb_strerror().
+ * Note that the libusb log messages controlled through libusb_set_debug()
+ * are not translated, they are always in English.
+ *
+ * For POSIX UTF-8 environments if you want libusb to follow the standard
+ * locale settings, call libusb_setlocale(setlocale(LC_MESSAGES, NULL)),
+ * after your app has done its locale setup.
+ *
+ * \param locale locale-string in the form of lang[_country_region][.codeset]
+ * or lang[-region], where lang is a 2 letter ISO 639-1 code
+ * \returns LIBUSB_SUCCESS on success
+ * \returns LIBUSB_ERROR_INVALID_PARAM if the locale doesn't meet the requirements
+ * \returns LIBUSB_ERROR_NOT_FOUND if the requested language is not supported
+ * \returns a LIBUSB_ERROR code on other errors
+ */
+
+int API_EXPORTED libusb_setlocale(const char *locale)
+{
+       int i;
+
+       if ( (locale == NULL) || (strlen(locale) < 2)
+         || ((strlen(locale) > 2) && (locale[2] != '-') && (locale[2] != '_') && (locale[2] != '.')) )
+               return LIBUSB_ERROR_INVALID_PARAM;
+
+       for (i=0; i<ARRAYSIZE(usbi_locale_supported); i++) {
+               if (strncasecmp(usbi_locale_supported[i], locale, 2) == 0)
+                       break;
+       }
+       if (i >= ARRAYSIZE(usbi_locale_supported)) {
+               return LIBUSB_ERROR_NOT_FOUND;
+       }
+
+       usbi_locale = i;
+
+       return LIBUSB_SUCCESS;
+}
+
+/** \ingroup misc
+ * Returns a constant string with a short description of the given error code,
+ * this description is intended for displaying to the end user and will be in
+ * the language set by libusb_setlocale().
+ *
+ * The returned string is encoded in UTF-8.
+ *
+ * The messages always start with a capital letter and end without any dot.
+ * The caller must not free() the returned string.
+ *
+ * \param errcode the error code whose description is desired
+ * \returns a short description of the error code in UTF-8 encoding
+ */
+DEFAULT_VISIBILITY const char* LIBUSB_CALL libusb_strerror(enum libusb_error errcode)
+{
+       int errcode_index = -errcode;
+
+       if ((errcode_index < 0) || (errcode_index >= LIBUSB_ERROR_COUNT)) {
+               /* "Other Error", which should always be our last message, is returned */
+               errcode_index = LIBUSB_ERROR_COUNT - 1;
+       }
+
+       return usbi_localized_errors[usbi_locale][errcode_index];
+}
index 2804c7d..47f4f0d 100644 (file)
@@ -1 +1 @@
-#define LIBUSB_NANO 10728
+#define LIBUSB_NANO 10733
index 9a8f6c3..82e5af5 100644 (file)
                                >
                        </File>
                        <File
+                               RelativePath="..\libusb\strerror.c"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\libusb\sync.c"
                                >
                        </File>
index 7648e57..7b435b2 100644 (file)
     <ClCompile Include="..\libusb\hotplug.c" />
     <ClCompile Include="..\libusb\io.c" />
     <ClCompile Include="..\libusb\os\poll_windows.c" />
+    <ClCompile Include="..\libusb\strerror.c" />
     <ClCompile Include="..\libusb\sync.c" />
     <ClCompile Include="..\libusb\os\threads_windows.c" />
     <ClCompile Include="..\libusb\os\windows_usb.c" />
index 40281f1..cc7d1aa 100644 (file)
@@ -29,6 +29,9 @@
     <ClCompile Include="..\libusb\os\poll_windows.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\libusb\strerror.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="..\libusb\sync.c">
       <Filter>Source Files</Filter>
     </ClCompile>
index 5920895..adcad4a 100644 (file)
     <ClCompile Include="..\libusb\hotplug.c" />
     <ClCompile Include="..\libusb\io.c" />
     <ClCompile Include="..\libusb\os\poll_windows.c" />
+    <ClCompile Include="..\libusb\strerror.c" />
     <ClCompile Include="..\libusb\sync.c" />
     <ClCompile Include="..\libusb\os\threads_windows.c" />
     <ClCompile Include="..\libusb\os\windows_usb.c" />
index fff52f0..ccada70 100644 (file)
@@ -26,6 +26,9 @@
     <ClCompile Include="..\libusb\os\poll_windows.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\libusb\strerror.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="..\libusb\sync.c">
       <Filter>Source Files</Filter>
     </ClCompile>
index 4238a4d..822404c 100644 (file)
                                >
                        </File>
                        <File
+                               RelativePath="..\libusb\strerror.c"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\libusb\sync.c"
                                >
                        </File>
index ca9bed8..308a666 100644 (file)
@@ -29,6 +29,7 @@ TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib
 SOURCES=..\core.c \
        ..\descriptor.c \
        ..\io.c \
+       ..\strerror.c \
        ..\sync.c \
        ..\hotplug.c \
        threads_windows.c \
index 68c9e2c..f7b8e45 100644 (file)
                                >
                        </File>
                        <File
+                               RelativePath="..\libusb\strerror.c"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\libusb\sync.c"
                                >
                        </File>
index 37ee80c..1958d11 100644 (file)
     <ClCompile Include="..\libusb\hotplug.c" />
     <ClCompile Include="..\libusb\io.c" />
     <ClCompile Include="..\libusb\os\poll_windows.c" />
+    <ClCompile Include="..\libusb\strerror.c" />
     <ClCompile Include="..\libusb\sync.c" />
     <ClCompile Include="..\libusb\os\threads_windows.c" />
     <ClCompile Include="..\libusb\os\windows_usb.c" />
index 74a29cd..5cd8060 100644 (file)
@@ -23,6 +23,9 @@
     <ClCompile Include="..\libusb\os\poll_windows.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\libusb\strerror.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="..\libusb\sync.c">
       <Filter>Source Files</Filter>
     </ClCompile>
index 7baa2ae..88605ba 100644 (file)
     <ClCompile Include="..\libusb\hotplug.c" />
     <ClCompile Include="..\libusb\io.c" />
     <ClCompile Include="..\libusb\os\poll_windows.c" />
+    <ClCompile Include="..\libusb\strerror.c" />
     <ClCompile Include="..\libusb\sync.c" />
     <ClCompile Include="..\libusb\os\threads_windows.c" />
     <ClCompile Include="..\libusb\os\windows_usb.c" />
index 74a29cd..5cd8060 100644 (file)
@@ -23,6 +23,9 @@
     <ClCompile Include="..\libusb\os\poll_windows.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\libusb\strerror.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="..\libusb\sync.c">
       <Filter>Source Files</Filter>
     </ClCompile>
index 54fd48d..a595319 100644 (file)
                                >
                        </File>
                        <File
+                               RelativePath="..\libusb\strerror.c"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\libusb\sync.c"
                                >
                        </File>