# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.559   -> 1.560  
#	include/linux/hiddev.h	1.2     -> 1.3    
#	Documentation/usb/hiddev.txt	1.1     -> 1.2    
#	drivers/usb/hiddev.c	1.6     -> 1.7    
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/03/22	stewart@inverse.wetlogic.net	1.560
# [PATCH] Re: [PATCH] hiddev code and docs cleanup
# 
# I took some time to clean up the code a little, and to add the new
# calls to the documentation.  See patch below.
# 
# --
# Paul
# --------------------------------------------
#
diff -Nru a/Documentation/usb/hiddev.txt b/Documentation/usb/hiddev.txt
--- a/Documentation/usb/hiddev.txt	Wed Apr  3 16:39:41 2002
+++ b/Documentation/usb/hiddev.txt	Wed Apr  3 16:39:41 2002
@@ -18,10 +18,10 @@
 The data flow for a HID event produced by a device is something like
 the following :
 
- usb.c ---> hid.c  ----> input.c ----> [keyboard/mouse/joystick/event]
-                    |
-                    |
-                    --> hiddev.c ----> POWER / MONITOR CONTROL 
+ usb.c ---> hid-core.c  ----> input.c ----> [keyboard/mouse/joystick/event]
+                         |
+                         |
+                          --> hiddev.c ----> POWER / MONITOR CONTROL 
 
 In addition, other subsystems (apart from USB) can potentially feed
 events into the input subsystem, but these have no effect on the hid
@@ -63,12 +63,18 @@
 
 The hiddev API uses a read() interface, and a set of ioctl() calls.
 
+HID devices exchange data with the host computer using data
+bundles called "reports".  Each report is divided into "fields",
+each of which can have one or more "usages".  In the hid-core,
+each one of these usages has a single signed 32 bit value.
 
 read():
-This is the event interface. When the HID device performs an
-interrupt transfer, indicating a change of state, data will be made
-available at the associated hiddev device with the content of a struct
-hiddev_event: 
+This is the event interface.  When the HID device's state changes,
+it performs an interrupt transfer containing a report which contains
+the changed value.  The hid-core.c module parses the report, and
+returns to hiddev.c the individual usages that have changed within
+the report.  In its basic mode, the hiddev will make these individual
+usage changes available to the reader using a struct hiddev_event:
 
        struct hiddev_event {
            unsigned hid;
@@ -78,7 +84,10 @@
 containing the HID usage identifier for the status that changed, and
 the value that it was changed to. Note that the structure is defined
 within <linux/hiddev.h>, along with some other useful #defines and
-structures. 
+structures.  The HID usage identifier is a composite of the HID usage
+page shifted to the 16 high order bits ORed with the usage code.  The
+behavior of the read() function can be modified using the HIDIOCSFLAG
+ioctl() described below.
 
 
 ioctl(): 
@@ -108,7 +117,9 @@
 Instructs the kernel to retrieve all input and feature report values
 from the device. At this point, all the usage structures will contain
 current values for the device, and will maintain it as the device
-changes.
+changes.  Note that the use of this ioctl is unnecessary in general,
+since later kernels automatically initialize the reports from the
+device at attach time.
 
 HIDIOCGNAME - string (variable length)
 Gets the device name
@@ -116,12 +127,12 @@
 HIDIOCGREPORT - struct hiddev_report_info (write)
 Instructs the kernel to get a feature or input report from the device,
 in order to selectively update the usage structures (in contrast to
-INITREPORT). 
+INITREPORT).
 
 HIDIOCSREPORT - struct hiddev_report_info (write)
 Instructs the kernel to send a report to the device. This report can
 be filled in by the user through HIDIOCSUSAGE calls (below) to fill in
-individual usage values in the report beforesending the report in full
+individual usage values in the report before sending the report in full
 to the device. 
 
 HIDIOCGREPORTINFO - struct hiddev_report_info (read/write)
@@ -157,6 +168,25 @@
 usage if it is found. 
 
 HIDIOCSUSAGE - struct hiddev_usage_ref (write)
-Sets the value of a usage in an output report.
-
-
+Sets the value of a usage in an output report.  The user fills in
+the hiddev_usage_ref structure as above, but additionally fills in
+the value field.
+
+HIDIOCGFLAG - int (read)
+HIDIOCSFLAG - int (write)
+These operations respectively inspect and replace the mode flags
+that influence the read() call above.  The flags are as follows:
+
+    HIDDEV_FLAG_UREF - read() calls will now return 
+        struct hiddev_usage_ref instead of struct hiddev_event.
+        This is a larger structure, but in situations where the
+        device has more than one usage in its reports with the
+        same usage code, this mode serves to resolve such
+        ambiguity.
+
+    HIDDEV_FLAG_REPORT - This flag can only be used in conjunction
+        with HIDDEV_FLAG_UREF.  With this flag set, when the device
+        sends a report, a struct hiddev_usage_ref will be returned
+        to read() filled in with the report_type and report_id, but 
+        with field_index set to FIELD_INDEX_NONE.  This serves as
+        additional notification when the device has sent a report.
diff -Nru a/drivers/usb/hiddev.c b/drivers/usb/hiddev.c
--- a/drivers/usb/hiddev.c	Wed Apr  3 16:39:41 2002
+++ b/drivers/usb/hiddev.c	Wed Apr  3 16:39:41 2002
@@ -341,9 +341,6 @@
 	return 0;
 }
 
-#define GET_TIMEOUT 3
-#define SET_TIMEOUT 3
-
 /*
  * "ioctl" file op
  */
@@ -529,36 +526,12 @@
 		return copy_to_user((void *) arg, &uref, sizeof(uref));
 
 	case HIDIOCGUSAGE:
-		if (copy_from_user(&uref, (void *) arg, sizeof(uref)))
-			return -EFAULT;
-
-		if (uref.report_id == HID_REPORT_ID_UNKNOWN) {
-			field = hiddev_lookup_usage(hid, &uref);
-			if (field == NULL)
-				return -EINVAL;
-		} else {
-			rinfo.report_type = uref.report_type;
-			rinfo.report_id = uref.report_id;
-			if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
-				return -EINVAL;
-
-			if (uref.field_index >= report->maxfield)
-				return -EINVAL;
-
-			field = report->field[uref.field_index];
-			if (uref.usage_index >= field->maxusage)
-				return -EINVAL;
-		}
-
-		uref.value = field->value[uref.usage_index];
-
-		return copy_to_user((void *) arg, &uref, sizeof(uref));
-
 	case HIDIOCSUSAGE:
 		if (copy_from_user(&uref, (void *) arg, sizeof(uref)))
 			return -EFAULT;
 
-		if (uref.report_type == HID_REPORT_TYPE_INPUT)
+		if (cmd == HIDIOCSUSAGE &&
+		    uref.report_type != HID_REPORT_TYPE_OUTPUT)
 			return -EINVAL;
 
 		if (uref.report_id == HID_REPORT_ID_UNKNOWN) {
@@ -579,7 +552,12 @@
 				return -EINVAL;
 		}
 
-		field->value[uref.usage_index] = uref.value;
+		if (cmd == HIDIOCGUSAGE) {
+			uref.value = field->value[uref.usage_index];
+			return copy_to_user((void *) arg, &uref, sizeof(uref));
+		} else {
+			field->value[uref.usage_index] = uref.value;
+		}
 
 		return 0;
 
diff -Nru a/include/linux/hiddev.h b/include/linux/hiddev.h
--- a/include/linux/hiddev.h	Wed Apr  3 16:39:41 2002
+++ b/include/linux/hiddev.h	Wed Apr  3 16:39:41 2002
@@ -119,6 +119,10 @@
 	__s32 value;
 };
 
+/* FIELD_INDEX_NONE is returned in read() data from the kernel when flags
+ * is set to (HIDDEV_FLAG_UREF | HIDDEV_FLAG_REPORT) and a new report has
+ * been sent by the device 
+ */
 #define HID_FIELD_INDEX_NONE 0xffffffff
 
 /*
@@ -139,20 +143,20 @@
 #define HIDIOCGNAME(len)	_IOC(_IOC_READ, 'H', 0x06, len)
 #define HIDIOCGREPORT		_IOW('H', 0x07, struct hiddev_report_info)
 #define HIDIOCSREPORT		_IOW('H', 0x08, struct hiddev_report_info)
-#define HIDIOCGREPORTINFO       _IOWR('H', 0x09, struct hiddev_report_info)
-#define HIDIOCGFIELDINFO        _IOWR('H', 0x0A, struct hiddev_field_info)
-#define HIDIOCGUSAGE            _IOWR('H', 0x0B, struct hiddev_usage_ref)
-#define HIDIOCSUSAGE            _IOW('H', 0x0C, struct hiddev_usage_ref)
-#define HIDIOCGUCODE            _IOWR('H', 0x0D, struct hiddev_usage_ref)
-#define HIDIOCGFLAG             _IOR('H', 0x0E, int)
-#define HIDIOCSFLAG             _IOW('H', 0x0F, int)
+#define HIDIOCGREPORTINFO	_IOWR('H', 0x09, struct hiddev_report_info)
+#define HIDIOCGFIELDINFO	_IOWR('H', 0x0A, struct hiddev_field_info)
+#define HIDIOCGUSAGE		_IOWR('H', 0x0B, struct hiddev_usage_ref)
+#define HIDIOCSUSAGE		_IOW('H', 0x0C, struct hiddev_usage_ref)
+#define HIDIOCGUCODE		_IOWR('H', 0x0D, struct hiddev_usage_ref)
+#define HIDIOCGFLAG		_IOR('H', 0x0E, int)
+#define HIDIOCSFLAG		_IOW('H', 0x0F, int)
 
 /* 
  * Flags to be used in HIDIOCSFLAG
  */
-#define HIDDEV_FLAG_UREF     0x1
-#define HIDDEV_FLAG_REPORT   0x2
-#define HIDDEV_FLAGS         0x3
+#define HIDDEV_FLAG_UREF	0x1
+#define HIDDEV_FLAG_REPORT	0x2
+#define HIDDEV_FLAGS		0x3
 
 /* To traverse the input report descriptor info for a HID device, perform the 
  * following: