]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
Manual merge with Linus
authorDmitry Torokhov <dtor_core@ameritech.net>
Sat, 10 Sep 2005 01:14:47 +0000 (20:14 -0500)
committerDmitry Torokhov <dtor_core@ameritech.net>
Sat, 10 Sep 2005 01:14:47 +0000 (20:14 -0500)
1  2 
Documentation/kernel-parameters.txt
drivers/char/keyboard.c
drivers/input/evdev.c
drivers/input/mouse/psmouse-base.c
drivers/usb/input/hid-core.c
include/linux/input.h

index 111e98056195d05b59a83e6b88e4d4993ed52e91,d2f0c67ba1fb01e419966178138629048d2202bb..db2603ceabba6f6743438a4e74d458865ba504bb
@@@ -549,7 -549,6 +549,7 @@@ running once the system is up
                             keyboard and can not control its state
                             (Don't attempt to blink the leds)
        i8042.noaux     [HW] Don't check for auxiliary (== mouse) port
 +      i8042.nokbd     [HW] Don't check/create keyboard port
        i8042.nomux     [HW] Don't check presence of an active multiplexing
                             controller
        i8042.nopnp     [HW] Don't use ACPIPnP / PnPBIOS to discover KBD/AUX
                        New name for the ramdisk parameter.
                        See Documentation/ramdisk.txt.
  
+       rdinit=         [KNL]
+                       Format: <full_path>
+                       Run specified binary instead of /init from the ramdisk,
+                       used for early userspace startup. See initrd.
        reboot=         [BUGS=IA-32,BUGS=ARM,BUGS=IA-64] Rebooting mode
                        Format: <reboot_mode>[,<reboot_mode2>[,...]]
                        See arch/*/kernel/reboot.c.
diff --combined drivers/char/keyboard.c
index 1ddaabeb8ef89acc25ae47262179077fe5d0deea,1745065d8f789f062b76fdb1c6a21bb565b0e0f5..b12d58ee532b6f7f0f75614536b9d8329525817e
@@@ -200,7 -200,7 +200,7 @@@ int setkeycode(unsigned int scancode, u
                return -EINVAL;
        if (keycode < 0 || keycode > KEY_MAX)
                return -EINVAL;
 -      if (keycode >> (dev->keycodesize * 8))
 +      if (dev->keycodesize < sizeof(keycode) && (keycode >> (dev->keycodesize * 8)))
                return -EINVAL;
  
        oldkey = SET_INPUT_KEYCODE(dev, scancode, keycode);
@@@ -233,8 -233,7 +233,7 @@@ static void kd_nosound(unsigned long ig
        }
  }
  
- static struct timer_list kd_mksound_timer =
-               TIMER_INITIALIZER(kd_nosound, 0, 0);
+ static DEFINE_TIMER(kd_mksound_timer, kd_nosound, 0, 0);
  
  void kd_mksound(unsigned int hz, unsigned int ticks)
  {
diff --combined drivers/input/evdev.c
index 3a8314bb79022b57d195765398efc7942a05b388,60b696e9336b8442df9e24e571e832862179e257..3738d173f9a65a43e3d075294f00d6f07851ecab
@@@ -160,6 -160,8 +160,8 @@@ struct input_event_compat 
  #  define COMPAT_TEST IS_IA32_PROCESS(ia64_task_regs(current))
  #elif defined(CONFIG_ARCH_S390)
  #  define COMPAT_TEST test_thread_flag(TIF_31BIT)
+ #elif defined(CONFIG_MIPS)
+ #  define COMPAT_TEST (current->thread.mflags & MF_32BIT_ADDR)
  #else
  #  define COMPAT_TEST test_thread_flag(TIF_32BIT)
  #endif
@@@ -320,7 -322,7 +322,7 @@@ static long evdev_ioctl(struct file *fi
                        if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) return -EINVAL;
                        if (get_user(v, ip + 1)) return -EFAULT;
                        if (v < 0 || v > KEY_MAX) return -EINVAL;
 -                      if (v >> (dev->keycodesize * 8)) return -EINVAL;
 +                      if (dev->keycodesize < sizeof(v) && (v >> (dev->keycodesize * 8))) return -EINVAL;
                        u = SET_INPUT_KEYCODE(dev, t, v);
                        clear_bit(u, dev->keybit);
                        set_bit(v, dev->keybit);
                                                case EV_LED: bits = dev->ledbit; len = LED_MAX; break;
                                                case EV_SND: bits = dev->sndbit; len = SND_MAX; break;
                                                case EV_FF:  bits = dev->ffbit;  len = FF_MAX;  break;
+                                               case EV_SW:  bits = dev->swbit;  len = SW_MAX;  break;
                                                default: return -EINVAL;
                                        }
                                        len = NBITS(len) * sizeof(long);
                                        return copy_to_user(p, dev->snd, len) ? -EFAULT : len;
                                }
  
+                               if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0))) {
+                                       int len;
+                                       len = NBITS(SW_MAX) * sizeof(long);
+                                       if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+                                       return copy_to_user(p, dev->sw, len) ? -EFAULT : len;
+                               }
                                if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) {
                                        int len;
                                        if (!dev->name) return -ENOENT;
@@@ -499,7 -509,7 +509,7 @@@ do { 
        int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \
        if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \
        for (i = 0; i < len / sizeof(compat_long_t); i++) \
-               if (copy_to_user((compat_long_t*) p + i, \
+               if (copy_to_user((compat_long_t __user *) p + i, \
                                 (compat_long_t*) (bit) + i + 1 - ((i % 2) << 1), \
                                 sizeof(compat_long_t))) \
                        return -EFAULT; \
index 0830c6e13ef63b601109c79286d152aeef48a199,12bdd3eff923ea32042d76f47110d217c43243f7..af24313ff5bb14973c5fdaa9bcbfcd5dc0f66dae
@@@ -25,7 -25,6 +25,7 @@@
  #include "logips2pp.h"
  #include "alps.h"
  #include "lifebook.h"
 +#include "trackpoint.h"
  
  #define DRIVER_DESC   "PS/2 mouse driver"
  
@@@ -58,30 -57,10 +58,30 @@@ static unsigned int psmouse_resetafter
  module_param_named(resetafter, psmouse_resetafter, uint, 0644);
  MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never).");
  
 -PSMOUSE_DEFINE_ATTR(protocol);
 -PSMOUSE_DEFINE_ATTR(rate);
 -PSMOUSE_DEFINE_ATTR(resolution);
 -PSMOUSE_DEFINE_ATTR(resetafter);
 +PSMOUSE_DEFINE_ATTR(protocol, S_IWUSR | S_IRUGO,
 +                      NULL,
 +                      psmouse_attr_show_protocol, psmouse_attr_set_protocol);
 +PSMOUSE_DEFINE_ATTR(rate, S_IWUSR | S_IRUGO,
 +                      (void *) offsetof(struct psmouse, rate),
 +                      psmouse_show_int_attr, psmouse_attr_set_rate);
 +PSMOUSE_DEFINE_ATTR(resolution, S_IWUSR | S_IRUGO,
 +                      (void *) offsetof(struct psmouse, resolution),
 +                      psmouse_show_int_attr, psmouse_attr_set_resolution);
 +PSMOUSE_DEFINE_ATTR(resetafter, S_IWUSR | S_IRUGO,
 +                      (void *) offsetof(struct psmouse, resetafter),
 +                      psmouse_show_int_attr, psmouse_set_int_attr);
 +
 +static struct attribute *psmouse_attributes[] = {
 +      &psmouse_attr_protocol.dattr.attr,
 +      &psmouse_attr_rate.dattr.attr,
 +      &psmouse_attr_resolution.dattr.attr,
 +      &psmouse_attr_resetafter.dattr.attr,
 +      NULL
 +};
 +
 +static struct attribute_group psmouse_attribute_group = {
 +      .attrs  = psmouse_attributes,
 +};
  
  __obsolete_setup("psmouse_noext");
  __obsolete_setup("psmouse_resolution=");
@@@ -540,12 -519,6 +540,12 @@@ static int psmouse_extensions(struct ps
        if (max_proto >= PSMOUSE_IMPS && intellimouse_detect(psmouse, set_properties) == 0)
                return PSMOUSE_IMPS;
  
 +/*
 + * Try to initialize the IBM TrackPoint
 + */
 +      if (max_proto > PSMOUSE_IMEX && trackpoint_detect(psmouse, set_properties) == 0)
 +              return PSMOUSE_TRACKPOINT;
 +
  /*
   * Okay, all failed, we have a standard mouse here. The number of the buttons
   * is still a question, though. We assume 3.
@@@ -626,12 -599,6 +626,12 @@@ static struct psmouse_protocol psmouse_
                .alias          = "lifebook",
                .init           = lifebook_init,
        },
 +      {
 +              .type           = PSMOUSE_TRACKPOINT,
 +              .name           = "TPPS/2",
 +              .alias          = "trackpoint",
 +              .detect         = trackpoint_detect,
 +      },
        {
                .type           = PSMOUSE_AUTO,
                .name           = "auto",
@@@ -820,7 -787,10 +820,7 @@@ static void psmouse_disconnect(struct s
  
        psmouse = serio_get_drvdata(serio);
  
 -      device_remove_file(&serio->dev, &psmouse_attr_protocol);
 -      device_remove_file(&serio->dev, &psmouse_attr_rate);
 -      device_remove_file(&serio->dev, &psmouse_attr_resolution);
 -      device_remove_file(&serio->dev, &psmouse_attr_resetafter);
 +      sysfs_remove_group(&serio->dev.kobj, &psmouse_attribute_group);
  
        down(&psmouse_sem);
  
@@@ -913,7 -883,7 +913,7 @@@ static int psmouse_connect(struct seri
                psmouse_deactivate(parent);
        }
  
-       if (!(psmouse = kcalloc(1, sizeof(struct psmouse), GFP_KERNEL))) {
+       if (!(psmouse = kzalloc(sizeof(struct psmouse), GFP_KERNEL))) {
                retval = -ENOMEM;
                goto out;
        }
        if (parent && parent->pt_activate)
                parent->pt_activate(parent);
  
 -      device_create_file(&serio->dev, &psmouse_attr_protocol);
 -      device_create_file(&serio->dev, &psmouse_attr_rate);
 -      device_create_file(&serio->dev, &psmouse_attr_resolution);
 -      device_create_file(&serio->dev, &psmouse_attr_resetafter);
 +      sysfs_create_group(&serio->dev.kobj, &psmouse_attribute_group);
  
        psmouse_activate(psmouse);
  
@@@ -1054,12 -1027,10 +1054,12 @@@ static struct serio_driver psmouse_drv 
        .cleanup        = psmouse_cleanup,
  };
  
 -ssize_t psmouse_attr_show_helper(struct device *dev, char *buf,
 -                               ssize_t (*handler)(struct psmouse *, char *))
 +ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *devattr,
 +                               char *buf)
  {
        struct serio *serio = to_serio_port(dev);
 +      struct psmouse_attribute *attr = to_psmouse_attr(devattr);
 +      struct psmouse *psmouse;
        int retval;
  
        retval = serio_pin_driver(serio);
                goto out;
        }
  
 -      retval = handler(serio_get_drvdata(serio), buf);
 +      psmouse = serio_get_drvdata(serio);
 +
 +      retval = attr->show(psmouse, attr->data, buf);
  
  out:
        serio_unpin_driver(serio);
        return retval;
  }
  
 -ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t count,
 -                              ssize_t (*handler)(struct psmouse *, const char *, size_t))
 +ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *devattr,
 +                              const char *buf, size_t count)
  {
        struct serio *serio = to_serio_port(dev);
 -      struct psmouse *psmouse = serio_get_drvdata(serio);
 -      struct psmouse *parent = NULL;
 +      struct psmouse_attribute *attr = to_psmouse_attr(devattr);
 +      struct psmouse *psmouse, *parent = NULL;
        int retval;
  
        retval = serio_pin_driver(serio);
        if (retval)
                goto out_unpin;
  
 +      psmouse = serio_get_drvdata(serio);
 +
        if (psmouse->state == PSMOUSE_IGNORE) {
                retval = -ENODEV;
                goto out_up;
  
        psmouse_deactivate(psmouse);
  
 -      retval = handler(psmouse, buf, count);
 +      retval = attr->set(psmouse, attr->data, buf, count);
  
        if (retval != -ENODEV)
                psmouse_activate(psmouse);
        return retval;
  }
  
 -static ssize_t psmouse_attr_show_protocol(struct psmouse *psmouse, char *buf)
 +static ssize_t psmouse_show_int_attr(struct psmouse *psmouse, void *offset, char *buf)
 +{
 +      unsigned long *field = (unsigned long *)((char *)psmouse + (size_t)offset);
 +
 +      return sprintf(buf, "%lu\n", *field);
 +}
 +
 +static ssize_t psmouse_set_int_attr(struct psmouse *psmouse, void *offset, const char *buf, size_t count)
 +{
 +      unsigned long *field = (unsigned long *)((char *)psmouse + (size_t)offset);
 +      unsigned long value;
 +      char *rest;
 +
 +      value = simple_strtoul(buf, &rest, 10);
 +      if (*rest)
 +              return -EINVAL;
 +
 +      *field = value;
 +
 +      return count;
 +}
 +
 +static ssize_t psmouse_attr_show_protocol(struct psmouse *psmouse, void *data, char *buf)
  {
        return sprintf(buf, "%s\n", psmouse_protocol_by_type(psmouse->type)->name);
  }
  
 -static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, const char *buf, size_t count)
 +static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, const char *buf, size_t count)
  {
        struct serio *serio = psmouse->ps2dev.serio;
        struct psmouse *parent = NULL;
        return count;
  }
  
 -static ssize_t psmouse_attr_show_rate(struct psmouse *psmouse, char *buf)
 -{
 -      return sprintf(buf, "%d\n", psmouse->rate);
 -}
 -
 -static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, const char *buf, size_t count)
 +static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, void *data, const char *buf, size_t count)
  {
        unsigned long value;
        char *rest;
        return count;
  }
  
 -static ssize_t psmouse_attr_show_resolution(struct psmouse *psmouse, char *buf)
 -{
 -      return sprintf(buf, "%d\n", psmouse->resolution);
 -}
 -
 -static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, const char *buf, size_t count)
 +static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, void *data, const char *buf, size_t count)
  {
        unsigned long value;
        char *rest;
        return count;
  }
  
 -static ssize_t psmouse_attr_show_resetafter(struct psmouse *psmouse, char *buf)
 -{
 -      return sprintf(buf, "%d\n", psmouse->resetafter);
 -}
 -
 -static ssize_t psmouse_attr_set_resetafter(struct psmouse *psmouse, const char *buf, size_t count)
 -{
 -      unsigned long value;
 -      char *rest;
 -
 -      value = simple_strtoul(buf, &rest, 10);
 -      if (*rest)
 -              return -EINVAL;
 -
 -      psmouse->resetafter = value;
 -      return count;
 -}
  
  static int psmouse_set_maxproto(const char *val, struct kernel_param *kp)
  {
  
        *((unsigned int *)kp->arg) = proto->type;
  
 -      return 0;                                       \
 +      return 0;
  }
  
  static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp)
index a721299004576e62cfeafebdb71166426eb9ed89,1ab95d24c5e25c8715078538ff6176b2b4f01883..e108e0a36b743fd88c191a7e96c8339dbe39f451
@@@ -2,8 -2,7 +2,8 @@@
   *  USB HID support for Linux
   *
   *  Copyright (c) 1999 Andreas Gal
 - *  Copyright (c) 2000-2001 Vojtech Pavlik <vojtech@suse.cz>
 + *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
 + *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
   */
  
  /*
@@@ -39,7 -38,7 +39,7 @@@
   * Version Information
   */
  
 -#define DRIVER_VERSION "v2.01"
 +#define DRIVER_VERSION "v2.6"
  #define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik"
  #define DRIVER_DESC "USB HID core driver"
  #define DRIVER_LICENSE "GPL"
@@@ -1059,8 -1058,8 +1059,8 @@@ static int hid_submit_ctrl(struct hid_d
                if (maxpacket > 0) {
                        padlen = (len + maxpacket - 1) / maxpacket;
                        padlen *= maxpacket;
 -                      if (padlen > HID_BUFFER_SIZE)
 -                              padlen = HID_BUFFER_SIZE;
 +                      if (padlen > hid->bufsize)
 +                              padlen = hid->bufsize;
                } else
                        padlen = 0;
                hid->urbctrl->transfer_buffer_length = padlen;
@@@ -1097,7 -1096,6 +1097,7 @@@ static void hid_irq_out(struct urb *urb
  
        switch (urb->status) {
                case 0:                 /* success */
 +                      break;
                case -ESHUTDOWN:        /* unplug */
                case -EILSEQ:           /* unplug timeout on uhci */
                        unplug = 1;
@@@ -1145,7 -1143,6 +1145,7 @@@ static void hid_ctrl(struct urb *urb, s
                case 0:                 /* success */
                        if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN)
                                hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, 0, regs);
 +                      break;
                case -ESHUTDOWN:        /* unplug */
                case -EILSEQ:           /* unplug timectrl on uhci */
                        unplug = 1;
@@@ -1287,8 -1284,13 +1287,8 @@@ void hid_init_reports(struct hid_devic
        struct hid_report *report;
        int err, ret;
  
 -      list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list) {
 -              int size = ((report->size - 1) >> 3) + 1 + hid->report_enum[HID_INPUT_REPORT].numbered;
 -              if (size > HID_BUFFER_SIZE) size = HID_BUFFER_SIZE;
 -              if (size > hid->urbin->transfer_buffer_length)
 -                      hid->urbin->transfer_buffer_length = size;
 +      list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list)
                hid_submit_report(hid, report, USB_DIR_IN);
 -      }
  
        list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
                hid_submit_report(hid, report, USB_DIR_IN);
  #define USB_VENDOR_ID_A4TECH          0x09da
  #define USB_DEVICE_ID_A4TECH_WCP32PU  0x0006
  
 -#define USB_VENDOR_ID_AASHIMA         0x06D6
 +#define USB_VENDOR_ID_AASHIMA         0x06d6
  #define USB_DEVICE_ID_AASHIMA_GAMEPAD 0x0025
 +#define USB_DEVICE_ID_AASHIMA_PREDATOR        0x0026
  
  #define USB_VENDOR_ID_CYPRESS         0x04b4
  #define USB_DEVICE_ID_CYPRESS_MOUSE   0x0001
  #define USB_DEVICE_ID_CYPRESS_HIDCOM  0x5500
 +#define USB_DEVICE_ID_CYPRESS_ULTRAMOUSE      0x7417
  
  #define USB_VENDOR_ID_BERKSHIRE               0x0c98
  #define USB_DEVICE_ID_BERKSHIRE_PCWD  0x1140
  #define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004
  
  #define USB_VENDOR_ID_LD              0x0f11
--#define USB_DEVICE_ID_CASSY           0x1000
++#define USB_DEVICE_ID_CASSY           0x1000
  #define USB_DEVICE_ID_POCKETCASSY     0x1010
  #define USB_DEVICE_ID_MOBILECASSY     0x1020
  #define USB_DEVICE_ID_JWM             0x1080
  #define USB_DEVICE_ID_POWERCONTROL    0x2030
  
  #define USB_VENDOR_ID_APPLE           0x05ac
 -#define USB_DEVICE_ID_APPLE_BLUETOOTH         0x1000
 +#define USB_DEVICE_ID_APPLE_POWERMOUSE        0x0304
++#define USB_DEVICE_ID_APPLE_BLUETOOTH 0x1000
  
  /*
   * Alphabetically sorted blacklist by quirk type.
@@@ -1464,13 -1464,13 +1465,14 @@@ static struct hid_blacklist 
        { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_22, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_BLUETOOTH, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW48, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE },
 +      { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_USBHUB_KB, HID_QUIRK_NOGET},
        { USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET },
  
 +      { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_POWERMOUSE, HID_QUIRK_2WHEEL_POWERMOUSE },
        { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 },
        { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 },
  
        { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD, HID_QUIRK_BADPAD },
 +      { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD },
        { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD },
        { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD },
        { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
        { 0, 0 }
  };
  
 +/*
 + * Traverse the supplied list of reports and find the longest
 + */
 +static void hid_find_max_report(struct hid_device *hid, unsigned int type, int *max)
 +{
 +      struct hid_report *report;
 +      int size;
 +
 +      list_for_each_entry(report, &hid->report_enum[type].report_list, list) {
 +              size = ((report->size - 1) >> 3) + 1;
 +              if (type == HID_INPUT_REPORT && hid->report_enum[type].numbered)
 +                      size++;
 +              if (*max < size)
 +                      *max = size;
 +      }
 +}
 +
  static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
  {
 -      if (!(hid->inbuf = usb_buffer_alloc(dev, HID_BUFFER_SIZE, SLAB_ATOMIC, &hid->inbuf_dma)))
 +      if (!(hid->inbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->inbuf_dma)))
                return -1;
 -      if (!(hid->outbuf = usb_buffer_alloc(dev, HID_BUFFER_SIZE, SLAB_ATOMIC, &hid->outbuf_dma)))
 +      if (!(hid->outbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->outbuf_dma)))
                return -1;
        if (!(hid->cr = usb_buffer_alloc(dev, sizeof(*(hid->cr)), SLAB_ATOMIC, &hid->cr_dma)))
                return -1;
 -      if (!(hid->ctrlbuf = usb_buffer_alloc(dev, HID_BUFFER_SIZE, SLAB_ATOMIC, &hid->ctrlbuf_dma)))
 +      if (!(hid->ctrlbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->ctrlbuf_dma)))
                return -1;
  
        return 0;
  static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
  {
        if (hid->inbuf)
 -              usb_buffer_free(dev, HID_BUFFER_SIZE, hid->inbuf, hid->inbuf_dma);
 +              usb_buffer_free(dev, hid->bufsize, hid->inbuf, hid->inbuf_dma);
        if (hid->outbuf)
 -              usb_buffer_free(dev, HID_BUFFER_SIZE, hid->outbuf, hid->outbuf_dma);
 +              usb_buffer_free(dev, hid->bufsize, hid->outbuf, hid->outbuf_dma);
        if (hid->cr)
                usb_buffer_free(dev, sizeof(*(hid->cr)), hid->cr, hid->cr_dma);
        if (hid->ctrlbuf)
 -              usb_buffer_free(dev, HID_BUFFER_SIZE, hid->ctrlbuf, hid->ctrlbuf_dma);
 +              usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma);
  }
  
  static struct hid_device *usb_hid_configure(struct usb_interface *intf)
        struct hid_device *hid;
        unsigned quirks = 0, rsize = 0;
        char *buf, *rdesc;
 -      int n;
 +      int n, insize = 0;
  
        for (n = 0; hid_blacklist[n].idVendor; n++)
                if ((hid_blacklist[n].idVendor == le16_to_cpu(dev->descriptor.idVendor)) &&
        kfree(rdesc);
        hid->quirks = quirks;
  
 +      hid->bufsize = HID_MIN_BUFFER_SIZE;
 +      hid_find_max_report(hid, HID_INPUT_REPORT, &hid->bufsize);
 +      hid_find_max_report(hid, HID_OUTPUT_REPORT, &hid->bufsize);
 +      hid_find_max_report(hid, HID_FEATURE_REPORT, &hid->bufsize);
 +
 +      if (hid->bufsize > HID_MAX_BUFFER_SIZE)
 +              hid->bufsize = HID_MAX_BUFFER_SIZE;
 +
 +      hid_find_max_report(hid, HID_INPUT_REPORT, &insize);
 +
 +      if (insize > HID_MAX_BUFFER_SIZE)
 +              insize = HID_MAX_BUFFER_SIZE;
 +
        if (hid_alloc_buffers(dev, hid)) {
                hid_free_buffers(dev, hid);
                goto fail;
                        if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL)))
                                goto fail;
                        pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
 -                      usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, 0,
 +                      usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, insize,
                                         hid_irq_in, hid, interval);
                        hid->urbin->transfer_dma = hid->inbuf_dma;
-                       hid->urbin->transfer_flags |=(URB_NO_TRANSFER_DMA_MAP | URB_ASYNC_UNLINK);
+                       hid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
                } else {
                        if (hid->urbout)
                                continue;
                        usb_fill_int_urb(hid->urbout, dev, pipe, hid->outbuf, 0,
                                         hid_irq_out, hid, interval);
                        hid->urbout->transfer_dma = hid->outbuf_dma;
-                       hid->urbout->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_ASYNC_UNLINK);
+                       hid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
                }
        }
  
                             hid->ctrlbuf, 1, hid_ctrl, hid);
        hid->urbctrl->setup_dma = hid->cr_dma;
        hid->urbctrl->transfer_dma = hid->ctrlbuf_dma;
-       hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP | URB_ASYNC_UNLINK);
+       hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
  
        return hid;
  
diff --combined include/linux/input.h
index 227a497c067828c83678e206f39426f446cfd921,4767e5429534dff11c004923b5a3ee9827bcac50..e8c296ff6257adeccdd9d60245f463d1ea0255a3
@@@ -66,6 -66,7 +66,7 @@@ struct input_absinfo 
  #define EVIOCGKEY(len)                _IOC(_IOC_READ, 'E', 0x18, len)         /* get global keystate */
  #define EVIOCGLED(len)                _IOC(_IOC_READ, 'E', 0x19, len)         /* get all LEDs */
  #define EVIOCGSND(len)                _IOC(_IOC_READ, 'E', 0x1a, len)         /* get all sounds status */
+ #define EVIOCGSW(len)         _IOC(_IOC_READ, 'E', 0x1b, len)         /* get all switch states */
  
  #define EVIOCGBIT(ev,len)     _IOC(_IOC_READ, 'E', 0x20 + ev, len)    /* get event bits */
  #define EVIOCGABS(abs)                _IOR('E', 0x40 + abs, struct input_absinfo)             /* get abs value/limits */
@@@ -86,6 -87,7 +87,7 @@@
  #define EV_REL                        0x02
  #define EV_ABS                        0x03
  #define EV_MSC                        0x04
+ #define EV_SW                 0x05
  #define EV_LED                        0x11
  #define EV_SND                        0x12
  #define EV_REP                        0x14
  #define KEY_SCROLLDOWN                178
  #define KEY_KPLEFTPAREN               179
  #define KEY_KPRIGHTPAREN      180
 +#define KEY_NEW                       181
 +#define KEY_REDO              182
  
  #define KEY_F13                       183
  #define KEY_F14                       184
  #define KEY_KBDILLUMDOWN      229
  #define KEY_KBDILLUMUP                230
  
 +#define KEY_SEND              231
 +#define KEY_REPLY             232
 +#define KEY_FORWARDMAIL               233
 +#define KEY_SAVE              234
 +#define KEY_DOCUMENTS         235
 +
  #define KEY_UNKNOWN           240
  
  #define BTN_MISC              0x100
  #define ABS_MISC              0x28
  #define ABS_MAX                       0x3f
  
+ /*
+  * Switch events
+  */
+ #define SW_0          0x00
+ #define SW_1          0x01
+ #define SW_2          0x02
+ #define SW_3          0x03
+ #define SW_4          0x04
+ #define SW_5          0x05
+ #define SW_6          0x06
+ #define SW_7          0x07
+ #define SW_MAX                0x0f
  /*
   * Misc events
   */
@@@ -832,6 -840,7 +848,7 @@@ struct input_dev 
        unsigned long ledbit[NBITS(LED_MAX)];
        unsigned long sndbit[NBITS(SND_MAX)];
        unsigned long ffbit[NBITS(FF_MAX)];
+       unsigned long swbit[NBITS(SW_MAX)];
        int ff_effects_max;
  
        unsigned int keycodemax;
        unsigned long key[NBITS(KEY_MAX)];
        unsigned long led[NBITS(LED_MAX)];
        unsigned long snd[NBITS(SND_MAX)];
+       unsigned long sw[NBITS(SW_MAX)];
  
        int absmax[ABS_MAX + 1];
        int absmin[ABS_MAX + 1];
  #define INPUT_DEVICE_ID_MATCH_LEDBIT  0x200
  #define INPUT_DEVICE_ID_MATCH_SNDBIT  0x400
  #define INPUT_DEVICE_ID_MATCH_FFBIT   0x800
+ #define INPUT_DEVICE_ID_MATCH_SWBIT   0x1000
  
  #define INPUT_DEVICE_ID_MATCH_DEVICE\
        (INPUT_DEVICE_ID_MATCH_BUS | INPUT_DEVICE_ID_MATCH_VENDOR | INPUT_DEVICE_ID_MATCH_PRODUCT)
@@@ -914,6 -925,7 +933,7 @@@ struct input_device_id 
        unsigned long ledbit[NBITS(LED_MAX)];
        unsigned long sndbit[NBITS(SND_MAX)];
        unsigned long ffbit[NBITS(FF_MAX)];
+       unsigned long swbit[NBITS(SW_MAX)];
  
        unsigned long driver_info;
  };
@@@ -1006,6 -1018,11 +1026,11 @@@ static inline void input_report_ff_stat
        input_event(dev, EV_FF_STATUS, code, value);
  }
  
+ static inline void input_report_switch(struct input_dev *dev, unsigned int code, int value)
+ {
+       input_event(dev, EV_SW, code, !!value);
+ }
  static inline void input_regs(struct input_dev *dev, struct pt_regs *regs)
  {
        dev->regs = regs;