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])
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;
}
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) {
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);
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;
}
}
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;
}
}
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);
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;
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);
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;
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) {
}
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");
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;
}
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);
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
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
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
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
/** \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) */
/** 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 {
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);
/* 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;
};
--- /dev/null
+/*
+ * 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];
+}
-#define LIBUSB_NANO 10728
+#define LIBUSB_NANO 10733
>
</File>
<File
+ RelativePath="..\libusb\strerror.c"
+ >
+ </File>
+ <File
RelativePath="..\libusb\sync.c"
>
</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" />
<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>
<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" />
<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>
>
</File>
<File
+ RelativePath="..\libusb\strerror.c"
+ >
+ </File>
+ <File
RelativePath="..\libusb\sync.c"
>
</File>
SOURCES=..\core.c \
..\descriptor.c \
..\io.c \
+ ..\strerror.c \
..\sync.c \
..\hotplug.c \
threads_windows.c \
>
</File>
<File
+ RelativePath="..\libusb\strerror.c"
+ >
+ </File>
+ <File
RelativePath="..\libusb\sync.c"
>
</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" />
<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>
<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" />
<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>
>
</File>
<File
+ RelativePath="..\libusb\strerror.c"
+ >
+ </File>
+ <File
RelativePath="..\libusb\sync.c"
>
</File>