From 3f8d588d253288f05e1e48a0f4033a98e103f4cf Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 19 Dec 2021 16:38:04 +0100 Subject: [PATCH] drivers (c,h) USB, HID and SHUT: converge parameter usage from strict int types to backend API dependent "usb_ctrl_*" and "usb_dev_handle" typedefs, then range-check and cast the numbers, and avoid build warnings --- drivers/hidparser.c | 28 ++- drivers/hidparser.h | 11 +- drivers/libhid.c | 213 +++++++++++++++++++++-- drivers/libhid.h | 2 +- drivers/libshut.c | 358 ++++++++++++++++++++++++++++++++------ drivers/libshut.h | 92 ++++++++-- drivers/libusb0.c | 146 ++++++++++++---- drivers/libusb1.c | 183 ++++++++++++++++--- drivers/nut_libusb.h | 15 +- drivers/nutdrv_atcl_usb.c | 16 +- drivers/richcomm_usb.c | 16 +- drivers/riello_usb.c | 2 +- drivers/tripplite_usb.c | 13 +- drivers/usb-common.h | 82 +++++++++ drivers/usbhid-ups.c | 15 +- 15 files changed, 1018 insertions(+), 174 deletions(-) diff --git a/drivers/hidparser.c b/drivers/hidparser.c index d172da03c4..f348d9f98e 100644 --- a/drivers/hidparser.c +++ b/drivers/hidparser.c @@ -35,6 +35,9 @@ static const uint8_t ItemSize[4] = { 0, 1, 2, 4 }; /* * HIDParser struct * -------------------------------------------------------------------------- */ +/* FIXME? Should this structure remain with reasonable fixed int types, + * or changed to align with libusb API version and usb_ctrl_* typedefs? + */ typedef struct { const unsigned char *ReportDesc; /* Report Descriptor */ size_t ReportDescSize; /* Size of Report Descriptor */ @@ -547,14 +550,31 @@ void SetValue(const HIDData_t *pData, unsigned char *Buf, long Value) Output: parsed data structure. Returns allocated HIDDesc structure on success, NULL on failure with errno set. Note: the value returned by this function must be freed with Free_ReportDesc(). */ -HIDDesc_t *Parse_ReportDesc(const unsigned char *ReportDesc, const size_t n) +HIDDesc_t *Parse_ReportDesc(const usb_ctrl_charbuf ReportDesc, const usb_ctrl_charbufsize n) { int ret = 0; HIDDesc_t *pDesc; HIDParser_t *parser; pDesc = calloc(1, sizeof(*pDesc)); - if (!pDesc) { + if (!pDesc +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE) ) +# pragma GCC diagnostic push +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS +# pragma GCC diagnostic ignored "-Wtype-limits" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE +# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE +# pragma GCC diagnostic ignored "-Wtautological-unsigned-zero-compare" +#endif + || n < 0 || (uintmax_t)n > SIZE_MAX +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE) ) +# pragma GCC diagnostic pop +#endif + ) { return NULL; } @@ -570,8 +590,8 @@ HIDDesc_t *Parse_ReportDesc(const unsigned char *ReportDesc, const size_t n) return NULL; } - parser->ReportDesc = ReportDesc; - parser->ReportDescSize = n; + parser->ReportDesc = (const unsigned char *)ReportDesc; + parser->ReportDescSize = (const size_t)n; for (pDesc->nitems = 0; pDesc->nitems < MAX_REPORT; pDesc->nitems += (size_t)ret) { uint8_t id; diff --git a/drivers/hidparser.h b/drivers/hidparser.h index 06849d9de5..64c7aab800 100644 --- a/drivers/hidparser.h +++ b/drivers/hidparser.h @@ -35,10 +35,19 @@ extern "C" { #include "config.h" #include "hidtypes.h" +/* Include "usb-common.h" or "libshut.h" as appropriate, to define the + * usb_ctrl_* types used below according to the backend USB API version + */ +#ifdef SHUT_MODE +# include "libshut.h" +#else +# include "usb-common.h" +#endif + /* * Parse_ReportDesc * -------------------------------------------------------------------------- */ -HIDDesc_t *Parse_ReportDesc(const unsigned char *ReportDesc, const size_t n); +HIDDesc_t *Parse_ReportDesc(const usb_ctrl_charbuf ReportDesc, const usb_ctrl_charbufsize n); /* * Free_ReportDesc diff --git a/drivers/libhid.c b/drivers/libhid.c index e25df048aa..0002fb222d 100644 --- a/drivers/libhid.c +++ b/drivers/libhid.c @@ -63,6 +63,9 @@ size_t max_report_size = 0; int interrupt_only = 0; size_t interrupt_size = 0; +#define SMIN(a, b) ( ((intmax_t)(a) < (intmax_t)(b)) ? (a) : (b) ) +#define UMIN(a, b) ( ((uintmax_t)(a) < (uintmax_t)(b)) ? (a) : (b) ) + /* ---------------------------------------------------------------------- */ /* report buffering system */ @@ -150,7 +153,7 @@ reportbuf_t *new_report_buffer(HIDDesc_t *arg_pDesc) depending on the max_report_size flag */ static int refresh_report_buffer(reportbuf_t *rbuf, hid_dev_handle_t udev, HIDData_t *pData, time_t age) { - int id = pData->ReportID; + usb_ctrl_repindex id = pData->ReportID; int ret; size_t r; @@ -160,8 +163,50 @@ static int refresh_report_buffer(reportbuf_t *rbuf, hid_dev_handle_t udev, HIDDa return 0; } - ret = comm_driver->get_report(udev, id, rbuf->data[id], - max_report_size ? sizeof(rbuf->data[id]) : rbuf->len[id]); + r = max_report_size ? sizeof(rbuf->data[id]) : rbuf->len[id]; +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE) ) +# pragma GCC diagnostic push +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS +# pragma GCC diagnostic ignored "-Wtype-limits" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE +# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE +# pragma GCC diagnostic ignored "-Wtautological-unsigned-zero-compare" +#endif + if ((uintmax_t)r > (uintmax_t)USB_CTRL_CHARBUFSIZE_MAX) { + upsdebugx(2, + "%s: suggested buffer size %zu exceeds " + "USB_CTRL_CHARBUFSIZE_MAX %ju; " + "report will be constrained", + __func__, r, (uintmax_t)USB_CTRL_CHARBUFSIZE_MAX); + if ((uintmax_t)USB_CTRL_CHARBUFSIZE_MAX <= (uintmax_t)SIZE_MAX + && USB_CTRL_CHARBUFSIZE_MAX > 0) { + r = (size_t)USB_CTRL_CHARBUFSIZE_MAX - 1; + } else { + /* SIZE_MAX is obviously too much here; least common + * denominator across libs can be UINT8 or UINT16. + * We should never hit this codepath unless definition + * above is bonkers, anyway. + */ + r = (size_t)UINT8_MAX - 1; + } + + /* Avoid overflowing known buffer size, to be sure: */ + r = UMIN(r, sizeof(rbuf->data[id])); + if (!max_report_size) { + r = UMIN(r, rbuf->len[id]); + } + } +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE) ) +# pragma GCC diagnostic pop +#endif + + ret = comm_driver->get_report(udev, id, + (usb_ctrl_charbuf)rbuf->data[id], + (usb_ctrl_charbufsize)r); if (ret <= 0) { return -1; @@ -169,12 +214,15 @@ static int refresh_report_buffer(reportbuf_t *rbuf, hid_dev_handle_t udev, HIDDa r = (size_t)ret; if (rbuf->len[id] != r) { + /* e.g. if maxreportsize flag was set */ upsdebugx(2, "%s: expected %zu bytes, but got %zu instead", __func__, rbuf->len[id], r); - upsdebug_hex(3, "Report[err]", rbuf->data[id], r); + upsdebug_hex(3, "Report[err]", + (usb_ctrl_charbuf)rbuf->data[id], r); } else { - upsdebug_hex(3, "Report[get]", rbuf->data[id], rbuf->len[id]); + upsdebug_hex(3, "Report[get]", + (usb_ctrl_charbuf)rbuf->data[id], rbuf->len[id]); } /* have (valid) report */ @@ -207,17 +255,54 @@ static int get_item_buffered(reportbuf_t *rbuf, hid_dev_handle_t udev, HIDData_t -1 and set errno. The updated value is sent to the device. */ static int set_item_buffered(reportbuf_t *rbuf, hid_dev_handle_t udev, HIDData_t *pData, long Value) { - int id = pData->ReportID; - int r; + usb_ctrl_repindex id = pData->ReportID; + int ret; + size_t r = rbuf->len[id]; SetValue(pData, rbuf->data[id], Value); - r = comm_driver->set_report(udev, id, rbuf->data[id], rbuf->len[id]); - if (r <= 0) { +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE) ) +# pragma GCC diagnostic push +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS +# pragma GCC diagnostic ignored "-Wtype-limits" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE +# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE +# pragma GCC diagnostic ignored "-Wtautological-unsigned-zero-compare" +#endif + if ((uintmax_t)r > (uintmax_t)USB_CTRL_CHARBUFSIZE_MAX) { + upsdebugx(2, + "%s: suggested buffer size %zu exceeds " + "USB_CTRL_CHARBUFSIZE_MAX %ju; " + "item setting will be constrained", + __func__, r, (uintmax_t)USB_CTRL_CHARBUFSIZE_MAX); + if ((uintmax_t)USB_CTRL_CHARBUFSIZE_MAX <= (uintmax_t)SIZE_MAX + && USB_CTRL_CHARBUFSIZE_MAX > 0) { + r = (size_t)USB_CTRL_CHARBUFSIZE_MAX - 1; + } else { + /* SIZE_MAX is obviously too much here; least common + * denominator across libs can be UINT8 or UINT16. + * We should never hit this codepath unless definition + * above is bonkers, anyway. + */ + r = (size_t)UINT8_MAX - 1; + } + } +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE) ) +# pragma GCC diagnostic pop +#endif + + ret = comm_driver->set_report(udev, id, + (usb_ctrl_charbuf)rbuf->data[id], + (usb_ctrl_charbufsize)r); + if (ret <= 0) { return -1; } - upsdebug_hex(3, "Report[set]", rbuf->data[id], rbuf->len[id]); + upsdebug_hex(3, "Report[set]", rbuf->data[id], r); /* expire report */ rbuf->ts[id] = 0; @@ -423,7 +508,59 @@ int HIDGetItemValue(hid_dev_handle_t udev, const char *hidpath, double *Value, u */ char *HIDGetIndexString(hid_dev_handle_t udev, const int Index, char *buf, size_t buflen) { - if (comm_driver->get_string(udev, Index, buf, buflen) < 1) + usb_ctrl_strindex idx; + +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE) ) +# pragma GCC diagnostic push +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS +# pragma GCC diagnostic ignored "-Wtype-limits" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE +# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE +# pragma GCC diagnostic ignored "-Wtautological-unsigned-zero-compare" +#endif + if ((uintmax_t)Index > (uintmax_t)USB_CTRL_STRINDEX_MAX + || (intmax_t)Index < (intmax_t)USB_CTRL_STRINDEX_MIN + ) { + upsdebugx(2, + "%s: requested index number is out of range, " + "expected %jd < %i < %ju", + __func__, + (intmax_t)USB_CTRL_STRINDEX_MIN, + Index, + (uintmax_t)USB_CTRL_STRINDEX_MAX); + return NULL; + } + idx = (usb_ctrl_strindex)Index; + + if ((uintmax_t)buflen > (uintmax_t)USB_CTRL_CHARBUFSIZE_MAX) { + upsdebugx(2, + "%s: suggested buffer size %zu exceeds " + "USB_CTRL_CHARBUFSIZE_MAX %ju; " + "index string will be constrained", + __func__, buflen, + (uintmax_t)USB_CTRL_CHARBUFSIZE_MAX); + + if ((uintmax_t)USB_CTRL_CHARBUFSIZE_MAX <= (uintmax_t)SIZE_MAX + && USB_CTRL_CHARBUFSIZE_MAX > 0) { + buflen = (size_t)USB_CTRL_CHARBUFSIZE_MAX - 1; + } else { + /* SIZE_MAX is obviously too much here; least common + * denominator across libs can be UINT8 or UINT16. + * We should never hit this codepath unless definition + * above is bonkers, anyway. + */ + buflen = (size_t)UINT8_MAX - 1; + } + } +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE) ) +# pragma GCC diagnostic pop +#endif + + if (comm_driver->get_string(udev, idx, buf, (usb_ctrl_charbufsize)buflen) < 1) buf[0] = '\0'; return str_rtrim(buf, '\n'); @@ -496,18 +633,62 @@ int HIDGetEvents(hid_dev_handle_t udev, HIDData_t **event, int eventsize) { unsigned char buf[SMALLBUF]; int itemCount = 0; - int buflen, r; - size_t i; + int buflen, ret; + size_t i, r; HIDData_t *pData; /* needs libusb-0.1.8 to work => use ifdef and autoconf */ - buflen = comm_driver->get_interrupt(udev, buf, interrupt_size ? interrupt_size : sizeof(buf), 750); + r = interrupt_size ? interrupt_size : sizeof(buf); +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE) ) +# pragma GCC diagnostic push +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS +# pragma GCC diagnostic ignored "-Wtype-limits" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE +# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE +# pragma GCC diagnostic ignored "-Wtautological-unsigned-zero-compare" +#endif + if ((uintmax_t)r > (uintmax_t)USB_CTRL_CHARBUFSIZE_MAX) { + /* FIXME: Should we try here, or plain abort? */ + upsdebugx(2, + "%s: suggested buffer size %zu exceeds " + "USB_CTRL_CHARBUFSIZE_MAX %ju; " + "report will be constrained", + __func__, r, (uintmax_t)USB_CTRL_CHARBUFSIZE_MAX); + + if ((uintmax_t)USB_CTRL_CHARBUFSIZE_MAX <= (uintmax_t)SIZE_MAX + && USB_CTRL_CHARBUFSIZE_MAX > 0) { + r = (size_t)USB_CTRL_CHARBUFSIZE_MAX - 1; + } else { + /* SIZE_MAX is obviously too much here; least common + * denominator across libs can be UINT8 or UINT16. + * We should never hit this codepath unless definition + * above is bonkers, anyway. + */ + r = (size_t)UINT8_MAX - 1; + } + + /* Avoid overflowing known buffer size, to be sure: */ + r = UMIN(r, sizeof(buf)); + } +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE) ) +# pragma GCC diagnostic pop +#endif + + buflen = comm_driver->get_interrupt( + udev, (usb_ctrl_charbuf)buf, + (usb_ctrl_charbufsize)r, + 750); + if (buflen <= 0) { return buflen; /* propagate "error" or "no event" code */ } - r = file_report_buffer(reportbuf, buf, (size_t)buflen); - if (r < 0) { + ret = file_report_buffer(reportbuf, buf, (size_t)buflen); + if (ret < 0) { upsdebug_with_errno(1, "%s: failed to buffer report", __func__); return -errno; } diff --git a/drivers/libhid.h b/drivers/libhid.h index 24da2f75f3..d422002b6a 100644 --- a/drivers/libhid.h +++ b/drivers/libhid.h @@ -40,7 +40,7 @@ #include "libshut.h" typedef SHUTDevice_t HIDDevice_t; typedef char HIDDeviceMatcher_t; - typedef int hid_dev_handle_t; + typedef usb_dev_handle hid_dev_handle_t; typedef shut_communication_subdriver_t communication_subdriver_t; #else #include "nut_libusb.h" /* includes usb-common.h */ diff --git a/drivers/libshut.c b/drivers/libshut.c index 3d6567fe76..be7d61d58b 100644 --- a/drivers/libshut.c +++ b/drivers/libshut.c @@ -180,16 +180,51 @@ struct my_hid_descriptor { /*! * SHUT functions for HID marshalling */ -static int shut_get_descriptor(int upsfd, unsigned char type, - unsigned char index, void *buf, int size); -static int shut_get_string_simple(int upsfd, int index, - char *buf, size_t buflen); -static int libshut_get_report(int upsfd, int ReportId, - unsigned char *raw_buf, int ReportSize ); -static int libshut_set_report(int upsfd, int id, unsigned char *pkt, int reportlen); -static int libshut_get_interrupt(int upsfd, unsigned char *buf, - int bufsize, int timeout); -static void libshut_close(int upsfd); +/* Expected evaluated types for the API after typedefs: + * static int shut_get_descriptor(int upsfd, unsigned char type, + * unsigned char index, void *buf, int size); + * static int shut_get_string_simple(int upsfd, int index, + * char *buf, size_t buflen); + * static int libshut_get_report(int upsfd, int ReportId, + * unsigned char *raw_buf, int ReportSize ); + * static int libshut_set_report(int upsfd, int id, unsigned char *pkt, + * int reportlen); + * static int libshut_get_interrupt(int upsfd, unsigned char *buf, + * int bufsize, int timeout); + * static void libshut_close(int upsfd); + */ +static int shut_get_descriptor( + usb_dev_handle upsfd, + usb_ctrl_requesttype type, + usb_ctrl_descindex index, + void *buf, + usb_ctrl_charbufsize size); + +static int shut_get_string_simple( + usb_dev_handle upsfd, + usb_ctrl_strindex index, + char *buf, + usb_ctrl_charbufsize buflen); + +static int libshut_get_report( + usb_dev_handle upsfd, + usb_ctrl_repindex ReportId, + usb_ctrl_charbuf raw_buf, + usb_ctrl_charbufsize ReportSize); + +static int libshut_set_report( + usb_dev_handle upsfd, + usb_ctrl_repindex id, + usb_ctrl_charbuf pkt, + usb_ctrl_charbufsize reportlen); + +static int libshut_get_interrupt( + usb_dev_handle upsfd, + usb_ctrl_charbuf buf, + usb_ctrl_charbufsize bufsize, + usb_ctrl_timeout_msec timeout); + +static void libshut_close(usb_dev_handle upsfd); /* FIXME */ static const char * shut_strerror(void) { return ""; } @@ -261,6 +296,7 @@ typedef union device_desc_data_t { #endif /* Low level SHUT (Serial HID UPS Transfer) routines */ +/* Expected evaluated types for the API after typedefs: static void setline(int upsfd, int set); static int shut_synchronise(int upsfd); static int shut_wait_ack(int upsfd); @@ -268,6 +304,31 @@ static int shut_interrupt_read(int upsfd, int ep, unsigned char *bytes, int size, int timeout); static int shut_control_msg(int upsfd, int requesttype, int request, int value, int index, unsigned char *bytes, int size, int timeout); + */ +static void setline( + usb_dev_handle upsfd, + int set); + +static int shut_synchronise(usb_dev_handle upsfd); + +static int shut_wait_ack(usb_dev_handle upsfd); + +static int shut_interrupt_read( + usb_dev_handle upsfd, + usb_ctrl_endpoint ep, + usb_ctrl_charbuf bytes, + usb_ctrl_charbufsize size, + usb_ctrl_timeout_msec timeout); + +static int shut_control_msg( + usb_dev_handle upsfd, + usb_ctrl_requesttype requesttype, + usb_ctrl_request request, + usb_ctrl_msgvalue value, + usb_ctrl_repindex index, + usb_ctrl_charbuf bytes, + usb_ctrl_charbufsize size, + usb_ctrl_timeout_msec timeout); /* Data portability */ /* realign packet data according to Endianess */ @@ -284,6 +345,12 @@ static void align_request(struct shut_ctrltransfer_s *ctrl) #endif } +#if (!defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_INSIDEFUNC) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS_BESIDEFUNC) +# pragma GCC diagnostic ignored "-Wtype-limits" +#endif +#if (!defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_INSIDEFUNC) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE_BESIDEFUNC) +# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare" +#endif /* On success, fill in the curDevice structure and return the report * descriptor length. On failure, return -1. * Note: When callback is not NULL, the report descriptor will be @@ -291,9 +358,17 @@ static void align_request(struct shut_ctrltransfer_s *ctrl) * information. This callback should return a value > 0 if the device * is accepted, or < 1 if not. */ -static int libshut_open(int *arg_upsfd, SHUTDevice_t *curDevice, char *arg_device_path, - int (*callback)(int arg_upsfd, SHUTDevice_t *hd, - unsigned char *rdbuf, int rdlen)) +/* Expected evaluated types for the API after typedefs: + * static int libshut_open(int *arg_upsfd, SHUTDevice_t *curDevice, char *arg_device_path, + * int (*callback)(int arg_upsfd, SHUTDevice_t *hd, + * unsigned char *rdbuf, int rdlen)) + */ +static int libshut_open( + usb_dev_handle *arg_upsfd, + SHUTDevice_t *curDevice, + char *arg_device_path, + int (*callback)(usb_dev_handle arg_upsfd, SHUTDevice_t *hd, + usb_ctrl_charbuf rdbuf, usb_ctrl_charbufsize rdlen)) { int ret, res; /* Below we cast this buffer as sometimes containing entried of type @@ -301,18 +376,18 @@ static int libshut_open(int *arg_upsfd, SHUTDevice_t *curDevice, char *arg_devic * Currently both of these are sized "2", and I don't see a way * to require a "max()" of such sizes to align for generally. */ - unsigned char buf[20] __attribute__((aligned(4))); + usb_ctrl_char buf[20] __attribute__((aligned(4))); char string[MAX_STRING_SIZE]; struct my_hid_descriptor *desc; struct device_descriptor_s *dev_descriptor; /* report descriptor */ - unsigned char rdbuf[MAX_REPORT_SIZE]; - int rdlen; + usb_ctrl_char rdbuf[MAX_REPORT_SIZE]; + usb_ctrl_charbufsize rdlen; /* All devices use HID descriptor at index 0. However, some newer * Eaton units have a light HID descriptor at index 0, and the full * version is at index 1 (in which case, bcdDevice == 0x0202) */ - int hid_desc_index = 0; + usb_ctrl_descindex hid_desc_index = 0; upsdebugx(2, "libshut_open: using port %s", arg_device_path); @@ -454,8 +529,32 @@ static int libshut_open(int *arg_upsfd, SHUTDevice_t *curDevice, char *arg_devic rdlen = desc->wDescriptorLength; - if (rdlen > (int)sizeof(rdbuf)) { - upsdebugx(2, "HID descriptor too long %d (max %d)", rdlen, (int)sizeof(rdbuf)); +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) ) +# pragma GCC diagnostic push +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS +# pragma GCC diagnostic ignored "-Wtype-limits" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE +# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare" +#endif +/* Older CLANG (e.g. clang-3.4) seems to not support the GCC pragmas above */ +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wtautological-compare" +#pragma clang diagnostic ignored "-Wtautological-constant-out-of-range-compare" +#endif + if (rdlen > sizeof(rdbuf) || rdlen > INT_MAX) { +#ifdef __clang__ +#pragma clang diagnostic pop +#endif +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) ) +# pragma GCC diagnostic pop +#endif + upsdebugx(2, + "HID descriptor too long %" PRI_NUT_USB_CTRL_CHARBUFSIZE + " (max %zu)", + rdlen, sizeof(rdbuf)); return -1; } @@ -464,7 +563,28 @@ static int libshut_open(int *arg_upsfd, SHUTDevice_t *curDevice, char *arg_devic /* res = shut_control_msg(devp, USB_ENDPOINT_IN+1, USB_REQ_GET_DESCRIPTOR, (USB_DT_REPORT << 8) + 0, 0, ReportDesc, desc->wDescriptorLength, SHUT_TIMEOUT); */ - if (res == rdlen) +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) ) +# pragma GCC diagnostic push +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS +# pragma GCC diagnostic ignored "-Wtype-limits" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE +# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare" +#endif +/* Older CLANG (e.g. clang-3.4) seems to not support the GCC pragmas above */ +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wtautological-compare" +#pragma clang diagnostic ignored "-Wtautological-constant-out-of-range-compare" +#endif + if (res >= 0 && (uintmax_t)res < (uintmax_t)SIZE_MAX && (size_t)res == rdlen) +#ifdef __clang__ +#pragma clang diagnostic pop +#endif +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) ) +# pragma GCC diagnostic pop +#endif { res = callback(*arg_upsfd, curDevice, rdbuf, rdlen); if (res < 1) { @@ -472,11 +592,13 @@ static int libshut_open(int *arg_upsfd, SHUTDevice_t *curDevice, char *arg_devic return -1; } - upsdebugx(2, "Report descriptor retrieved (Reportlen = %d)", rdlen); + upsdebugx(2, + "Report descriptor retrieved (Reportlen = %" + PRI_NUT_USB_CTRL_CHARBUFSIZE ")", rdlen); upsdebugx(2, "Found HID device"); fflush(stdout); - return rdlen; + return (int)rdlen; } if (res < 0) @@ -485,7 +607,10 @@ static int libshut_open(int *arg_upsfd, SHUTDevice_t *curDevice, char *arg_devic } else { - upsdebugx(2, "Report descriptor too short (expected %d, got %d)", rdlen, res); + upsdebugx(2, + "Report descriptor too short (expected %" + PRI_NUT_USB_CTRL_CHARBUFSIZE ", got %d)", + rdlen, res); } upsdebugx(2, "libshut: No appropriate HID device found"); @@ -493,8 +618,14 @@ static int libshut_open(int *arg_upsfd, SHUTDevice_t *curDevice, char *arg_devic return -1; } +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_BESIDEFUNC) && (!defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_INSIDEFUNC) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS_BESIDEFUNC) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE_BESIDEFUNC) ) +# pragma GCC diagnostic pop +#endif -static void libshut_close(int arg_upsfd) +/* Expected evaluated types for the API after typedefs: + * static void libshut_close(int arg_upsfd) + */ +static void libshut_close(usb_dev_handle arg_upsfd) { if (arg_upsfd < 1) { return; @@ -506,8 +637,15 @@ static void libshut_close(int arg_upsfd) /* return the report of ID=type in report * return -1 on failure, report length on success */ -static int libshut_get_report(int arg_upsfd, int ReportId, - unsigned char *raw_buf, int ReportSize ) +/* Expected evaluated types for the API after typedefs: + * static int libshut_get_report(int arg_upsfd, int ReportId, + * unsigned char *raw_buf, int ReportSize) + */ +static int libshut_get_report( + usb_dev_handle arg_upsfd, + usb_ctrl_repindex ReportId, + usb_ctrl_charbuf raw_buf, + usb_ctrl_charbufsize ReportSize) { if (arg_upsfd < 1) { return 0; @@ -524,8 +662,15 @@ static int libshut_get_report(int arg_upsfd, int ReportId, } /* return ReportSize upon success ; -1 otherwise */ -static int libshut_set_report(int arg_upsfd, int ReportId, - unsigned char *raw_buf, int ReportSize ) +/* Expected evaluated types for the API after typedefs: + * static int libshut_set_report(int arg_upsfd, int ReportId, + * unsigned char *raw_buf, int ReportSize) + */ +static int libshut_set_report( + usb_dev_handle arg_upsfd, + usb_ctrl_repindex ReportId, + usb_ctrl_charbuf raw_buf, + usb_ctrl_charbufsize ReportSize) { int ret; @@ -533,9 +678,16 @@ static int libshut_set_report(int arg_upsfd, int ReportId, return 0; } - upsdebugx(1, "Entering libshut_set_report (report %x, len %i)", + upsdebugx(1, + "Entering libshut_set_report (report %x, " + "len %" PRI_NUT_USB_CTRL_CHARBUFSIZE ")", ReportId, ReportSize); + if ((uintmax_t)ReportSize > (uintmax_t)INT_MAX) { + upsdebugx(1, "%s: ReportSize exceeds INT_MAX", __func__); + return -1; + } + upsdebug_hex (4, "==> Report after set", raw_buf, ReportSize); ret = shut_control_msg(arg_upsfd, @@ -545,10 +697,18 @@ static int libshut_set_report(int arg_upsfd, int ReportId, ReportId+(0x03<<8), /* HID_REPORT_TYPE_FEATURE */ 0, raw_buf, ReportSize, SHUT_TIMEOUT); - return ((ret == 0) ? ReportSize : ret); + return ((ret == 0) ? (int)ReportSize : ret); } -static int libshut_get_string(int arg_upsfd, int StringIdx, char *buf, size_t buflen) +/* Expected evaluated types for the API after typedefs: + * static int libshut_get_string(int arg_upsfd, + * int StringIdx, char *buf, size_t buflen) + */ +static int libshut_get_string( + usb_dev_handle arg_upsfd, + usb_ctrl_strindex StringIdx, + char *buf, + usb_ctrl_charbufsize buflen) { int ret; @@ -565,8 +725,15 @@ static int libshut_get_string(int arg_upsfd, int StringIdx, char *buf, size_t bu return ret; } -static int libshut_get_interrupt(int arg_upsfd, unsigned char *buf, - int bufsize, int timeout) +/* Expected evaluated types for the API after typedefs: + * static int libshut_get_interrupt(int arg_upsfd, unsigned char *buf, + * int bufsize, int timeout) + */ +static int libshut_get_interrupt( + usb_dev_handle arg_upsfd, + usb_ctrl_charbuf buf, + usb_ctrl_charbufsize bufsize, + usb_ctrl_timeout_msec timeout) { int ret; @@ -605,7 +772,10 @@ shut_communication_subdriver_t shut_subdriver = { * set : 1 to set comm * set : 0 to stop commupsh. */ -void setline(int arg_upsfd, int set) +/* Expected evaluated types for the API after typedefs: + * void setline(int arg_upsfd, int set) + */ +void setline(usb_dev_handle arg_upsfd, int set) { if (arg_upsfd < 1) { return; @@ -630,7 +800,10 @@ void setline(int arg_upsfd, int set) * return TRUE on success, FALSE on failure * *****************************************************************************/ -int shut_synchronise(int arg_upsfd) +/* Expected evaluated types for the API after typedefs: + * int shut_synchronise(int arg_upsfd) + */ +int shut_synchronise(usb_dev_handle arg_upsfd) { int retCode = 0; unsigned char c = SHUT_SYNC_OFF, reply; @@ -679,9 +852,14 @@ int shut_synchronise(int arg_upsfd) /*! * Compute a SHUT checksum for the packet "buf" */ -static unsigned char shut_checksum(const unsigned char *buf, int bufsize) +/* Expected evaluated types for the API after typedefs: + * static unsigned char shut_checksum(const unsigned char *buf, int bufsize) + */ +static unsigned char shut_checksum( + const usb_ctrl_charbuf buf, + usb_ctrl_charbufsize bufsize) { - int i; + usb_ctrl_charbufsize i; unsigned char chk=0; for(i=0; i0 && Retry<3) { @@ -733,7 +918,9 @@ static int shut_packet_recv(int arg_upsfd, unsigned char *Buf, int datalen) upsdebug_hex(4, "Receive", Start, 2); Size=Start[1]&0x0F; if( Size > 8 ) { - upsdebugx (4, "shut_packet_recv: invalid frame size = %d", Size); + upsdebugx (4, + "shut_packet_recv: invalid frame size = %d", + Size); ser_send_char(arg_upsfd, SHUT_NOK); Retry++; break; @@ -777,7 +964,9 @@ static int shut_packet_recv(int arg_upsfd, unsigned char *Buf, int datalen) } } else - upsdebugx (4, "need more data (%i)!", datalen); + upsdebugx (4, + "need more data (%" PRI_NUT_USB_CTRL_CHARBUFSIZE ")!", + datalen); } else { @@ -801,8 +990,17 @@ static int shut_packet_recv(int arg_upsfd, unsigned char *Buf, int datalen) } /**********************************************************************/ -static int shut_interrupt_read(int arg_upsfd, int ep, unsigned char *bytes, int size, - int timeout) +/* Expected evaluated types for the API after typedefs: + * static int shut_interrupt_read(int arg_upsfd, int ep, + * unsigned char *bytes, int size, + * int timeout) + */ +static int shut_interrupt_read( + usb_dev_handle arg_upsfd, + usb_ctrl_endpoint ep, + usb_ctrl_charbuf bytes, + usb_ctrl_charbufsize size, + usb_ctrl_timeout_msec timeout) { /* usleep(timeout * 1000); @@ -817,10 +1015,17 @@ static int shut_interrupt_read(int arg_upsfd, int ep, unsigned char *bytes, int } /**********************************************************************/ -static int shut_get_string_simple(int arg_upsfd, int index, - char *buf, size_t buflen) +/* Expected evaluated types for the API after typedefs: + * static int shut_get_string_simple(int arg_upsfd, int index, + * char *buf, size_t buflen) + */ +static int shut_get_string_simple( + usb_dev_handle arg_upsfd, + usb_ctrl_strindex index, + char *buf, + usb_ctrl_charbufsize buflen) { - unsigned char tbuf[255]; /* Some devices choke on size > 255 */ + usb_ctrl_char tbuf[255]; /* Some devices choke on size > 255 */ int ret, si, di; ret = shut_control_msg(arg_upsfd, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, @@ -855,7 +1060,7 @@ static int shut_get_string_simple(int arg_upsfd, int index, *********************************************************************/ /********************************************************************** - * shut_get_descriptor(int desctype, unsigned char *pkt) + * shut_get_descriptor(int desctype, usb_ctrl_charbuf pkt) * * get descriptor specified by DescType and return it in Buf * @@ -865,24 +1070,46 @@ static int shut_get_string_simple(int arg_upsfd, int index, * return 0 on success, -1 on failure, -2 on NACK * *********************************************************************/ -static int shut_get_descriptor(int arg_upsfd, unsigned char type, - unsigned char index, void *buf, int size) +/* Expected evaluated types for the API after typedefs: + * static int shut_get_descriptor(int arg_upsfd, unsigned char type, + * unsigned char index, void *buf, int size) + */ +static int shut_get_descriptor( + usb_dev_handle arg_upsfd, + usb_ctrl_requesttype type, + usb_ctrl_descindex index, + void *buf, + usb_ctrl_charbufsize size) { memset(buf, 0, size); - upsdebugx (2, "entering shut_get_descriptor(n %02x, %i)", type, size); + upsdebugx (2, + "entering shut_get_descriptor(n %02x, %" PRI_NUT_USB_CTRL_CHARBUFSIZE ")", + type, size); return shut_control_msg(arg_upsfd, USB_ENDPOINT_IN+(type>=USB_DT_HID?1:0), USB_REQ_GET_DESCRIPTOR, (type << 8) + index, 0, buf, size, SHUT_TIMEOUT); } /* Take care of a SHUT transfer (sending and receiving data) */ -static int shut_control_msg(int arg_upsfd, int requesttype, int request, - int value, int index, unsigned char *bytes, int size, int timeout) +/* Expected evaluated types for the API after typedefs: + * static int shut_control_msg(int arg_upsfd, int requesttype, int request, + * int value, int index, unsigned char *bytes, int size, + * int timeout) + */ +static int shut_control_msg( + usb_dev_handle arg_upsfd, + usb_ctrl_requesttype requesttype, + usb_ctrl_request request, + usb_ctrl_msgvalue value, + usb_ctrl_repindex index, + usb_ctrl_charbuf bytes, + usb_ctrl_charbufsize size, + usb_ctrl_timeout_msec timeout) { unsigned char shut_pkt[11]; short Retry=1, set_pass = -1; - short data_size, remaining_size = size; + usb_ctrl_charbufsize data_size, remaining_size = size; int i; struct shut_ctrltransfer_s ctrl; int ret = 0; @@ -897,12 +1124,30 @@ static int shut_control_msg(int arg_upsfd, int requesttype, int request, remaining_size+= 8; } +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE) ) +# pragma GCC diagnostic push +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS +# pragma GCC diagnostic ignored "-Wtype-limits" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE +# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE +# pragma GCC diagnostic ignored "-Wtautological-unsigned-zero-compare" +#endif + /* Note: checking against limits of protocol struct fields, + * not against USB_CTRL_REQUEST_MAX et al, which are mostly int + */ if (requesttype < 0 || (uintmax_t)requesttype > UINT8_MAX || request < 0 || (uintmax_t)request > UINT8_MAX || value < 0 || (uintmax_t)value > UINT16_MAX || index < 0 || (uintmax_t)index > UINT16_MAX || (uintmax_t)size > UINT16_MAX || (uintmax_t)timeout > UINT32_MAX +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE) ) +# pragma GCC diagnostic pop +#endif ) { upsdebugx (1, "%s: input values out of range", __func__); return -1; @@ -1023,7 +1268,10 @@ static int shut_control_msg(int arg_upsfd, int requesttype, int request, * returns 0 on success, -1 on error, -2 on NACK, -3 on NOTIFICATION * *********************************************************************/ -int shut_wait_ack(int arg_upsfd) +/* Expected evaluated types for the API after typedefs: + * int shut_wait_ack(int arg_upsfd) + */ +int shut_wait_ack(usb_dev_handle arg_upsfd) { int retCode = -1; unsigned char c = '\0'; diff --git a/drivers/libshut.h b/drivers/libshut.h index a7f0f2421b..8cc59bff4c 100644 --- a/drivers/libshut.h +++ b/drivers/libshut.h @@ -28,10 +28,75 @@ #define NUT_LIBSHUT_H_SEEN 1 #include "main.h" /* for subdrv_info_t */ -#include "nut_stdint.h" /* for uint16_t */ +#include "nut_stdint.h" /* for uint16_t, size_t, PRIsize etc. */ extern upsdrv_info_t comm_upsdrv_info; +/* These typedefs are also named in usb-common.h (=> nut_libusb.h), adhering + * to one or another libusb API version. For consistency of "ifdef SHUT_MODE" + * handling in libhid.c and some drivers, these symbolic names are used in + * all the headers and are expected to match binary code of object files at + * (monolithic) driver build time. + * + * The MIN/MAX definitions here are primarily to generalize range-check + * code (especially if anything is done outside the libraries). + * FIXME: It may make sense to constrain the limits to lowest common + * denominator that should fit alll of libusb-0.1, libusb-1.0 and libshut, + * so that any build of the practical (driver) code knows to not exceed + * any use-case. + * + * Types below were mined from existing method signatures; see also the + * my_hid_descriptor struct in libshut.c for practical fixed-size types. + */ + +/* Essentially the file descriptor type, "int" - as in ser_get_char() etc.: */ +typedef int usb_dev_handle; + +/* Originally "int" cast to "uint8_t" in shut_control_msg(), + * and "unsigned char" in shut_get_descriptor() */ +typedef unsigned char usb_ctrl_requesttype; +#define USB_CTRL_REQUESTTYPE_MIN 0 +#define USB_CTRL_REQUESTTYPE_MAX UCHAR_MAX + +typedef int usb_ctrl_request; +#define USB_CTRL_REQUEST_MIN INT_MIN +#define USB_CTRL_REQUEST_MAX INT_MAX + +typedef int usb_ctrl_endpoint; +#define USB_CTRL_ENDPOINT_MIN INT_MIN +#define USB_CTRL_ENDPOINT_MAX INT_MAX + +typedef int usb_ctrl_msgvalue; +#define USB_CTRL_MSGVALUE_MIN INT_MIN +#define USB_CTRL_MSGVALUE_MAX INT_MAX + +typedef int usb_ctrl_repindex; +#define USB_CTRL_REPINDEX_MIN INT_MIN +#define USB_CTRL_REPINDEX_MAX INT_MAX + +typedef int usb_ctrl_strindex; +#define USB_CTRL_STRINDEX_MIN INT_MIN +#define USB_CTRL_STRINDEX_MAX INT_MAX + +typedef unsigned char usb_ctrl_descindex; +#define USB_CTRL_DESCINDEX_MIN 0 +#define USB_CTRL_DESCINDEX_MAX UCHAR_MAX + +/* Here MIN/MAX should not matter much, type mostly used for casting */ +typedef unsigned char* usb_ctrl_charbuf; +typedef unsigned char usb_ctrl_char; +#define USB_CTRL_CHAR_MIN 0 +#define USB_CTRL_CHAR_MAX UCHAR_MAX + +typedef size_t usb_ctrl_charbufsize; /*typedef int usb_ctrl_charbufsize;*/ +#define USB_CTRL_CHARBUFSIZE_MIN 0 +#define USB_CTRL_CHARBUFSIZE_MAX SIZE_MAX +#define PRI_NUT_USB_CTRL_CHARBUFSIZE PRIsize + +typedef int usb_ctrl_timeout_msec; /* in milliseconds */ +#define USB_CTRL_TIMEOUTMSEC_MIN INT_MIN +#define USB_CTRL_TIMEOUTMSEC_MAX INT_MAX + /*! * SHUTDevice_t: Describe a SHUT device. This structure contains exactly * the 5 pieces of information by which a SHUT device identifies @@ -59,25 +124,26 @@ typedef struct shut_communication_subdriver_s { const char *name; /* name of this subdriver */ const char *version; /* version of this subdriver */ - int (*open)(int *upsfd, /* try to open the next available */ + int (*open)(usb_dev_handle *upsfd, /* try to open the next available */ SHUTDevice_t *curDevice, /* device matching USBDeviceMatcher_t */ char *device_path, - int (*callback)(int upsfd, SHUTDevice_t *hd, - unsigned char *rdbuf, int rdlen)); + int (*callback)(usb_dev_handle upsfd, SHUTDevice_t *hd, + usb_ctrl_charbuf rdbuf, usb_ctrl_charbufsize rdlen)); - void (*close)(int upsfd); + void (*close)(usb_dev_handle upsfd); - int (*get_report)(int upsfd, int ReportId, - unsigned char *raw_buf, int ReportSize); + int (*get_report)(usb_dev_handle upsfd, usb_ctrl_repindex ReportId, + usb_ctrl_charbuf raw_buf, usb_ctrl_charbufsize ReportSize); - int (*set_report)(int upsfd, int ReportId, - unsigned char *raw_buf, int ReportSize); + int (*set_report)(usb_dev_handle upsfd, usb_ctrl_repindex ReportId, + usb_ctrl_charbuf raw_buf, usb_ctrl_charbufsize ReportSize); - int (*get_string)(int upsfd, - int StringIdx, char *buf, size_t buflen); + int (*get_string)(usb_dev_handle upsfd, + usb_ctrl_strindex StringIdx, char *buf, usb_ctrl_charbufsize buflen); - int (*get_interrupt)(int upsfd, - unsigned char *buf, int bufsize, int timeout); + int (*get_interrupt)(usb_dev_handle upsfd, + usb_ctrl_charbuf buf, usb_ctrl_charbufsize bufsize, + usb_ctrl_timeout_msec timeout); } shut_communication_subdriver_t; extern shut_communication_subdriver_t shut_subdriver; diff --git a/drivers/libusb0.c b/drivers/libusb0.c index 952aff1ac9..30c16d78d8 100644 --- a/drivers/libusb0.c +++ b/drivers/libusb0.c @@ -69,10 +69,13 @@ void nut_usb_addvars(void) dstate_setinfo("driver.version.usb", "libusb-0.1 (or compat)"); } -/* From usbutils: workaround libusb API goofs: "byte" should never be sign extended; - * using "char" is trouble. Likewise, sizes should never be negative. +/* From usbutils: workaround libusb (0.1) API goofs: + * "byte" should never be sign extended; + * using "char" is trouble. + * Likewise, sizes should never be negative. */ +/* static inline int typesafe_control_msg(usb_dev_handle *dev, unsigned char requesttype, unsigned char request, int value, int index, @@ -81,6 +84,22 @@ static inline int typesafe_control_msg(usb_dev_handle *dev, return usb_control_msg(dev, requesttype, request, value, index, (char *) bytes, (int) size, timeout); } +*/ + +static inline int typesafe_control_msg( + usb_dev_handle *dev, + unsigned char requesttype, + unsigned char request, + int value, + int index, + usb_ctrl_charbuf bytes, + usb_ctrl_charbufsize size, + usb_ctrl_timeout_msec timeout) +{ + return usb_control_msg(dev, requesttype, request, value, index, + (char *) bytes, (int) size, timeout); +} + /* invoke matcher against device */ static inline int matches(USBDeviceMatcher_t *matcher, USBDevice_t *device) { @@ -144,13 +163,13 @@ static int nut_usb_set_altinterface(usb_dev_handle *udev) static int libusb_open(usb_dev_handle **udevp, USBDevice_t *curDevice, USBDeviceMatcher_t *matcher, int (*callback)(usb_dev_handle *udev, - USBDevice_t *hd, unsigned char *rdbuf, int rdlen) + USBDevice_t *hd, usb_ctrl_charbuf rdbuf, usb_ctrl_charbufsize rdlen) ) { #ifdef HAVE_USB_DETACH_KERNEL_DRIVER_NP int retries; #endif - int rdlen1, rdlen2; /* report descriptor length, method 1+2 */ + usb_ctrl_charbufsize rdlen1, rdlen2; /* report descriptor length, method 1+2 */ USBDeviceMatcher_t *m; struct usb_device *dev; struct usb_bus *bus; @@ -158,14 +177,14 @@ static int libusb_open(usb_dev_handle **udevp, struct usb_interface_descriptor *iface; int ret, res; - unsigned char buf[20]; - unsigned char *p; + usb_ctrl_char buf[20]; + usb_ctrl_char *p; char string[256]; int i; /* report descriptor */ - unsigned char rdbuf[MAX_REPORT_SIZE]; - int rdlen; + usb_ctrl_char rdbuf[MAX_REPORT_SIZE]; + usb_ctrl_charbufsize rdlen; /* libusb base init */ usb_init(); @@ -364,7 +383,9 @@ static int libusb_open(usb_dev_handle **udevp, if (rdlen1 < -1) { upsdebugx(2, "Warning: HID descriptor, method 1 failed"); } - upsdebugx(3, "HID descriptor length (method 1) %d", rdlen1); + upsdebugx(3, + "HID descriptor length (method 1) %" PRI_NUT_USB_CTRL_CHARBUFSIZE, + rdlen1); /* SECOND METHOD: find HID descriptor among "extra" bytes of interface descriptor, i.e., bytes tucked onto the end of @@ -379,8 +400,12 @@ static int libusb_open(usb_dev_handle **udevp, for (i=0; iextralen; i+=iface->extra[i]) { upsdebugx(4, "i=%d, extra[i]=%02x, extra[i+1]=%02x", i, iface->extra[i], iface->extra[i+1]); - if (i+9 <= iface->extralen && iface->extra[i] >= 9 && iface->extra[i+1] == 0x21) { - p = &iface->extra[i]; + + if (i+9 <= iface->extralen + && iface->extra[i] >= 9 + && iface->extra[i+1] == 0x21 + ) { + p = (usb_ctrl_char *)&iface->extra[i]; upsdebug_hex(3, "HID descriptor, method 2", p, 9); rdlen2 = p[7] | (p[8] << 8); break; @@ -390,7 +415,9 @@ static int libusb_open(usb_dev_handle **udevp, if (rdlen2 < -1) { upsdebugx(2, "Warning: HID descriptor, method 2 failed"); } - upsdebugx(3, "HID descriptor length (method 2) %d", rdlen2); + upsdebugx(3, + "HID descriptor length (method 2) %" PRI_NUT_USB_CTRL_CHARBUFSIZE, + rdlen2); /* when available, always choose the second value, as it seems to be more reliable (it is the one reported e.g. by @@ -410,14 +437,20 @@ static int libusb_open(usb_dev_handle **udevp, } if (rdlen1 >= 0 && rdlen2 >= 0 && rdlen1 != rdlen2) { upsdebugx(2, "Warning: two different HID descriptors retrieved " - "(Reportlen = %d vs. %d)", rdlen1, rdlen2); + "(Reportlen = %" PRI_NUT_USB_CTRL_CHARBUFSIZE + " vs. %" PRI_NUT_USB_CTRL_CHARBUFSIZE ")", + rdlen1, rdlen2); } - upsdebugx(2, "HID descriptor length %d", rdlen); + upsdebugx(2, + "HID descriptor length %" PRI_NUT_USB_CTRL_CHARBUFSIZE, + rdlen); - if (rdlen > (int)sizeof(rdbuf)) { - upsdebugx(2, "HID descriptor too long %d (max %d)", - rdlen, (int)sizeof(rdbuf)); + if ((uintmax_t)rdlen > sizeof(rdbuf)) { + upsdebugx(2, + "HID descriptor too long %" PRI_NUT_USB_CTRL_CHARBUFSIZE + " (max %zu)", + rdlen, sizeof(rdbuf)); goto next_device; } @@ -429,7 +462,7 @@ static int libusb_open(usb_dev_handle **udevp, USB_REQ_GET_DESCRIPTOR, (USB_DT_REPORT << 8) + usb_subdriver.hid_desc_index, usb_subdriver.hid_rep_index, - rdbuf, (unsigned)rdlen, USB_TIMEOUT); + rdbuf, rdlen, USB_TIMEOUT); if (res < 0) { @@ -440,7 +473,8 @@ static int libusb_open(usb_dev_handle **udevp, if (res < rdlen) { upsdebugx(2, "Warning: report descriptor too short " - "(expected %d, got %d)", rdlen, res); + "(expected %" PRI_NUT_USB_CTRL_CHARBUFSIZE + ", got %d)", rdlen, res); rdlen = res; /* correct rdlen if necessary */ } @@ -450,7 +484,9 @@ static int libusb_open(usb_dev_handle **udevp, goto next_device; } - upsdebugx(2, "Report descriptor retrieved (Reportlen = %d)", rdlen); + upsdebugx(2, + "Report descriptor retrieved (Reportlen = %" + PRI_NUT_USB_CTRL_CHARBUFSIZE ")", rdlen); upsdebugx(2, "Found HID device"); fflush(stdout); @@ -518,8 +554,15 @@ static int libusb_strerror(const int ret, const char *desc) * return -1 on failure, report length on success */ -static int libusb_get_report(usb_dev_handle *udev, - int ReportId, unsigned char *raw_buf, int ReportSize ) +/* Expected evaluated types for the API: + * static int libusb_get_report(usb_dev_handle *udev, + * int ReportId, unsigned char *raw_buf, int ReportSize) + */ +static int libusb_get_report( + usb_dev_handle *udev, + usb_ctrl_repindex ReportId, + usb_ctrl_charbuf raw_buf, + usb_ctrl_charbufsize ReportSize) { int ret; @@ -544,8 +587,15 @@ static int libusb_get_report(usb_dev_handle *udev, return libusb_strerror(ret, __func__); } -static int libusb_set_report(usb_dev_handle *udev, - int ReportId, unsigned char *raw_buf, int ReportSize ) +/* Expected evaluated types for the API: + * static int libusb_set_report(usb_dev_handle *udev, + * int ReportId, unsigned char *raw_buf, int ReportSize) + */ +static int libusb_set_report( + usb_dev_handle *udev, + usb_ctrl_repindex ReportId, + usb_ctrl_charbuf raw_buf, + usb_ctrl_charbufsize ReportSize) { int ret; @@ -568,22 +618,58 @@ static int libusb_set_report(usb_dev_handle *udev, return libusb_strerror(ret, __func__); } -static int libusb_get_string(usb_dev_handle *udev, - int StringIdx, char *buf, size_t buflen) +/* Expected evaluated types for the API: + * static int libusb_get_string(usb_dev_handle *udev, + * int StringIdx, char *buf, size_t buflen) + */ +static int libusb_get_string( + usb_dev_handle *udev, + usb_ctrl_strindex StringIdx, + char *buf, + usb_ctrl_charbufsize buflen) { int ret; - if (!udev) { + if (!udev +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE) ) +# pragma GCC diagnostic push +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS +# pragma GCC diagnostic ignored "-Wtype-limits" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE +# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE +# pragma GCC diagnostic ignored "-Wtautological-unsigned-zero-compare" +#endif + /* + * usb.h:int usb_get_string_simple(usb_dev_handle *dev, int index, + * usb.h- char *buf, size_t buflen); + */ + || StringIdx < 0 || (uintmax_t)StringIdx > INT_MAX + || buflen < 0 || (uintmax_t)buflen > (uintmax_t)SIZE_MAX +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE) ) +# pragma GCC diagnostic pop +#endif + ) { return -1; } - ret = usb_get_string_simple(udev, StringIdx, buf, buflen); + ret = usb_get_string_simple(udev, StringIdx, buf, (size_t)buflen); return libusb_strerror(ret, __func__); } -static int libusb_get_interrupt(usb_dev_handle *udev, - unsigned char *buf, int bufsize, int timeout) +/* Expected evaluated types for the API: + * static int libusb_get_interrupt(usb_dev_handle *udev, + * unsigned char *buf, int bufsize, int timeout) + */ +static int libusb_get_interrupt( + usb_dev_handle *udev, + usb_ctrl_charbuf buf, + usb_ctrl_charbufsize bufsize, + usb_ctrl_timeout_msec timeout) { int ret; diff --git a/drivers/libusb1.c b/drivers/libusb1.c index 3e643066fb..1564ce9961 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -4,6 +4,7 @@ * * @author Copyright (C) 2016 Eaton * Copyright (C) 2016 Arnaud Quette + * Copyright (C) 2021 Jim Klimov * * The logic of this file is ripped from mge-shut driver (also from * Arnaud Quette), which is a "HID over serial link" UPS driver for @@ -134,7 +135,7 @@ static int nut_usb_set_altinterface(libusb_device_handle *udev) static int nut_libusb_open(libusb_device_handle **udevp, USBDevice_t *curDevice, USBDeviceMatcher_t *matcher, int (*callback)(libusb_device_handle *udev, - USBDevice_t *hd, unsigned char *rdbuf, int rdlen) + USBDevice_t *hd, usb_ctrl_charbuf rdbuf, usb_ctrl_charbufsize rdlen) ) { #if (defined HAVE_LIBUSB_DETACH_KERNEL_DRIVER) || (defined HAVE_LIBUSB_DETACH_KERNEL_DRIVER_NP) @@ -301,7 +302,9 @@ static int nut_libusb_open(libusb_device_handle **udevp, upsdebugx(2, "Reading first configuration descriptor"); - ret = libusb_get_config_descriptor(device, usb_subdriver.hid_rep_index, &conf_desc); + ret = libusb_get_config_descriptor(device, + (uint8_t)usb_subdriver.hid_rep_index, + &conf_desc); /*ret = libusb_get_active_config_descriptor(device, &conf_desc);*/ if (ret < 0) upsdebugx(2, "result: %i (%s)", @@ -489,7 +492,7 @@ static int nut_libusb_open(libusb_device_handle **udevp, goto next_device; } -#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) ) +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE) ) # pragma GCC diagnostic push #endif #ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS @@ -497,9 +500,12 @@ static int nut_libusb_open(libusb_device_handle **udevp, #endif #ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE # pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE +# pragma GCC diagnostic ignored "-Wtautological-unsigned-zero-compare" #endif if ((uintmax_t)rdlen > UINT16_MAX) { -#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) ) +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE) ) # pragma GCC diagnostic pop #endif upsdebugx(2, "HID descriptor too long %d (max %u)", @@ -528,7 +534,18 @@ static int nut_libusb_open(libusb_device_handle **udevp, rdlen = res; /* correct rdlen if necessary */ } - res = callback(udev, curDevice, rdbuf, rdlen); + if (rdlen < USB_CTRL_CHARBUFSIZE_MIN + || (uintmax_t)rdlen > (uintmax_t)USB_CTRL_CHARBUFSIZE_MAX + ) { + upsdebugx(2, + "Report descriptor length is out of range on this device: " + "should be %ji < %d < %ju", + (intmax_t)USB_CTRL_CHARBUFSIZE_MIN, rdlen, + (uintmax_t)USB_CTRL_CHARBUFSIZE_MAX); + goto next_device; + } + + res = callback(udev, curDevice, rdbuf, (usb_ctrl_charbufsize)rdlen); if (res < 1) { upsdebugx(2, "Caller doesn't like this device"); goto next_device; @@ -612,14 +629,39 @@ static int nut_libusb_strerror(const int ret, const char *desc) * return -1 on failure, report length on success */ -static int nut_libusb_get_report(libusb_device_handle *udev, - int ReportId, unsigned char *raw_buf, int ReportSize ) +/* Expected evaluated types for the API: + * static int nut_libusb_get_report(libusb_device_handle *udev, + * int ReportId, unsigned char *raw_buf, int ReportSize ) + */ +static int nut_libusb_get_report( + libusb_device_handle *udev, + usb_ctrl_repindex ReportId, + usb_ctrl_charbuf raw_buf, + usb_ctrl_charbufsize ReportSize) { int ret; upsdebugx(4, "Entering libusb_get_report"); - if (!udev) { + if (!udev +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE) ) +# pragma GCC diagnostic push +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS +# pragma GCC diagnostic ignored "-Wtype-limits" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE +# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE +# pragma GCC diagnostic ignored "-Wtautological-unsigned-zero-compare" +#endif + || ReportId < 0 || (uintmax_t)ReportId > UINT16_MAX + || ReportSize < 0 || (uintmax_t)ReportSize > UINT16_MAX +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE) ) +# pragma GCC diagnostic pop +#endif + ) { return 0; } @@ -627,9 +669,9 @@ static int nut_libusb_get_report(libusb_device_handle *udev, ret = libusb_control_transfer(udev, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE, 0x01, /* HID_REPORT_GET */ - ReportId+(0x03<<8), /* HID_REPORT_TYPE_FEATURE */ + (uint16_t)ReportId + (0x03<<8), /* HID_REPORT_TYPE_FEATURE */ usb_subdriver.hid_rep_index, - raw_buf, ReportSize, USB_TIMEOUT); + raw_buf, (uint16_t)ReportSize, USB_TIMEOUT); /* Ignore "protocol stall" (for unsupported request) on control endpoint */ if (ret == LIBUSB_ERROR_PIPE) { @@ -639,12 +681,37 @@ static int nut_libusb_get_report(libusb_device_handle *udev, return nut_libusb_strerror(ret, __func__); } -static int nut_libusb_set_report(libusb_device_handle *udev, - int ReportId, unsigned char *raw_buf, int ReportSize ) +/* Expected evaluated types for the API: + * static int nut_libusb_set_report(libusb_device_handle *udev, + * int ReportId, unsigned char *raw_buf, int ReportSize ) + */ +static int nut_libusb_set_report( + libusb_device_handle *udev, + usb_ctrl_repindex ReportId, + usb_ctrl_charbuf raw_buf, + usb_ctrl_charbufsize ReportSize) { int ret; - if (!udev) { + if (!udev +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE) ) +# pragma GCC diagnostic push +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS +# pragma GCC diagnostic ignored "-Wtype-limits" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE +# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE +# pragma GCC diagnostic ignored "-Wtautological-unsigned-zero-compare" +#endif + || ReportId < 0 || (uintmax_t)ReportId > UINT16_MAX + || ReportSize < 0 || (uintmax_t)ReportSize > UINT16_MAX +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE) ) +# pragma GCC diagnostic pop +#endif + ) { return 0; } @@ -652,9 +719,9 @@ static int nut_libusb_set_report(libusb_device_handle *udev, ret = libusb_control_transfer(udev, LIBUSB_ENDPOINT_OUT|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE, 0x09, /* HID_REPORT_SET = 0x09*/ - ReportId+(0x03<<8), /* HID_REPORT_TYPE_FEATURE */ + (uint16_t)ReportId + (0x03<<8), /* HID_REPORT_TYPE_FEATURE */ usb_subdriver.hid_rep_index, - raw_buf, ReportSize, USB_TIMEOUT); + raw_buf, (uint16_t)ReportSize, USB_TIMEOUT); /* Ignore "protocol stall" (for unsupported request) on control endpoint */ if (ret == LIBUSB_ERROR_PIPE) { @@ -664,35 +731,94 @@ static int nut_libusb_set_report(libusb_device_handle *udev, return nut_libusb_strerror(ret, __func__); } -static int nut_libusb_get_string(libusb_device_handle *udev, - int StringIdx, char *buf, size_t buflen) +/* Expected evaluated types for the API: + * static int nut_libusb_get_string(libusb_device_handle *udev, + * int StringIdx, char *buf, int buflen) + */ +static int nut_libusb_get_string( + libusb_device_handle *udev, + usb_ctrl_strindex StringIdx, + char *buf, + usb_ctrl_charbufsize buflen) { int ret; - if (!udev) { + if (!udev +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE) ) +# pragma GCC diagnostic push +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS +# pragma GCC diagnostic ignored "-Wtype-limits" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE +# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE +# pragma GCC diagnostic ignored "-Wtautological-unsigned-zero-compare" +#endif + || StringIdx < 0 || (uintmax_t)StringIdx > UINT8_MAX + || buflen < 0 || (uintmax_t)buflen > (uintmax_t)INT_MAX +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE) ) +# pragma GCC diagnostic pop +#endif + ) { return -1; } - ret = libusb_get_string_descriptor_ascii(udev, StringIdx, - (unsigned char*)buf, buflen); + ret = libusb_get_string_descriptor_ascii(udev, (uint8_t)StringIdx, + (unsigned char*)buf, (int)buflen); return nut_libusb_strerror(ret, __func__); } -static int nut_libusb_get_interrupt(libusb_device_handle *udev, - unsigned char *buf, int bufsize, int timeout) +/* Expected evaluated types for the API: + * static int nut_libusb_get_interrupt(libusb_device_handle *udev, + * unsigned char *buf, int bufsize, int timeout) + */ +static int nut_libusb_get_interrupt( + libusb_device_handle *udev, + usb_ctrl_charbuf buf, + usb_ctrl_charbufsize bufsize, + usb_ctrl_timeout_msec timeout) { - int ret; + int ret, tmpbufsize; - if (!udev) { + if (!udev +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE) ) +# pragma GCC diagnostic push +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS +# pragma GCC diagnostic ignored "-Wtype-limits" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE +# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare" +#endif +#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE +# pragma GCC diagnostic ignored "-Wtautological-unsigned-zero-compare" +#endif + || bufsize < 0 || (uintmax_t)bufsize > (uintmax_t)INT_MAX +#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_UNSIGNED_ZERO_COMPARE) ) +# pragma GCC diagnostic pop +#endif + ) { return -1; } + /* NOTE: With all the fuss about word sized arguments, + * the libusb_interrupt_transfer() lengths are about ints: + * int LIBUSB_CALL libusb_interrupt_transfer(libusb_device_handle *dev_handle, + * unsigned char endpoint, unsigned char *data, int length, + * int *actual_length, unsigned int timeout); + */ + tmpbufsize = (int)bufsize; + /* FIXME: hardcoded interrupt EP => need to get EP descr for IF descr */ /* ret = libusb_interrupt_transfer(udev, 0x81, buf, bufsize, &bufsize, timeout); */ /* libusb0: ret = usb_interrupt_read(udev, USB_ENDPOINT_IN + usb_subdriver.hid_ep_in, (char *)buf, bufsize, timeout); */ /* Interrupt EP is LIBUSB_ENDPOINT_IN with offset defined in hid_ep_in, which is 0 by default, unless overridden in subdriver. */ - ret = libusb_interrupt_transfer(udev, LIBUSB_ENDPOINT_IN + usb_subdriver.hid_ep_in, (unsigned char *)buf, bufsize, &bufsize, timeout); + ret = libusb_interrupt_transfer(udev, + LIBUSB_ENDPOINT_IN + usb_subdriver.hid_ep_in, + (unsigned char *)buf, tmpbufsize, &tmpbufsize, timeout); /* Clear stall condition */ if (ret == LIBUSB_ERROR_PIPE) { @@ -701,7 +827,12 @@ static int nut_libusb_get_interrupt(libusb_device_handle *udev, /* In case of success, return the operation size, as done with libusb 0.1 */ if (ret == LIBUSB_SUCCESS) { - ret = bufsize; + if (tmpbufsize < 0 + || (uintmax_t)tmpbufsize > (uintmax_t)USB_CTRL_CHARBUFSIZE_MAX + ) { + return -1; + } + ret = (usb_ctrl_charbufsize)bufsize; } return nut_libusb_strerror(ret, __func__); diff --git a/drivers/nut_libusb.h b/drivers/nut_libusb.h index 4c54789277..20473d3fca 100644 --- a/drivers/nut_libusb.h +++ b/drivers/nut_libusb.h @@ -56,21 +56,22 @@ typedef struct usb_communication_subdriver_s { USBDevice_t *curDevice, /* device matching USBDeviceMatcher_t */ USBDeviceMatcher_t *matcher, int (*callback)(usb_dev_handle *udev, USBDevice_t *hd, - unsigned char *rdbuf, int rdlen)); + usb_ctrl_charbuf rdbuf, usb_ctrl_charbufsize rdlen)); void (*close)(usb_dev_handle *sdev); - int (*get_report)(usb_dev_handle *sdev, int ReportId, - unsigned char *raw_buf, int ReportSize); + int (*get_report)(usb_dev_handle *sdev, usb_ctrl_repindex ReportId, + usb_ctrl_charbuf raw_buf, usb_ctrl_charbufsize ReportSize); - int (*set_report)(usb_dev_handle *sdev, int ReportId, - unsigned char *raw_buf, int ReportSize); + int (*set_report)(usb_dev_handle *sdev, usb_ctrl_repindex ReportId, + usb_ctrl_charbuf raw_buf, usb_ctrl_charbufsize ReportSize); int (*get_string)(usb_dev_handle *sdev, - int StringIdx, char *buf, size_t buflen); + usb_ctrl_strindex StringIdx, char *buf, usb_ctrl_charbufsize buflen); int (*get_interrupt)(usb_dev_handle *sdev, - unsigned char *buf, int bufsize, int timeout); + usb_ctrl_charbuf buf, usb_ctrl_charbufsize bufsize, + usb_ctrl_timeout_msec timeout); /* Used for Powervar UPS or similar cases to make sure * we use the right interface in the Composite device. diff --git a/drivers/nutdrv_atcl_usb.c b/drivers/nutdrv_atcl_usb.c index c5d07f4171..a7da0cd56c 100644 --- a/drivers/nutdrv_atcl_usb.c +++ b/drivers/nutdrv_atcl_usb.c @@ -263,7 +263,7 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev libusb_exit(NULL); fatal_with_errno(EXIT_FAILURE, "Failed to init libusb 1.0"); } -#else +#else /* => WITH_LIBUSB_0_1 */ usb_init(); usb_find_busses(); usb_find_devices(); @@ -295,7 +295,7 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev libusb_get_device_descriptor(dev, &dev_desc); ret = libusb_open(dev, &handle); *handlep = handle; -#else +#else /* => WITH_LIBUSB_0_1 */ struct usb_bus *bus; for (bus = usb_busses; bus; bus = bus->next) { @@ -349,7 +349,7 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev iManufacturer = dev_desc.iManufacturer; iProduct = dev_desc.iProduct; iSerialNumber = dev_desc.iSerialNumber; -#else +#else /* => WITH_LIBUSB_0_1 */ device->VendorID = dev->descriptor.idVendor; device->ProductID = dev->descriptor.idProduct; device->Bus = xstrdup(bus->dirname); @@ -469,7 +469,8 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev } else { upsdebugx(4, "detached kernel driver from USB device..."); } -#elif HAVE_LIBUSB_DETACH_KERNEL_DRIVER +#else +# ifdef HAVE_LIBUSB_DETACH_KERNEL_DRIVER if ((ret = libusb_detach_kernel_driver(udev, 0)) < 0) { upsdebugx(4, "failed to detach kernel driver from USB device: %s", @@ -477,7 +478,8 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev } else { upsdebugx(4, "detached kernel driver from USB device..."); } -#elif HAVE_LIBUSB_DETACH_KERNEL_DRIVER_NP +# else +# ifdef HAVE_LIBUSB_DETACH_KERNEL_DRIVER_NP if ((ret = libusb_detach_kernel_driver_np(udev, 0)) < 0) { upsdebugx(4, "failed to detach kernel driver from USB device: %s", @@ -485,6 +487,8 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev } else { upsdebugx(4, "detached kernel driver from USB device..."); } +# endif /* HAVE_LIBUSB_DETACH_KERNEL_DRIVER_NP */ +# endif /* HAVE_LIBUSB_DETACH_KERNEL_DRIVER */ #endif /* HAVE_USB_DETACH_KERNEL_DRIVER_NP or HAVE_LIBUSB_DETACH_KERNEL_DRIVER or HAVE_LIBUSB_DETACH_KERNEL_DRIVER_NP */ } @@ -498,7 +502,7 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev next_device: usb_close(handle); -#if (!WITH_LIBUSB_1_0) +#if (!WITH_LIBUSB_1_0) /* => WITH_LIBUSB_0_1 */ } #endif /* WITH_LIBUSB_1_0 */ } diff --git a/drivers/richcomm_usb.c b/drivers/richcomm_usb.c index e6c4c0d5af..99af7913b5 100644 --- a/drivers/richcomm_usb.c +++ b/drivers/richcomm_usb.c @@ -310,7 +310,7 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev libusb_exit(NULL); fatal_with_errno(EXIT_FAILURE, "Failed to init libusb 1.0"); } -#else +#else /* => WITH_LIBUSB_0_1 */ usb_init(); usb_find_busses(); usb_find_devices(); @@ -342,7 +342,7 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev libusb_get_device_descriptor(dev, &dev_desc); ret = libusb_open(dev, &handle); *handlep = handle; -#else +#else /* => WITH_LIBUSB_0_1 */ struct usb_bus *bus; for (bus = usb_busses; bus; bus = bus->next) { @@ -396,7 +396,7 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev iManufacturer = dev_desc.iManufacturer; iProduct = dev_desc.iProduct; iSerialNumber = dev_desc.iSerialNumber; -#else +#else /* => WITH_LIBUSB_0_1 */ device->VendorID = dev->descriptor.idVendor; device->ProductID = dev->descriptor.idProduct; device->Bus = xstrdup(bus->dirname); @@ -517,7 +517,8 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev } else { upsdebugx(4, "detached kernel driver from USB device..."); } -#elif HAVE_LIBUSB_DETACH_KERNEL_DRIVER +#else +# ifdef HAVE_LIBUSB_DETACH_KERNEL_DRIVER if ((ret = libusb_detach_kernel_driver(handle, 0)) < 0) { upsdebugx(4, "failed to detach kernel driver from USB device: %s", @@ -525,7 +526,8 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev } else { upsdebugx(4, "detached kernel driver from USB device..."); } -#elif HAVE_LIBUSB_DETACH_KERNEL_DRIVER_NP +# else +# ifdef HAVE_LIBUSB_DETACH_KERNEL_DRIVER_NP if ((ret = libusb_detach_kernel_driver_np(udev, 0)) < 0) { upsdebugx(4, "failed to detach kernel driver from USB device: %s", @@ -533,6 +535,8 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev } else { upsdebugx(4, "detached kernel driver from USB device..."); } +# endif /* HAVE_LIBUSB_DETACH_KERNEL_DRIVER_NP */ +# endif /* HAVE_LIBUSB_DETACH_KERNEL_DRIVER */ #endif /* HAVE_USB_DETACH_KERNEL_DRIVER_NP or HAVE_LIBUSB_DETACH_KERNEL_DRIVER or HAVE_LIBUSB_DETACH_KERNEL_DRIVER_NP */ } @@ -545,7 +549,7 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev next_device: usb_close(handle); -#if (!WITH_LIBUSB_1_0) +#if (!WITH_LIBUSB_1_0) /* => WITH_LIBUSB_0_1 */ } #endif /* WITH_LIBUSB_1_0 */ } diff --git a/drivers/riello_usb.c b/drivers/riello_usb.c index 2e046896d6..28195da8af 100644 --- a/drivers/riello_usb.c +++ b/drivers/riello_usb.c @@ -307,7 +307,7 @@ static USBDeviceMatcher_t device_matcher = { * caller, don't do this here. Return < 0 on error, 0 or higher on * success. */ -static int driver_callback(usb_dev_handle *handle, USBDevice_t *device, unsigned char *rdbuf, int rdlen) +static int driver_callback(usb_dev_handle *handle, USBDevice_t *device, usb_ctrl_charbuf rdbuf, usb_ctrl_charbufsize rdlen) { int ret = 0; NUT_UNUSED_VARIABLE(device); diff --git a/drivers/tripplite_usb.c b/drivers/tripplite_usb.c index af66c8687d..ab67664498 100644 --- a/drivers/tripplite_usb.c +++ b/drivers/tripplite_usb.c @@ -613,11 +613,13 @@ static int send_cmd(const unsigned char *msg, size_t msg_len, unsigned char *rep for(send_try=0; !done && send_try < MAX_SEND_TRIES; send_try++) { upsdebugx(6, "send_cmd send_try %d", send_try+1); - ret = comm_driver->set_report(udev, 0, buffer_out, sizeof(buffer_out)); + ret = comm_driver->set_report(udev, 0, + (usb_ctrl_charbuf)buffer_out, + (usb_ctrl_charbufsize)sizeof(buffer_out)); if(ret != sizeof(buffer_out)) { - upslogx(1, "libusb_set_report() returned %d instead of %u", - ret, (unsigned)(sizeof(buffer_out))); + upslogx(1, "libusb_set_report() returned %d instead of %zu", + ret, sizeof(buffer_out)); return ret; } @@ -627,7 +629,10 @@ static int send_cmd(const unsigned char *msg, size_t msg_len, unsigned char *rep for(recv_try=0; !done && recv_try < MAX_RECV_TRIES; recv_try++) { upsdebugx(7, "send_cmd recv_try %d", recv_try+1); - ret = comm_driver->get_interrupt(udev, reply, sizeof(buffer_out), RECV_WAIT_MSEC); + ret = comm_driver->get_interrupt(udev, + (usb_ctrl_charbuf)reply, + (usb_ctrl_charbufsize)sizeof(buffer_out), + RECV_WAIT_MSEC); if(ret != sizeof(buffer_out)) { upslogx(1, "libusb_get_interrupt() returned %d instead of %u while sending %s", ret, (unsigned)(sizeof(buffer_out)), diff --git a/drivers/usb-common.h b/drivers/usb-common.h index 1c46a3e412..7be98b31cd 100644 --- a/drivers/usb-common.h +++ b/drivers/usb-common.h @@ -84,19 +84,62 @@ /* Structures */ /* #define usb_dev_handle libusb_device_handle */ typedef libusb_device_handle usb_dev_handle; +/* These typedefs are also named in libshut.h, so we can consistenly + * handle the "ifdef SHUT_MODE" handling in libhid.c and some drivers. + * These symbolic names are used in all the headers and are expected to + * match binary code of object files at (monolithic) driver build time. + * + * The MIN/MAX definitions here are primarily to generalize range-check + * code (especially if anything is done outside the libraries). + * FIXME: It may make sense to constrain the limits to lowest common + * denominator that should fit alll of libusb-0.1, libusb-1.0 and libshut, + * so that any build of the practical (driver) code knows to not exceed + * any use-case. + */ typedef uint8_t usb_ctrl_requesttype; + #define USB_CTRL_REQUESTTYPE_MIN 0 + #define USB_CTRL_REQUESTTYPE_MAX UINT8_MAX + typedef uint8_t usb_ctrl_request; + #define USB_CTRL_REQUEST_MIN 0 + #define USB_CTRL_REQUEST_MAX UINT8_MAX + typedef unsigned char usb_ctrl_endpoint; + #define USB_CTRL_ENDPOINT_MIN 0 + #define USB_CTRL_ENDPOINT_MAX UCHAR_MAX + typedef uint16_t usb_ctrl_msgvalue; + #define USB_CTRL_MSGVALUE_MIN 0 + #define USB_CTRL_MSGVALUE_MAX UINT16_MAX + typedef uint16_t usb_ctrl_repindex; + #define USB_CTRL_REPINDEX_MIN 0 + #define USB_CTRL_REPINDEX_MAX UINT16_MAX + typedef uint8_t usb_ctrl_strindex; + #define USB_CTRL_STRINDEX_MIN 0 + #define USB_CTRL_STRINDEX_MAX UINT8_MAX + typedef uint8_t usb_ctrl_descindex; + #define USB_CTRL_DESCINDEX_MIN 0 + #define USB_CTRL_DESCINDEX_MAX UINT8_MAX + typedef unsigned char* usb_ctrl_charbuf; + typedef unsigned char usb_ctrl_char; + #define USB_CTRL_CHAR_MIN 0 + #define USB_CTRL_CHAR_MAX UCHAR_MAX + + /* Here MIN/MAX should not matter much, type mostly used for casting */ typedef uint16_t usb_ctrl_charbufsize; + #define USB_CTRL_CHARBUFSIZE_MIN 0 + #define USB_CTRL_CHARBUFSIZE_MAX UINT16_MAX #define PRI_NUT_USB_CTRL_CHARBUFSIZE PRIu16 + typedef unsigned int usb_ctrl_timeout_msec; /* in milliseconds */ /* Note: there does not seem to be a standard type * for milliseconds, like there is an useconds_t */ + #define USB_CTRL_TIMEOUTMSEC_MIN 0 + #define USB_CTRL_TIMEOUTMSEC_MAX UINT_MAX /* defines */ #define USB_CLASS_PER_INTERFACE LIBUSB_CLASS_PER_INTERFACE @@ -319,18 +362,57 @@ #if WITH_LIBUSB_0_1 # include /* Structures */ + /* See detailed comments above, in libusb-1.0 definitions + * FIXME: It may make sense to constrain the limits to lowest common + * denominator that should fit alll of libusb-0.1, libusb-1.0 and libshut, + * so that any build of the practical (driver) code knows to not exceed + * any use-case. + */ + /* no typedef for usb_dev_handle - part of libusb-0.1 API names */ + typedef int usb_ctrl_requesttype; + #define USB_CTRL_REQUESTTYPE_MIN INT_MIN + #define USB_CTRL_REQUESTTYPE_MAX INT_MAX + typedef int usb_ctrl_request; + #define USB_CTRL_REQUEST_MIN INT_MIN + #define USB_CTRL_REQUEST_MAX INT_MAX + typedef int usb_ctrl_endpoint; + #define USB_CTRL_ENDPOINT_MIN INT_MIN + #define USB_CTRL_ENDPOINT_MAX INT_MAX + typedef int usb_ctrl_msgvalue; + #define USB_CTRL_MSGVALUE_MIN INT_MIN + #define USB_CTRL_MSGVALUE_MAX INT_MAX + typedef int usb_ctrl_repindex; + #define USB_CTRL_REPINDEX_MIN INT_MIN + #define USB_CTRL_REPINDEX_MAX INT_MAX + typedef int usb_ctrl_strindex; + #define USB_CTRL_STRINDEX_MIN INT_MIN + #define USB_CTRL_STRINDEX_MAX INT_MAX + typedef int usb_ctrl_descindex; + #define USB_CTRL_DESCINDEX_MIN INT_MIN + #define USB_CTRL_DESCINDEX_MAX INT_MAX + + /* Here MIN/MAX should not matter much, type mostly used for casting */ typedef char* usb_ctrl_charbuf; + typedef char usb_ctrl_char; + #define USB_CTRL_CHAR_MIN CHAR_MIN + #define USB_CTRL_CHAR_MAX CHAR_MAX + typedef int usb_ctrl_charbufsize; + #define USB_CTRL_CHARBUFSIZE_MIN INT_MIN + #define USB_CTRL_CHARBUFSIZE_MAX INT_MAX /* There is no PRIi :) So we define directly by spec */ #define PRI_NUT_USB_CTRL_CHARBUFSIZE "i" + typedef int usb_ctrl_timeout_msec; /* in milliseconds */ + #define USB_CTRL_TIMEOUTMSEC_MIN INT_MIN + #define USB_CTRL_TIMEOUTMSEC_MAX INT_MAX /* defines */ #define ERROR_ACCESS -EACCES diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index c2ea786e49..f13fd6ad81 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -156,7 +156,8 @@ static void ups_status_set(void); static bool_t hid_ups_walk(walkmode_t mode); static int reconnect_ups(void); static int ups_infoval_set(hid_info_t *item, double value); -static int callback(hid_dev_handle_t argudev, HIDDevice_t *arghd, unsigned char *rdbuf, int rdlen); +static int callback(hid_dev_handle_t argudev, HIDDevice_t *arghd, + usb_ctrl_charbuf rdbuf, usb_ctrl_charbufsize rdlen); #ifdef DEBUG static double interval(void); #endif @@ -1163,15 +1164,21 @@ static void process_boolean_info(const char *nutvalue) upsdebugx(5, "Warning: %s not in list of known values", nutvalue); } -static int callback(hid_dev_handle_t argudev, HIDDevice_t *arghd, unsigned char *rdbuf, int rdlen) +static int callback( + hid_dev_handle_t argudev, + HIDDevice_t *arghd, + usb_ctrl_charbuf rdbuf, + usb_ctrl_charbufsize rdlen) { int i; const char *mfr = NULL, *model = NULL, *serial = NULL; #ifndef SHUT_MODE int ret; #endif - upsdebugx(2, "Report Descriptor size = %d", rdlen); - upsdebug_hex(3, "Report Descriptor", rdbuf, (size_t)rdlen); + upsdebugx(2, "Report Descriptor size = %" PRI_NUT_USB_CTRL_CHARBUFSIZE, rdlen); + if ((uintmax_t)rdlen < (uintmax_t)SIZE_MAX) { + upsdebug_hex(3, "Report Descriptor", rdbuf, (size_t)rdlen); + } /* Save the global "hd" for this driver instance */ hd = arghd;