diff --git a/lib/libusb/libusb.h b/lib/libusb/libusb.h --- a/lib/libusb/libusb.h +++ b/lib/libusb/libusb.h @@ -210,6 +210,8 @@ LIBUSB_ERROR_OTHER = -99, }; +#define LIBUSB_ERROR_COUNT 14 + enum libusb_speed { LIBUSB_SPEED_UNKNOWN = 0, LIBUSB_SPEED_LOW = 1, @@ -482,7 +484,8 @@ int libusb_init(libusb_context ** context); int libusb_init_context(libusb_context **, const struct libusb_init_option [], int num_options); void libusb_exit(struct libusb_context *ctx); -int libusb_has_capability(uint32_t capability); +int libusb_has_capability(uint32_t capability); +int libusb_setlocale(const char *locale); /* Device handling and enumeration */ diff --git a/lib/libusb/libusb10.h b/lib/libusb/libusb10.h --- a/lib/libusb/libusb10.h +++ b/lib/libusb/libusb10.h @@ -150,6 +150,12 @@ struct libusb20_device *os_priv; }; +struct libusb_language_context { + const char *lang_name; + const char + *err_strs[LIBUSB_ERROR_COUNT + 1]; /* All error Plus 1 UNKNOWN */ +}; + extern struct libusb_context *usbi_default_context; void libusb10_add_pollfd(libusb_context *ctx, struct libusb_super_pollfd *pollfd, struct libusb20_device *pdev, int fd, short events); diff --git a/lib/libusb/libusb10.c b/lib/libusb/libusb10.c --- a/lib/libusb/libusb10.c +++ b/lib/libusb/libusb10.c @@ -29,6 +29,8 @@ #ifdef LIBUSB_GLOBAL_INCLUDE_FILE #include LIBUSB_GLOBAL_INCLUDE_FILE #else + +#include #include #include #include @@ -81,6 +83,48 @@ .describe = "https://www.freebsd.org" }; +static const struct libusb_language_context libusb_language_ctx[] = { + { + .lang_name = "en", + .err_strs = { "Success", "I/O error", + "Invalid parameter", + "Permissions error", + "No device", + "Not found", + "Device busy", + "Timeout", + "Overflow", + "Pipe error", + "Interrupted", + "Out of memory", + "Not supported", + "Other error", + "Unknown error", + } + }, + { + .lang_name = "zh", + .err_strs = { "成功", "I/O 錯誤", + "不合法的參數", + "權限錯誤", + "找不到設備", + "找不到", + "設備忙碌中", + "超時", + "溢位", + "管線錯誤", + "被中斷", + "記憶體不足", + "不支援", + "其他錯誤", + "未知錯誤", + } + }, +}; + +static const struct libusb_language_context *default_language_context = + &libusb_language_ctx[0]; + const struct libusb_version * libusb_get_version(void) { @@ -1696,38 +1740,20 @@ const char * libusb_strerror(int code) { - switch (code) { - case LIBUSB_SUCCESS: - return ("Success"); - case LIBUSB_ERROR_IO: - return ("I/O error"); - case LIBUSB_ERROR_INVALID_PARAM: - return ("Invalid parameter"); - case LIBUSB_ERROR_ACCESS: - return ("Permissions error"); - case LIBUSB_ERROR_NO_DEVICE: - return ("No device"); - case LIBUSB_ERROR_NOT_FOUND: - return ("Not found"); - case LIBUSB_ERROR_BUSY: - return ("Device busy"); - case LIBUSB_ERROR_TIMEOUT: - return ("Timeout"); - case LIBUSB_ERROR_OVERFLOW: - return ("Overflow"); - case LIBUSB_ERROR_PIPE: - return ("Pipe error"); - case LIBUSB_ERROR_INTERRUPTED: - return ("Interrupted"); - case LIBUSB_ERROR_NO_MEM: - return ("Out of memory"); - case LIBUSB_ERROR_NOT_SUPPORTED: - return ("Not supported"); - case LIBUSB_ERROR_OTHER: - return ("Other error"); - default: - return ("Unknown error"); - } + int entry = -code; + + /* + * The libusb upstream consider all code out of range a + * LIBUSB_ERROR_OTHER. In FreeBSD, it is a special unknown error. We + * preserve the FreeBSD implementation as I think it make sense. + */ + if (entry < 0 || entry >= LIBUSB_ERROR_COUNT) + return (default_language_context->err_strs[LIBUSB_ERROR_COUNT]); + + if (code == LIBUSB_ERROR_OTHER) + entry = 13; + + return default_language_context->err_strs[entry]; } const char * @@ -1781,3 +1807,30 @@ return (0); } } + +int +libusb_setlocale(const char *locale) +{ + int idx; + const char *lang; + const int nitems = sizeof(libusb_language_ctx) / + sizeof(*libusb_language_ctx); + + if (locale == NULL || strlen(locale) < 2 || + (locale[2] != '\0' && (*strchr("-_.", locale[2]) == 0))) + return (LIBUSB_ERROR_INVALID_PARAM); + + for (idx = 0; idx < nitems; ++idx) { + lang = libusb_language_ctx[idx].lang_name; + if (tolower(locale[0]) == lang[0] && + tolower(locale[1]) == lang[1]) + break; + } + + if (idx == nitems) + return (LIBUSB_ERROR_INVALID_PARAM); + + default_language_context = &libusb_language_ctx[idx]; + + return (LIBUSB_SUCCESS); +}