diff -dur linux-2.6.1-orig/drivers/usb/input/hiddev.c linux-2.6.1/drivers/usb/input/hiddev.c
--- linux-2.6.1-orig/drivers/usb/input/hiddev.c	2004-01-08 22:59:26.000000000 -0800
+++ linux-2.6.1/drivers/usb/input/hiddev.c	2004-01-16 09:37:27.000000000 -0800
@@ -404,6 +404,7 @@
 	struct hiddev_report_info rinfo;
 	struct hiddev_field_info finfo;
 	struct hiddev_usage_ref uref;
+	struct hiddev_usage_ref_multi uref_multi;
 	struct hiddev_devinfo dinfo;
 	struct hid_report *report;
 	struct hid_field *field;
@@ -640,6 +641,61 @@
 
 		return 0;
 
+	case HIDIOCGUSAGES:
+	case HIDIOCSUSAGES: 
+	{
+		unsigned val_index;
+
+		if (copy_from_user(&uref_multi, (void *) arg, 
+				   sizeof(uref_multi)))
+			return -EFAULT;
+
+		if (cmd != HIDIOCGUSAGE && 
+		    uref_multi.report_type == HID_REPORT_TYPE_INPUT)
+			return -EINVAL;
+
+		if (uref_multi.report_id == HID_REPORT_ID_UNKNOWN) {
+			/* This cast should be ok because the fields we are
+			 * referencing occur in the same offsets in both 
+			 * structures.
+			 */
+			field = hiddev_lookup_usage(hid, (struct hiddev_usage_ref *) &uref_multi);
+			if (field == NULL)
+				return -EINVAL;
+		} else {
+			rinfo.report_type = uref_multi.report_type;
+			rinfo.report_id = uref_multi.report_id;
+			if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
+				return -EINVAL;
+
+			if (uref_multi.field_index >= report->maxfield)
+				return -EINVAL;
+
+			field = report->field[uref_multi.field_index];
+			if (uref_multi.num_values >= HID_MAX_USAGES || 
+			    uref_multi.usage_index >= field->maxusage || 
+			   (uref_multi.usage_index + uref_multi.num_values) >= 
+			    field->maxusage)
+				return -EINVAL;
+		}
+		for (val_index = 0; val_index < uref_multi.num_values; 
+		     val_index++) {
+			if (cmd == HIDIOCGUSAGES)
+				uref_multi.values[val_index] = 
+					field->value[uref_multi.usage_index + 
+					val_index];
+			else if (cmd == HIDIOCSUSAGES)
+				field->value[uref_multi.usage_index + val_index] = 
+					uref_multi.values[val_index];
+
+		}
+		if (cmd == HIDIOCGUSAGES)
+			if (copy_to_user((void *) arg, &uref_multi, 
+					 sizeof(uref_multi)))
+				return -EFAULT;
+		return 0;
+	}
+
 	case HIDIOCGCOLLECTIONINFO:
 		if (copy_from_user(&cinfo, (void *) arg, sizeof(cinfo)))
 			return -EFAULT;
diff -dur linux-2.6.1-orig/include/linux/hiddev.h linux-2.6.1/include/linux/hiddev.h
--- linux-2.6.1-orig/include/linux/hiddev.h	2004-01-08 22:59:19.000000000 -0800
+++ linux-2.6.1/include/linux/hiddev.h	2004-01-16 09:36:32.000000000 -0800
@@ -126,6 +126,18 @@
 	__s32 value;
 };
 
+/* hiddev_usage_ref_multi is used for sending multiple bytes to a control.
+ * It really manifests itself as setting the value of consecutive usages */
+struct hiddev_usage_ref_multi {
+	unsigned report_type;
+	unsigned report_id;
+	unsigned field_index;
+	unsigned usage_index;
+	unsigned usage_code;
+	unsigned short num_values;
+	__s32 values[HID_MAX_USAGES];
+};
+
 /* 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 
@@ -161,6 +173,10 @@
 #define HIDIOCGCOLLECTIONINFO	_IOWR('H', 0x11, struct hiddev_collection_info)
 #define HIDIOCGPHYS(len)	_IOC(_IOC_READ, 'H', 0x12, len)
 
+/* For writing/reading to multiple/consecutive usages */
+#define HIDIOCGUSAGES		_IOWR('H', 0x13, struct hiddev_usage_ref_multi)
+#define HIDIOCSUSAGES		_IOW('H', 0x14, struct hiddev_usage_ref_multi)
+
 /* 
  * Flags to be used in HIDIOCSFLAG
  */
