Skip to content

Commit e8243e1

Browse files
authored
libusb: make hid.c compile cleanly as C++ (#811)
libusb/hid.c relied on three C-only patterns that produce errors when the file is built with a C++ compiler (as reported in #671): - void* from malloc/calloc/pthread-style params implicitly assigned to typed pointers (6 sites); - int libusb return codes implicitly stored in `enum libusb_error` struct fields and passed to a function taking `enum libusb_error` (13 sites); - `#define _GNU_SOURCE` without an #ifndef guard, which produces a "redefined" warning when the macro is also supplied via -D. Fix: - Guard _GNU_SOURCE with #ifndef. - Change `hidapi_error_ctx`'s error_code / last_error_code_cache fields and `register_libusb_error()`'s error parameter from `enum libusb_error` to plain int. The struct is internal, the values stored are already a mix of libusb_error codes and a `1` sentinel used by register_string_error(), and int removes the 13 call-site conversions in one go. - Add explicit casts on the 6 malloc/calloc/void* sites, matching the convention already used in windows/hid.c and mac/hid.c. - Drop a now-redundant `(enum libusb_error)` cast. After this, `g++ -xc++ -Wall -Wextra -c libusb/hid.c` and the equivalent gcc invocation both build cleanly, and the full CMake build of the libusb backend (including hidtest_libusb) links unchanged. Closes: #671 Assisted-by: Claude:claude-opus-4.7
1 parent 5bec589 commit e8243e1

1 file changed

Lines changed: 17 additions & 10 deletions

File tree

libusb/hid.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
https://github.com/libusb/hidapi .
2121
********************************************************/
2222

23+
#ifndef _GNU_SOURCE
2324
#define _GNU_SOURCE /* needed for wcsdup() before glibc 2.10 */
25+
#endif
2426

2527
/* C */
2628
#include <stdio.h>
@@ -86,11 +88,16 @@ struct input_report {
8688

8789

8890
typedef struct hidapi_error_ctx_ {
89-
enum libusb_error error_code;
91+
/* libusb error code (negative LIBUSB_ERROR_* values or LIBUSB_SUCCESS),
92+
* or a sentinel non-zero value when set via register_string_error().
93+
* Stored as plain int so call sites can pass libusb return values
94+
* (which are typed as int) without an explicit cast — that keeps
95+
* libusb/hid.c compilable as C++ as well as C. */
96+
int error_code;
9097
/* designed to hold string literals only - do not free */
9198
const char *error_context;
9299

93-
enum libusb_error last_error_code_cache;
100+
int last_error_code_cache;
94101
const char *last_error_context_cache;
95102
/* dynamically allocated */
96103
wchar_t *last_error_str;
@@ -334,7 +341,7 @@ static wchar_t *ctowcdup(const char *s, size_t slen)
334341
}
335342

336343

337-
static void register_libusb_error(hidapi_error_ctx *err, enum libusb_error error, const char *error_context)
344+
static void register_libusb_error(hidapi_error_ctx *err, int error, const char *error_context)
338345
{
339346
err->error_code = error;
340347
err->error_context = error_context;
@@ -382,7 +389,7 @@ static wchar_t *utf_to_wchar(char *utf, size_t utfbytes, const char *fromcode, s
382389
}
383390

384391
wbuf_size = (max_expected_wchar + 1) * sizeof(wchar_t);
385-
wbuf = malloc(wbuf_size);
392+
wbuf = (wchar_t *) malloc(wbuf_size);
386393
if (!wbuf) {
387394
goto end;
388395
}
@@ -719,7 +726,7 @@ static void invasive_fill_device_info_usage(struct hid_device_info *cur_dev, lib
719726
static struct hid_device_info * create_device_info_for_device(libusb_device *device, libusb_device_handle *handle, struct libusb_device_descriptor *desc, int config_number, int interface_num)
720727
{
721728
int res = 0;
722-
struct hid_device_info *cur_dev = calloc(1, sizeof(struct hid_device_info));
729+
struct hid_device_info *cur_dev = (struct hid_device_info *) calloc(1, sizeof(struct hid_device_info));
723730
if (cur_dev == NULL) {
724731
return NULL;
725732
}
@@ -923,7 +930,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
923930

924931
num_devs = libusb_get_device_list(usb_context, &devs);
925932
if (num_devs < 0) {
926-
register_libusb_error(&last_global_error, (enum libusb_error)num_devs, "libusb_get_device_list");
933+
register_libusb_error(&last_global_error, num_devs, "libusb_get_device_list");
927934
return NULL;
928935
}
929936
while ((dev = devs[i++]) != NULL) {
@@ -1091,7 +1098,7 @@ hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const
10911098

10921099
static void LIBUSB_CALL read_callback(struct libusb_transfer *transfer)
10931100
{
1094-
hid_device *dev = transfer->user_data;
1101+
hid_device *dev = (hid_device *) transfer->user_data;
10951102
int res;
10961103

10971104
if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {
@@ -1160,7 +1167,7 @@ static void LIBUSB_CALL read_callback(struct libusb_transfer *transfer)
11601167
static void *read_thread(void *param)
11611168
{
11621169
int res;
1163-
hid_device *dev = param;
1170+
hid_device *dev = (hid_device *) param;
11641171
uint8_t *buf;
11651172
const size_t length = dev->input_ep_max_packet_size;
11661173

@@ -1636,7 +1643,7 @@ static int return_data(hid_device *dev, unsigned char *data, size_t length)
16361643

16371644
static void cleanup_mutex(void *param)
16381645
{
1639-
hid_device *dev = param;
1646+
hid_device *dev = (hid_device *) param;
16401647
hidapi_thread_mutex_unlock(&dev->thread_state);
16411648
}
16421649

@@ -2100,7 +2107,7 @@ HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev)
21002107
return L"Error string format error";
21012108
}
21022109

2103-
buffer = malloc((size_t)len + 1); /* +1 for terminating NULL */
2110+
buffer = (char *) malloc((size_t)len + 1); /* +1 for terminating NULL */
21042111
if (!buffer) {
21052112
return L"Error string memory allocation error";
21062113
}

0 commit comments

Comments
 (0)