]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'for-4.3/logitech' into for-next
authorJiri Kosina <jkosina@suse.com>
Wed, 29 Jul 2015 12:09:40 +0000 (14:09 +0200)
committerJiri Kosina <jkosina@suse.com>
Wed, 29 Jul 2015 12:09:40 +0000 (14:09 +0200)
20 files changed:
drivers/hid/Kconfig
drivers/hid/hid-core.c
drivers/hid/hid-cp2112.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-microsoft.c
drivers/hid/hid-multitouch.c
drivers/hid/hid-picolcd_backlight.c
drivers/hid/hid-picolcd_cir.c
drivers/hid/hid-picolcd_lcd.c
drivers/hid/hid-rmi.c
drivers/hid/hid-sensor-hub.c
drivers/hid/hid-sony.c
drivers/hid/hid-uclogic.c
drivers/hid/i2c-hid/i2c-hid.c
drivers/hid/usbhid/hid-core.c
drivers/hid/usbhid/hid-quirks.c
drivers/hid/wacom_sys.c
drivers/hid/wacom_wac.c
drivers/hid/wacom_wac.h

index cc4c6649d19503e236f905e8feafe21440237fea..57c94d7d5834bc7ccd1bb4a4ff0ca9d60d548f21 100644 (file)
@@ -480,6 +480,7 @@ config HID_MULTITOUCH
          - Atmel panels
          - Cando dual touch panels
          - Chunghwa panels
+         - CJTouch panels
          - CVTouch panels
          - Cypress TrueTouch panels
          - Elan Microelectronics touch panels
index 157c627750535e8943769e3078de068e4f1c7a47..e4b6244f21cdf4cecf00127142c6745d3eed9d11 100644 (file)
@@ -427,6 +427,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
 {
        __u32 data;
        unsigned n;
+       __u32 count;
 
        data = item_udata(item);
 
@@ -490,6 +491,24 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
                if (item->size <= 2)
                        data = (parser->global.usage_page << 16) + data;
 
+               count = data - parser->local.usage_minimum;
+               if (count + parser->local.usage_index >= HID_MAX_USAGES) {
+                       /*
+                        * We do not warn if the name is not set, we are
+                        * actually pre-scanning the device.
+                        */
+                       if (dev_name(&parser->device->dev))
+                               hid_warn(parser->device,
+                                        "ignoring exceeding usage max\n");
+                       data = HID_MAX_USAGES - parser->local.usage_index +
+                               parser->local.usage_minimum - 1;
+                       if (data <= 0) {
+                               hid_err(parser->device,
+                                       "no more usage index available\n");
+                               return -1;
+                       }
+               }
+
                for (n = parser->local.usage_minimum; n <= data; n++)
                        if (hid_add_usage(parser, n)) {
                                dbg_hid("hid_add_usage failed\n");
@@ -705,8 +724,9 @@ static void hid_scan_collection(struct hid_parser *parser, unsigned type)
                hid->group = HID_GROUP_SENSOR_HUB;
 
        if (hid->vendor == USB_VENDOR_ID_MICROSOFT &&
-           (hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3 ||
-            hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3_JP ||
+           (hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3 ||
+            hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP ||
+            hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3 ||
             hid->product == USB_DEVICE_ID_MS_POWER_COVER) &&
            hid->group == HID_GROUP_MULTITOUCH)
                hid->group = HID_GROUP_GENERIC;
@@ -1902,8 +1922,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3_JP) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) },
index a2dbbbe0d8d7e81b06ac6d646737413fe4d1d357..7afc3fcc122c476a42e20f1e85e1ed409c93a734 100644 (file)
@@ -156,6 +156,7 @@ struct cp2112_device {
        wait_queue_head_t wait;
        u8 read_data[61];
        u8 read_length;
+       u8 hwversion;
        int xfer_status;
        atomic_t read_avail;
        atomic_t xfer_avail;
@@ -446,6 +447,24 @@ static int cp2112_i2c_write_req(void *buf, u8 slave_address, u8 *data,
        return data_length + 3;
 }
 
+static int cp2112_i2c_write_read_req(void *buf, u8 slave_address,
+                                    u8 *addr, int addr_length,
+                                    int read_length)
+{
+       struct cp2112_write_read_req_report *report = buf;
+
+       if (read_length < 1 || read_length > 512 ||
+           addr_length > sizeof(report->target_address))
+               return -EINVAL;
+
+       report->report = CP2112_DATA_WRITE_READ_REQUEST;
+       report->slave_address = slave_address << 1;
+       report->length = cpu_to_be16(read_length);
+       report->target_address_length = addr_length;
+       memcpy(report->target_address, addr, addr_length);
+       return addr_length + 5;
+}
+
 static int cp2112_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
                           int num)
 {
@@ -453,26 +472,46 @@ static int cp2112_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
        struct hid_device *hdev = dev->hdev;
        u8 buf[64];
        ssize_t count;
+       ssize_t read_length = 0;
+       u8 *read_buf = NULL;
        unsigned int retries;
        int ret;
 
        hid_dbg(hdev, "I2C %d messages\n", num);
 
-       if (num != 1) {
+       if (num == 1) {
+               if (msgs->flags & I2C_M_RD) {
+                       hid_dbg(hdev, "I2C read %#04x len %d\n",
+                               msgs->addr, msgs->len);
+                       read_length = msgs->len;
+                       read_buf = msgs->buf;
+                       count = cp2112_read_req(buf, msgs->addr, msgs->len);
+               } else {
+                       hid_dbg(hdev, "I2C write %#04x len %d\n",
+                               msgs->addr, msgs->len);
+                       count = cp2112_i2c_write_req(buf, msgs->addr,
+                                                    msgs->buf, msgs->len);
+               }
+               if (count < 0)
+                       return count;
+       } else if (dev->hwversion > 1 &&  /* no repeated start in rev 1 */
+                  num == 2 &&
+                  msgs[0].addr == msgs[1].addr &&
+                  !(msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD)) {
+               hid_dbg(hdev, "I2C write-read %#04x wlen %d rlen %d\n",
+                       msgs[0].addr, msgs[0].len, msgs[1].len);
+               read_length = msgs[1].len;
+               read_buf = msgs[1].buf;
+               count = cp2112_i2c_write_read_req(buf, msgs[0].addr,
+                               msgs[0].buf, msgs[0].len, msgs[1].len);
+               if (count < 0)
+                       return count;
+       } else {
                hid_err(hdev,
                        "Multi-message I2C transactions not supported\n");
                return -EOPNOTSUPP;
        }
 
-       if (msgs->flags & I2C_M_RD)
-               count = cp2112_read_req(buf, msgs->addr, msgs->len);
-       else
-               count = cp2112_i2c_write_req(buf, msgs->addr, msgs->buf,
-                                            msgs->len);
-
-       if (count < 0)
-               return count;
-
        ret = hid_hw_power(hdev, PM_HINT_FULLON);
        if (ret < 0) {
                hid_err(hdev, "power management error: %d\n", ret);
@@ -508,21 +547,34 @@ static int cp2112_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
                goto power_normal;
        }
 
-       if (!(msgs->flags & I2C_M_RD))
-               goto finish;
-
-       ret = cp2112_read(dev, msgs->buf, msgs->len);
-       if (ret < 0)
-               goto power_normal;
-       if (ret != msgs->len) {
-               hid_warn(hdev, "short read: %d < %d\n", ret, msgs->len);
-               ret = -EIO;
-               goto power_normal;
+       for (count = 0; count < read_length;) {
+               ret = cp2112_read(dev, read_buf + count, read_length - count);
+               if (ret < 0)
+                       goto power_normal;
+               if (ret == 0) {
+                       hid_err(hdev, "read returned 0\n");
+                       ret = -EIO;
+                       goto power_normal;
+               }
+               count += ret;
+               if (count > read_length) {
+                       /*
+                        * The hardware returned too much data.
+                        * This is mostly harmless because cp2112_read()
+                        * has a limit check so didn't overrun our
+                        * buffer.  Nevertheless, we return an error
+                        * because something is seriously wrong and
+                        * it shouldn't go unnoticed.
+                        */
+                       hid_err(hdev, "long read: %d > %zd\n",
+                               ret, read_length - count + ret);
+                       ret = -EIO;
+                       goto power_normal;
+               }
        }
 
-finish:
        /* return the number of transferred messages */
-       ret = 1;
+       ret = num;
 
 power_normal:
        hid_hw_power(hdev, PM_HINT_NORMAL);
@@ -537,7 +589,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
        struct cp2112_device *dev = (struct cp2112_device *)adap->algo_data;
        struct hid_device *hdev = dev->hdev;
        u8 buf[64];
-       __be16 word;
+       __le16 word;
        ssize_t count;
        size_t read_length = 0;
        unsigned int retries;
@@ -554,7 +606,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
                if (I2C_SMBUS_READ == read_write)
                        count = cp2112_read_req(buf, addr, read_length);
                else
-                       count = cp2112_write_req(buf, addr, data->byte, NULL,
+                       count = cp2112_write_req(buf, addr, command, NULL,
                                                 0);
                break;
        case I2C_SMBUS_BYTE_DATA:
@@ -569,7 +621,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
                break;
        case I2C_SMBUS_WORD_DATA:
                read_length = 2;
-               word = cpu_to_be16(data->word);
+               word = cpu_to_le16(data->word);
 
                if (I2C_SMBUS_READ == read_write)
                        count = cp2112_write_read_req(buf, addr, read_length,
@@ -582,7 +634,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
                size = I2C_SMBUS_WORD_DATA;
                read_write = I2C_SMBUS_READ;
                read_length = 2;
-               word = cpu_to_be16(data->word);
+               word = cpu_to_le16(data->word);
 
                count = cp2112_write_read_req(buf, addr, read_length, command,
                                              (u8 *)&word, 2);
@@ -675,7 +727,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
                data->byte = buf[0];
                break;
        case I2C_SMBUS_WORD_DATA:
-               data->word = be16_to_cpup((__be16 *)buf);
+               data->word = le16_to_cpup((__le16 *)buf);
                break;
        case I2C_SMBUS_BLOCK_DATA:
                if (read_length > I2C_SMBUS_BLOCK_MAX) {
@@ -1030,6 +1082,7 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
        dev->adap.dev.parent    = &hdev->dev;
        snprintf(dev->adap.name, sizeof(dev->adap.name),
                 "CP2112 SMBus Bridge on hiddev%d", hdev->minor);
+       dev->hwversion = buf[2];
        init_waitqueue_head(&dev->wait);
 
        hid_device_io_start(hdev);
index 653bfd4b9490305011e92a1fd5197dccba7149ce..3f6dd18fe37741396c91946c43482bb96b4ff85e 100644 (file)
 
 #define USB_VENDOR_ID_CIDC             0x1677
 
+#define USB_VENDOR_ID_CJTOUCH          0x24b8
+#define USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0020 0x0020
+#define USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0040 0x0040
+
 #define USB_VENDOR_ID_CMEDIA           0x0d8c
 #define USB_DEVICE_ID_CM109            0x000e
 
 #define USB_VENDOR_ID_IRTOUCHSYSTEMS   0x6615
 #define USB_DEVICE_ID_IRTOUCH_INFRARED_USB     0x0070
 
+#define USB_VENDOR_ID_ITE               0x048d
+#define USB_DEVICE_ID_ITE_LENOVO_YOGA   0x8386
+
 #define USB_VENDOR_ID_JABRA            0x0b0e
 #define USB_DEVICE_ID_JABRA_SPEAK_410  0x0412
 #define USB_DEVICE_ID_JABRA_SPEAK_510  0x0420
 #define USB_DEVICE_ID_MS_SURFACE_PRO_2   0x0799
 #define USB_DEVICE_ID_MS_TOUCH_COVER_2   0x07a7
 #define USB_DEVICE_ID_MS_TYPE_COVER_2    0x07a9
-#define USB_DEVICE_ID_MS_TYPE_COVER_3    0x07dc
-#define USB_DEVICE_ID_MS_TYPE_COVER_3_JP 0x07dd
+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3    0x07dc
+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP 0x07dd
+#define USB_DEVICE_ID_MS_TYPE_COVER_3    0x07de
 #define USB_DEVICE_ID_MS_POWER_COVER     0x07da
 
 #define USB_VENDOR_ID_MOJO             0x8282
index 3511bbaba505a4524ad382297ec1e486e21e7e48..14aebe4832194ab0d3f59e7d2bfdb180bb802b48 100644 (file)
@@ -1163,8 +1163,11 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
 
        input_event(input, usage->type, usage->code, value);
 
-       if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY))
+       if ((field->flags & HID_MAIN_ITEM_RELATIVE) &&
+           usage->type == EV_KEY && value) {
+               input_sync(input);
                input_event(input, usage->type, usage->code, 0);
+       }
 }
 
 void hidinput_report_event(struct hid_device *hid, struct hid_report *report)
index 32a596f554afe1605b9eaabc984c263f1398ff13..9aa3515090a7252abc0459c8849bc9bea32d733e 100644 (file)
@@ -276,9 +276,11 @@ static const struct hid_device_id ms_devices[] = {
                .driver_data = MS_NOGET },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500),
                .driver_data = MS_DUPLICATE_USAGES },
-       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3),
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3),
+               .driver_data = MS_HIDINPUT },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP),
                .driver_data = MS_HIDINPUT },
-       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3_JP),
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3),
                .driver_data = MS_HIDINPUT },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER),
                .driver_data = MS_HIDINPUT },
index 7c811252c1cefebb2418944a7f391117a8a92b6d..426b2f1a34501c7516ab39dc631d3c2073591aac 100644 (file)
@@ -1145,6 +1145,14 @@ static const struct hid_device_id mt_devices[] = {
                MT_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT,
                        USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) },
 
+       /* CJTouch panels */
+       { .driver_data = MT_CLS_NSMU,
+               MT_USB_DEVICE(USB_VENDOR_ID_CJTOUCH,
+                       USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0020) },
+       { .driver_data = MT_CLS_NSMU,
+               MT_USB_DEVICE(USB_VENDOR_ID_CJTOUCH,
+                       USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0040) },
+
        /* CVTouch panels */
        { .driver_data = MT_CLS_NSMU,
                MT_USB_DEVICE(USB_VENDOR_ID_CVTOUCH,
index a32c5f86b0b3f667466b921f1ed4581ad1857b1e..808807ad388f9c9c6048cbd30c7969e8cd1937e2 100644 (file)
@@ -94,8 +94,7 @@ void picolcd_exit_backlight(struct picolcd_data *data)
        struct backlight_device *bdev = data->backlight;
 
        data->backlight = NULL;
-       if (bdev)
-               backlight_device_unregister(bdev);
+       backlight_device_unregister(bdev);
 }
 
 int picolcd_resume_backlight(struct picolcd_data *data)
index 045f8ebf16b53747746bf92c110f434ffdaff319..96286510f42e990eef1a0fd6a03abfd57fd42f57 100644 (file)
@@ -145,7 +145,6 @@ void picolcd_exit_cir(struct picolcd_data *data)
        struct rc_dev *rdev = data->rc_dev;
 
        data->rc_dev = NULL;
-       if (rdev)
-               rc_unregister_device(rdev);
+       rc_unregister_device(rdev);
 }
 
index 89821c2da6d76b766347ae629314d68df3033942..22dcbe13da892cc3ede9f9cdccf280d752035d92 100644 (file)
@@ -92,8 +92,7 @@ void picolcd_exit_lcd(struct picolcd_data *data)
        struct lcd_device *ldev = data->lcd;
 
        data->lcd = NULL;
-       if (ldev)
-               lcd_device_unregister(ldev);
+       lcd_device_unregister(ldev);
 }
 
 int picolcd_resume_lcd(struct picolcd_data *data)
index 4cf80bb276dc34f481f8aaf10bec55966fe80657..2c148129beb2f0a746f4661660be47e79421274e 100644 (file)
 #define RMI_READ_DATA_PENDING          1
 #define RMI_STARTED                    2
 
+#define RMI_SLEEP_NORMAL               0x0
+#define RMI_SLEEP_DEEP_SLEEP           0x1
+
 /* device flags */
 #define RMI_DEVICE                     BIT(0)
 #define RMI_DEVICE_HAS_PHYS_BUTTONS    BIT(1)
 
+/*
+ * retrieve the ctrl registers
+ * the ctrl register has a size of 20 but a fw bug split it into 16 + 4,
+ * and there is no way to know if the first 20 bytes are here or not.
+ * We use only the first 12 bytes, so get only them.
+ */
+#define RMI_F11_CTRL_REG_COUNT         12
+
 enum rmi_mode_type {
        RMI_MODE_OFF                    = 0,
        RMI_MODE_ATTN_REPORTS           = 1,
@@ -113,6 +124,8 @@ struct rmi_data {
        unsigned int max_y;
        unsigned int x_size_mm;
        unsigned int y_size_mm;
+       bool read_f11_ctrl_regs;
+       u8 f11_ctrl_regs[RMI_F11_CTRL_REG_COUNT];
 
        unsigned int gpio_led_count;
        unsigned int button_count;
@@ -126,6 +139,10 @@ struct rmi_data {
 
        unsigned long device_flags;
        unsigned long firmware_id;
+
+       u8 f01_ctrl0;
+       u8 interrupt_enable_mask;
+       bool restore_interrupt_mask;
 };
 
 #define RMI_PAGE(addr) (((addr) >> 8) & 0xff)
@@ -346,13 +363,34 @@ static void rmi_f11_process_touch(struct rmi_data *hdata, int slot,
        }
 }
 
+static int rmi_reset_attn_mode(struct hid_device *hdev)
+{
+       struct rmi_data *data = hid_get_drvdata(hdev);
+       int ret;
+
+       ret = rmi_set_mode(hdev, RMI_MODE_ATTN_REPORTS);
+       if (ret)
+               return ret;
+
+       if (data->restore_interrupt_mask) {
+               ret = rmi_write(hdev, data->f01.control_base_addr + 1,
+                               &data->interrupt_enable_mask);
+               if (ret) {
+                       hid_err(hdev, "can not write F01 control register\n");
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
 static void rmi_reset_work(struct work_struct *work)
 {
        struct rmi_data *hdata = container_of(work, struct rmi_data,
                                                reset_work);
 
        /* switch the device to RMI if we receive a generic mouse report */
-       rmi_set_mode(hdata->hdev, RMI_MODE_ATTN_REPORTS);
+       rmi_reset_attn_mode(hdata->hdev);
 }
 
 static inline int rmi_schedule_reset(struct hid_device *hdev)
@@ -532,14 +570,77 @@ static int rmi_event(struct hid_device *hdev, struct hid_field *field,
 }
 
 #ifdef CONFIG_PM
+static int rmi_set_sleep_mode(struct hid_device *hdev, int sleep_mode)
+{
+       struct rmi_data *data = hid_get_drvdata(hdev);
+       int ret;
+       u8 f01_ctrl0;
+
+       f01_ctrl0 = (data->f01_ctrl0 & ~0x3) | sleep_mode;
+
+       ret = rmi_write(hdev, data->f01.control_base_addr,
+                       &f01_ctrl0);
+       if (ret) {
+               hid_err(hdev, "can not write sleep mode\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int rmi_suspend(struct hid_device *hdev, pm_message_t message)
+{
+       struct rmi_data *data = hid_get_drvdata(hdev);
+       int ret;
+       u8 buf[RMI_F11_CTRL_REG_COUNT];
+
+       ret = rmi_read_block(hdev, data->f11.control_base_addr, buf,
+                               RMI_F11_CTRL_REG_COUNT);
+       if (ret)
+               hid_warn(hdev, "can not read F11 control registers\n");
+       else
+               memcpy(data->f11_ctrl_regs, buf, RMI_F11_CTRL_REG_COUNT);
+
+
+       if (!device_may_wakeup(hdev->dev.parent))
+               return rmi_set_sleep_mode(hdev, RMI_SLEEP_DEEP_SLEEP);
+
+       return 0;
+}
+
 static int rmi_post_reset(struct hid_device *hdev)
 {
-       return rmi_set_mode(hdev, RMI_MODE_ATTN_REPORTS);
+       struct rmi_data *data = hid_get_drvdata(hdev);
+       int ret;
+
+       ret = rmi_reset_attn_mode(hdev);
+       if (ret) {
+               hid_err(hdev, "can not set rmi mode\n");
+               return ret;
+       }
+
+       if (data->read_f11_ctrl_regs) {
+               ret = rmi_write_block(hdev, data->f11.control_base_addr,
+                               data->f11_ctrl_regs, RMI_F11_CTRL_REG_COUNT);
+               if (ret)
+                       hid_warn(hdev,
+                               "can not write F11 control registers after reset\n");
+       }
+
+       if (!device_may_wakeup(hdev->dev.parent)) {
+               ret = rmi_set_sleep_mode(hdev, RMI_SLEEP_NORMAL);
+               if (ret) {
+                       hid_err(hdev, "can not write sleep mode\n");
+                       return ret;
+               }
+       }
+
+       return ret;
 }
 
 static int rmi_post_resume(struct hid_device *hdev)
 {
-       return rmi_set_mode(hdev, RMI_MODE_ATTN_REPORTS);
+       return rmi_reset_attn_mode(hdev);
 }
 #endif /* CONFIG_PM */
 
@@ -595,6 +696,7 @@ static void rmi_register_function(struct rmi_data *data,
                f->interrupt_count = pdt_entry->interrupt_source_count;
                f->irq_mask = rmi_gen_mask(f->interrupt_base,
                                                f->interrupt_count);
+               data->interrupt_enable_mask |= f->irq_mask;
        }
 }
 
@@ -732,6 +834,35 @@ static int rmi_populate_f01(struct hid_device *hdev)
                data->firmware_id += info[2] * 65536;
        }
 
+       ret = rmi_read_block(hdev, data->f01.control_base_addr, info,
+                               2);
+
+       if (ret) {
+               hid_err(hdev, "can not read f01 ctrl registers\n");
+               return ret;
+       }
+
+       data->f01_ctrl0 = info[0];
+
+       if (!info[1]) {
+               /*
+                * Do to a firmware bug in some touchpads the F01 interrupt
+                * enable control register will be cleared on reset.
+                * This will stop the touchpad from reporting data, so
+                * if F01 CTRL1 is 0 then we need to explicitly enable
+                * interrupts for the functions we want data for.
+                */
+               data->restore_interrupt_mask = true;
+
+               ret = rmi_write(hdev, data->f01.control_base_addr + 1,
+                               &data->interrupt_enable_mask);
+               if (ret) {
+                       hid_err(hdev, "can not write to control reg 1: %d.\n",
+                               ret);
+                       return ret;
+               }
+       }
+
        return 0;
 }
 
@@ -904,24 +1035,23 @@ static int rmi_populate_f11(struct hid_device *hdev)
        if (has_data40)
                data->f11.report_size += data->max_fingers * 2;
 
-       /*
-        * retrieve the ctrl registers
-        * the ctrl register has a size of 20 but a fw bug split it into 16 + 4,
-        * and there is no way to know if the first 20 bytes are here or not.
-        * We use only the first 12 bytes, so get only them.
-        */
-       ret = rmi_read_block(hdev, data->f11.control_base_addr, buf, 12);
+       ret = rmi_read_block(hdev, data->f11.control_base_addr,
+                       data->f11_ctrl_regs, RMI_F11_CTRL_REG_COUNT);
        if (ret) {
                hid_err(hdev, "can not read ctrl block of size 11: %d.\n", ret);
                return ret;
        }
 
-       data->max_x = buf[6] | (buf[7] << 8);
-       data->max_y = buf[8] | (buf[9] << 8);
+       /* data->f11_ctrl_regs now contains valid register data */
+       data->read_f11_ctrl_regs = true;
+
+       data->max_x = data->f11_ctrl_regs[6] | (data->f11_ctrl_regs[7] << 8);
+       data->max_y = data->f11_ctrl_regs[8] | (data->f11_ctrl_regs[9] << 8);
 
        if (has_dribble) {
-               buf[0] = buf[0] & ~BIT(6);
-               ret = rmi_write(hdev, data->f11.control_base_addr, buf);
+               data->f11_ctrl_regs[0] = data->f11_ctrl_regs[0] & ~BIT(6);
+               ret = rmi_write(hdev, data->f11.control_base_addr,
+                               data->f11_ctrl_regs);
                if (ret) {
                        hid_err(hdev, "can not write to control reg 0: %d.\n",
                                ret);
@@ -930,9 +1060,9 @@ static int rmi_populate_f11(struct hid_device *hdev)
        }
 
        if (has_palm_detect) {
-               buf[11] = buf[11] & ~BIT(0);
+               data->f11_ctrl_regs[11] = data->f11_ctrl_regs[11] & ~BIT(0);
                ret = rmi_write(hdev, data->f11.control_base_addr + 11,
-                               &buf[11]);
+                               &data->f11_ctrl_regs[11]);
                if (ret) {
                        hid_err(hdev, "can not write to control reg 11: %d.\n",
                                ret);
@@ -1273,6 +1403,7 @@ static struct hid_driver rmi_driver = {
        .input_mapping          = rmi_input_mapping,
        .input_configured       = rmi_input_configured,
 #ifdef CONFIG_PM
+       .suspend                = rmi_suspend,
        .resume                 = rmi_post_resume,
        .reset_resume           = rmi_post_reset,
 #endif
index 090a1ba0abb6fb1f6c937a7190980bbd8f318a0c..a76eb2a0a987b33da708dbbaf581ef914901ffbd 100644 (file)
@@ -774,6 +774,9 @@ static const struct hid_device_id sensor_hub_devices[] = {
        { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_TEXAS_INSTRUMENTS,
                        USB_DEVICE_ID_TEXAS_INSTRUMENTS_LENOVO_YOGA),
                        .driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
+       { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_ITE,
+                       USB_DEVICE_ID_ITE_LENOVO_YOGA),
+                       .driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
        { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, HID_ANY_ID,
                     HID_ANY_ID) },
        { }
index ed2f008f840377c394f1a910c331ea5f472a231e..ed0496abf573a90be06b0c1f7a2cd785e1a52616 100644 (file)
@@ -296,7 +296,14 @@ static __u8 navigation_rdesc[] = {
        0x09, 0x01,         /*          Usage (Pointer),            */
        0x81, 0x02,         /*          Input (Variable),           */
        0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
-       0x95, 0x20,         /*          Report Count (26),          */
+       0x95, 0x01,         /*          Report Count (1),           */
+       0x81, 0x02,         /*          Input (Variable),           */
+       0x05, 0x01,         /*          Usage Page (Desktop),       */
+       0x95, 0x01,         /*          Report Count (1),           */
+       0x09, 0x01,         /*          Usage (Pointer),            */
+       0x81, 0x02,         /*          Input (Variable),           */
+       0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
+       0x95, 0x1E,         /*          Report Count (24),          */
        0x81, 0x02,         /*          Input (Variable),           */
        0x75, 0x08,         /*          Report Size (8),            */
        0x95, 0x30,         /*          Report Count (48),          */
@@ -1270,6 +1277,17 @@ static int sony_raw_event(struct hid_device *hdev, struct hid_report *report,
         * has to be BYTE_SWAPPED before passing up to joystick interface
         */
        if ((sc->quirks & SIXAXIS_CONTROLLER) && rd[0] == 0x01 && size == 49) {
+               /*
+                * When connected via Bluetooth the Sixaxis occasionally sends
+                * a report with the second byte 0xff and the rest zeroed.
+                *
+                * This report does not reflect the actual state of the
+                * controller must be ignored to avoid generating false input
+                * events.
+                */
+               if (rd[1] == 0xff)
+                       return -EINVAL;
+
                swap(rd[41], rd[42]);
                swap(rd[43], rd[44]);
                swap(rd[45], rd[46]);
index 94167310e15a4c95001d339d4da3b7319f9005eb..b905d501e752d607b6fc1731ad89ff3d23ce7cd0 100644 (file)
@@ -858,7 +858,7 @@ static int uclogic_tablet_enable(struct hid_device *hdev)
        for (p = drvdata->rdesc;
             p <= drvdata->rdesc + drvdata->rsize - 4;) {
                if (p[0] == 0xFE && p[1] == 0xED && p[2] == 0x1D &&
-                   p[3] < sizeof(params)) {
+                   p[3] < ARRAY_SIZE(params)) {
                        v = params[p[3]];
                        put_unaligned(cpu_to_le32(v), (s32 *)p);
                        p += 4;
index f77469d4edfb0ecb1709032361913d4a92ceb919..9ed69b5121f71bcaa2fba2d9b53d8bae1ea10c08 100644 (file)
@@ -1092,13 +1092,13 @@ static int i2c_hid_suspend(struct device *dev)
        struct hid_device *hid = ihid->hid;
        int ret = 0;
 
+       if (hid->driver && hid->driver->suspend)
+               ret = hid->driver->suspend(hid, PMSG_SUSPEND);
+
        disable_irq(ihid->irq);
        if (device_may_wakeup(&client->dev))
                enable_irq_wake(ihid->irq);
 
-       if (hid->driver && hid->driver->suspend)
-               ret = hid->driver->suspend(hid, PMSG_SUSPEND);
-
        /* Save some power */
        i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
 
index bfbe1bedda7f34396db34e85b79c89ee1a251209..1a23d78fe5e70228bfe2db590b58ba794a24d4c2 100644 (file)
@@ -710,7 +710,8 @@ int usbhid_open(struct hid_device *hid)
                 * Wait 50 msec for the queue to empty before allowing events
                 * to go through hid.
                 */
-               msleep(50);
+               if (res == 0 && !(hid->quirks & HID_QUIRK_ALWAYS_POLL))
+                       msleep(50);
                clear_bit(HID_RESUME_RUNNING, &usbhid->iofl);
        }
 done:
index 20f9a653444c21d0ef89f4561d4d68544dff4bf0..03decf053cdad04a54693d5e8eec4bda3d5e02bf 100644 (file)
@@ -90,8 +90,9 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_PRO_2, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3, HID_QUIRK_NO_INIT_REPORTS },
-       { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3_JP, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS },
index 44958d79d598dfc3a7e6938a2babbf3e1fdc2188..708df9e3b70a0a57d746c5467ae80bebe41803c3 100644 (file)
@@ -1130,7 +1130,7 @@ static struct input_dev *wacom_allocate_input(struct wacom *wacom)
        if (!input_dev)
                return NULL;
 
-       input_dev->name = wacom_wac->pen_name;
+       input_dev->name = wacom_wac->features.name;
        input_dev->phys = hdev->phys;
        input_dev->dev.parent = &hdev->dev;
        input_dev->open = wacom_open;
@@ -1145,43 +1145,6 @@ static struct input_dev *wacom_allocate_input(struct wacom *wacom)
        return input_dev;
 }
 
-static void wacom_free_inputs(struct wacom *wacom)
-{
-       struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
-
-       if (wacom_wac->pen_input)
-               input_free_device(wacom_wac->pen_input);
-       if (wacom_wac->touch_input)
-               input_free_device(wacom_wac->touch_input);
-       if (wacom_wac->pad_input)
-               input_free_device(wacom_wac->pad_input);
-       wacom_wac->pen_input = NULL;
-       wacom_wac->touch_input = NULL;
-       wacom_wac->pad_input = NULL;
-}
-
-static int wacom_allocate_inputs(struct wacom *wacom)
-{
-       struct input_dev *pen_input_dev, *touch_input_dev, *pad_input_dev;
-       struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
-
-       pen_input_dev = wacom_allocate_input(wacom);
-       touch_input_dev = wacom_allocate_input(wacom);
-       pad_input_dev = wacom_allocate_input(wacom);
-       if (!pen_input_dev || !touch_input_dev || !pad_input_dev) {
-               wacom_free_inputs(wacom);
-               return -ENOMEM;
-       }
-
-       wacom_wac->pen_input = pen_input_dev;
-       wacom_wac->touch_input = touch_input_dev;
-       wacom_wac->touch_input->name = wacom_wac->touch_name;
-       wacom_wac->pad_input = pad_input_dev;
-       wacom_wac->pad_input->name = wacom_wac->pad_name;
-
-       return 0;
-}
-
 static void wacom_clean_inputs(struct wacom *wacom)
 {
        if (wacom->wacom_wac.pen_input) {
@@ -1208,6 +1171,25 @@ static void wacom_clean_inputs(struct wacom *wacom)
        wacom_destroy_leds(wacom);
 }
 
+static int wacom_allocate_inputs(struct wacom *wacom)
+{
+       struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
+
+       wacom_wac->pen_input = wacom_allocate_input(wacom);
+       wacom_wac->touch_input = wacom_allocate_input(wacom);
+       wacom_wac->pad_input = wacom_allocate_input(wacom);
+       if (!wacom_wac->pen_input || !wacom_wac->touch_input || !wacom_wac->pad_input) {
+               wacom_clean_inputs(wacom);
+               return -ENOMEM;
+       }
+
+       wacom_wac->pen_input->name = wacom_wac->pen_name;
+       wacom_wac->touch_input->name = wacom_wac->touch_name;
+       wacom_wac->pad_input->name = wacom_wac->pad_name;
+
+       return 0;
+}
+
 static int wacom_register_inputs(struct wacom *wacom)
 {
        struct input_dev *pen_input_dev, *touch_input_dev, *pad_input_dev;
@@ -1710,7 +1692,6 @@ static struct hid_driver wacom_driver = {
        .id_table =     wacom_ids,
        .probe =        wacom_probe,
        .remove =       wacom_remove,
-       .event =        wacom_wac_event,
        .report =       wacom_wac_report,
 #ifdef CONFIG_PM
        .resume =       wacom_resume,
index 0d244239e55def103f786254f3f617a84b2f0ba2..80628a2beee60e1be77049fb8f532de9003b99e6 100644 (file)
@@ -1437,6 +1437,12 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
        return 0;
 }
 
+static void wacom_wac_pen_pre_report(struct hid_device *hdev,
+               struct hid_report *report)
+{
+       return;
+}
+
 static void wacom_wac_pen_report(struct hid_device *hdev,
                struct hid_report *report)
 {
@@ -1491,6 +1497,13 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
                        wacom_map_usage(input, usage, field, EV_ABS,
                                        ABS_MT_POSITION_Y, 4);
                break;
+       case HID_DG_WIDTH:
+       case HID_DG_HEIGHT:
+               features->last_slot_field = usage->hid;
+               wacom_map_usage(input, usage, field, EV_ABS, ABS_MT_TOUCH_MAJOR, 0);
+               wacom_map_usage(input, usage, field, EV_ABS, ABS_MT_TOUCH_MINOR, 0);
+               input_set_abs_params(input, ABS_MT_ORIENTATION, 0, 1, 0, 0);
+               break;
        case HID_DG_CONTACTID:
                features->last_slot_field = usage->hid;
                break;
@@ -1504,6 +1517,10 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
                features->last_slot_field = usage->hid;
                wacom_map_usage(input, usage, field, EV_KEY, BTN_TOUCH, 0);
                break;
+       case HID_DG_CONTACTCOUNT:
+               wacom_wac->hid_data.cc_index = field->index;
+               wacom_wac->hid_data.cc_value_index = usage->usage_index;
+               break;
        }
 }
 
@@ -1515,6 +1532,10 @@ static void wacom_wac_finger_slot(struct wacom_wac *wacom_wac,
        bool prox = hid_data->tipswitch &&
                    !wacom_wac->shared->stylus_in_proximity;
 
+       wacom_wac->hid_data.num_received++;
+       if (wacom_wac->hid_data.num_received > wacom_wac->hid_data.num_expected)
+               return;
+
        if (mt) {
                int slot;
 
@@ -1531,6 +1552,13 @@ static void wacom_wac_finger_slot(struct wacom_wac *wacom_wac,
                                 hid_data->x);
                input_report_abs(input, mt ? ABS_MT_POSITION_Y : ABS_Y,
                                 hid_data->y);
+
+               if (test_bit(ABS_MT_TOUCH_MAJOR, input->absbit)) {
+                       input_report_abs(input, ABS_MT_TOUCH_MAJOR, max(hid_data->width, hid_data->height));
+                       input_report_abs(input, ABS_MT_TOUCH_MINOR, min(hid_data->width, hid_data->height));
+                       if (hid_data->width != hid_data->height)
+                               input_report_abs(input, ABS_MT_ORIENTATION, hid_data->width <= hid_data->height ? 0 : 1);
+               }
        }
 }
 
@@ -1547,6 +1575,12 @@ static int wacom_wac_finger_event(struct hid_device *hdev,
        case HID_GD_Y:
                wacom_wac->hid_data.y = value;
                break;
+       case HID_DG_WIDTH:
+               wacom_wac->hid_data.width = value;
+               break;
+       case HID_DG_HEIGHT:
+               wacom_wac->hid_data.height = value;
+               break;
        case HID_DG_CONTACTID:
                wacom_wac->hid_data.id = value;
                break;
@@ -1564,6 +1598,24 @@ static int wacom_wac_finger_event(struct hid_device *hdev,
        return 0;
 }
 
+static void wacom_wac_finger_pre_report(struct hid_device *hdev,
+               struct hid_report *report)
+{
+       struct wacom *wacom = hid_get_drvdata(hdev);
+       struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+       struct hid_data* hid_data = &wacom_wac->hid_data;
+
+       if (hid_data->cc_index >= 0) {
+               struct hid_field *field = report->field[hid_data->cc_index];
+               int value = field->value[hid_data->cc_value_index];
+               if (value)
+                       hid_data->num_expected = value;
+       }
+       else {
+               hid_data->num_expected = wacom_wac->features.touch_max;
+       }
+}
+
 static void wacom_wac_finger_report(struct hid_device *hdev,
                struct hid_report *report)
 {
@@ -1572,10 +1624,18 @@ static void wacom_wac_finger_report(struct hid_device *hdev,
        struct input_dev *input = wacom_wac->touch_input;
        unsigned touch_max = wacom_wac->features.touch_max;
 
+       /* If more packets of data are expected, give us a chance to
+        * process them rather than immediately syncing a partial
+        * update.
+        */
+       if (wacom_wac->hid_data.num_received < wacom_wac->hid_data.num_expected)
+               return;
+
        if (touch_max > 1)
                input_mt_sync_frame(input);
 
        input_sync(input);
+       wacom_wac->hid_data.num_received = 0;
 
        /* keep touch state for pen event */
        wacom_wac->shared->touch_down = wacom_wac_finger_count_touches(wacom_wac);
@@ -1615,6 +1675,25 @@ int wacom_wac_event(struct hid_device *hdev, struct hid_field *field,
        return 0;
 }
 
+static void wacom_report_events(struct hid_device *hdev, struct hid_report *report)
+{
+       int r;
+
+       for (r = 0; r < report->maxfield; r++) {
+               struct hid_field *field;
+               unsigned count, n;
+
+               field = report->field[r];
+               count = field->report_count;
+
+               if (!(HID_MAIN_ITEM_VARIABLE & field->flags))
+                       continue;
+
+               for (n = 0; n < count; n++)
+                       wacom_wac_event(hdev, field, &field->usage[n], field->value[n]);
+       }
+}
+
 void wacom_wac_report(struct hid_device *hdev, struct hid_report *report)
 {
        struct wacom *wacom = hid_get_drvdata(hdev);
@@ -1624,6 +1703,14 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report)
        if (wacom_wac->features.type != HID_GENERIC)
                return;
 
+       if (WACOM_PEN_FIELD(field))
+               wacom_wac_pen_pre_report(hdev, report);
+
+       if (WACOM_FINGER_FIELD(field))
+               wacom_wac_finger_pre_report(hdev, report);
+
+       wacom_report_events(hdev, report);
+
        if (WACOM_PEN_FIELD(field))
                return wacom_wac_pen_report(hdev, report);
 
@@ -2223,10 +2310,10 @@ void wacom_setup_device_quirks(struct wacom *wacom)
         * 0, whose HID descriptor has an application usage of 0xFF0D
         * (i.e., WACOM_VENDORDEFINED_PEN). We route pen packets back
         * out through the HID_GENERIC device created for interface 1,
-        * so rewrite this one to be of type BTN_TOOL_FINGER.
+        * so rewrite this one to be of type WACOM_DEVICETYPE_TOUCH.
         */
        if (features->type == BAMBOO_PAD)
-               features->device_type |= WACOM_DEVICETYPE_TOUCH;
+               features->device_type = WACOM_DEVICETYPE_TOUCH;
 
        if (wacom->hdev->bus == BUS_BLUETOOTH)
                features->quirks |= WACOM_QUIRK_BATTERY;
index 2978c303909d396acfe9f8e0cbe96307cf8aefa4..c245a6628224c5e70cd2a9ca619bb909a0045363 100644 (file)
@@ -193,6 +193,10 @@ struct hid_data {
        int width;
        int height;
        int id;
+       int cc_index;
+       int cc_value_index;
+       int num_expected;
+       int num_received;
 };
 
 struct wacom_wac {