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>
This commit is contained in:
Johann Fischer 2024-05-29 14:57:52 +02:00 committed by Henrik Brix Andersen
parent a33341ac66
commit af63e488f0
2 changed files with 16 additions and 5 deletions

View file

@ -106,8 +106,10 @@ struct hid_device_ops {
* 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,

View file

@ -231,25 +231,34 @@ static int handle_get_report(const struct device *dev,
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;
}