HID: uhid: forward raw output reports to user-space
[linux-2.6.git] / drivers / hid / uhid.c
index 0226ba3..421c492 100644 (file)
@@ -112,6 +112,24 @@ static void uhid_hid_close(struct hid_device *hid)
 static int uhid_hid_input(struct input_dev *input, unsigned int type,
                          unsigned int code, int value)
 {
+       struct hid_device *hid = input_get_drvdata(input);
+       struct uhid_device *uhid = hid->driver_data;
+       unsigned long flags;
+       struct uhid_event *ev;
+
+       ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
+       if (!ev)
+               return -ENOMEM;
+
+       ev->type = UHID_OUTPUT_EV;
+       ev->u.output_ev.type = type;
+       ev->u.output_ev.code = code;
+       ev->u.output_ev.value = value;
+
+       spin_lock_irqsave(&uhid->qlock, flags);
+       uhid_queue(uhid, ev);
+       spin_unlock_irqrestore(&uhid->qlock, flags);
+
        return 0;
 }
 
@@ -131,7 +149,39 @@ static int uhid_hid_get_raw(struct hid_device *hid, unsigned char rnum,
 static int uhid_hid_output_raw(struct hid_device *hid, __u8 *buf, size_t count,
                               unsigned char report_type)
 {
-       return 0;
+       struct uhid_device *uhid = hid->driver_data;
+       __u8 rtype;
+       unsigned long flags;
+       struct uhid_event *ev;
+
+       switch (report_type) {
+       case HID_FEATURE_REPORT:
+               rtype = UHID_FEATURE_REPORT;
+               break;
+       case HID_OUTPUT_REPORT:
+               rtype = UHID_OUTPUT_REPORT;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (count < 1 || count > UHID_DATA_MAX)
+               return -EINVAL;
+
+       ev = kzalloc(sizeof(*ev), GFP_KERNEL);
+       if (!ev)
+               return -ENOMEM;
+
+       ev->type = UHID_OUTPUT;
+       ev->u.output.size = count;
+       ev->u.output.rtype = rtype;
+       memcpy(ev->u.output.data, buf, count);
+
+       spin_lock_irqsave(&uhid->qlock, flags);
+       uhid_queue(uhid, ev);
+       spin_unlock_irqrestore(&uhid->qlock, flags);
+
+       return count;
 }
 
 static struct hid_ll_driver uhid_hid_driver = {