usb: device_next: hid: fix Get Report buffer handling

After the get_report() callback, we need to determine how many bytes the
HID device wrote to the report buffer. Use the callback return value to
do this, and modify the net_buf data length value if get_report was
successful.

Reported-by: Marek Pieta <Marek.Pieta@nordicsemi.no>
Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
diff --git a/include/zephyr/usb/class/usbd_hid.h b/include/zephyr/usb/class/usbd_hid.h
index 5dd6d0d..9798b08 100644
--- a/include/zephyr/usb/class/usbd_hid.h
+++ b/include/zephyr/usb/class/usbd_hid.h
@@ -106,8 +106,10 @@
 	 * feature, input, or output report, which is specified by the argument
 	 * type. If there is no report ID in the report descriptor, the id
 	 * argument is zero. The callback implementation must check the
-	 * arguments, such as whether the report type is supported, and return
-	 * a nonzero value to indicate an unsupported type or an error.
+	 * arguments, such as whether the report type is supported and the
+	 * report length, and return a negative value to indicate an
+	 * unsupported type or an error, or return the length of the report
+	 * written to the buffer.
 	 */
 	int (*get_report)(const struct device *dev,
 			  const uint8_t type, const uint8_t id,
diff --git a/subsys/usb/device_next/class/usbd_hid.c b/subsys/usb/device_next/class/usbd_hid.c
index 6fef55d..1b39aa1 100644
--- a/subsys/usb/device_next/class/usbd_hid.c
+++ b/subsys/usb/device_next/class/usbd_hid.c
@@ -231,25 +231,34 @@
 	const uint8_t id = HID_GET_REPORT_ID(setup->wValue);
 	struct hid_device_data *const ddata = dev->data;
 	const struct hid_device_ops *ops = ddata->ops;
+	const size_t size = net_buf_tailroom(buf);
+	int ret = 0;
 
 	switch (type) {
 	case HID_REPORT_TYPE_INPUT:
 		LOG_DBG("Get Report, Input Report ID %u", id);
-		errno = ops->get_report(dev, type, id, net_buf_tailroom(buf), buf->data);
+		ret = ops->get_report(dev, type, id, size, buf->data);
 		break;
 	case HID_REPORT_TYPE_OUTPUT:
 		LOG_DBG("Get Report, Output Report ID %u", id);
-		errno = ops->get_report(dev, type, id, net_buf_tailroom(buf), buf->data);
+		ret = ops->get_report(dev, type, id, size, buf->data);
 		break;
 	case HID_REPORT_TYPE_FEATURE:
 		LOG_DBG("Get Report, Feature Report ID %u", id);
-		errno = ops->get_report(dev, type, id, net_buf_tailroom(buf), buf->data);
+		ret = ops->get_report(dev, type, id, size, buf->data);
 		break;
 	default:
 		errno = -ENOTSUP;
 		break;
 	}
 
+	if (ret > 0) {
+		__ASSERT(ret <= size, "Buffer overflow in the HID driver");
+		net_buf_add(buf, MIN(size, ret));
+	} else {
+		errno = ret ? ret : -ENOTSUP;
+	}
+
 	return 0;
 }