HID: uhid: forward raw output reports to user-space
[linux-2.6.git] / drivers / hid / uhid.c
index 3d1ebda..421c492 100644 (file)
@@ -82,31 +82,62 @@ static int uhid_queue_event(struct uhid_device *uhid, __u32 event)
 
 static int uhid_hid_start(struct hid_device *hid)
 {
-       return 0;
+       struct uhid_device *uhid = hid->driver_data;
+
+       return uhid_queue_event(uhid, UHID_START);
 }
 
 static void uhid_hid_stop(struct hid_device *hid)
 {
+       struct uhid_device *uhid = hid->driver_data;
+
+       hid->claimed = 0;
+       uhid_queue_event(uhid, UHID_STOP);
 }
 
 static int uhid_hid_open(struct hid_device *hid)
 {
-       return 0;
+       struct uhid_device *uhid = hid->driver_data;
+
+       return uhid_queue_event(uhid, UHID_OPEN);
 }
 
 static void uhid_hid_close(struct hid_device *hid)
 {
+       struct uhid_device *uhid = hid->driver_data;
+
+       uhid_queue_event(uhid, UHID_CLOSE);
 }
 
 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;
 }
 
 static int uhid_hid_parse(struct hid_device *hid)
 {
-       return 0;
+       struct uhid_device *uhid = hid->driver_data;
+
+       return hid_parse_report(hid, uhid->rd_data, uhid->rd_size);
 }
 
 static int uhid_hid_get_raw(struct hid_device *hid, unsigned char rnum,
@@ -118,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 = {