aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/uhid.c
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@googlemail.com>2012-06-10 09:16:24 -0400
committerJiri Kosina <jkosina@suse.cz>2012-06-18 07:42:02 -0400
commit3b3baa82e4306b5160692643fab2fa322ceb94f9 (patch)
tree04885740c41ff3b9f85af8a641d942b4a9b9dd81 /drivers/hid/uhid.c
parentf80e13601c51a836b2aac583b8a3b4327c0c27ce (diff)
HID: uhid: forward raw output reports to user-space
Some drivers that use non-standard HID features require raw output reports sent to the device. We now forward these requests directly to user-space so the transport-level driver can correctly send it to the device or handle it correspondingly. There is no way to signal back whether the transmission was successful, moreover, there might be lots of messages coming out from the driver flushing the output-queue. However, there is currently no driver that causes this so we are safe. If some drivers need to transmit lots of data this way, we need a method to synchronize this and can implement another UHID_OUTPUT_SYNC event. Signed-off-by: David Herrmann <dh.herrmann@googlemail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/uhid.c')
-rw-r--r--drivers/hid/uhid.c34
1 files changed, 33 insertions, 1 deletions
diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c
index 4dd693e1c8b8..421c492dc824 100644
--- a/drivers/hid/uhid.c
+++ b/drivers/hid/uhid.c
@@ -149,7 +149,39 @@ static int uhid_hid_get_raw(struct hid_device *hid, unsigned char rnum,
149static int uhid_hid_output_raw(struct hid_device *hid, __u8 *buf, size_t count, 149static int uhid_hid_output_raw(struct hid_device *hid, __u8 *buf, size_t count,
150 unsigned char report_type) 150 unsigned char report_type)
151{ 151{
152 return 0; 152 struct uhid_device *uhid = hid->driver_data;
153 __u8 rtype;
154 unsigned long flags;
155 struct uhid_event *ev;
156
157 switch (report_type) {
158 case HID_FEATURE_REPORT:
159 rtype = UHID_FEATURE_REPORT;
160 break;
161 case HID_OUTPUT_REPORT:
162 rtype = UHID_OUTPUT_REPORT;
163 break;
164 default:
165 return -EINVAL;
166 }
167
168 if (count < 1 || count > UHID_DATA_MAX)
169 return -EINVAL;
170
171 ev = kzalloc(sizeof(*ev), GFP_KERNEL);
172 if (!ev)
173 return -ENOMEM;
174
175 ev->type = UHID_OUTPUT;
176 ev->u.output.size = count;
177 ev->u.output.rtype = rtype;
178 memcpy(ev->u.output.data, buf, count);
179
180 spin_lock_irqsave(&uhid->qlock, flags);
181 uhid_queue(uhid, ev);
182 spin_unlock_irqrestore(&uhid->qlock, flags);
183
184 return count;
153} 185}
154 186
155static struct hid_ll_driver uhid_hid_driver = { 187static struct hid_ll_driver uhid_hid_driver = {