On Fri, Jun 08, 2001 at 07:43:31AM +1000, root wrote:
> While running a descriptor dump (code attached) on my USB speakers with
> the hiddev ioctl()s in 2.4.5-ac7, I hit the following oops using JE's
> UHCI. Repeatable on this HCD, not tried on OHCI or GA's UHCI.
> 
> >>EIP; 00000000 Before first symbol
> Trace; c885d423 <[hid]hiddev_ioctl+293/920>
> Trace; c019a702 <write_chan+1d2/1f0>
> Trace; c019534d <tty_write+26d/350>
> Trace; c019a530 <write_chan+0/1f0>
> Trace; c0196ec2 <tty_ioctl+3d2/3f0>
> Trace; c014e8b7 <sys_ioctl+237/2c0>
> Trace; c0107437 <system_call+33/38>
> 
> On a related note, what is the concensus about whether speaker HID
> should be directed to input or to raw HID events? I am currently
> thinking input events, because that would allow common work with
> equivalent buttons on a keyboard.

It doesn't work in -ac7. My fault. A patch against ac9 (already sent to
Alan) to make it work is attached.

-- 
Vojtech Pavlik
SuSE Labs
diff -urN linux-2.4.5-ac9/drivers/usb/hid-core.c linux/drivers/usb/hid-core.c
--- linux-2.4.5-ac9/drivers/usb/hid-core.c      Wed Jun  6 10:41:18 2001
+++ linux/drivers/usb/hid-core.c        Wed Jun  6 15:13:52 2001
@@ -737,7 +737,7 @@
                hidinput_hid_event(hid, field, usage, value);
 #ifdef CONFIG_USB_HIDDEV
        if (hid->claimed & HID_CLAIMED_HIDDEV)
-               hiddev_hid_event(hid->hiddev.private, usage->hid, value);
+               hiddev_hid_event(hid, usage->hid, value);
 #endif
 }
 
@@ -796,9 +796,9 @@
        memcpy(field->value, value, count * sizeof(__s32));
 }
 
-static int hid_input_report(u8 *data, int len, struct hid_device *hid)
+static int hid_input_report(int type, u8 *data, int len, struct hid_device *hid)
 {
-       struct hid_report_enum *report_enum = hid->report_enum + HID_INPUT_REPORT;
+       struct hid_report_enum *report_enum = hid->report_enum + type;
        struct hid_report *report;
        int n, size;
 
@@ -884,14 +884,14 @@
                return;
        }
 
-       hid_input_report(urb->transfer_buffer, urb->actual_length, urb->context);
+       hid_input_report(HID_INPUT_REPORT, urb->transfer_buffer, urb->actual_length, 
+urb->context);
 }
 
 /*
  * hid_read_report() reads in report values without waiting for an irq urb.
  */
 
-static void hid_read_report(struct hid_device *hid, struct hid_report *report)
+void hid_read_report(struct hid_device *hid, struct hid_report *report)
 {
        int len = ((report->size - 1) >> 3) + 1 + 
hid->report_enum[report->type].numbered;
        u8 data[len];
@@ -902,7 +902,7 @@
                return;
        }
 
-       hid_input_report(data, len, hid);
+       hid_input_report(report->type, data, len, hid);
 }
 
 /*
@@ -1051,7 +1051,7 @@
 /*
  * Initialize all readable reports
  */
-static void hid_init_reports(struct hid_device *hid)
+void hid_init_reports(struct hid_device *hid)
 {
        int i;
        struct hid_report *report;
@@ -1126,7 +1126,7 @@
                }
 
 #ifdef DEBUG_DATA
-               printk(KERN_DEBUG __FILE__ ": report (size %u, read %d) = ", rsize, n);
+               printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = 
+", rsize, n);
                for (n = 0; n < rsize; n++)
                        printk(" %02x", (unsigned) rdesc[n]);
                printk("\n");
@@ -1232,7 +1232,7 @@
        if (hid->claimed == (HID_CLAIMED_INPUT | HID_CLAIMED_HIDDEV))
                printk(",");
        if (hid->claimed & HID_CLAIMED_HIDDEV)
-               printk("hiddev%d", hid->hiddev.minor);
+               printk("hiddev%d", hid->minor);
 
        c = "Device";
        for (i = 0; i < hid->maxapplication; i++)
diff -urN linux-2.4.5-ac9/drivers/usb/hid-debug.h linux/drivers/usb/hid-debug.h
--- linux-2.4.5-ac9/drivers/usb/hid-debug.h     Wed Jun  6 10:41:18 2001
+++ linux/drivers/usb/hid-debug.h       Wed Jun  6 14:03:47 2001
@@ -231,7 +231,7 @@
 }
 
 static void hid_dump_input(struct hid_usage *usage, __s32 value) {
-       printk("hidd: input ");
+       printk("hid-debug: input ");
        resolv_usage(usage->hid);
        printk(" = %d\n", value);
 }
diff -urN linux-2.4.5-ac9/drivers/usb/hid.h linux/drivers/usb/hid.h
--- linux-2.4.5-ac9/drivers/usb/hid.h   Wed Jun  6 10:41:18 2001
+++ linux/drivers/usb/hid.h     Wed Jun  6 15:12:12 2001
@@ -288,14 +288,6 @@
        char buffer[HID_BUFFER_SIZE];
 };
 
-struct hid_iodev {
-       int minor;
-       void *private;                                          /* hiddev opaque 
device structure */
-       void (*read_report)(struct hid_device *, struct hid_report *);
-       void (*read_all_reports)(struct hid_device *);
-       void (*write_report)(struct hid_device *, struct hid_report *);
-};
-
 #define HID_CLAIMED_INPUT      1
 #define HID_CLAIMED_HIDDEV     2
 
@@ -322,7 +314,8 @@
        unsigned quirks;                                                /* Various 
quirks the device can pull on us */
 
        struct input_dev input;                                         /* The input 
structure */
-       struct hid_iodev hiddev;                                        /* The hiddev 
structure */
+       void *hiddev;                                                   /* The hiddev 
+structure */
+       int minor;                                                      /* Hiddev 
+minor number */
 
        int open;                                                       /* is the 
device open by anyone? */
        char name[128];                                                 /* Device name 
*/
@@ -376,3 +369,5 @@
 int hid_find_field(struct hid_device *, unsigned int, unsigned int, struct hid_field 
**);
 int hid_set_field(struct hid_field *, unsigned, __s32);
 void hid_write_report(struct hid_device *, struct hid_report *);
+void hid_read_report(struct hid_device *, struct hid_report *);
+void hid_init_reports(struct hid_device *hid);
diff -urN linux-2.4.5-ac9/drivers/usb/hiddev.c linux/drivers/usb/hiddev.c
--- linux-2.4.5-ac9/drivers/usb/hiddev.c        Wed Jun  6 10:41:18 2001
+++ linux/drivers/usb/hiddev.c  Wed Jun  6 15:14:54 2001
@@ -146,9 +146,9 @@
  * This is where hid.c calls into hiddev to pass an event that occurred over
  * the interrupt pipe
  */
-void hiddev_hid_event(void *private, unsigned int usage, int value)
+void hiddev_hid_event(struct hid_device *hid, unsigned int usage, int value)
 {
-       struct hiddev *hiddev = private;
+       struct hiddev *hiddev = hid->hiddev;
        struct hiddev_list *list = hiddev->list;
 
        while (list) {
@@ -176,15 +176,6 @@
 }
 
 /*
- * If there are no more readers, deregister interest in interrupt events
- */
-static void hiddev_close(struct hiddev *hiddev)
-{
-       struct hid_device *hid = hiddev->hid;
-       if (!--hid->open) usb_unlink_urb(&hid->urb);
-}
-
-/*
  * De-allocate a hiddev structure
  */
 static void hiddev_cleanup(struct hiddev *hiddev)
@@ -211,11 +202,10 @@
        *listptr = (*listptr)->next;
 
        if (!--list->hiddev->open) {
-               if (list->hiddev->exist) {
-                       hiddev_close(list->hiddev);
-               } else {
+               if (list->hiddev->exist) 
+                       hid_close(list->hiddev->hid);
+               else
                        hiddev_cleanup(list->hiddev);
-               }
        }
 
        kfree(list);
@@ -229,7 +219,6 @@
  */
 static int hiddev_open(struct inode * inode, struct file * file) {
        struct hiddev_list *list;
-       struct hid_device *hid;
 
        int i = MINOR(inode->i_rdev) - HIDDEV_MINOR_BASE;
 
@@ -247,13 +236,8 @@
        file->private_data = list;
 
        if (!list->hiddev->open++)
-               if (list->hiddev->exist) {
-                       hid = hiddev_table[i]->hid;
-                       if (!hid->open++) {
-                               hid->urb.dev = hid->dev;
-                               if (usb_submit_urb(&hid->urb)) return -EIO;
-                       }
-               }
+               if (list->hiddev->exist)
+                       hid_open(hiddev_table[i]->hid);
 
        return 0;
 }
@@ -403,7 +387,8 @@
                }
 
        case HIDIOCINITREPORT:
-               (*hid->hiddev.read_all_reports)(hid);
+
+               hid_init_reports(hid);
 
                return 0;
 
@@ -417,7 +402,7 @@
                if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
                        return -EINVAL;
 
-               (*hid->hiddev.read_report)(hid, report);
+               hid_read_report(hid, report);
 
                return 0;
 
@@ -431,7 +416,7 @@
                if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
                        return -EINVAL;
 
-               (*hid->hiddev.write_report)(hid, report);
+               hid_write_report(hid, report);
 
                return 0;
 
@@ -622,8 +607,8 @@
                                       minor + HIDDEV_MINOR_BASE,
                                       S_IFCHR | S_IRUGO | S_IWUSR,
                                       &hiddev_fops, NULL);
-       hid->hiddev.minor = minor;
-       hid->hiddev.private = hiddev;
+       hid->minor = minor;
+       hid->hiddev = hiddev;
 
        return 0;
 }
@@ -632,14 +617,14 @@
  * This is where hid.c calls us to disconnect a hiddev device from the
  * corresponding hid device (usually because the usb device has disconnected)
  */
-void hiddev_disconnect(void *private)
+void hiddev_disconnect(struct hid_device *hid)
 {
-       struct hiddev *hiddev = private;
+       struct hiddev *hiddev = hid->hiddev;
 
        hiddev->exist = 0;
 
        if (hiddev->open) {
-               hiddev_close(hiddev);
+               hid_close(hiddev->hid);
                wake_up_interruptible(&hiddev->wait);
        } else {
                hiddev_cleanup(hiddev);
diff -urN linux-2.4.5-ac9/include/linux/hiddev.h linux/include/linux/hiddev.h
--- linux-2.4.5-ac9/include/linux/hiddev.h      Wed Jun  6 10:41:19 2001
+++ linux/include/linux/hiddev.h        Wed Jun  6 15:16:12 2001
@@ -178,14 +178,14 @@
 
 #ifdef CONFIG_USB_HIDDEV
 int hiddev_connect(struct hid_device *);
-void hiddev_disconnect(void *);
-void hiddev_hid_event(void *private, unsigned int usage, int value);
+void hiddev_disconnect(struct hid_device *);
+void hiddev_hid_event(struct hid_device *, unsigned int usage, int value);
 int __init hiddev_init(void);
 void __exit hiddev_exit(void);
 #else
 static inline void *hiddev_connect(struct hid_device *hid) { return NULL; }
-static inline void hiddev_disconnect(void *private) { }
-static inline void hiddev_event(void *private, unsigned int usage, int value) { }
+static inline void hiddev_disconnect(struct hid_device *hid) { }
+static inline void hiddev_event(struct hid_device *hid, unsigned int usage, int 
+value) { }
 static inline int hiddev_init(void) { return 0; }
 static inline void hiddev_exit(void) { }
 #endif

Reply via email to