Merge branch 'for-linus' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/jikos/hid
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 15 Nov 2017 17:43:57 +0000 (09:43 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 15 Nov 2017 17:43:57 +0000 (09:43 -0800)
Pull HID updates from Jiri Kosina:

 - high resolution mode for Dell canvas support, from Benjamin Tissoires

 - pen handling fixes for the Wacom driver, from Jason Gerecke

 - i2c-hid: Apollo-Lake based laptops improvements, from Hans de Goede

 - Input/Core: eraser tool support, from Ping Cheng

 - new ALPS touchpad (T4, found currently on HP EliteBook 1000, Zbook
   Stduio and HP Elite book x360) supportm from Masaki Ota

 - other smaller assorted fixes

* 'for-linus' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (33 commits)
  HID: cp2112: fix broken gpio_direction_input callback
  HID: cp2112: fix interface specification URL
  HID: Wacom: switch Dell canvas into highres mode
  HID: wacom: generic: Send BTN_STYLUS3 when both barrel switches are set
  HID: sony: Fix SHANWAN pad rumbling on USB
  HID: i2c-hid: Add no-irq-after-reset quirk for 0911:5288 device
  HID: add backlight level quirk for Asus ROG laptops
  HID: cp2112: add HIDRAW dependency
  HID: Add ID 044f:b605 ThrustMaster, Inc. force feedback Racing Wheel
  HID: hid-logitech: remove redundant assignment to pointer value
  HID: wacom: generic: Recognize WACOM_HID_WD_PEN as a type of pen collection
  HID: rmi: Check that a device is a RMI device before calling RMI functions
  HID: add multi-input quirk for GamepadBlock
  HID: alps: add new U1 device ID
  HID: alps: add support for Alps T4 Touchpad device
  HID: alps: remove variables local to u1_init() from the device struct
  HID: alps: properly handle max_fingers and minimum on X and Y axis
  HID: alps: Separate U1 device code
  HID: alps: delete unnecessary struct u1_dev devInfo
  HID: usbhid: Convert timers to use timer_setup()
  ...

22 files changed:
drivers/hid/Kconfig
drivers/hid/hid-alps.c
drivers/hid/hid-asus.c
drivers/hid/hid-core.c
drivers/hid/hid-cp2112.c
drivers/hid/hid-hyperv.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-lg.c
drivers/hid/hid-lg4ff.c
drivers/hid/hid-multitouch.c
drivers/hid/hid-rmi.c
drivers/hid/hid-sony.c
drivers/hid/hid-tmff.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
include/linux/hid.h
include/uapi/linux/input-event-codes.h

index 374301fcbc86791e5005ba3e1b45a35c496174ad..779c5ae47f36b5857dfed6a67342472ce4ddc571 100644 (file)
@@ -230,7 +230,7 @@ config HID_CMEDIA
 
 config HID_CP2112
        tristate "Silicon Labs CP2112 HID USB-to-SMBus Bridge support"
-       depends on USB_HID && I2C && GPIOLIB
+       depends on USB_HID && HIDRAW && I2C && GPIOLIB
        select GPIOLIB_IRQCHIP
        ---help---
        Support for Silicon Labs CP2112 HID USB to SMBus Master Bridge.
@@ -750,11 +750,10 @@ config HID_PRIMAX
        HID standard.
 
 config HID_RETRODE
-       tristate "Retrode"
+       tristate "Retrode 2 USB adapter for vintage video games"
        depends on USB_HID
        ---help---
        Support for
-
          * Retrode 2 cartridge and controller adapter
 
 config HID_ROCCAT
index ed9c0ea5b026efa698462bc389307bd16427f98c..b1eeb4839bfc8f4747a1610077fda3ae6c7e77a7 100644 (file)
 #define ADDRESS_U1_PAD_BTN             0x00800052
 #define ADDRESS_U1_SP_BTN              0x0080009F
 
+#define T4_INPUT_REPORT_LEN                    sizeof(struct t4_input_report)
+#define T4_FEATURE_REPORT_LEN          T4_INPUT_REPORT_LEN
+#define T4_FEATURE_REPORT_ID           7
+#define T4_CMD_REGISTER_READ                   0x08
+#define T4_CMD_REGISTER_WRITE                  0x07
+
+#define T4_ADDRESS_BASE                                0xC2C0
+#define PRM_SYS_CONFIG_1                       (T4_ADDRESS_BASE + 0x0002)
+#define T4_PRM_FEED_CONFIG_1           (T4_ADDRESS_BASE + 0x0004)
+#define T4_PRM_FEED_CONFIG_4           (T4_ADDRESS_BASE + 0x001A)
+#define T4_PRM_ID_CONFIG_3                     (T4_ADDRESS_BASE + 0x00B0)
+
+
+#define T4_FEEDCFG4_ADVANCED_ABS_ENABLE                        0x01
+#define T4_I2C_ABS     0x78
+
+#define T4_COUNT_PER_ELECTRODE         256
 #define MAX_TOUCHES    5
 
+enum dev_num {
+       U1,
+       T4,
+       UNKNOWN,
+};
 /**
  * struct u1_data
  *
  * @input2: pointer to the kernel input2 device
  * @hdev: pointer to the struct hid_device
  *
- * @dev_ctrl: device control parameter
  * @dev_type: device type
- * @sen_line_num_x: number of sensor line of X
- * @sen_line_num_y: number of sensor line of Y
- * @pitch_x: sensor pitch of X
- * @pitch_y: sensor pitch of Y
- * @resolution: resolution
- * @btn_info: button information
+ * @max_fingers: total number of fingers
+ * @has_sp: boolean of sp existense
+ * @sp_btn_info: button information
  * @x_active_len_mm: active area length of X (mm)
  * @y_active_len_mm: active area length of Y (mm)
  * @x_max: maximum x coordinate value
  * @y_max: maximum y coordinate value
+ * @x_min: minimum x coordinate value
+ * @y_min: minimum y coordinate value
  * @btn_cnt: number of buttons
  * @sp_btn_cnt: number of stick buttons
  */
-struct u1_dev {
+struct alps_dev {
        struct input_dev *input;
        struct input_dev *input2;
        struct hid_device *hdev;
 
-       u8      dev_ctrl;
-       u8      dev_type;
-       u8      sen_line_num_x;
-       u8      sen_line_num_y;
-       u8      pitch_x;
-       u8      pitch_y;
-       u8      resolution;
-       u8      btn_info;
+       enum dev_num dev_type;
+       u8  max_fingers;
+       u8  has_sp;
        u8      sp_btn_info;
        u32     x_active_len_mm;
        u32     y_active_len_mm;
        u32     x_max;
        u32     y_max;
+       u32     x_min;
+       u32     y_min;
        u32     btn_cnt;
        u32     sp_btn_cnt;
 };
 
+struct t4_contact_data {
+       u8  palm;
+       u8      x_lo;
+       u8      x_hi;
+       u8      y_lo;
+       u8      y_hi;
+};
+
+struct t4_input_report {
+       u8  reportID;
+       u8  numContacts;
+       struct t4_contact_data contact[5];
+       u8  button;
+       u8  track[5];
+       u8  zx[5], zy[5];
+       u8  palmTime[5];
+       u8  kilroy;
+       u16 timeStamp;
+};
+
+static u16 t4_calc_check_sum(u8 *buffer,
+               unsigned long offset, unsigned long length)
+{
+       u16 sum1 = 0xFF, sum2 = 0xFF;
+       unsigned long i = 0;
+
+       if (offset + length >= 50)
+               return 0;
+
+       while (length > 0) {
+               u32 tlen = length > 20 ? 20 : length;
+
+               length -= tlen;
+
+               do {
+                       sum1 += buffer[offset + i];
+                       sum2 += sum1;
+                       i++;
+               } while (--tlen > 0);
+
+               sum1 = (sum1 & 0xFF) + (sum1 >> 8);
+               sum2 = (sum2 & 0xFF) + (sum2 >> 8);
+       }
+
+       sum1 = (sum1 & 0xFF) + (sum1 >> 8);
+       sum2 = (sum2 & 0xFF) + (sum2 >> 8);
+
+       return(sum2 << 8 | sum1);
+}
+
+static int t4_read_write_register(struct hid_device *hdev, u32 address,
+       u8 *read_val, u8 write_val, bool read_flag)
+{
+       int ret;
+       u16 check_sum;
+       u8 *input;
+       u8 *readbuf;
+
+       input = kzalloc(T4_FEATURE_REPORT_LEN, GFP_KERNEL);
+       if (!input)
+               return -ENOMEM;
+
+       input[0] = T4_FEATURE_REPORT_ID;
+       if (read_flag) {
+               input[1] = T4_CMD_REGISTER_READ;
+               input[8] = 0x00;
+       } else {
+               input[1] = T4_CMD_REGISTER_WRITE;
+               input[8] = write_val;
+       }
+       put_unaligned_le32(address, input + 2);
+       input[6] = 1;
+       input[7] = 0;
+
+       /* Calculate the checksum */
+       check_sum = t4_calc_check_sum(input, 1, 8);
+       input[9] = (u8)check_sum;
+       input[10] = (u8)(check_sum >> 8);
+       input[11] = 0;
+
+       ret = hid_hw_raw_request(hdev, T4_FEATURE_REPORT_ID, input,
+                       T4_FEATURE_REPORT_LEN,
+                       HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
+
+       if (ret < 0) {
+               dev_err(&hdev->dev, "failed to read command (%d)\n", ret);
+               goto exit;
+       }
+
+       readbuf = kzalloc(T4_FEATURE_REPORT_LEN, GFP_KERNEL);
+       if (read_flag) {
+               if (!readbuf) {
+                       ret = -ENOMEM;
+                       goto exit;
+               }
+
+               ret = hid_hw_raw_request(hdev, T4_FEATURE_REPORT_ID, readbuf,
+                               T4_FEATURE_REPORT_LEN,
+                               HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
+               if (ret < 0) {
+                       dev_err(&hdev->dev, "failed read register (%d)\n", ret);
+                       goto exit_readbuf;
+               }
+
+               if (*(u32 *)&readbuf[6] != address) {
+                       dev_err(&hdev->dev, "read register address error (%x,%x)\n",
+                       *(u32 *)&readbuf[6], address);
+                       goto exit_readbuf;
+               }
+
+               if (*(u16 *)&readbuf[10] != 1) {
+                       dev_err(&hdev->dev, "read register size error (%x)\n",
+                       *(u16 *)&readbuf[10]);
+                       goto exit_readbuf;
+               }
+
+               check_sum = t4_calc_check_sum(readbuf, 6, 7);
+               if (*(u16 *)&readbuf[13] != check_sum) {
+                       dev_err(&hdev->dev, "read register checksum error (%x,%x)\n",
+                       *(u16 *)&readbuf[13], check_sum);
+                       goto exit_readbuf;
+               }
+
+               *read_val = readbuf[12];
+       }
+
+       ret = 0;
+
+exit_readbuf:
+       kfree(readbuf);
+exit:
+       kfree(input);
+       return ret;
+}
+
 static int u1_read_write_register(struct hid_device *hdev, u32 address,
        u8 *read_val, u8 write_val, bool read_flag)
 {
@@ -165,21 +317,60 @@ exit:
        return ret;
 }
 
-static int alps_raw_event(struct hid_device *hdev,
-               struct hid_report *report, u8 *data, int size)
+static int t4_raw_event(struct alps_dev *hdata, u8 *data, int size)
+{
+       unsigned int x, y, z;
+       int i;
+       struct t4_input_report *p_report = (struct t4_input_report *)data;
+
+       if (!data)
+               return 0;
+       for (i = 0; i < hdata->max_fingers; i++) {
+               x = p_report->contact[i].x_hi << 8 | p_report->contact[i].x_lo;
+               y = p_report->contact[i].y_hi << 8 | p_report->contact[i].y_lo;
+               y = hdata->y_max - y + hdata->y_min;
+               z = (p_report->contact[i].palm < 0x80 &&
+                       p_report->contact[i].palm > 0) * 62;
+               if (x == 0xffff) {
+                       x = 0;
+                       y = 0;
+                       z = 0;
+               }
+               input_mt_slot(hdata->input, i);
+
+               input_mt_report_slot_state(hdata->input,
+                       MT_TOOL_FINGER, z != 0);
+
+               if (!z)
+                       continue;
+
+               input_report_abs(hdata->input, ABS_MT_POSITION_X, x);
+               input_report_abs(hdata->input, ABS_MT_POSITION_Y, y);
+               input_report_abs(hdata->input, ABS_MT_PRESSURE, z);
+       }
+       input_mt_sync_frame(hdata->input);
+
+       input_report_key(hdata->input, BTN_LEFT, p_report->button);
+
+       input_sync(hdata->input);
+       return 1;
+}
+
+static int u1_raw_event(struct alps_dev *hdata, u8 *data, int size)
 {
        unsigned int x, y, z;
        int i;
        short sp_x, sp_y;
-       struct u1_dev *hdata = hid_get_drvdata(hdev);
 
+       if (!data)
+               return 0;
        switch (data[0]) {
        case U1_MOUSE_REPORT_ID:
                break;
        case U1_FEATURE_REPORT_ID:
                break;
        case U1_ABSOLUTE_REPORT_ID:
-               for (i = 0; i < MAX_TOUCHES; i++) {
+               for (i = 0; i < hdata->max_fingers; i++) {
                        u8 *contact = &data[i * 5];
 
                        x = get_unaligned_le16(contact + 3);
@@ -241,122 +432,253 @@ static int alps_raw_event(struct hid_device *hdev,
        return 0;
 }
 
-#ifdef CONFIG_PM
-static int alps_post_reset(struct hid_device *hdev)
+static int alps_raw_event(struct hid_device *hdev,
+               struct hid_report *report, u8 *data, int size)
 {
-       return u1_read_write_register(hdev, ADDRESS_U1_DEV_CTRL_1,
-                               NULL, U1_TP_ABS_MODE | U1_SP_ABS_MODE, false);
+       int ret = 0;
+       struct alps_dev *hdata = hid_get_drvdata(hdev);
+
+       switch (hdev->product) {
+       case HID_PRODUCT_ID_T4_BTNLESS:
+               ret = t4_raw_event(hdata, data, size);
+               break;
+       default:
+               ret = u1_raw_event(hdata, data, size);
+               break;
+       }
+       return ret;
 }
 
-static int alps_post_resume(struct hid_device *hdev)
+static int __maybe_unused alps_post_reset(struct hid_device *hdev)
 {
-       return u1_read_write_register(hdev, ADDRESS_U1_DEV_CTRL_1,
-                               NULL, U1_TP_ABS_MODE | U1_SP_ABS_MODE, false);
+       int ret = -1;
+       struct alps_dev *data = hid_get_drvdata(hdev);
+
+       switch (data->dev_type) {
+       case T4:
+               ret = t4_read_write_register(hdev, T4_PRM_FEED_CONFIG_1,
+                       NULL, T4_I2C_ABS, false);
+               ret = t4_read_write_register(hdev, T4_PRM_FEED_CONFIG_4,
+                       NULL, T4_FEEDCFG4_ADVANCED_ABS_ENABLE, false);
+               break;
+       case U1:
+               ret = u1_read_write_register(hdev,
+                       ADDRESS_U1_DEV_CTRL_1, NULL,
+                       U1_TP_ABS_MODE | U1_SP_ABS_MODE, false);
+               break;
+       default:
+               break;
+       }
+       return ret;
 }
-#endif /* CONFIG_PM */
 
-static int alps_input_configured(struct hid_device *hdev, struct hid_input *hi)
+static int __maybe_unused alps_post_resume(struct hid_device *hdev)
 {
-       struct u1_dev *data = hid_get_drvdata(hdev);
-       struct input_dev *input = hi->input, *input2;
-       struct u1_dev devInfo;
-       int ret;
-       int res_x, res_y, i;
-
-       data->input = input;
-
-       hid_dbg(hdev, "Opening low level driver\n");
-       ret = hid_hw_open(hdev);
-       if (ret)
-               return ret;
+       return alps_post_reset(hdev);
+}
 
-       /* Allow incoming hid reports */
-       hid_device_io_start(hdev);
+static int u1_init(struct hid_device *hdev, struct alps_dev *pri_data)
+{
+       int ret;
+       u8 tmp, dev_ctrl, sen_line_num_x, sen_line_num_y;
+       u8 pitch_x, pitch_y, resolution;
 
        /* Device initialization */
        ret = u1_read_write_register(hdev, ADDRESS_U1_DEV_CTRL_1,
-                       &devInfo.dev_ctrl, 0, true);
+                       &dev_ctrl, 0, true);
        if (ret < 0) {
                dev_err(&hdev->dev, "failed U1_DEV_CTRL_1 (%d)\n", ret);
                goto exit;
        }
 
-       devInfo.dev_ctrl &= ~U1_DISABLE_DEV;
-       devInfo.dev_ctrl |= U1_TP_ABS_MODE;
+       dev_ctrl &= ~U1_DISABLE_DEV;
+       dev_ctrl |= U1_TP_ABS_MODE;
        ret = u1_read_write_register(hdev, ADDRESS_U1_DEV_CTRL_1,
-                       NULL, devInfo.dev_ctrl, false);
+                       NULL, dev_ctrl, false);
        if (ret < 0) {
                dev_err(&hdev->dev, "failed to change TP mode (%d)\n", ret);
                goto exit;
        }
 
        ret = u1_read_write_register(hdev, ADDRESS_U1_NUM_SENS_X,
-                       &devInfo.sen_line_num_x, 0, true);
+                       &sen_line_num_x, 0, true);
        if (ret < 0) {
                dev_err(&hdev->dev, "failed U1_NUM_SENS_X (%d)\n", ret);
                goto exit;
        }
 
        ret = u1_read_write_register(hdev, ADDRESS_U1_NUM_SENS_Y,
-                       &devInfo.sen_line_num_y, 0, true);
+                       &sen_line_num_y, 0, true);
                if (ret < 0) {
                dev_err(&hdev->dev, "failed U1_NUM_SENS_Y (%d)\n", ret);
                goto exit;
        }
 
        ret = u1_read_write_register(hdev, ADDRESS_U1_PITCH_SENS_X,
-                       &devInfo.pitch_x, 0, true);
+                       &pitch_x, 0, true);
        if (ret < 0) {
                dev_err(&hdev->dev, "failed U1_PITCH_SENS_X (%d)\n", ret);
                goto exit;
        }
 
        ret = u1_read_write_register(hdev, ADDRESS_U1_PITCH_SENS_Y,
-                       &devInfo.pitch_y, 0, true);
+                       &pitch_y, 0, true);
        if (ret < 0) {
                dev_err(&hdev->dev, "failed U1_PITCH_SENS_Y (%d)\n", ret);
                goto exit;
        }
 
        ret = u1_read_write_register(hdev, ADDRESS_U1_RESO_DWN_ABS,
-               &devInfo.resolution, 0, true);
+               &resolution, 0, true);
        if (ret < 0) {
                dev_err(&hdev->dev, "failed U1_RESO_DWN_ABS (%d)\n", ret);
                goto exit;
        }
+       pri_data->x_active_len_mm =
+               (pitch_x * (sen_line_num_x - 1)) / 10;
+       pri_data->y_active_len_mm =
+               (pitch_y * (sen_line_num_y - 1)) / 10;
+
+       pri_data->x_max =
+               (resolution << 2) * (sen_line_num_x - 1);
+       pri_data->x_min = 1;
+       pri_data->y_max =
+               (resolution << 2) * (sen_line_num_y - 1);
+       pri_data->y_min = 1;
 
        ret = u1_read_write_register(hdev, ADDRESS_U1_PAD_BTN,
-                       &devInfo.btn_info, 0, true);
+                       &tmp, 0, true);
        if (ret < 0) {
                dev_err(&hdev->dev, "failed U1_PAD_BTN (%d)\n", ret);
                goto exit;
        }
+       if ((tmp & 0x0F) == (tmp & 0xF0) >> 4) {
+               pri_data->btn_cnt = (tmp & 0x0F);
+       } else {
+               /* Button pad */
+               pri_data->btn_cnt = 1;
+       }
 
+       pri_data->has_sp = 0;
        /* Check StickPointer device */
        ret = u1_read_write_register(hdev, ADDRESS_U1_DEVICE_TYP,
-                       &devInfo.dev_type, 0, true);
+                       &tmp, 0, true);
        if (ret < 0) {
                dev_err(&hdev->dev, "failed U1_DEVICE_TYP (%d)\n", ret);
                goto exit;
        }
+       if (tmp & U1_DEVTYPE_SP_SUPPORT) {
+               dev_ctrl |= U1_SP_ABS_MODE;
+               ret = u1_read_write_register(hdev, ADDRESS_U1_DEV_CTRL_1,
+                       NULL, dev_ctrl, false);
+               if (ret < 0) {
+                       dev_err(&hdev->dev, "failed SP mode (%d)\n", ret);
+                       goto exit;
+               }
 
-       devInfo.x_active_len_mm =
-               (devInfo.pitch_x * (devInfo.sen_line_num_x - 1)) / 10;
-       devInfo.y_active_len_mm =
-               (devInfo.pitch_y * (devInfo.sen_line_num_y - 1)) / 10;
+               ret = u1_read_write_register(hdev, ADDRESS_U1_SP_BTN,
+                       &pri_data->sp_btn_info, 0, true);
+               if (ret < 0) {
+                       dev_err(&hdev->dev, "failed U1_SP_BTN (%d)\n", ret);
+                       goto exit;
+               }
+               pri_data->has_sp = 1;
+       }
+       pri_data->max_fingers = 5;
+exit:
+       return ret;
+}
 
-       devInfo.x_max =
-               (devInfo.resolution << 2) * (devInfo.sen_line_num_x - 1);
-       devInfo.y_max =
-               (devInfo.resolution << 2) * (devInfo.sen_line_num_y - 1);
+static int T4_init(struct hid_device *hdev, struct alps_dev *pri_data)
+{
+       int ret;
+       u8 tmp, sen_line_num_x, sen_line_num_y;
+
+       ret = t4_read_write_register(hdev, T4_PRM_ID_CONFIG_3, &tmp, 0, true);
+       if (ret < 0) {
+               dev_err(&hdev->dev, "failed T4_PRM_ID_CONFIG_3 (%d)\n", ret);
+               goto exit;
+       }
+       sen_line_num_x = 16 + ((tmp & 0x0F)  | (tmp & 0x08 ? 0xF0 : 0));
+       sen_line_num_y = 12 + (((tmp & 0xF0) >> 4)  | (tmp & 0x80 ? 0xF0 : 0));
+
+       pri_data->x_max = sen_line_num_x * T4_COUNT_PER_ELECTRODE;
+       pri_data->x_min = T4_COUNT_PER_ELECTRODE;
+       pri_data->y_max = sen_line_num_y * T4_COUNT_PER_ELECTRODE;
+       pri_data->y_min = T4_COUNT_PER_ELECTRODE;
+       pri_data->x_active_len_mm = pri_data->y_active_len_mm = 0;
+       pri_data->btn_cnt = 1;
+
+       ret = t4_read_write_register(hdev, PRM_SYS_CONFIG_1, &tmp, 0, true);
+       if (ret < 0) {
+               dev_err(&hdev->dev, "failed PRM_SYS_CONFIG_1 (%d)\n", ret);
+               goto exit;
+       }
+       tmp |= 0x02;
+       ret = t4_read_write_register(hdev, PRM_SYS_CONFIG_1, NULL, tmp, false);
+       if (ret < 0) {
+               dev_err(&hdev->dev, "failed PRM_SYS_CONFIG_1 (%d)\n", ret);
+               goto exit;
+       }
+
+       ret = t4_read_write_register(hdev, T4_PRM_FEED_CONFIG_1,
+                                       NULL, T4_I2C_ABS, false);
+       if (ret < 0) {
+               dev_err(&hdev->dev, "failed T4_PRM_FEED_CONFIG_1 (%d)\n", ret);
+               goto exit;
+       }
+
+       ret = t4_read_write_register(hdev, T4_PRM_FEED_CONFIG_4, NULL,
+                               T4_FEEDCFG4_ADVANCED_ABS_ENABLE, false);
+       if (ret < 0) {
+               dev_err(&hdev->dev, "failed T4_PRM_FEED_CONFIG_4 (%d)\n", ret);
+               goto exit;
+       }
+       pri_data->max_fingers = 5;
+       pri_data->has_sp = 0;
+exit:
+       return ret;
+}
+
+static int alps_input_configured(struct hid_device *hdev, struct hid_input *hi)
+{
+       struct alps_dev *data = hid_get_drvdata(hdev);
+       struct input_dev *input = hi->input, *input2;
+       int ret;
+       int res_x, res_y, i;
+
+       data->input = input;
+
+       hid_dbg(hdev, "Opening low level driver\n");
+       ret = hid_hw_open(hdev);
+       if (ret)
+               return ret;
+
+       /* Allow incoming hid reports */
+       hid_device_io_start(hdev);
+       switch (data->dev_type) {
+       case T4:
+               ret = T4_init(hdev, data);
+               break;
+       case U1:
+               ret = u1_init(hdev, data);
+               break;
+       default:
+               break;
+       }
+
+       if (ret)
+               goto exit;
 
        __set_bit(EV_ABS, input->evbit);
-       input_set_abs_params(input, ABS_MT_POSITION_X, 1, devInfo.x_max, 0, 0);
-       input_set_abs_params(input, ABS_MT_POSITION_Y, 1, devInfo.y_max, 0, 0);
+       input_set_abs_params(input, ABS_MT_POSITION_X,
+                                               data->x_min, data->x_max, 0, 0);
+       input_set_abs_params(input, ABS_MT_POSITION_Y,
+                                               data->y_min, data->y_max, 0, 0);
 
-       if (devInfo.x_active_len_mm && devInfo.y_active_len_mm) {
-               res_x = (devInfo.x_max - 1) / devInfo.x_active_len_mm;
-               res_y = (devInfo.y_max - 1) / devInfo.y_active_len_mm;
+       if (data->x_active_len_mm && data->y_active_len_mm) {
+               res_x = (data->x_max - 1) / data->x_active_len_mm;
+               res_y = (data->y_max - 1) / data->y_active_len_mm;
 
                input_abs_set_res(input, ABS_MT_POSITION_X, res_x);
                input_abs_set_res(input, ABS_MT_POSITION_Y, res_y);
@@ -364,49 +686,25 @@ static int alps_input_configured(struct hid_device *hdev, struct hid_input *hi)
 
        input_set_abs_params(input, ABS_MT_PRESSURE, 0, 64, 0, 0);
 
-       input_mt_init_slots(input, MAX_TOUCHES, INPUT_MT_POINTER);
+       input_mt_init_slots(input, data->max_fingers, INPUT_MT_POINTER);
 
        __set_bit(EV_KEY, input->evbit);
-       if ((devInfo.btn_info & 0x0F) == (devInfo.btn_info & 0xF0) >> 4) {
-               devInfo.btn_cnt = (devInfo.btn_info & 0x0F);
-       } else {
-               /* Button pad */
-               devInfo.btn_cnt = 1;
+
+       if (data->btn_cnt == 1)
                __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
-       }
 
-       for (i = 0; i < devInfo.btn_cnt; i++)
+       for (i = 0; i < data->btn_cnt; i++)
                __set_bit(BTN_LEFT + i, input->keybit);
 
-
        /* Stick device initialization */
-       if (devInfo.dev_type & U1_DEVTYPE_SP_SUPPORT) {
-
+       if (data->has_sp) {
                input2 = input_allocate_device();
                if (!input2) {
-                       ret = -ENOMEM;
-                       goto exit;
-               }
-
-               data->input2 = input2;
-
-               devInfo.dev_ctrl |= U1_SP_ABS_MODE;
-               ret = u1_read_write_register(hdev, ADDRESS_U1_DEV_CTRL_1,
-                       NULL, devInfo.dev_ctrl, false);
-               if (ret < 0) {
-                       dev_err(&hdev->dev, "failed SP mode (%d)\n", ret);
-                       input_free_device(input2);
-                       goto exit;
-               }
-
-               ret = u1_read_write_register(hdev, ADDRESS_U1_SP_BTN,
-                       &devInfo.sp_btn_info, 0, true);
-               if (ret < 0) {
-                       dev_err(&hdev->dev, "failed U1_SP_BTN (%d)\n", ret);
                        input_free_device(input2);
                        goto exit;
                }
 
+               data->input2 = input2;
                input2->phys = input->phys;
                input2->name = "DualPoint Stick";
                input2->id.bustype = BUS_I2C;
@@ -416,8 +714,8 @@ static int alps_input_configured(struct hid_device *hdev, struct hid_input *hi)
                input2->dev.parent = input->dev.parent;
 
                __set_bit(EV_KEY, input2->evbit);
-               devInfo.sp_btn_cnt = (devInfo.sp_btn_info & 0x0F);
-               for (i = 0; i < devInfo.sp_btn_cnt; i++)
+               data->sp_btn_cnt = (data->sp_btn_info & 0x0F);
+               for (i = 0; i < data->sp_btn_cnt; i++)
                        __set_bit(BTN_LEFT + i, input2->keybit);
 
                __set_bit(EV_REL, input2->evbit);
@@ -426,8 +724,7 @@ static int alps_input_configured(struct hid_device *hdev, struct hid_input *hi)
                __set_bit(INPUT_PROP_POINTER, input2->propbit);
                __set_bit(INPUT_PROP_POINTING_STICK, input2->propbit);
 
-               ret = input_register_device(data->input2);
-               if (ret) {
+               if (input_register_device(data->input2)) {
                        input_free_device(input2);
                        goto exit;
                }
@@ -448,10 +745,9 @@ static int alps_input_mapping(struct hid_device *hdev,
 
 static int alps_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
-       struct u1_dev *data = NULL;
+       struct alps_dev *data = NULL;
        int ret;
-
-       data = devm_kzalloc(&hdev->dev, sizeof(struct u1_dev), GFP_KERNEL);
+       data = devm_kzalloc(&hdev->dev, sizeof(struct alps_dev), GFP_KERNEL);
        if (!data)
                return -ENOMEM;
 
@@ -466,6 +762,18 @@ static int alps_probe(struct hid_device *hdev, const struct hid_device_id *id)
                return ret;
        }
 
+       switch (hdev->product) {
+       case HID_DEVICE_ID_ALPS_T4_BTNLESS:
+               data->dev_type = T4;
+               break;
+       case HID_DEVICE_ID_ALPS_U1_DUAL:
+       case HID_DEVICE_ID_ALPS_U1:
+               data->dev_type = U1;
+               break;
+       default:
+               data->dev_type = UNKNOWN;
+       }
+
        ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
        if (ret) {
                hid_err(hdev, "hw start failed\n");
@@ -483,6 +791,10 @@ static void alps_remove(struct hid_device *hdev)
 static const struct hid_device_id alps_id[] = {
        { HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY,
                USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1_DUAL) },
+       { HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY,
+               USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1) },
+       { HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY,
+               USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_T4_BTNLESS) },
        { }
 };
 MODULE_DEVICE_TABLE(hid, alps_id);
index 50c294be8324ab803450c00165717962e1603d13..1bb7b63b31508cf95c23e661370e32965c978c3a 100644 (file)
@@ -67,6 +67,7 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
 #define QUIRK_USE_KBD_BACKLIGHT                BIT(5)
 #define QUIRK_T100_KEYBOARD            BIT(6)
 #define QUIRK_T100CHI                  BIT(7)
+#define QUIRK_G752_KEYBOARD            BIT(8)
 
 #define I2C_KEYBOARD_QUIRKS                    (QUIRK_FIX_NOTEBOOK_REPORT | \
                                                 QUIRK_NO_INIT_REPORTS | \
@@ -670,6 +671,11 @@ static void asus_remove(struct hid_device *hdev)
        hid_hw_stop(hdev);
 }
 
+static const __u8 asus_g752_fixed_rdesc[] = {
+        0x19, 0x00,                    /*   Usage Minimum (0x00)       */
+        0x2A, 0xFF, 0x00,              /*   Usage Maximum (0xFF)       */
+};
+
 static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                unsigned int *rsize)
 {
@@ -708,6 +714,27 @@ static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                rdesc[391] = 0xff;
                rdesc[402] = 0x00;
        }
+       if (drvdata->quirks & QUIRK_G752_KEYBOARD &&
+                *rsize == 75 && rdesc[61] == 0x15 && rdesc[62] == 0x00) {
+               /* report is missing usage mninum and maximum */
+               __u8 *new_rdesc;
+               size_t new_size = *rsize + sizeof(asus_g752_fixed_rdesc);
+
+               new_rdesc = devm_kzalloc(&hdev->dev, new_size, GFP_KERNEL);
+               if (new_rdesc == NULL)
+                       return rdesc;
+
+               hid_info(hdev, "Fixing up Asus G752 keyb report descriptor\n");
+               /* copy the valid part */
+               memcpy(new_rdesc, rdesc, 61);
+               /* insert missing part */
+               memcpy(new_rdesc + 61, asus_g752_fixed_rdesc, sizeof(asus_g752_fixed_rdesc));
+               /* copy remaining data */
+               memcpy(new_rdesc + 61 + sizeof(asus_g752_fixed_rdesc), rdesc + 61, *rsize - 61);
+
+               *rsize = new_size;
+               rdesc = new_rdesc;
+       }
 
        return rdesc;
 }
@@ -718,9 +745,11 @@ static const struct hid_device_id asus_devices[] = {
        { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK,
                USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD), I2C_TOUCHPAD_QUIRKS },
        { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
-               USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1) },
+               USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1), QUIRK_USE_KBD_BACKLIGHT },
        { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
                USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2), QUIRK_USE_KBD_BACKLIGHT },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
+               USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD3), QUIRK_G752_KEYBOARD },
        { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
                USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD),
          QUIRK_T100_KEYBOARD | QUIRK_NO_CONSUMER_USAGES },
index 330ca983828ba6d11feaf5538841a6810d84f5c6..f3fcb836a1f9edd0af5b1f31362987d22eff11b2 100644 (file)
@@ -1662,7 +1662,7 @@ static struct bin_attribute dev_bin_attr_report_desc = {
        .size = HID_MAX_DESCRIPTOR_SIZE,
 };
 
-static struct device_attribute dev_attr_country = {
+static const struct device_attribute dev_attr_country = {
        .attr = { .name = "country", .mode = 0444 },
        .show = show_country,
 };
@@ -1889,6 +1889,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
 #endif
 #if IS_ENABLED(CONFIG_HID_ALPS)
        { HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1_DUAL) },
+       { HID_I2C_DEVICE(USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1_DUAL) },
+       { HID_I2C_DEVICE(USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1) },
+       { HID_I2C_DEVICE(USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_T4_BTNLESS) },
 #endif
 #if IS_ENABLED(CONFIG_HID_APPLE)
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) },
@@ -1979,6 +1982,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD3) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_ASUS_MD_5112) },
        { HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_ASUS_MD_5110) },
@@ -2329,6 +2333,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb323) },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb324) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb605) },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651) },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb653) },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) },
@@ -3121,4 +3126,3 @@ MODULE_AUTHOR("Andreas Gal");
 MODULE_AUTHOR("Vojtech Pavlik");
 MODULE_AUTHOR("Jiri Kosina");
 MODULE_LICENSE("GPL");
-
index 078026f63b6f40999a2aa1feb8023d3905a6044c..68cdc962265b1051d7e399e0c6a181a4426673ed 100644 (file)
@@ -21,7 +21,7 @@
  * Data Sheet:
  *   http://www.silabs.com/Support%20Documents/TechnicalDocs/CP2112.pdf
  * Programming Interface Specification:
- *   http://www.silabs.com/Support%20Documents/TechnicalDocs/AN495.pdf
+ *   https://www.silabs.com/documents/public/application-notes/an495-cp2112-interface-specification.pdf
  */
 
 #include <linux/gpio.h>
@@ -196,6 +196,8 @@ static int cp2112_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
                                 HID_REQ_GET_REPORT);
        if (ret != CP2112_GPIO_CONFIG_LENGTH) {
                hid_err(hdev, "error requesting GPIO config: %d\n", ret);
+               if (ret >= 0)
+                       ret = -EIO;
                goto exit;
        }
 
@@ -205,8 +207,10 @@ static int cp2112_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
        ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf,
                                 CP2112_GPIO_CONFIG_LENGTH, HID_FEATURE_REPORT,
                                 HID_REQ_SET_REPORT);
-       if (ret < 0) {
+       if (ret != CP2112_GPIO_CONFIG_LENGTH) {
                hid_err(hdev, "error setting GPIO config: %d\n", ret);
+               if (ret >= 0)
+                       ret = -EIO;
                goto exit;
        }
 
@@ -214,7 +218,7 @@ static int cp2112_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 
 exit:
        mutex_unlock(&dev->lock);
-       return ret < 0 ? ret : -EIO;
+       return ret;
 }
 
 static void cp2112_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
index 6039f071fab1370da4a684e801883ef23e9706d4..3aa2bb9f0f811dbe118de6f31ce25900c33f7fd1 100644 (file)
@@ -313,7 +313,7 @@ static void mousevsc_on_receive(struct hv_device *device,
 
                break;
        default:
-               pr_err("unsupported hid msg type - type %d len %d",
+               pr_err("unsupported hid msg type - type %d len %d\n",
                       hid_msg->header.type, hid_msg->header.size);
                break;
        }
index be2e005c3c516c6cb522a68a891d75e48f8f800f..5da3d6256d25353054060dbc8dfbb91ec62ca563 100644 (file)
@@ -77,6 +77,9 @@
 #define HID_DEVICE_ID_ALPS_U1_DUAL     0x120B
 #define HID_DEVICE_ID_ALPS_U1_DUAL_PTP 0x121F
 #define HID_DEVICE_ID_ALPS_U1_DUAL_3BTN_PTP    0x1220
+#define HID_DEVICE_ID_ALPS_U1          0x1215
+#define HID_DEVICE_ID_ALPS_T4_BTNLESS  0x120C
+
 
 #define USB_VENDOR_ID_AMI              0x046b
 #define USB_DEVICE_ID_AMI_VIRT_KEYBOARD_AND_MOUSE      0xff10
 #define USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD     0x0101
 #define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1 0x1854
 #define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2 0x1837
+#define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD3 0x1822
 
 #define USB_VENDOR_ID_ATEN             0x0557
 #define USB_DEVICE_ID_ATEN_UC100KM     0x2004
 #define USB_DEVICE_ID_GYRATION_REMOTE_2 0x0003
 #define USB_DEVICE_ID_GYRATION_REMOTE_3 0x0008
 
+#define I2C_VENDOR_ID_HANTICK          0x0911
+#define I2C_PRODUCT_ID_HANTICK_5288    0x5288
+
 #define USB_VENDOR_ID_HANWANG          0x0b57
 #define USB_DEVICE_ID_HANWANG_TABLET_FIRST     0x5000
 #define USB_DEVICE_ID_HANWANG_TABLET_LAST      0x8fff
 #define USB_DEVICE_ID_MCC_PMD1024LS    0x0076
 #define USB_DEVICE_ID_MCC_PMD1208LS    0x007a
 
+#define USB_VENDOR_ID_MCS              0x16d0
+#define USB_DEVICE_ID_MCS_GAMEPADBLOCK 0x0bcc
+
 #define USB_VENDOR_ID_MGE              0x0463
 #define USB_DEVICE_ID_MGE_UPS          0xffff
 #define USB_DEVICE_ID_MGE_UPS1         0x0001
index 199f6a01fc629ead34108da7ddc895269ed0820a..04d01b57d94c8280d2d6a63ef863136165555c11 100644 (file)
@@ -797,6 +797,15 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                        map_key_clear(BTN_STYLUS);
                        break;
 
+               case 0x45: /* ERASER */
+                       /*
+                        * This event is reported when eraser tip touches the surface.
+                        * Actual eraser (BTN_TOOL_RUBBER) is set by Invert usage when
+                        * tool gets in proximity.
+                        */
+                       map_key_clear(BTN_TOUCH);
+                       break;
+
                case 0x46: /* TabletPick */
                case 0x5a: /* SecondaryBarrelSwitch */
                        map_key_clear(BTN_STYLUS2);
index 52026dc94d5c4b0306ce585be293cbe2cb1910d9..596227ddb6e078af028b2d83102d40e5006b147a 100644 (file)
@@ -756,7 +756,9 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
 
        /* Setup wireless link with Logitech Wii wheel */
        if (hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) {
-               const unsigned char cbuf[] = { 0x00, 0xAF,  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+               static const unsigned char cbuf[] = {
+                       0x00, 0xAF,  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+               };
                u8 *buf = kmemdup(cbuf, sizeof(cbuf), GFP_KERNEL);
 
                if (!buf) {
index 1fc12e3570359248f2cd2847aad219ad4f134a81..512d67e1aae386e37b90288f800734b5a826aebe 100644 (file)
@@ -474,9 +474,7 @@ static int lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *effec
 static void lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitude)
 {
        struct hid_device *hid = input_get_drvdata(dev);
-       struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
-       struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
-       s32 *value = report->field[0]->value;
+       s32 *value;
        u32 expand_a, expand_b;
        struct lg4ff_device_entry *entry;
        struct lg_drv_data *drv_data;
index 9e8c4d2ba11d2cc7c2559f34dc46fe646640e131..65ea23be9677b6dbd0b539ee2cc7ca1abd58958a 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/input/mt.h>
+#include <linux/jiffies.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 
@@ -112,6 +113,7 @@ struct mt_device {
        struct mt_slot curdata; /* placeholder of incoming data */
        struct mt_class mtclass;        /* our mt device class */
        struct timer_list release_timer;        /* to release sticky fingers */
+       struct hid_device *hdev;        /* hid_device we're attached to */
        struct mt_fields *fields;       /* temporary placeholder for storing the
                                           multitouch fields */
        unsigned long mt_io_flags;      /* mt flags (MT_IO_FLAGS_*) */
@@ -136,6 +138,9 @@ struct mt_device {
        bool serial_maybe;      /* need to check for serial protocol */
        bool curvalid;          /* is the current contact valid? */
        unsigned mt_flags;      /* flags to pass to input-mt */
+       __s32 dev_time;         /* the scan time provided by the device */
+       unsigned long jiffies;  /* the frame's jiffies */
+       int timestamp;          /* the timestamp to be sent */
 };
 
 static void mt_post_parse_default_settings(struct mt_device *td);
@@ -177,6 +182,12 @@ static void mt_post_parse(struct mt_device *td);
 #define MT_DEFAULT_MAXCONTACT  10
 #define MT_MAX_MAXCONTACT      250
 
+/*
+ * Resync device and local timestamps after that many microseconds without
+ * receiving data.
+ */
+#define MAX_TIMESTAMP_INTERVAL 1000000
+
 #define MT_USB_DEVICE(v, p)    HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH, v, p)
 #define MT_BT_DEVICE(v, p)     HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_MULTITOUCH, v, p)
 
@@ -583,6 +594,12 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                                cls->sn_pressure);
                        mt_store_field(usage, td, hi);
                        return 1;
+               case HID_DG_SCANTIME:
+                       hid_map_usage(hi, usage, bit, max,
+                               EV_MSC, MSC_TIMESTAMP);
+                       input_set_capability(hi->input, EV_MSC, MSC_TIMESTAMP);
+                       mt_store_field(usage, td, hi);
+                       return 1;
                case HID_DG_CONTACTCOUNT:
                        /* Ignore if indexes are out of bounds. */
                        if (field->index >= field->report->maxfield ||
@@ -718,6 +735,7 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
 static void mt_sync_frame(struct mt_device *td, struct input_dev *input)
 {
        input_mt_sync_frame(input);
+       input_event(input, EV_MSC, MSC_TIMESTAMP, td->timestamp);
        input_sync(input);
        td->num_received = 0;
        if (test_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags))
@@ -727,6 +745,28 @@ static void mt_sync_frame(struct mt_device *td, struct input_dev *input)
        clear_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags);
 }
 
+static int mt_compute_timestamp(struct mt_device *td, struct hid_field *field,
+               __s32 value)
+{
+       long delta = value - td->dev_time;
+       unsigned long jdelta = jiffies_to_usecs(jiffies - td->jiffies);
+
+       td->jiffies = jiffies;
+       td->dev_time = value;
+
+       if (delta < 0)
+               delta += field->logical_maximum;
+
+       /* HID_DG_SCANTIME is expressed in 100us, we want it in us. */
+       delta *= 100;
+
+       if (jdelta > MAX_TIMESTAMP_INTERVAL)
+               /* No data received for a while, resync the timestamp. */
+               return 0;
+       else
+               return td->timestamp + delta;
+}
+
 static int mt_touch_event(struct hid_device *hid, struct hid_field *field,
                                struct hid_usage *usage, __s32 value)
 {
@@ -787,6 +827,9 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
                case HID_DG_HEIGHT:
                        td->curdata.h = value;
                        break;
+               case HID_DG_SCANTIME:
+                       td->timestamp = mt_compute_timestamp(td, field, value);
+                       break;
                case HID_DG_CONTACTCOUNT:
                        break;
                case HID_DG_TOUCH:
@@ -1246,10 +1289,10 @@ static void mt_release_contacts(struct hid_device *hid)
        td->num_received = 0;
 }
 
-static void mt_expired_timeout(unsigned long arg)
+static void mt_expired_timeout(struct timer_list *t)
 {
-       struct hid_device *hdev = (void *)arg;
-       struct mt_device *td = hid_get_drvdata(hdev);
+       struct mt_device *td = from_timer(td, t, release_timer);
+       struct hid_device *hdev = td->hdev;
 
        /*
         * An input report came in just before we release the sticky fingers,
@@ -1280,6 +1323,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
                dev_err(&hdev->dev, "cannot allocate multitouch data\n");
                return -ENOMEM;
        }
+       td->hdev = hdev;
        td->mtclass = *mtclass;
        td->inputmode = -1;
        td->maxcontact_report_id = -1;
@@ -1331,7 +1375,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
         */
        hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
 
-       setup_timer(&td->release_timer, mt_expired_timeout, (long)hdev);
+       timer_setup(&td->release_timer, mt_expired_timeout, 0);
 
        ret = hid_parse(hdev);
        if (ret != 0)
index ef241d66562e00950e8979ef4fd0633fd4efdca3..0f43c4292685fcd4bcde4eeeb6268d17a31fe89e 100644 (file)
@@ -368,6 +368,11 @@ static int rmi_check_sanity(struct hid_device *hdev, u8 *data, int size)
 static int rmi_raw_event(struct hid_device *hdev,
                struct hid_report *report, u8 *data, int size)
 {
+       struct rmi_data *hdata = hid_get_drvdata(hdev);
+
+       if (!(hdata->device_flags & RMI_DEVICE))
+               return 0;
+
        size = rmi_check_sanity(hdev, data, size);
        if (size < 2)
                return 0;
@@ -713,9 +718,11 @@ static void rmi_remove(struct hid_device *hdev)
 {
        struct rmi_data *hdata = hid_get_drvdata(hdev);
 
-       clear_bit(RMI_STARTED, &hdata->flags);
-       cancel_work_sync(&hdata->reset_work);
-       rmi_unregister_transport_device(&hdata->xport);
+       if (hdata->device_flags & RMI_DEVICE) {
+               clear_bit(RMI_STARTED, &hdata->flags);
+               cancel_work_sync(&hdata->reset_work);
+               rmi_unregister_transport_device(&hdata->xport);
+       }
 
        hid_hw_stop(hdev);
 }
index d03203a82e8f78962697791590ef45b35c003833..b9dc3ac4d4aad8301bf55c2ef5ba803b0b742261 100644 (file)
@@ -1439,10 +1439,16 @@ static int sixaxis_set_operational_usb(struct hid_device *hdev)
                goto out;
        }
 
-       ret = hid_hw_output_report(hdev, buf, 1);
-       if (ret < 0) {
-               hid_info(hdev, "can't set operational mode: step 3, ignoring\n");
-               ret = 0;
+       /*
+        * But the USB interrupt would cause SHANWAN controllers to
+        * start rumbling non-stop.
+        */
+       if (strcmp(hdev->name, "SHANWAN PS3 GamePad")) {
+               ret = hid_hw_output_report(hdev, buf, 1);
+               if (ret < 0) {
+                       hid_info(hdev, "can't set operational mode: step 3, ignoring\n");
+                       ret = 0;
+               }
        }
 
 out:
index b83376077d72282ac3373fe700e8d273d303fc1f..bea8def64f437ed13ed5576a479634cee0a27ca4 100644 (file)
@@ -242,6 +242,8 @@ static const struct hid_device_id tm_devices[] = {
                .driver_data = (unsigned long)ff_rumble },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb324),   /* Dual Trigger 3-in-1 (PS3 Mode) */
                .driver_data = (unsigned long)ff_rumble },
+       { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb605),   /* NASCAR PRO FF2 Wheel */
+               .driver_data = (unsigned long)ff_joystick },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651),   /* FGT Rumble Force Wheel */
                .driver_data = (unsigned long)ff_rumble },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb653),   /* RGT Force Feedback CLUTCH Raging Wheel */
index 9145c2129a967464e1e7ed8978dbe53c6db9e86e..e054ee43c1e275da0adff1d6ee5e8ec49bb1ecbc 100644 (file)
@@ -46,6 +46,7 @@
 
 /* quirks to control the device */
 #define I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV       BIT(0)
+#define I2C_HID_QUIRK_NO_IRQ_AFTER_RESET       BIT(1)
 
 /* flags */
 #define I2C_HID_STARTED                0
@@ -168,6 +169,8 @@ static const struct i2c_hid_quirks {
                I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV },
        { USB_VENDOR_ID_WEIDA, USB_DEVICE_ID_WEIDA_8755,
                I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV },
+       { I2C_VENDOR_ID_HANTICK, I2C_PRODUCT_ID_HANTICK_5288,
+               I2C_HID_QUIRK_NO_IRQ_AFTER_RESET },
        { 0, 0 }
 };
 
@@ -252,7 +255,9 @@ static int __i2c_hid_command(struct i2c_client *client,
 
        ret = 0;
 
-       if (wait) {
+       if (wait && (ihid->quirks & I2C_HID_QUIRK_NO_IRQ_AFTER_RESET)) {
+               msleep(100);
+       } else if (wait) {
                i2c_hid_dbg(ihid, "%s: waiting...\n", __func__);
                if (!wait_event_timeout(ihid->wait,
                                !test_bit(I2C_HID_RESET_PENDING, &ihid->flags),
index 045b5da9b992873ce74f5d401de34855b93a6f8e..640dfb937c6910f9ff9091a5a455b18c640f9edd 100644 (file)
@@ -101,10 +101,10 @@ static int hid_start_in(struct hid_device *hid)
 }
 
 /* I/O retry timer routine */
-static void hid_retry_timeout(unsigned long _hid)
+static void hid_retry_timeout(struct timer_list *t)
 {
-       struct hid_device *hid = (struct hid_device *) _hid;
-       struct usbhid_device *usbhid = hid->driver_data;
+       struct usbhid_device *usbhid = from_timer(usbhid, t, io_retry);
+       struct hid_device *hid = usbhid->hid;
 
        dev_dbg(&usbhid->intf->dev, "retrying intr urb\n");
        if (hid_start_in(hid))
@@ -1373,7 +1373,7 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *
 
        init_waitqueue_head(&usbhid->wait);
        INIT_WORK(&usbhid->reset_work, hid_reset);
-       setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
+       timer_setup(&usbhid->io_retry, hid_retry_timeout, 0);
        spin_lock_init(&usbhid->lock);
 
        ret = hid_add_device(hid);
index f489a5cfcb48cf5216a532091482ac669786e61d..331f7f34ec14e68c85f3cd4a0b051b4e4ffdb365 100644 (file)
@@ -170,6 +170,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_2NES2SNES, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_4NES4SNES, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_INNOMEDIA, USB_DEVICE_ID_INNEX_GENESIS_ATARI, HID_QUIRK_MULTI_INPUT },
+       { USB_VENDOR_ID_MCS, USB_DEVICE_ID_MCS_GAMEPADBLOCK, HID_QUIRK_MULTI_INPUT },
 
        { 0, 0 }
 };
index 906e654fb0ba42fe85b49e3813beebabe86d7b3e..ee71ad9b6cc1693e14a585848ca9ad3289f06454 100644 (file)
@@ -196,6 +196,13 @@ static void wacom_feature_mapping(struct hid_device *hdev,
                kfree(data);
                break;
        }
+
+       if (hdev->vendor == USB_VENDOR_ID_WACOM &&
+           hdev->product == 0x4200 /* Dell Canvas 27 */ &&
+           field->application == HID_UP_MSVENDOR) {
+               wacom->wacom_wac.mode_report = field->report->id;
+               wacom->wacom_wac.mode_value = 2;
+       }
 }
 
 /*
index aa692e28b2cd60e52bbae7dcb93454fa145ee69a..16af6886e82887982054cc8e75cc02de1a39ad08 100644 (file)
@@ -2140,6 +2140,12 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
        case HID_DG_TIPSWITCH:
                wacom_wac->hid_data.tipswitch |= value;
                return;
+       case HID_DG_BARRELSWITCH:
+               wacom_wac->hid_data.barrelswitch = value;
+               return;
+       case HID_DG_BARRELSWITCH2:
+               wacom_wac->hid_data.barrelswitch2 = value;
+               return;
        case HID_DG_TOOLSERIALNUMBER:
                if (value) {
                        wacom_wac->serial[0] = (wacom_wac->serial[0] & ~0xFFFFFFFFULL);
@@ -2217,11 +2223,11 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
        if (!usage->type || delay_pen_events(wacom_wac))
                return;
 
-       /* send pen events only when the pen is in/entering/leaving proximity */
-       if (!wacom_wac->hid_data.inrange_state && !wacom_wac->tool[0])
-               return;
-
-       input_event(input, usage->type, usage->code, value);
+       /* send pen events only when the pen is in range */
+       if (wacom_wac->hid_data.inrange_state)
+               input_event(input, usage->type, usage->code, value);
+       else if (wacom_wac->shared->stylus_in_proximity && !wacom_wac->hid_data.sense_state)
+               input_event(input, usage->type, usage->code, 0);
 }
 
 static void wacom_wac_pen_pre_report(struct hid_device *hdev,
@@ -2236,11 +2242,11 @@ static void wacom_wac_pen_report(struct hid_device *hdev,
        struct wacom *wacom = hid_get_drvdata(hdev);
        struct wacom_wac *wacom_wac = &wacom->wacom_wac;
        struct input_dev *input = wacom_wac->pen_input;
-       bool prox = wacom_wac->hid_data.inrange_state;
-       bool range = wacom_wac->hid_data.sense_state;
+       bool range = wacom_wac->hid_data.inrange_state;
+       bool sense = wacom_wac->hid_data.sense_state;
 
-       if (!wacom_wac->tool[0] && prox) { /* first in prox */
-               /* Going into proximity select tool */
+       if (!wacom_wac->tool[0] && range) { /* first in range */
+               /* Going into range select tool */
                if (wacom_wac->hid_data.invert_state)
                        wacom_wac->tool[0] = BTN_TOOL_RUBBER;
                else if (wacom_wac->id[0])
@@ -2250,10 +2256,16 @@ static void wacom_wac_pen_report(struct hid_device *hdev,
        }
 
        /* keep pen state for touch events */
-       wacom_wac->shared->stylus_in_proximity = range;
+       wacom_wac->shared->stylus_in_proximity = sense;
 
        if (!delay_pen_events(wacom_wac) && wacom_wac->tool[0]) {
                int id = wacom_wac->id[0];
+               int sw_state = wacom_wac->hid_data.barrelswitch |
+                              (wacom_wac->hid_data.barrelswitch2 << 1);
+
+               input_report_key(input, BTN_STYLUS, sw_state == 1);
+               input_report_key(input, BTN_STYLUS2, sw_state == 2);
+               input_report_key(input, BTN_STYLUS3, sw_state == 3);
 
                /*
                 * Non-USI EMR tools should have their IDs mangled to
@@ -2269,10 +2281,10 @@ static void wacom_wac_pen_report(struct hid_device *hdev,
                 */
                input_report_key(input, BTN_TOUCH,
                                wacom_wac->hid_data.tipswitch);
-               input_report_key(input, wacom_wac->tool[0], prox);
+               input_report_key(input, wacom_wac->tool[0], sense);
                if (wacom_wac->serial[0]) {
                        input_event(input, EV_MSC, MSC_SERIAL, wacom_wac->serial[0]);
-                       input_report_abs(input, ABS_MISC, prox ? id : 0);
+                       input_report_abs(input, ABS_MISC, sense ? id : 0);
                }
 
                wacom_wac->hid_data.tipswitch = false;
@@ -2280,7 +2292,7 @@ static void wacom_wac_pen_report(struct hid_device *hdev,
                input_sync(input);
        }
 
-       if (!prox) {
+       if (!sense) {
                wacom_wac->tool[0] = 0;
                wacom_wac->id[0] = 0;
                wacom_wac->serial[0] = 0;
@@ -3300,9 +3312,11 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev,
        else
                __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
 
-       if (features->type == HID_GENERIC)
-               /* setup has already been done */
+       if (features->type == HID_GENERIC) {
+               /* setup has already been done; apply otherwise-undetectible quirks */
+               input_set_capability(input_dev, EV_KEY, BTN_STYLUS3);
                return 0;
+       }
 
        __set_bit(BTN_TOUCH, input_dev->keybit);
        __set_bit(ABS_MISC, input_dev->absbit);
index 8a03654048bf611a008e61b4101f35262fb9a5d2..64d8f014602ea0dae29830bd4259e6a1dba42f7e 100644 (file)
                                 ((f)->physical == HID_DG_PEN) || \
                                 ((f)->application == HID_DG_PEN) || \
                                 ((f)->application == HID_DG_DIGITIZER) || \
+                                ((f)->application == WACOM_HID_WD_PEN) || \
                                 ((f)->application == WACOM_HID_WD_DIGITIZER) || \
                                 ((f)->application == WACOM_HID_G9_PEN) || \
                                 ((f)->application == WACOM_HID_G11_PEN))
@@ -291,6 +292,8 @@ struct hid_data {
        bool inrange_state;
        bool invert_state;
        bool tipswitch;
+       bool barrelswitch;
+       bool barrelswitch2;
        int x;
        int y;
        int pressure;
index ab05a86269dc1770181340b8b21c460d83412cb9..d491027a7c22059a46e283ffd045fcf080a1b6c0 100644 (file)
@@ -289,6 +289,7 @@ struct hid_item {
 #define HID_DG_DEVICEINDEX     0x000d0053
 #define HID_DG_CONTACTCOUNT    0x000d0054
 #define HID_DG_CONTACTMAX      0x000d0055
+#define HID_DG_SCANTIME                0x000d0056
 #define HID_DG_BUTTONTYPE      0x000d0059
 #define HID_DG_BARRELSWITCH2   0x000d005a
 #define HID_DG_TOOLSERIALNUMBER        0x000d005b
@@ -753,6 +754,7 @@ struct hid_driver {
  * @stop: called on remove
  * @open: called by input layer on open
  * @close: called by input layer on close
+ * @power: request underlying hardware to enter requested power mode
  * @parse: this method is called only once to parse the device data,
  *        shouldn't allocate anything to not leak memory
  * @request: send report request to device (e.g. feature report)
index f4058bd4c373117e1068ba2d1a20a6f6e47feebc..061fa62958a223f5916c8bc0640c2efff991ad49 100644 (file)
 #define BTN_TOOL_MOUSE         0x146
 #define BTN_TOOL_LENS          0x147
 #define BTN_TOOL_QUINTTAP      0x148   /* Five fingers on trackpad */
+#define BTN_STYLUS3            0x149
 #define BTN_TOUCH              0x14a
 #define BTN_STYLUS             0x14b
 #define BTN_STYLUS2            0x14c