Commit d4bfa033 authored by Jiri Kosina's avatar Jiri Kosina

HID: make raw reports possible for both feature and output reports

In commit 2da31939 ("Bluetooth: Implement raw output support for HIDP
layer"), support for Bluetooth hid_output_raw_report was added, but it
pushes the data to the intr socket instead of the ctrl one. This has been
fixed by 6bf8268f ("Bluetooth: Use the control channel for raw HID reports")

Still, it is necessary to distinguish whether the report in question should be
either FEATURE or OUTPUT. For this, we have to extend the generic HID API,
so that hid_output_raw_report() callback provides means to specify this
value so that it can be passed down to lower level hardware drivers (currently
Bluetooth and USB).

Based on original patch by Bastien Nocera <hadess@hadess.net>
Acked-by: default avatarMarcel Holtmann <marcel@holtmann.org>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
parent c80d292f
......@@ -134,7 +134,7 @@ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t
goto out;
}
ret = dev->hid_output_raw_report(dev, buf, count);
ret = dev->hid_output_raw_report(dev, buf, count, HID_OUTPUT_REPORT);
out:
kfree(buf);
return ret;
......
......@@ -774,7 +774,8 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
return 0;
}
static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t count)
static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t count,
unsigned char report_type)
{
struct usbhid_device *usbhid = hid->driver_data;
struct usb_device *dev = hid_to_usb_dev(hid);
......@@ -785,7 +786,7 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co
ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
HID_REQ_SET_REPORT,
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
((HID_OUTPUT_REPORT + 1) << 8) | *buf,
((report_type + 1) << 8) | *buf,
interface->desc.bInterfaceNumber, buf + 1, count - 1,
USB_CTRL_SET_TIMEOUT);
......
......@@ -501,7 +501,7 @@ struct hid_device { /* device report descriptor */
void (*hiddev_report_event) (struct hid_device *, struct hid_report *);
/* handler for raw output data, used by hidraw */
int (*hid_output_raw_report) (struct hid_device *, __u8 *, size_t);
int (*hid_output_raw_report) (struct hid_device *, __u8 *, size_t, unsigned char);
/* debugging support via debugfs */
unsigned short debug;
......
......@@ -313,10 +313,21 @@ static int hidp_send_report(struct hidp_session *session, struct hid_report *rep
return hidp_queue_report(session, buf, rsize);
}
static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count)
static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count,
unsigned char report_type)
{
if (hidp_send_ctrl_message(hid->driver_data,
HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE,
switch (report_type) {
case HID_FEATURE_REPORT:
report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE;
break;
case HID_OUTPUT_REPORT:
report_type = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
break;
default:
return -EINVAL;
}
if (hidp_send_ctrl_message(hid->driver_data, report_type,
data, count))
return -ENOMEM;
return count;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment