patch-2.3.40 linux/drivers/usb/hid.c
Next file: linux/drivers/usb/hid.h
Previous file: linux/drivers/usb/hid-debug.h
Back to the patch index
Back to the overall index
- Lines: 256
- Date:
Thu Jan 20 09:48:48 2000
- Orig file:
v2.3.39/linux/drivers/usb/hid.c
- Orig date:
Tue Jan 11 22:31:41 2000
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/hid.c linux/drivers/usb/hid.c
@@ -2,7 +2,7 @@
* hid.c Version 0.8
*
* Copyright (c) 1999 Andreas Gal
- * Copyright (c) 1999 Vojtech Pavlik
+ * Copyright (c) 2000 Vojtech Pavlik
*
* USB HID support for the Linux input drivers
*
@@ -41,6 +41,7 @@
#include <linux/spinlock.h>
#undef DEBUG
+#undef DEBUG_DATA
#include "usb.h"
#include "hid.h"
@@ -709,7 +710,7 @@
static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value)
{
report += (offset >> 5) << 2; offset &= 31;
- *(__u64*)report &= cpu_to_le64(~((1ULL << n) - 1) << offset);
+ *(__u64*)report &= cpu_to_le64(~((((__u64) 1 << n) - 1) << offset));
*(__u64*)report |= cpu_to_le64((__u64)value << offset);
}
@@ -762,6 +763,12 @@
}
break;
+ case HID_UP_LED:
+
+ usage->code = (usage->hid - 1) & 0xf;
+ usage->type = EV_LED; bit = input->ledbit; max = LED_MAX;
+ break;
+
default:
if (field->flags & HID_MAIN_ITEM_RELATIVE) {
@@ -904,7 +911,7 @@
return;
}
-#ifdef DEBUG
+#ifdef DEBUG_DATA
printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered) = ", len, report_enum->numbered ? "" : "un");
for (n = 0; n < len; n++)
printk(" %02x", data[n]);
@@ -952,10 +959,10 @@
static void hid_read_report(struct hid_device *hid, struct hid_report *report)
{
#if 0
- int rlen = ((report->size - 1) >> 3) + 1 + report_enum->numbered;
+ int rlen = ((report->size - 1) >> 3) + 1 + hid->report_enum[HID_INPUT_REPORT].numbered;
char rdata[rlen];
struct urb urb;
- int read;
+ int read, j;
memset(&urb, 0, sizeof(struct urb));
memset(rdata, 0, rlen);
@@ -973,7 +980,7 @@
for (j = 0; j < rlen; j++) printk(" %02x", rdata[j]);
printk("\n");
#endif
- continue;
+ return;
}
hid_irq(&urb);
@@ -981,33 +988,6 @@
}
/*
- * Configure the input layer interface
- * Read all reports and initalize the absoulte field values.
- */
-
-static void hid_init_input(struct hid_device *hid)
-{
- struct hid_report_enum *report_enum = hid->report_enum + HID_INPUT_REPORT;
- struct list_head *list;
- int i, j;
-
- list = report_enum->report_list.next;
-
- while (list != &report_enum->report_list) {
-
- struct hid_report *report = (struct hid_report *) list;
-
- list = list->next;
-
- for (i = 0; i < report->maxfield; i++)
- for (j = 0; j < report->field[i]->maxusage; j++)
- hid_configure_usage(hid, report->field[i], report->field[i]->usage + j);
-
- hid_read_report(hid, report);
- }
-}
-
-/*
* Output the field into the report.
*/
@@ -1034,9 +1014,11 @@
{
unsigned n;
+#if 0
/* skip the ID if we have a single report */
if (report->device->report_enum[report->type].numbered)
*data++ = report->id;
+#endif
for (n = 0; n < report->maxfield; n++)
hid_output_field(report->field[n], data);
@@ -1051,6 +1033,8 @@
int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
{
unsigned size = field->report_size;
+
+ hid_dump_input(field->usage + offset, value);
if (offset >= field->report_count) {
dbg("offset exceeds report_count");
@@ -1071,10 +1055,104 @@
return 0;
}
+static int hid_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field)
+{
+ struct hid_report_enum *report_enum = hid->report_enum + HID_OUTPUT_REPORT;
+ struct list_head *list = report_enum->report_list.next;
+ int i, j;
+
+ while (list != &report_enum->report_list) {
+ struct hid_report *report = (struct hid_report *) list;
+ list = list->next;
+ for (i = 0; i < report->maxfield; i++) {
+ *field = report->field[i];
+ for (j = 0; j < (*field)->maxusage; j++)
+ if ((*field)->usage[j].type == type && (*field)->usage[j].code == code)
+ return j;
+ }
+ }
+ return -1;
+}
+
+static void hid_ctrl(struct urb *urb)
+{
+ if (urb->status)
+ warn("ctrl urb status %d received", urb->status);
+}
+
+static int hid_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+{
+ struct hid_device *hid = dev->private;
+ struct hid_field *field = NULL;
+ int offset;
+
+ if ((offset = hid_find_field(hid, type, code, &field)) == -1) {
+ warn("event field not found");
+ return -1;
+ }
+
+ hid_set_field(field, offset, value);
+
+ if (hid->urbout.status == -EINPROGRESS) {
+ warn("had to kill output urb");
+ usb_unlink_urb(&hid->urbout);
+ }
+
+ hid_output_report(field->report, hid->bufout);
+
+ hid->dr.value = 0x200 | field->report->id;
+ hid->dr.length = ((field->report->size - 1) >> 3) + 1;
+ hid->urbout.transfer_buffer_length = hid->dr.length;
+
+ if (usb_submit_urb(&hid->urbout)) {
+ err("usb_submit_urb(out) failed");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Configure the input layer interface
+ * Read all reports and initalize the absoulte field values.
+ */
+
+static void hid_init_input(struct hid_device *hid)
+{
+ struct hid_report_enum *report_enum;
+ struct list_head *list;
+ int i, j, k;
+
+ hid->input.private = hid;
+ hid->input.event = hid_event;
+
+ for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
+
+ report_enum = hid->report_enum + k;
+ list = report_enum->report_list.next;
+
+ while (list != &report_enum->report_list) {
+
+ struct hid_report *report = (struct hid_report *) list;
+
+ list = list->next;
+
+ for (i = 0; i < report->maxfield; i++)
+ for (j = 0; j < report->field[i]->maxusage; j++)
+ hid_configure_usage(hid, report->field[i], report->field[i]->usage + j);
+
+ if (k == HID_INPUT_REPORT) {
+ usb_set_idle(hid->dev, 0, report->id);
+ hid_read_report(hid, report);
+ }
+ }
+ }
+}
+
static struct hid_device *usb_hid_configure(struct usb_device *dev, int ifnum)
{
struct usb_interface_descriptor *interface = &dev->actconfig->interface[ifnum].altsetting[0];
- struct usb_hid_descriptor *hdesc;
+ struct hid_descriptor *hdesc;
struct hid_device *hid;
unsigned rsize = 0;
int n;
@@ -1105,7 +1183,7 @@
return NULL;
}
-#ifdef DEBUG
+#ifdef DEBUG_DATA
printk(KERN_DEBUG __FILE__ ": report (size %u, read %d) = ", rsize, n);
for (n = 0; n < rsize; n++)
printk(" %02x", (unsigned) rdesc[n]);
@@ -1147,6 +1225,15 @@
hid_free_device(hid);
return NULL;
}
+
+ hid->dr.requesttype = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+ hid->dr.request = USB_REQ_SET_REPORT;
+ hid->dr.value = 0x200;
+ hid->dr.index = interface->bInterfaceNumber;
+ hid->dr.length = 1;
+
+ FILL_CONTROL_URB(&hid->urbout, dev, usb_sndctrlpipe(dev, 0),
+ (void*) &hid->dr, hid->bufout, 1, hid_ctrl, hid);
hid->version = hdesc->bcdHID;
hid->country = hdesc->bCountryCode;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)