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 = {
 
        UHID_STOP,
        UHID_OPEN,
        UHID_CLOSE,
+       UHID_OUTPUT,
        UHID_OUTPUT_EV,
        UHID_INPUT,
 };
 
 #define UHID_DATA_MAX 4096
 
+enum uhid_report_type {
+       UHID_FEATURE_REPORT,
+       UHID_OUTPUT_REPORT,
+       UHID_INPUT_REPORT,
+};
+
 struct uhid_input_req {
        __u8 data[UHID_DATA_MAX];
        __u16 size;
 } __attribute__((__packed__));
 
+struct uhid_output_req {
+       __u8 data[UHID_DATA_MAX];
+       __u16 size;
+       __u8 rtype;
+} __attribute__((__packed__));
+
 struct uhid_output_ev_req {
        __u16 type;
        __u16 code;
        union {
                struct uhid_create_req create;
                struct uhid_input_req input;
+               struct uhid_output_req output;
                struct uhid_output_ev_req output_ev;
        } u;
 } __attribute__((__packed__));