summary refs log tree commit diff
path: root/drivers/hid/usbhid
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2007-10-14 14:47:56 +0200
committerJiri Kosina <jkosina@suse.cz>2007-10-14 14:47:56 +0200
commitd057fd4cb892087955568a139d15eae4115a0174 (patch)
tree4fd631492ff8d2d78c394fd2b054175588a7d633 /drivers/hid/usbhid
parentbb6c8d8fa9b5587eea18078ce0bcf6bb2905789f (diff)
parent709d27c04f4eccbc99d57a5569bce028915a4345 (diff)
downloadlinux-d057fd4cb892087955568a139d15eae4115a0174.tar.gz
Merge branch 'hidraw' into for-linus
Diffstat (limited to 'drivers/hid/usbhid')
-rw-r--r--drivers/hid/usbhid/hid-core.c38
1 files changed, 36 insertions, 2 deletions
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index a34e0f098f63..b38e559b7a46 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -32,6 +32,7 @@
 #include <linux/hid.h>
 #include <linux/hiddev.h>
 #include <linux/hid-debug.h>
+#include <linux/hidraw.h>
 #include "usbhid.h"
 
 /*
@@ -639,6 +640,28 @@ 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)
+{
+	struct usbhid_device *usbhid = hid->driver_data;
+	struct usb_device *dev = hid_to_usb_dev(hid);
+	struct usb_interface *intf = usbhid->intf;
+	struct usb_host_interface *interface = intf->cur_altsetting;
+	int ret;
+
+	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+		HID_REQ_SET_REPORT,
+		USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+		cpu_to_le16(((HID_OUTPUT_REPORT + 1) << 8) | *buf),
+		interface->desc.bInterfaceNumber, buf + 1, count - 1,
+		USB_CTRL_SET_TIMEOUT);
+
+	/* count also the report id */
+	if (ret > 0)
+		ret++;
+
+	return ret;
+}
+
 static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
 {
 	struct usbhid_device *usbhid = hid->driver_data;
@@ -882,6 +905,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
 	hid->hiddev_hid_event = hiddev_hid_event;
 	hid->hiddev_report_event = hiddev_report_event;
 #endif
+	hid->hid_output_raw_report = usbhid_output_raw_report;
 	return hid;
 
 fail:
@@ -920,6 +944,8 @@ static void hid_disconnect(struct usb_interface *intf)
 		hidinput_disconnect(hid);
 	if (hid->claimed & HID_CLAIMED_HIDDEV)
 		hiddev_disconnect(hid);
+	if (hid->claimed & HID_CLAIMED_HIDRAW)
+		hidraw_disconnect(hid);
 
 	usb_free_urb(usbhid->urbin);
 	usb_free_urb(usbhid->urbctrl);
@@ -952,11 +978,13 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
 		hid->claimed |= HID_CLAIMED_INPUT;
 	if (!hiddev_connect(hid))
 		hid->claimed |= HID_CLAIMED_HIDDEV;
+	if (!hidraw_connect(hid))
+		hid->claimed |= HID_CLAIMED_HIDRAW;
 
 	usb_set_intfdata(intf, hid);
 
 	if (!hid->claimed) {
-		printk ("HID device not claimed by input or hiddev\n");
+		printk ("HID device claimed by neither input, hiddev nor hidraw\n");
 		hid_disconnect(intf);
 		return -ENODEV;
 	}
@@ -972,10 +1000,16 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
 
 	if (hid->claimed & HID_CLAIMED_INPUT)
 		printk("input");
-	if (hid->claimed == (HID_CLAIMED_INPUT | HID_CLAIMED_HIDDEV))
+	if ((hid->claimed & HID_CLAIMED_INPUT) && ((hid->claimed & HID_CLAIMED_HIDDEV) ||
+				hid->claimed & HID_CLAIMED_HIDRAW))
 		printk(",");
 	if (hid->claimed & HID_CLAIMED_HIDDEV)
 		printk("hiddev%d", hid->minor);
+	if ((hid->claimed & HID_CLAIMED_INPUT) && (hid->claimed & HID_CLAIMED_HIDDEV) &&
+			(hid->claimed & HID_CLAIMED_HIDRAW))
+		printk(",");
+	if (hid->claimed & HID_CLAIMED_HIDRAW)
+		printk("hidraw%d", ((struct hidraw*)hid->hidraw)->minor);
 
 	c = "Device";
 	for (i = 0; i < hid->maxcollection; i++) {