-
Notifications
You must be signed in to change notification settings - Fork 429
Implement hid_error
#690
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement hid_error
#690
Changes from all commits
1f1d55e
69db339
277cac9
9cc5ac0
ec4d74a
9b6bef5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -123,6 +123,9 @@ struct hid_device_ { | |
#ifdef DETACH_KERNEL_DRIVER | ||
int is_driver_detached; | ||
#endif | ||
|
||
int error; | ||
const char *error_context; | ||
}; | ||
|
||
static struct hid_api_version api_version = { | ||
|
@@ -140,6 +143,8 @@ static hid_device *new_hid_device(void) | |
{ | ||
hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device)); | ||
dev->blocking = 1; | ||
dev->error = LIBUSB_SUCCESS; | ||
dev->error_context = NULL; | ||
|
||
hidapi_thread_state_init(&dev->thread_state); | ||
|
||
|
@@ -340,6 +345,88 @@ static int is_language_supported(libusb_device_handle *dev, uint16_t lang) | |
return 0; | ||
} | ||
|
||
static wchar_t *utf8_to_wchar(char *s) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we already have a similar routine (using iconv) - would be great to have a common implementation if possible |
||
{ | ||
wchar_t *w = NULL; | ||
|
||
/* we don't use iconv on Android, or when it is explicitly disabled */ | ||
#if defined(__ANDROID__) || defined(NO_ICONV) | ||
|
||
w = wcsdup(L"not implemented"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. but we need a fallback implementation anyway |
||
|
||
#else | ||
size_t slen = strlen(s); | ||
wchar_t *wbuf = malloc((slen + 1) * sizeof(wchar_t)); | ||
if (!wbuf) { goto err; } | ||
/* iconv variables */ | ||
iconv_t ic; | ||
size_t inbytes; | ||
size_t outbytes; | ||
size_t res; | ||
char ** restrict inptr; | ||
char *outptr; | ||
/* buf does not need to be explicitly NULL-terminated because | ||
it is only passed into iconv() which does not need it. */ | ||
|
||
/* Initialize iconv. */ | ||
ic = iconv_open("WCHAR_T", "UTF-8"); | ||
if (ic == (iconv_t)-1) { | ||
LOG("iconv_open() failed\n"); | ||
return NULL; | ||
} | ||
|
||
/* Convert to native wchar_t (UTF-32 on glibc/BSD systems). */ | ||
inptr = &s; | ||
inbytes = slen; | ||
outptr = (char*) wbuf; | ||
outbytes = slen * sizeof(wchar_t); | ||
res = iconv(ic, inptr, &inbytes, &outptr, &outbytes); | ||
if (res == (size_t)-1) { | ||
LOG("iconv() failed\n"); | ||
goto err; | ||
} | ||
|
||
/* Write the terminating NULL. */ | ||
wbuf[slen] = 0; | ||
|
||
w = wbuf; | ||
|
||
err: | ||
iconv_close(ic); | ||
|
||
#endif | ||
|
||
return w; | ||
} | ||
|
||
static wchar_t *libusb_error_wchar(int e, const char * (*f)(int)) | ||
{ | ||
const char *cs; | ||
char *s; | ||
wchar_t *w; | ||
|
||
cs = f(e); | ||
s = strdup(cs); | ||
w = utf8_to_wchar(s); | ||
|
||
free(s); | ||
|
||
return w; | ||
} | ||
|
||
static wchar_t *libusb_error_name_wchar(int error) { | ||
return libusb_error_wchar(error, libusb_error_name); | ||
} | ||
|
||
static wchar_t *libusb_strerror_wchar(int error) { | ||
return libusb_error_wchar(error, libusb_strerror); | ||
} | ||
Comment on lines
+417
to
+423
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. doesn't look like it is being used |
||
|
||
static void set_error(hid_device *dev, int error, const char *error_context) | ||
{ | ||
dev->error = error; | ||
dev->error_context = error_context; | ||
} | ||
|
||
/* This function returns a newly allocated wide string containing the USB | ||
device string numbered by the index. The returned string must be freed | ||
|
@@ -1582,8 +1669,31 @@ int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char | |
(unsigned char *)data, length, | ||
1000/*timeout millis*/); | ||
|
||
if (res < 0) | ||
if (res < 0) { | ||
const char *context = NULL; | ||
|
||
switch (res) { | ||
case LIBUSB_ERROR_TIMEOUT: | ||
context = "Transfer timed out"; | ||
break; | ||
case LIBUSB_ERROR_PIPE: | ||
context = "Control request not supported by device"; | ||
break; | ||
case LIBUSB_ERROR_NO_DEVICE: | ||
context = "Device has disconnected"; | ||
break; | ||
case LIBUSB_ERROR_BUSY: | ||
context = "Called from event handling context"; | ||
break; | ||
case LIBUSB_ERROR_INVALID_PARAM: | ||
context = "Transfer size larger than supported"; | ||
break; | ||
} | ||
Comment on lines
+1675
to
+1691
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if these are documented by libusb itself - even stronger reason not to have it here at all |
||
|
||
set_error(dev, res, context); | ||
|
||
return -1; | ||
} | ||
|
||
/* Account for the report ID */ | ||
if (skipped_report_id) | ||
|
@@ -1778,11 +1888,38 @@ int HID_API_EXPORT_CALL hid_get_report_descriptor(hid_device *dev, unsigned char | |
return hid_get_report_descriptor_libusb(dev->device_handle, dev->interface, dev->report_descriptor_size, buf, buf_size); | ||
} | ||
|
||
|
||
HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) | ||
{ | ||
(void)dev; | ||
return L"hid_error is not implemented yet"; | ||
static const char format_simple[] = "%s: %s"; | ||
static const char format_context[] = "%s: %s (%s)"; | ||
const char *name, *message, *context, *format; | ||
char *buffer; | ||
wchar_t *w; | ||
size_t len; | ||
|
||
if (dev->error == LIBUSB_SUCCESS) { | ||
return NULL; | ||
} | ||
|
||
name = libusb_error_name(dev->error); | ||
message = libusb_strerror(dev->error); | ||
context = dev->error_context; | ||
format = context? format_context : format_simple; | ||
|
||
len = 1 + snprintf(NULL, 0, format, name, message, context); | ||
|
||
buffer = malloc(len); | ||
if (!buffer) { | ||
return NULL; | ||
} | ||
|
||
snprintf(buffer, len, format, name, message, context); | ||
|
||
w = utf8_to_wchar(buffer); | ||
|
||
free(buffer); | ||
|
||
return w; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. and this is a memory leak - by the documentation what is returned by hid_error - is owned by HIDAPI |
||
} | ||
|
||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.