aboutsummaryrefslogtreecommitdiff
path: root/lib/libusb
diff options
context:
space:
mode:
authorHans Petter Selasky <hselasky@FreeBSD.org>2019-12-27 20:35:12 +0000
committerHans Petter Selasky <hselasky@FreeBSD.org>2019-12-27 20:35:12 +0000
commit34b0ca243f6272d998475afd019d3a9e175cd817 (patch)
treeec0a06b0ea9d1a4623486baeeea3db145ef414ff /lib/libusb
parent7082625d976f0ad1b4207a12afe3c72e2acd9145 (diff)
downloadsrc-34b0ca243f6272d998475afd019d3a9e175cd817.tar.gz
src-34b0ca243f6272d998475afd019d3a9e175cd817.zip
Implement new libusb v2.0 API function, libusb20_dev_get_stats().
This function is useful when debugging USB device issues. MFC after: 1 week Sponsored by: Mellanox Technologies
Notes
Notes: svn path=/head/; revision=356136
Diffstat (limited to 'lib/libusb')
-rw-r--r--lib/libusb/Makefile1
-rw-r--r--lib/libusb/libusb20.314
-rw-r--r--lib/libusb/libusb20.c26
-rw-r--r--lib/libusb/libusb20.h7
-rw-r--r--lib/libusb/libusb20_int.h3
-rw-r--r--lib/libusb/libusb20_ugen20.c24
6 files changed, 73 insertions, 2 deletions
diff --git a/lib/libusb/Makefile b/lib/libusb/Makefile
index 2a97f5f1adb5..a594211363b8 100644
--- a/lib/libusb/Makefile
+++ b/lib/libusb/Makefile
@@ -219,6 +219,7 @@ MLINKS += libusb20.3 libusb20_dev_get_backend_name.3
MLINKS += libusb20.3 libusb20_dev_get_info.3
MLINKS += libusb20.3 libusb20_dev_get_iface_desc.3
MLINKS += libusb20.3 libusb20_dev_get_desc.3
+MLINKS += libusb20.3 libusb20_dev_get_stats.3
MLINKS += libusb20.3 libusb20_dev_close.3
MLINKS += libusb20.3 libusb20_dev_detach_kernel_driver.3
MLINKS += libusb20.3 libusb20_dev_set_config_index.3
diff --git a/lib/libusb/libusb20.3 b/lib/libusb/libusb20.3
index 590ff3c03c1c..eef79bd4658d 100644
--- a/lib/libusb/libusb20.3
+++ b/lib/libusb/libusb20.3
@@ -1,5 +1,5 @@
.\"
-.\" Copyright (c) 2008 Hans Petter Selasky
+.\" Copyright (c) 2008-2019 Hans Petter Selasky
.\"
.\" All rights reserved.
.\"
@@ -26,7 +26,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 3, 2013
+.Dd December 27, 2019
.Dt LIBUSB20 3
.Os
.Sh NAME
@@ -122,6 +122,8 @@ USB access library (libusb -lusb)
.Ft const char *
.Fn libusb20_dev_get_desc "struct libusb20_device *pdev"
.Ft int
+.Fn libusb20_dev_get_stats "struct libusb20_device *pdev" "struct libusb20_device_stats *pstats"
+.Ft int
.Fn libusb20_dev_close "struct libusb20_device *pdev"
.Ft int
.Fn libusb20_dev_detach_kernel_driver "struct libusb20_device *pdev" "uint8_t iface_index"
@@ -597,6 +599,14 @@ The format of the string is: "drivername<unit>: <description>"
.
.Pp
.
+.Fn libusb20_dev_get_stats
+retrieves the device statistics into the structure pointed to by the
+.Fa pstats
+argument.
+This function returns zero on success else a LIBUSB20_ERROR value is returned.
+.
+.Pp
+.
.Fn libusb20_dev_close
will close the given USB device.
.
diff --git a/lib/libusb/libusb20.c b/lib/libusb/libusb20.c
index 255e7d5ed516..6c2bf721bea9 100644
--- a/lib/libusb/libusb20.c
+++ b/lib/libusb/libusb20.c
@@ -78,6 +78,7 @@ dummy_callback(struct libusb20_transfer *xfer)
#define dummy_set_power_mode (void *)dummy_int
#define dummy_get_power_mode (void *)dummy_int
#define dummy_get_power_usage (void *)dummy_int
+#define dummy_get_stats (void *)dummy_int
#define dummy_kernel_driver_active (void *)dummy_int
#define dummy_detach_kernel_driver (void *)dummy_int
#define dummy_do_request_sync (void *)dummy_int
@@ -1049,6 +1050,31 @@ libusb20_dev_get_speed(struct libusb20_device *pdev)
return (pdev->usb_speed);
}
+int
+libusb20_dev_get_stats(struct libusb20_device *pdev, struct libusb20_device_stats *pstats)
+{
+ uint8_t do_close;
+ int error;
+
+ if (!pdev->is_opened) {
+ error = libusb20_dev_open(pdev, 0);
+ if (error == 0) {
+ do_close = 1;
+ } else {
+ do_close = 0;
+ }
+ } else {
+ do_close = 0;
+ }
+
+ error = pdev->methods->get_stats(pdev, pstats);
+
+ if (do_close)
+ (void) libusb20_dev_close(pdev);
+
+ return (error);
+}
+
/* if this function returns an error, the device is gone */
int
libusb20_dev_process(struct libusb20_device *pdev)
diff --git a/lib/libusb/libusb20.h b/lib/libusb/libusb20.h
index a35cde59b609..52684aa802d5 100644
--- a/lib/libusb/libusb20.h
+++ b/lib/libusb/libusb20.h
@@ -195,6 +195,12 @@ struct libusb20_quirk {
char quirkname[64 - 12];
};
+struct libusb20_device_stats {
+ uint64_t xfer_ok[4]; /* sorted by USB transfer type, UE_XXX */
+ uint64_t xfer_fail[4]; /* sorted by USB transfer type, UE_XXX */
+ uint64_t xfer_reserved[24]; /* reserved */
+};
+
#define LIBUSB20_MAX_FRAME_PRE_SCALE (1U << 31)
/* USB transfer operations */
@@ -243,6 +249,7 @@ int libusb20_dev_detach_kernel_driver(struct libusb20_device *pdev, uint8_t ifac
int libusb20_dev_set_config_index(struct libusb20_device *pdev, uint8_t configIndex);
int libusb20_dev_get_debug(struct libusb20_device *pdev);
int libusb20_dev_get_fd(struct libusb20_device *pdev);
+int libusb20_dev_get_stats(struct libusb20_device *pdev, struct libusb20_device_stats *pstat);
int libusb20_dev_kernel_driver_active(struct libusb20_device *pdev, uint8_t iface_index);
int libusb20_dev_open(struct libusb20_device *pdev, uint16_t transfer_max);
int libusb20_dev_process(struct libusb20_device *pdev);
diff --git a/lib/libusb/libusb20_int.h b/lib/libusb/libusb20_int.h
index 9c6b0138281d..5f54ee3717fc 100644
--- a/lib/libusb/libusb20_int.h
+++ b/lib/libusb/libusb20_int.h
@@ -108,10 +108,12 @@ typedef int (libusb20_reset_device_t)(struct libusb20_device *pdev);
typedef int (libusb20_set_power_mode_t)(struct libusb20_device *pdev, uint8_t power_mode);
typedef int (libusb20_get_power_mode_t)(struct libusb20_device *pdev, uint8_t *power_mode);
typedef int (libusb20_get_power_usage_t)(struct libusb20_device *pdev, uint16_t *power_usage);
+typedef int (libusb20_get_stats_t)(struct libusb20_device *pdev, struct libusb20_device_stats *pstats);
typedef int (libusb20_set_alt_index_t)(struct libusb20_device *pdev, uint8_t iface_index, uint8_t alt_index);
typedef int (libusb20_set_config_index_t)(struct libusb20_device *pdev, uint8_t index);
typedef int (libusb20_check_connected_t)(struct libusb20_device *pdev);
+
/* USB transfer specific */
typedef int (libusb20_tr_open_t)(struct libusb20_transfer *xfer, uint32_t MaxBufSize, uint32_t MaxFrameCount, uint8_t ep_no, uint16_t stream_id, uint8_t pre_scale);
typedef int (libusb20_tr_close_t)(struct libusb20_transfer *xfer);
@@ -131,6 +133,7 @@ typedef void (libusb20_tr_cancel_async_t)(struct libusb20_transfer *xfer);
m(n, set_power_mode) \
m(n, get_power_mode) \
m(n, get_power_usage) \
+ m(n, get_stats) \
m(n, set_alt_index) \
m(n, set_config_index) \
m(n, tr_cancel_async) \
diff --git a/lib/libusb/libusb20_ugen20.c b/lib/libusb/libusb20_ugen20.c
index d28e674c1fe3..5687caf97e4f 100644
--- a/lib/libusb/libusb20_ugen20.c
+++ b/lib/libusb/libusb20_ugen20.c
@@ -80,6 +80,7 @@ static libusb20_check_connected_t ugen20_check_connected;
static libusb20_set_power_mode_t ugen20_set_power_mode;
static libusb20_get_power_mode_t ugen20_get_power_mode;
static libusb20_get_power_usage_t ugen20_get_power_usage;
+static libusb20_get_stats_t ugen20_get_stats;
static libusb20_kernel_driver_active_t ugen20_kernel_driver_active;
static libusb20_detach_kernel_driver_t ugen20_detach_kernel_driver;
static libusb20_do_request_sync_t ugen20_do_request_sync;
@@ -670,6 +671,29 @@ ugen20_get_power_usage(struct libusb20_device *pdev, uint16_t *power_usage)
}
static int
+ugen20_get_stats(struct libusb20_device *pdev, struct libusb20_device_stats *pstats)
+{
+ struct usb_device_stats st;
+
+ if (ioctl(pdev->file_ctrl, IOUSB(USB_DEVICESTATS), &st))
+ return (LIBUSB20_ERROR_OTHER);
+
+ memset(pstats, 0, sizeof(*pstats));
+
+ pstats->xfer_ok[0] = st.uds_requests_ok[0];
+ pstats->xfer_ok[1] = st.uds_requests_ok[1];
+ pstats->xfer_ok[2] = st.uds_requests_ok[2];
+ pstats->xfer_ok[3] = st.uds_requests_ok[3];
+
+ pstats->xfer_fail[0] = st.uds_requests_fail[0];
+ pstats->xfer_fail[1] = st.uds_requests_fail[1];
+ pstats->xfer_fail[2] = st.uds_requests_fail[2];
+ pstats->xfer_fail[3] = st.uds_requests_fail[3];
+
+ return (0); /* success */
+}
+
+static int
ugen20_kernel_driver_active(struct libusb20_device *pdev,
uint8_t iface_index)
{