Merge branches 'for-3.15/multitouch', 'for-3.15/sony' and 'for-3.15/uhid' into for...
authorJiri Kosina <jkosina@suse.cz>
Tue, 1 Apr 2014 17:06:50 +0000 (19:06 +0200)
committerJiri Kosina <jkosina@suse.cz>
Tue, 1 Apr 2014 17:06:50 +0000 (19:06 +0200)
19 files changed:
drivers/hid/hid-apple.c
drivers/hid/hid-core.c
drivers/hid/hid-hyperv.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-lg4ff.c
drivers/hid/hid-microsoft.c
drivers/hid/hid-multitouch.c
drivers/hid/hid-sensor-hub.c
drivers/hid/hid-sony.c
drivers/hid/hidraw.c
drivers/hid/i2c-hid/i2c-hid.c
drivers/hid/usbhid/hid-quirks.c
drivers/iio/common/hid-sensors/hid-sensor-trigger.c
include/linux/hid-sensor-hub.h
include/linux/hid-sensor-ids.h
include/linux/hid.h
net/bluetooth/hidp/core.c
net/bluetooth/hidp/hidp.h

index 4975581..f822fd2 100644 (file)
@@ -469,6 +469,9 @@ static const struct hid_device_id apple_devices[] = {
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
                                USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI),
                .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
+                               USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS),
+               .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS),
                .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI),
index ddb981d..dbe548b 100644 (file)
@@ -1719,6 +1719,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO) },
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
        { HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) },
@@ -1820,6 +1821,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) },
        { 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_TYPE_COVER_2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
        { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) },
        { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1) },
index 0658cc4..f52dbcb 100644 (file)
@@ -157,6 +157,7 @@ struct mousevsc_dev {
        u32                     report_desc_size;
        struct hv_input_dev_info hid_dev_info;
        struct hid_device       *hid_device;
+       u8                      input_buf[HID_MAX_BUFFER_SIZE];
 };
 
 
@@ -256,6 +257,7 @@ static void mousevsc_on_receive(struct hv_device *device,
        struct synthhid_msg *hid_msg;
        struct mousevsc_dev *input_dev = hv_get_drvdata(device);
        struct synthhid_input_report *input_report;
+       size_t len;
 
        pipe_msg = (struct pipe_prt_msg *)((unsigned long)packet +
                                                (packet->offset8 << 3));
@@ -300,9 +302,12 @@ static void mousevsc_on_receive(struct hv_device *device,
                        (struct synthhid_input_report *)pipe_msg->data;
                if (!input_dev->init_complete)
                        break;
-               hid_input_report(input_dev->hid_device,
-                               HID_INPUT_REPORT, input_report->buffer,
-                               input_report->header.size, 1);
+
+               len = min(input_report->header.size,
+                         (u32)sizeof(input_dev->input_buf));
+               memcpy(input_dev->input_buf, input_report->buffer, len);
+               hid_input_report(input_dev->hid_device, HID_INPUT_REPORT,
+                                input_dev->input_buf, len, 1);
                break;
        default:
                pr_err("unsupported hid msg type - type %d len %d",
index 239f29c..548c1a5 100644 (file)
@@ -67,6 +67,9 @@
 #define USB_VENDOR_ID_ALPS             0x0433
 #define USB_DEVICE_ID_IBM_GAMEPAD      0x1101
 
+#define USB_VENDOR_ID_ANTON            0x1130
+#define USB_DEVICE_ID_ANTON_TOUCH_PAD  0x3101
+
 #define USB_VENDOR_ID_APPLE            0x05ac
 #define USB_DEVICE_ID_APPLE_MIGHTYMOUSE        0x0304
 #define USB_DEVICE_ID_APPLE_MAGICMOUSE 0x030d
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS   0x023b
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI  0x0255
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO   0x0256
+#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS   0x0257
 #define USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI   0x0290
 #define USB_DEVICE_ID_APPLE_WELLSPRING8_ISO    0x0291
 #define USB_DEVICE_ID_APPLE_WELLSPRING8_JIS    0x0292
 
 #define USB_VENDOR_ID_CYGNAL           0x10c4
 #define USB_DEVICE_ID_CYGNAL_RADIO_SI470X      0x818a
+#define USB_DEVICE_ID_FOCALTECH_FTXXXX_MULTITOUCH      0x81b9
 #define USB_DEVICE_ID_CYGNAL_CP2112    0xea90
 
 #define USB_VENDOR_ID_CYPRESS          0x04b4
 #define USB_VENDOR_ID_INTEL_1          0x8087
 #define USB_DEVICE_ID_INTEL_HID_SENSOR 0x09fa
 
+#define USB_VENDOR_ID_STM_0             0x0483
+#define USB_DEVICE_ID_STM_HID_SENSOR    0x91d1
+
 #define USB_VENDOR_ID_ION              0x15e4
 #define USB_DEVICE_ID_ICADE            0x0132
 
 
 #define USB_VENDOR_ID_MICROSOFT                0x045e
 #define USB_DEVICE_ID_SIDEWINDER_GV    0x003b
+#define USB_DEVICE_ID_MS_OFFICE_KB     0x0048
 #define USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0 0x009d
 #define USB_DEVICE_ID_MS_NE4K          0x00db
 #define USB_DEVICE_ID_MS_NE4K_JP       0x00dc
 #define USB_DEVICE_ID_MS_PRESENTER_8K_USB      0x0713
 #define USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K      0x0730
 #define USB_DEVICE_ID_MS_COMFORT_MOUSE_4500    0x076c
+#define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7
+#define USB_DEVICE_ID_MS_TYPE_COVER_2  0x07a9
 
 #define USB_VENDOR_ID_MOJO             0x8282
 #define USB_DEVICE_ID_RETRO_ADAPTER    0x3201
 
 #define USB_VENDOR_ID_NEXIO            0x1870
 #define USB_DEVICE_ID_NEXIO_MULTITOUCH_420     0x010d
+#define USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750 0x0110
 
 #define USB_VENDOR_ID_NEXTWINDOW       0x1926
 #define USB_DEVICE_ID_NEXTWINDOW_TOUCHSCREEN   0x0003
index f5aef79..e7e8b19 100644 (file)
@@ -789,10 +789,13 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                case 0x199: map_key_clear(KEY_CHAT);            break;
                case 0x19c: map_key_clear(KEY_LOGOFF);          break;
                case 0x19e: map_key_clear(KEY_COFFEE);          break;
+               case 0x1a3: map_key_clear(KEY_NEXT);            break;
+               case 0x1a4: map_key_clear(KEY_PREVIOUS);        break;
                case 0x1a6: map_key_clear(KEY_HELP);            break;
                case 0x1a7: map_key_clear(KEY_DOCUMENTS);       break;
                case 0x1ab: map_key_clear(KEY_SPELLCHECK);      break;
                case 0x1ae: map_key_clear(KEY_KEYBOARD);        break;
+               case 0x1b4: map_key_clear(KEY_FILE);            break;
                case 0x1b6: map_key_clear(KEY_IMAGES);          break;
                case 0x1b7: map_key_clear(KEY_AUDIO);           break;
                case 0x1b8: map_key_clear(KEY_VIDEO);           break;
@@ -1178,7 +1181,7 @@ static void hidinput_led_worker(struct work_struct *work)
 
        /* fall back to generic raw-output-report */
        len = ((report->size - 1) >> 3) + 1 + (report->id > 0);
-       buf = kmalloc(len, GFP_KERNEL);
+       buf = hid_alloc_report_buf(report, GFP_KERNEL);
        if (!buf)
                return;
 
index befe0e3..24883b4 100644 (file)
@@ -43,6 +43,7 @@
 #define G25_REV_MIN 0x22
 #define G27_REV_MAJ 0x12
 #define G27_REV_MIN 0x38
+#define G27_2_REV_MIN 0x39
 
 #define to_hid_device(pdev) container_of(pdev, struct hid_device, dev)
 
@@ -130,6 +131,7 @@ static const struct lg4ff_usb_revision lg4ff_revs[] = {
        {DFP_REV_MAJ,  DFP_REV_MIN,  &native_dfp},      /* Driving Force Pro */
        {G25_REV_MAJ,  G25_REV_MIN,  &native_g25},      /* G25 */
        {G27_REV_MAJ,  G27_REV_MIN,  &native_g27},      /* G27 */
+       {G27_REV_MAJ,  G27_2_REV_MIN,  &native_g27},    /* G27 v2 */
 };
 
 /* Recalculates X axis value accordingly to currently selected range */
index c6ef6ee..6fd5817 100644 (file)
@@ -62,9 +62,48 @@ static int ms_ergonomy_kb_quirk(struct hid_input *hi, struct hid_usage *usage,
 {
        struct input_dev *input = hi->input;
 
+       if ((usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER) {
+               switch (usage->hid & HID_USAGE) {
+               /*
+                * Microsoft uses these 2 reserved usage ids for 2 keys on
+                * the MS office kb labelled "Office Home" and "Task Pane".
+                */
+               case 0x29d:
+                       ms_map_key_clear(KEY_PROG1);
+                       return 1;
+               case 0x29e:
+                       ms_map_key_clear(KEY_PROG2);
+                       return 1;
+               }
+               return 0;
+       }
+
+       if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
+               return 0;
+
        switch (usage->hid & HID_USAGE) {
        case 0xfd06: ms_map_key_clear(KEY_CHAT);        break;
        case 0xfd07: ms_map_key_clear(KEY_PHONE);       break;
+       case 0xff00:
+               /* Special keypad keys */
+               ms_map_key_clear(KEY_KPEQUAL);
+               set_bit(KEY_KPLEFTPAREN, input->keybit);
+               set_bit(KEY_KPRIGHTPAREN, input->keybit);
+               break;
+       case 0xff01:
+               /* Scroll wheel */
+               hid_map_usage_clear(hi, usage, bit, max, EV_REL, REL_WHEEL);
+               break;
+       case 0xff02:
+               /*
+                * This byte contains a copy of the modifier keys byte of a
+                * standard hid keyboard report, as send by interface 0
+                * (this usage is found on interface 1).
+                *
+                * This byte only gets send when another key in the same report
+                * changes state, and as such is useless, ignore it.
+                */
+               return -1;
        case 0xff05:
                set_bit(EV_REP, input->evbit);
                ms_map_key_clear(KEY_F13);
@@ -83,6 +122,9 @@ static int ms_ergonomy_kb_quirk(struct hid_input *hi, struct hid_usage *usage,
 static int ms_presenter_8k_quirk(struct hid_input *hi, struct hid_usage *usage,
                unsigned long **bit, int *max)
 {
+       if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
+               return 0;
+
        set_bit(EV_REP, hi->input->evbit);
        switch (usage->hid & HID_USAGE) {
        case 0xfd08: ms_map_key_clear(KEY_FORWARD);     break;
@@ -102,9 +144,6 @@ static int ms_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 {
        unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
 
-       if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
-               return 0;
-
        if (quirks & MS_ERGONOMY) {
                int ret = ms_ergonomy_kb_quirk(hi, usage, bit, max);
                if (ret)
@@ -134,14 +173,39 @@ static int ms_event(struct hid_device *hdev, struct hid_field *field,
                struct hid_usage *usage, __s32 value)
 {
        unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+       struct input_dev *input;
 
        if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
                        !usage->type)
                return 0;
 
+       input = field->hidinput->input;
+
        /* Handling MS keyboards special buttons */
+       if (quirks & MS_ERGONOMY && usage->hid == (HID_UP_MSVENDOR | 0xff00)) {
+               /* Special keypad keys */
+               input_report_key(input, KEY_KPEQUAL, value & 0x01);
+               input_report_key(input, KEY_KPLEFTPAREN, value & 0x02);
+               input_report_key(input, KEY_KPRIGHTPAREN, value & 0x04);
+               return 1;
+       }
+
+       if (quirks & MS_ERGONOMY && usage->hid == (HID_UP_MSVENDOR | 0xff01)) {
+               /* Scroll wheel */
+               int step = ((value & 0x60) >> 5) + 1;
+
+               switch (value & 0x1f) {
+               case 0x01:
+                       input_report_rel(input, REL_WHEEL, step);
+                       break;
+               case 0x1f:
+                       input_report_rel(input, REL_WHEEL, -step);
+                       break;
+               }
+               return 1;
+       }
+
        if (quirks & MS_ERGONOMY && usage->hid == (HID_UP_MSVENDOR | 0xff05)) {
-               struct input_dev *input = field->hidinput->input;
                static unsigned int last_key = 0;
                unsigned int key = 0;
                switch (value) {
@@ -194,6 +258,8 @@ err_free:
 static const struct hid_device_id ms_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV),
                .driver_data = MS_HIDINPUT },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB),
+               .driver_data = MS_ERGONOMY },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K),
                .driver_data = MS_ERGONOMY },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K_JP),
@@ -208,6 +274,10 @@ 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_2),
+               .driver_data = 0 },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2),
+               .driver_data = 0 },
 
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT),
                .driver_data = MS_PRESENTER },
index f134d73..35278e4 100644 (file)
@@ -68,6 +68,9 @@ MODULE_LICENSE("GPL");
 #define MT_QUIRK_HOVERING              (1 << 11)
 #define MT_QUIRK_CONTACT_CNT_ACCURATE  (1 << 12)
 
+#define MT_INPUTMODE_TOUCHSCREEN       0x02
+#define MT_INPUTMODE_TOUCHPAD          0x03
+
 struct mt_slot {
        __s32 x, y, cx, cy, p, w, h;
        __s32 contactid;        /* the device ContactID assigned to this slot */
@@ -84,6 +87,7 @@ struct mt_class {
        __s32 sn_pressure;      /* Signal/noise ratio for pressure events */
        __u8 maxcontacts;
        bool is_indirect;       /* true for touchpads */
+       bool export_all_inputs; /* do not ignore mouse, keyboards, etc... */
 };
 
 struct mt_fields {
@@ -100,11 +104,11 @@ struct mt_device {
        int cc_value_index;     /* contact count value index in the field */
        unsigned last_slot_field;       /* the last field of a slot */
        unsigned mt_report_id;  /* the report ID of the multitouch device */
-       unsigned pen_report_id; /* the report ID of the pen device */
        __s16 inputmode;        /* InputMode HID feature, -1 if non-existent */
        __s16 inputmode_index;  /* InputMode HID feature index in the report */
        __s16 maxcontact_report_id;     /* Maximum Contact Number HID feature,
                                   -1 if non-existent */
+       __u8 inputmode_value;  /* InputMode HID feature value */
        __u8 num_received;      /* how many contacts we received */
        __u8 num_expected;      /* expected last contact index */
        __u8 maxcontacts;
@@ -128,16 +132,17 @@ static void mt_post_parse(struct mt_device *td);
 #define MT_CLS_CONFIDENCE_MINUS_ONE            0x0005
 #define MT_CLS_DUAL_INRANGE_CONTACTID          0x0006
 #define MT_CLS_DUAL_INRANGE_CONTACTNUMBER      0x0007
-#define MT_CLS_DUAL_NSMU_CONTACTID             0x0008
+/* reserved                                    0x0008 */
 #define MT_CLS_INRANGE_CONTACTNUMBER           0x0009
 #define MT_CLS_NSMU                            0x000a
-#define MT_CLS_DUAL_CONTACT_NUMBER             0x0010
-#define MT_CLS_DUAL_CONTACT_ID                 0x0011
+/* reserved                                    0x0010 */
+/* reserved                                    0x0011 */
 #define MT_CLS_WIN_8                           0x0012
+#define MT_CLS_EXPORT_ALL_INPUTS               0x0013
 
 /* vendor specific classes */
 #define MT_CLS_3M                              0x0101
-#define MT_CLS_CYPRESS                         0x0102
+/* reserved                                    0x0102 */
 #define MT_CLS_EGALAX                          0x0103
 #define MT_CLS_EGALAX_SERIAL                   0x0104
 #define MT_CLS_TOPSEED                         0x0105
@@ -189,28 +194,18 @@ static struct mt_class mt_classes[] = {
                .quirks = MT_QUIRK_VALID_IS_INRANGE |
                        MT_QUIRK_SLOT_IS_CONTACTNUMBER,
                .maxcontacts = 2 },
-       { .name = MT_CLS_DUAL_NSMU_CONTACTID,
-               .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
-                       MT_QUIRK_SLOT_IS_CONTACTID,
-               .maxcontacts = 2 },
        { .name = MT_CLS_INRANGE_CONTACTNUMBER,
                .quirks = MT_QUIRK_VALID_IS_INRANGE |
                        MT_QUIRK_SLOT_IS_CONTACTNUMBER },
-       { .name = MT_CLS_DUAL_CONTACT_NUMBER,
-               .quirks = MT_QUIRK_ALWAYS_VALID |
-                       MT_QUIRK_CONTACT_CNT_ACCURATE |
-                       MT_QUIRK_SLOT_IS_CONTACTNUMBER,
-               .maxcontacts = 2 },
-       { .name = MT_CLS_DUAL_CONTACT_ID,
-               .quirks = MT_QUIRK_ALWAYS_VALID |
-                       MT_QUIRK_CONTACT_CNT_ACCURATE |
-                       MT_QUIRK_SLOT_IS_CONTACTID,
-               .maxcontacts = 2 },
        { .name = MT_CLS_WIN_8,
                .quirks = MT_QUIRK_ALWAYS_VALID |
                        MT_QUIRK_IGNORE_DUPLICATES |
                        MT_QUIRK_HOVERING |
                        MT_QUIRK_CONTACT_CNT_ACCURATE },
+       { .name = MT_CLS_EXPORT_ALL_INPUTS,
+               .quirks = MT_QUIRK_ALWAYS_VALID |
+                       MT_QUIRK_CONTACT_CNT_ACCURATE,
+               .export_all_inputs = true },
 
        /*
         * vendor specific classes
@@ -223,10 +218,6 @@ static struct mt_class mt_classes[] = {
                .sn_height = 128,
                .maxcontacts = 60,
        },
-       { .name = MT_CLS_CYPRESS,
-               .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
-                       MT_QUIRK_CYPRESS,
-               .maxcontacts = 10 },
        { .name = MT_CLS_EGALAX,
                .quirks =  MT_QUIRK_SLOT_IS_CONTACTID |
                        MT_QUIRK_VALID_IS_INRANGE,
@@ -360,45 +351,6 @@ static void mt_store_field(struct hid_usage *usage, struct mt_device *td,
        f->usages[f->length++] = usage->hid;
 }
 
-static int mt_pen_input_mapping(struct hid_device *hdev, struct hid_input *hi,
-               struct hid_field *field, struct hid_usage *usage,
-               unsigned long **bit, int *max)
-{
-       struct mt_device *td = hid_get_drvdata(hdev);
-
-       td->pen_report_id = field->report->id;
-
-       return 0;
-}
-
-static int mt_pen_input_mapped(struct hid_device *hdev, struct hid_input *hi,
-               struct hid_field *field, struct hid_usage *usage,
-               unsigned long **bit, int *max)
-{
-       return 0;
-}
-
-static int mt_pen_event(struct hid_device *hid, struct hid_field *field,
-                               struct hid_usage *usage, __s32 value)
-{
-       /* let hid-input handle it */
-       return 0;
-}
-
-static void mt_pen_report(struct hid_device *hid, struct hid_report *report)
-{
-       struct hid_field *field = report->field[0];
-
-       input_sync(field->hidinput->input);
-}
-
-static void mt_pen_input_configured(struct hid_device *hdev,
-                                       struct hid_input *hi)
-{
-       /* force BTN_STYLUS to allow tablet matching in udev */
-       __set_bit(BTN_STYLUS, hi->input->keybit);
-}
-
 static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                struct hid_field *field, struct hid_usage *usage,
                unsigned long **bit, int *max)
@@ -415,8 +367,10 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
         * Model touchscreens providing buttons as touchpads.
         */
        if (field->application == HID_DG_TOUCHPAD ||
-           (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON)
+           (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) {
                td->mt_flags |= INPUT_MT_POINTER;
+               td->inputmode_value = MT_INPUTMODE_TOUCHPAD;
+       }
 
        if (usage->usage_index)
                prev_usage = &field->usage[usage->usage_index - 1];
@@ -776,28 +730,52 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                struct hid_field *field, struct hid_usage *usage,
                unsigned long **bit, int *max)
 {
-       /* Only map fields from TouchScreen or TouchPad collections.
-       * We need to ignore fields that belong to other collections
-       * such as Mouse that might have the same GenericDesktop usages. */
-       if (field->application != HID_DG_TOUCHSCREEN &&
+       struct mt_device *td = hid_get_drvdata(hdev);
+
+       /*
+        * If mtclass.export_all_inputs is not set, only map fields from
+        * TouchScreen or TouchPad collections. We need to ignore fields
+        * that belong to other collections such as Mouse that might have
+        * the same GenericDesktop usages.
+        */
+       if (!td->mtclass.export_all_inputs &&
+           field->application != HID_DG_TOUCHSCREEN &&
            field->application != HID_DG_PEN &&
            field->application != HID_DG_TOUCHPAD)
                return -1;
 
+       /*
+        * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN"
+        * for the stylus.
+        */
        if (field->physical == HID_DG_STYLUS)
-               return mt_pen_input_mapping(hdev, hi, field, usage, bit, max);
+               return 0;
+
+       if (field->application == HID_DG_TOUCHSCREEN ||
+           field->application == HID_DG_TOUCHPAD)
+               return mt_touch_input_mapping(hdev, hi, field, usage, bit, max);
 
-       return mt_touch_input_mapping(hdev, hi, field, usage, bit, max);
+       /* let hid-core decide for the others */
+       return 0;
 }
 
 static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
                struct hid_field *field, struct hid_usage *usage,
                unsigned long **bit, int *max)
 {
+       /*
+        * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN"
+        * for the stylus.
+        */
        if (field->physical == HID_DG_STYLUS)
-               return mt_pen_input_mapped(hdev, hi, field, usage, bit, max);
+               return 0;
+
+       if (field->application == HID_DG_TOUCHSCREEN ||
+           field->application == HID_DG_TOUCHPAD)
+               return mt_touch_input_mapped(hdev, hi, field, usage, bit, max);
 
-       return mt_touch_input_mapped(hdev, hi, field, usage, bit, max);
+       /* let hid-core decide for the others */
+       return 0;
 }
 
 static int mt_event(struct hid_device *hid, struct hid_field *field,
@@ -808,25 +786,22 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
        if (field->report->id == td->mt_report_id)
                return mt_touch_event(hid, field, usage, value);
 
-       if (field->report->id == td->pen_report_id)
-               return mt_pen_event(hid, field, usage, value);
-
-       /* ignore other reports */
-       return 1;
+       return 0;
 }
 
 static void mt_report(struct hid_device *hid, struct hid_report *report)
 {
        struct mt_device *td = hid_get_drvdata(hid);
+       struct hid_field *field = report->field[0];
 
        if (!(hid->claimed & HID_CLAIMED_INPUT))
                return;
 
        if (report->id == td->mt_report_id)
-               mt_touch_report(hid, report);
+               return mt_touch_report(hid, report);
 
-       if (report->id == td->pen_report_id)
-               mt_pen_report(hid, report);
+       if (field && field->hidinput && field->hidinput->input)
+               input_sync(field->hidinput->input);
 }
 
 static void mt_set_input_mode(struct hid_device *hdev)
@@ -841,7 +816,7 @@ static void mt_set_input_mode(struct hid_device *hdev)
        re = &(hdev->report_enum[HID_FEATURE_REPORT]);
        r = re->report_id_hash[td->inputmode];
        if (r) {
-               r->field[0]->value[td->inputmode_index] = 0x02;
+               r->field[0]->value[td->inputmode_index] = td->inputmode_value;
                hid_hw_request(hdev, r, HID_REQ_SET_REPORT);
        }
 }
@@ -907,13 +882,49 @@ static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
        struct mt_device *td = hid_get_drvdata(hdev);
        char *name;
        const char *suffix = NULL;
+       struct hid_field *field = hi->report->field[0];
 
        if (hi->report->id == td->mt_report_id)
                mt_touch_input_configured(hdev, hi);
 
+       /*
+        * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN"
+        * for the stylus. Check this first, and then rely on the application
+        * field.
+        */
        if (hi->report->field[0]->physical == HID_DG_STYLUS) {
                suffix = "Pen";
-               mt_pen_input_configured(hdev, hi);
+               /* force BTN_STYLUS to allow tablet matching in udev */
+               __set_bit(BTN_STYLUS, hi->input->keybit);
+       } else {
+               switch (field->application) {
+               case HID_GD_KEYBOARD:
+                       suffix = "Keyboard";
+                       break;
+               case HID_GD_KEYPAD:
+                       suffix = "Keypad";
+                       break;
+               case HID_GD_MOUSE:
+                       suffix = "Mouse";
+                       break;
+               case HID_DG_STYLUS:
+                       suffix = "Pen";
+                       /* force BTN_STYLUS to allow tablet matching in udev */
+                       __set_bit(BTN_STYLUS, hi->input->keybit);
+                       break;
+               case HID_DG_TOUCHSCREEN:
+                       /* we do not set suffix = "Touchscreen" */
+                       break;
+               case HID_GD_SYSTEM_CONTROL:
+                       suffix = "System Control";
+                       break;
+               case HID_CP_CONSUMER_CONTROL:
+                       suffix = "Consumer Control";
+                       break;
+               default:
+                       suffix = "UNKNOWN";
+                       break;
+               }
        }
 
        if (suffix) {
@@ -973,9 +984,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
        td->mtclass = *mtclass;
        td->inputmode = -1;
        td->maxcontact_report_id = -1;
+       td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN;
        td->cc_index = -1;
        td->mt_report_id = -1;
-       td->pen_report_id = -1;
        hid_set_drvdata(hdev, td);
 
        td->fields = devm_kzalloc(&hdev->dev, sizeof(struct mt_fields),
@@ -1034,6 +1045,12 @@ static void mt_remove(struct hid_device *hdev)
        hid_hw_stop(hdev);
 }
 
+/*
+ * This list contains only:
+ * - VID/PID of products not working with the default multitouch handling
+ * - 2 generic rules.
+ * So there is no point in adding here any device with MT_CLS_DEFAULT.
+ */
 static const struct hid_device_id mt_devices[] = {
 
        /* 3M panels */
@@ -1047,15 +1064,12 @@ static const struct hid_device_id mt_devices[] = {
                MT_USB_DEVICE(USB_VENDOR_ID_3M,
                        USB_DEVICE_ID_3M3266) },
 
-       /* ActionStar panels */
-       { .driver_data = MT_CLS_NSMU,
-               MT_USB_DEVICE(USB_VENDOR_ID_ACTIONSTAR,
-                       USB_DEVICE_ID_ACTIONSTAR_1011) },
+       /* Anton devices */
+       { .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
+               MT_USB_DEVICE(USB_VENDOR_ID_ANTON,
+                       USB_DEVICE_ID_ANTON_TOUCH_PAD) },
 
        /* Atmel panels */
-       { .driver_data = MT_CLS_SERIAL,
-               MT_USB_DEVICE(USB_VENDOR_ID_ATMEL,
-                       USB_DEVICE_ID_ATMEL_MULTITOUCH) },
        { .driver_data = MT_CLS_SERIAL,
                MT_USB_DEVICE(USB_VENDOR_ID_ATMEL,
                        USB_DEVICE_ID_ATMEL_MXT_DIGITIZER) },
@@ -1064,16 +1078,11 @@ static const struct hid_device_id mt_devices[] = {
        { .driver_data = MT_CLS_NSMU,
                MT_USB_DEVICE(USB_VENDOR_ID_BAANTO,
                        USB_DEVICE_ID_BAANTO_MT_190W2) },
+
        /* Cando panels */
        { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
                MT_USB_DEVICE(USB_VENDOR_ID_CANDO,
                        USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
-       { .driver_data = MT_CLS_DUAL_CONTACT_NUMBER,
-               MT_USB_DEVICE(USB_VENDOR_ID_CANDO,
-                       USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) },
-       { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
-               MT_USB_DEVICE(USB_VENDOR_ID_CANDO,
-                       USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
        { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
                MT_USB_DEVICE(USB_VENDOR_ID_CANDO,
                        USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
@@ -1088,16 +1097,6 @@ static const struct hid_device_id mt_devices[] = {
                MT_USB_DEVICE(USB_VENDOR_ID_CVTOUCH,
                        USB_DEVICE_ID_CVTOUCH_SCREEN) },
 
-       /* Cypress panel */
-       { .driver_data = MT_CLS_CYPRESS,
-               HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS,
-                       USB_DEVICE_ID_CYPRESS_TRUETOUCH) },
-
-       /* Data Modul easyMaxTouch */
-       { .driver_data = MT_CLS_DEFAULT,
-               MT_USB_DEVICE(USB_VENDOR_ID_DATA_MODUL,
-                       USB_VENDOR_ID_DATA_MODUL_EASYMAXTOUCH) },
-
        /* eGalax devices (resistive) */
        { .driver_data = MT_CLS_EGALAX,
                MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
@@ -1156,16 +1155,16 @@ static const struct hid_device_id mt_devices[] = {
                MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
                        USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) },
 
-       /* Elo TouchSystems IntelliTouch Plus panel */
-       { .driver_data = MT_CLS_DUAL_CONTACT_ID,
-               MT_USB_DEVICE(USB_VENDOR_ID_ELO,
-                       USB_DEVICE_ID_ELO_TS2515) },
-
        /* Flatfrog Panels */
        { .driver_data = MT_CLS_FLATFROG,
                MT_USB_DEVICE(USB_VENDOR_ID_FLATFROG,
                        USB_DEVICE_ID_MULTITOUCH_3200) },
 
+       /* FocalTech Panels */
+       { .driver_data = MT_CLS_SERIAL,
+               MT_USB_DEVICE(USB_VENDOR_ID_CYGNAL,
+                       USB_DEVICE_ID_FOCALTECH_FTXXXX_MULTITOUCH) },
+
        /* GeneralTouch panel */
        { .driver_data = MT_CLS_GENERALTOUCH_TWOFINGERS,
                MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
@@ -1204,37 +1203,11 @@ static const struct hid_device_id mt_devices[] = {
                MT_USB_DEVICE(USB_VENDOR_ID_HANVON_ALT,
                        USB_DEVICE_ID_HANVON_ALT_MULTITOUCH) },
 
-       /* Ideacom panel */
-       { .driver_data = MT_CLS_SERIAL,
-               MT_USB_DEVICE(USB_VENDOR_ID_IDEACOM,
-                       USB_DEVICE_ID_IDEACOM_IDC6650) },
-       { .driver_data = MT_CLS_SERIAL,
-               MT_USB_DEVICE(USB_VENDOR_ID_IDEACOM,
-                       USB_DEVICE_ID_IDEACOM_IDC6651) },
-
        /* Ilitek dual touch panel */
        {  .driver_data = MT_CLS_NSMU,
                MT_USB_DEVICE(USB_VENDOR_ID_ILITEK,
                        USB_DEVICE_ID_ILITEK_MULTITOUCH) },
 
-       /* IRTOUCH panels */
-       { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
-               MT_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS,
-                       USB_DEVICE_ID_IRTOUCH_INFRARED_USB) },
-
-       /* LG Display panels */
-       { .driver_data = MT_CLS_DEFAULT,
-               MT_USB_DEVICE(USB_VENDOR_ID_LG,
-                       USB_DEVICE_ID_LG_MULTITOUCH) },
-
-       /* Lumio panels */
-       { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
-               MT_USB_DEVICE(USB_VENDOR_ID_LUMIO,
-                       USB_DEVICE_ID_CRYSTALTOUCH) },
-       { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
-               MT_USB_DEVICE(USB_VENDOR_ID_LUMIO,
-                       USB_DEVICE_ID_CRYSTALTOUCH_DUAL) },
-
        /* MosArt panels */
        { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
                MT_USB_DEVICE(USB_VENDOR_ID_ASUS,
@@ -1246,11 +1219,6 @@ static const struct hid_device_id mt_devices[] = {
                MT_USB_DEVICE(USB_VENDOR_ID_TURBOX,
                        USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) },
 
-       /* Nexio panels */
-       { .driver_data = MT_CLS_DEFAULT,
-               MT_USB_DEVICE(USB_VENDOR_ID_NEXIO,
-                       USB_DEVICE_ID_NEXIO_MULTITOUCH_420)},
-
        /* Panasonic panels */
        { .driver_data = MT_CLS_PANASONIC,
                MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC,
@@ -1264,11 +1232,6 @@ static const struct hid_device_id mt_devices[] = {
                MT_USB_DEVICE(USB_VENDOR_ID_NOVATEK,
                        USB_DEVICE_ID_NOVATEK_PCT) },
 
-       /* PenMount panels */
-       { .driver_data = MT_CLS_CONFIDENCE,
-               MT_USB_DEVICE(USB_VENDOR_ID_PENMOUNT,
-                       USB_DEVICE_ID_PENMOUNT_PCI) },
-
        /* PixArt optical touch screen */
        { .driver_data = MT_CLS_INRANGE_CONTACTNUMBER,
                MT_USB_DEVICE(USB_VENDOR_ID_PIXART,
@@ -1281,45 +1244,19 @@ static const struct hid_device_id mt_devices[] = {
                        USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2) },
 
        /* PixCir-based panels */
-       { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
-               MT_USB_DEVICE(USB_VENDOR_ID_HANVON,
-                       USB_DEVICE_ID_HANVON_MULTITOUCH) },
        { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
                MT_USB_DEVICE(USB_VENDOR_ID_CANDO,
                        USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
 
        /* Quanta-based panels */
-       { .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID,
-               MT_USB_DEVICE(USB_VENDOR_ID_QUANTA,
-                       USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) },
        { .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID,
                MT_USB_DEVICE(USB_VENDOR_ID_QUANTA,
                        USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001) },
-       { .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID,
-               MT_USB_DEVICE(USB_VENDOR_ID_QUANTA,
-                       USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008) },
-
-       /* SiS panels */
-       { .driver_data = MT_CLS_DEFAULT,
-               HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH,
-               USB_DEVICE_ID_SIS9200_TOUCH) },
-       { .driver_data = MT_CLS_DEFAULT,
-               HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH,
-               USB_DEVICE_ID_SIS817_TOUCH) },
-       { .driver_data = MT_CLS_DEFAULT,
-               HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH,
-               USB_DEVICE_ID_SIS1030_TOUCH) },
 
        /* Stantum panels */
-       { .driver_data = MT_CLS_CONFIDENCE,
-               MT_USB_DEVICE(USB_VENDOR_ID_STANTUM,
-                       USB_DEVICE_ID_MTP)},
        { .driver_data = MT_CLS_CONFIDENCE,
                MT_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM,
                        USB_DEVICE_ID_MTP_STM)},
-       { .driver_data = MT_CLS_DEFAULT,
-               MT_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX,
-                       USB_DEVICE_ID_MTP_SITRONIX)},
 
        /* TopSeed panels */
        { .driver_data = MT_CLS_TOPSEED,
@@ -1378,11 +1315,6 @@ static const struct hid_device_id mt_devices[] = {
                MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
                        USB_DEVICE_ID_XIROKU_CSR2) },
 
-       /* Zytronic panels */
-       { .driver_data = MT_CLS_SERIAL,
-               MT_USB_DEVICE(USB_VENDOR_ID_ZYTRONIC,
-                       USB_DEVICE_ID_ZYTRONIC_ZXY100) },
-
        /* Generic MT device */
        { HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH, HID_ANY_ID, HID_ANY_ID) },
 
index 46f4480..5182031 100644 (file)
@@ -56,9 +56,9 @@ struct sensor_hub_pending {
  * @dyn_callback_lock: spin lock to protect callback list
  * @hid_sensor_hub_client_devs:        Stores all MFD cells for a hub instance.
  * @hid_sensor_client_cnt: Number of MFD cells, (no of sensors attached).
+ * @ref_cnt:           Number of MFD clients have opened this device
  */
 struct sensor_hub_data {
-       struct hid_sensor_hub_device *hsdev;
        struct mutex mutex;
        spinlock_t lock;
        struct sensor_hub_pending pending;
@@ -67,6 +67,7 @@ struct sensor_hub_data {
        struct mfd_cell *hid_sensor_hub_client_devs;
        int hid_sensor_client_cnt;
        unsigned long quirks;
+       int ref_cnt;
 };
 
 /**
@@ -79,6 +80,7 @@ struct sensor_hub_data {
 struct hid_sensor_hub_callbacks_list {
        struct list_head list;
        u32 usage_id;
+       struct hid_sensor_hub_device *hsdev;
        struct hid_sensor_hub_callbacks *usage_callback;
        void *priv;
 };
@@ -97,20 +99,18 @@ static struct hid_report *sensor_hub_report(int id, struct hid_device *hdev,
        return NULL;
 }
 
-static int sensor_hub_get_physical_device_count(
-                               struct hid_report_enum *report_enum)
+static int sensor_hub_get_physical_device_count(struct hid_device *hdev)
 {
-       struct hid_report *report;
-       struct hid_field *field;
-       int cnt = 0;
+       int i;
+       int count = 0;
 
-       list_for_each_entry(report, &report_enum->report_list, list) {
-               field = report->field[0];
-               if (report->maxfield && field && field->physical)
-                       cnt++;
+       for (i = 0; i < hdev->maxcollection; ++i) {
+               struct hid_collection *collection = &hdev->collection[i];
+               if (collection->type == HID_COLLECTION_PHYSICAL)
+                       ++count;
        }
 
-       return cnt;
+       return count;
 }
 
 static void sensor_hub_fill_attr_info(
@@ -128,15 +128,23 @@ static void sensor_hub_fill_attr_info(
 
 static struct hid_sensor_hub_callbacks *sensor_hub_get_callback(
                                        struct hid_device *hdev,
-                                       u32 usage_id, void **priv)
+                                       u32 usage_id,
+                                       int collection_index,
+                                       struct hid_sensor_hub_device **hsdev,
+                                       void **priv)
 {
        struct hid_sensor_hub_callbacks_list *callback;
        struct sensor_hub_data *pdata = hid_get_drvdata(hdev);
 
        spin_lock(&pdata->dyn_callback_lock);
        list_for_each_entry(callback, &pdata->dyn_callback_list, list)
-               if (callback->usage_id == usage_id) {
+               if (callback->usage_id == usage_id &&
+                       (collection_index >=
+                               callback->hsdev->start_collection_index) &&
+                       (collection_index <
+                               callback->hsdev->end_collection_index)) {
                        *priv = callback->priv;
+                       *hsdev = callback->hsdev;
                        spin_unlock(&pdata->dyn_callback_lock);
                        return callback->usage_callback;
                }
@@ -154,7 +162,8 @@ int sensor_hub_register_callback(struct hid_sensor_hub_device *hsdev,
 
        spin_lock(&pdata->dyn_callback_lock);
        list_for_each_entry(callback, &pdata->dyn_callback_list, list)
-               if (callback->usage_id == usage_id) {
+               if (callback->usage_id == usage_id &&
+                                               callback->hsdev == hsdev) {
                        spin_unlock(&pdata->dyn_callback_lock);
                        return -EINVAL;
                }
@@ -163,6 +172,7 @@ int sensor_hub_register_callback(struct hid_sensor_hub_device *hsdev,
                spin_unlock(&pdata->dyn_callback_lock);
                return -ENOMEM;
        }
+       callback->hsdev = hsdev;
        callback->usage_callback = usage_callback;
        callback->usage_id = usage_id;
        callback->priv = NULL;
@@ -181,7 +191,8 @@ int sensor_hub_remove_callback(struct hid_sensor_hub_device *hsdev,
 
        spin_lock(&pdata->dyn_callback_lock);
        list_for_each_entry(callback, &pdata->dyn_callback_list, list)
-               if (callback->usage_id == usage_id) {
+               if (callback->usage_id == usage_id &&
+                                               callback->hsdev == hsdev) {
                        list_del(&callback->list);
                        kfree(callback);
                        break;
@@ -260,13 +271,12 @@ int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
 
        spin_lock_irqsave(&data->lock, flags);
        data->pending.status = true;
+       spin_unlock_irqrestore(&data->lock, flags);
        report = sensor_hub_report(report_id, hsdev->hdev, HID_INPUT_REPORT);
-       if (!report) {
-               spin_unlock_irqrestore(&data->lock, flags);
+       if (!report)
                goto err_free;
-       }
+
        hid_hw_request(hsdev->hdev, report, HID_REQ_GET_REPORT);
-       spin_unlock_irqrestore(&data->lock, flags);
        wait_for_completion_interruptible_timeout(&data->pending.ready, HZ*5);
        switch (data->pending.raw_size) {
        case 1:
@@ -291,6 +301,28 @@ err_free:
 }
 EXPORT_SYMBOL_GPL(sensor_hub_input_attr_get_raw_value);
 
+int hid_sensor_get_usage_index(struct hid_sensor_hub_device *hsdev,
+                               u32 report_id, int field_index, u32 usage_id)
+{
+       struct hid_report *report;
+       struct hid_field *field;
+       int i;
+
+       report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT);
+       if (!report || (field_index >= report->maxfield))
+               goto done_proc;
+
+       field = report->field[field_index];
+       for (i = 0; i < field->maxusage; ++i) {
+               if (field->usage[i].hid == usage_id)
+                       return field->usage[i].usage_index;
+       }
+
+done_proc:
+       return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(hid_sensor_get_usage_index);
+
 int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
                                u8 type,
                                u32 usage_id,
@@ -298,8 +330,7 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
                                struct hid_sensor_hub_attribute_info *info)
 {
        int ret = -1;
-       int i, j;
-       int collection_index = -1;
+       int i;
        struct hid_report *report;
        struct hid_field *field;
        struct hid_report_enum *report_enum;
@@ -313,44 +344,31 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
        info->units = -1;
        info->unit_expo = -1;
 
-       for (i = 0; i < hdev->maxcollection; ++i) {
-               struct hid_collection *collection = &hdev->collection[i];
-               if (usage_id == collection->usage) {
-                       collection_index = i;
-                       break;
-               }
-       }
-       if (collection_index == -1)
-               goto err_ret;
-
        report_enum = &hdev->report_enum[type];
        list_for_each_entry(report, &report_enum->report_list, list) {
                for (i = 0; i < report->maxfield; ++i) {
                        field = report->field[i];
-                       if (field->physical == usage_id &&
-                               field->logical == attr_usage_id) {
-                               sensor_hub_fill_attr_info(info, i, report->id,
-                                                         field);
-                               ret = 0;
-                       } else {
-                               for (j = 0; j < field->maxusage; ++j) {
-                                       if (field->usage[j].hid ==
-                                       attr_usage_id &&
-                                       field->usage[j].collection_index ==
-                                       collection_index) {
-                                               sensor_hub_fill_attr_info(info,
-                                                         i, report->id, field);
-                                               ret = 0;
-                                               break;
-                                       }
+                       if (field->maxusage) {
+                               if (field->physical == usage_id &&
+                                       (field->logical == attr_usage_id ||
+                                       field->usage[0].hid ==
+                                                       attr_usage_id) &&
+                                       (field->usage[0].collection_index >=
+                                       hsdev->start_collection_index) &&
+                                       (field->usage[0].collection_index <
+                                       hsdev->end_collection_index)) {
+
+                                       sensor_hub_fill_attr_info(info, i,
+                                                               report->id,
+                                                               field);
+                                       ret = 0;
+                                       break;
                                }
                        }
-                       if (ret == 0)
-                               break;
                }
+
        }
 
-err_ret:
        return ret;
 }
 EXPORT_SYMBOL_GPL(sensor_hub_input_get_attribute_info);
@@ -366,7 +384,7 @@ static int sensor_hub_suspend(struct hid_device *hdev, pm_message_t message)
        list_for_each_entry(callback, &pdata->dyn_callback_list, list) {
                if (callback->usage_callback->suspend)
                        callback->usage_callback->suspend(
-                                       pdata->hsdev, callback->priv);
+                                       callback->hsdev, callback->priv);
        }
        spin_unlock(&pdata->dyn_callback_lock);
 
@@ -383,7 +401,7 @@ static int sensor_hub_resume(struct hid_device *hdev)
        list_for_each_entry(callback, &pdata->dyn_callback_list, list) {
                if (callback->usage_callback->resume)
                        callback->usage_callback->resume(
-                                       pdata->hsdev, callback->priv);
+                                       callback->hsdev, callback->priv);
        }
        spin_unlock(&pdata->dyn_callback_lock);
 
@@ -410,6 +428,7 @@ static int sensor_hub_raw_event(struct hid_device *hdev,
        struct hid_sensor_hub_callbacks *callback = NULL;
        struct hid_collection *collection = NULL;
        void *priv = NULL;
+       struct hid_sensor_hub_device *hsdev = NULL;
 
        hid_dbg(hdev, "sensor_hub_raw_event report id:0x%x size:%d type:%d\n",
                         report->id, size, report->type);
@@ -444,23 +463,26 @@ static int sensor_hub_raw_event(struct hid_device *hdev,
                                report->field[i]->usage->collection_index];
                hid_dbg(hdev, "collection->usage %x\n",
                                        collection->usage);
-               callback = sensor_hub_get_callback(pdata->hsdev->hdev,
-                                               report->field[i]->physical,
-                                                       &priv);
+
+               callback = sensor_hub_get_callback(hdev,
+                               report->field[i]->physical,
+                               report->field[i]->usage[0].collection_index,
+                               &hsdev, &priv);
+
                if (callback && callback->capture_sample) {
                        if (report->field[i]->logical)
-                               callback->capture_sample(pdata->hsdev,
+                               callback->capture_sample(hsdev,
                                        report->field[i]->logical, sz, ptr,
                                        callback->pdev);
                        else
-                               callback->capture_sample(pdata->hsdev,
+                               callback->capture_sample(hsdev,
                                        report->field[i]->usage->hid, sz, ptr,
                                        callback->pdev);
                }
                ptr += sz;
        }
        if (callback && collection && callback->send_event)
-               callback->send_event(pdata->hsdev, collection->usage,
+               callback->send_event(hsdev, collection->usage,
                                callback->pdev);
        spin_unlock_irqrestore(&pdata->lock, flags);
 
@@ -473,7 +495,7 @@ int sensor_hub_device_open(struct hid_sensor_hub_device *hsdev)
        struct sensor_hub_data *data =  hid_get_drvdata(hsdev->hdev);
 
        mutex_lock(&data->mutex);
-       if (!hsdev->ref_cnt) {
+       if (!data->ref_cnt) {
                ret = hid_hw_open(hsdev->hdev);
                if (ret) {
                        hid_err(hsdev->hdev, "failed to open hid device\n");
@@ -481,7 +503,7 @@ int sensor_hub_device_open(struct hid_sensor_hub_device *hsdev)
                        return ret;
                }
        }
-       hsdev->ref_cnt++;
+       data->ref_cnt++;
        mutex_unlock(&data->mutex);
 
        return ret;
@@ -493,8 +515,8 @@ void sensor_hub_device_close(struct hid_sensor_hub_device *hsdev)
        struct sensor_hub_data *data =  hid_get_drvdata(hsdev->hdev);
 
        mutex_lock(&data->mutex);
-       hsdev->ref_cnt--;
-       if (!hsdev->ref_cnt)
+       data->ref_cnt--;
+       if (!data->ref_cnt)
                hid_hw_close(hsdev->hdev);
        mutex_unlock(&data->mutex);
 }
@@ -541,26 +563,19 @@ static int sensor_hub_probe(struct hid_device *hdev,
        struct sensor_hub_data *sd;
        int i;
        char *name;
-       struct hid_report *report;
-       struct hid_report_enum *report_enum;
-       struct hid_field *field;
        int dev_cnt;
+       struct hid_sensor_hub_device *hsdev;
+       struct hid_sensor_hub_device *last_hsdev = NULL;
 
        sd = devm_kzalloc(&hdev->dev, sizeof(*sd), GFP_KERNEL);
        if (!sd) {
                hid_err(hdev, "cannot allocate Sensor data\n");
                return -ENOMEM;
        }
-       sd->hsdev = devm_kzalloc(&hdev->dev, sizeof(*sd->hsdev), GFP_KERNEL);
-       if (!sd->hsdev) {
-               hid_err(hdev, "cannot allocate hid_sensor_hub_device\n");
-               return -ENOMEM;
-       }
+
        hid_set_drvdata(hdev, sd);
        sd->quirks = id->driver_data;
-       sd->hsdev->hdev = hdev;
-       sd->hsdev->vendor_id = hdev->vendor;
-       sd->hsdev->product_id = hdev->product;
+
        spin_lock_init(&sd->lock);
        spin_lock_init(&sd->dyn_callback_lock);
        mutex_init(&sd->mutex);
@@ -578,9 +593,8 @@ static int sensor_hub_probe(struct hid_device *hdev,
        }
        INIT_LIST_HEAD(&sd->dyn_callback_list);
        sd->hid_sensor_client_cnt = 0;
-       report_enum = &hdev->report_enum[HID_INPUT_REPORT];
 
-       dev_cnt = sensor_hub_get_physical_device_count(report_enum);
+       dev_cnt = sensor_hub_get_physical_device_count(hdev);
        if (dev_cnt > HID_MAX_PHY_DEVICES) {
                hid_err(hdev, "Invalid Physical device count\n");
                ret = -EINVAL;
@@ -594,42 +608,63 @@ static int sensor_hub_probe(struct hid_device *hdev,
                        ret = -ENOMEM;
                        goto err_stop_hw;
        }
-       list_for_each_entry(report, &report_enum->report_list, list) {
-               hid_dbg(hdev, "Report id:%x\n", report->id);
-               field = report->field[0];
-               if (report->maxfield && field &&
-                                       field->physical) {
+
+       for (i = 0; i < hdev->maxcollection; ++i) {
+               struct hid_collection *collection = &hdev->collection[i];
+
+               if (collection->type == HID_COLLECTION_PHYSICAL) {
+
+                       hsdev = kzalloc(sizeof(*hsdev), GFP_KERNEL);
+                       if (!hsdev) {
+                               hid_err(hdev, "cannot allocate hid_sensor_hub_device\n");
+                               ret = -ENOMEM;
+                               goto err_no_mem;
+                       }
+                       hsdev->hdev = hdev;
+                       hsdev->vendor_id = hdev->vendor;
+                       hsdev->product_id = hdev->product;
+                       hsdev->start_collection_index = i;
+                       if (last_hsdev)
+                               last_hsdev->end_collection_index = i;
+                       last_hsdev = hsdev;
                        name = kasprintf(GFP_KERNEL, "HID-SENSOR-%x",
-                                               field->physical);
+                                       collection->usage);
                        if (name == NULL) {
                                hid_err(hdev, "Failed MFD device name\n");
                                        ret = -ENOMEM;
-                                       goto err_free_names;
+                                       goto err_no_mem;
                        }
                        sd->hid_sensor_hub_client_devs[
-                               sd->hid_sensor_client_cnt].id = PLATFORM_DEVID_AUTO;
+                               sd->hid_sensor_client_cnt].id =
+                                                       PLATFORM_DEVID_AUTO;
                        sd->hid_sensor_hub_client_devs[
                                sd->hid_sensor_client_cnt].name = name;
                        sd->hid_sensor_hub_client_devs[
                                sd->hid_sensor_client_cnt].platform_data =
-                                               sd->hsdev;
+                                                       hsdev;
                        sd->hid_sensor_hub_client_devs[
                                sd->hid_sensor_client_cnt].pdata_size =
-                                               sizeof(*sd->hsdev);
-                       hid_dbg(hdev, "Adding %s:%p\n", name, sd);
+                                                       sizeof(*hsdev);
+                       hid_dbg(hdev, "Adding %s:%d\n", name,
+                                       hsdev->start_collection_index);
                        sd->hid_sensor_client_cnt++;
                }
        }
+       if (last_hsdev)
+               last_hsdev->end_collection_index = i;
+
        ret = mfd_add_devices(&hdev->dev, 0, sd->hid_sensor_hub_client_devs,
                sd->hid_sensor_client_cnt, NULL, 0, NULL);
        if (ret < 0)
-               goto err_free_names;
+               goto err_no_mem;
 
        return ret;
 
-err_free_names:
-       for (i = 0; i < sd->hid_sensor_client_cnt ; ++i)
+err_no_mem:
+       for (i = 0; i < sd->hid_sensor_client_cnt; ++i) {
                kfree(sd->hid_sensor_hub_client_devs[i].name);
+               kfree(sd->hid_sensor_hub_client_devs[i].platform_data);
+       }
        kfree(sd->hid_sensor_hub_client_devs);
 err_stop_hw:
        hid_hw_stop(hdev);
@@ -651,8 +686,10 @@ static void sensor_hub_remove(struct hid_device *hdev)
                complete(&data->pending.ready);
        spin_unlock_irqrestore(&data->lock, flags);
        mfd_remove_devices(&hdev->dev);
-       for (i = 0; i < data->hid_sensor_client_cnt ; ++i)
+       for (i = 0; i < data->hid_sensor_client_cnt; ++i) {
                kfree(data->hid_sensor_hub_client_devs[i].name);
+               kfree(data->hid_sensor_hub_client_devs[i].platform_data);
+       }
        kfree(data->hid_sensor_hub_client_devs);
        hid_set_drvdata(hdev, NULL);
        mutex_destroy(&data->mutex);
@@ -665,6 +702,9 @@ static const struct hid_device_id sensor_hub_devices[] = {
        { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_INTEL_1,
                        USB_DEVICE_ID_INTEL_HID_SENSOR),
                        .driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
+       { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_STM_0,
+                       USB_DEVICE_ID_STM_HID_SENSOR),
+                       .driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
        { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, HID_ANY_ID,
                     HID_ANY_ID) },
        { }
index 4884bb5..4d348c0 100644 (file)
@@ -863,7 +863,7 @@ static void sixaxis_parse_report(struct sony_sc *sc, __u8 *rd, int size)
                battery_capacity = sixaxis_battery_capacity[index];
                battery_charging = 0;
        }
-       cable_state = !((rd[31] >> 4) & 0x01);
+       cable_state = !(rd[31] & 0x04);
 
        spin_lock_irqsave(&sc->lock, flags);
        sc->cable_state = cable_state;
@@ -1632,11 +1632,21 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
                sc->worker_initialized = 1;
                INIT_WORK(&sc->state_worker, sixaxis_state_worker);
        } else if (sc->quirks & SIXAXIS_CONTROLLER_BT) {
+               /*
+                * The Sixaxis wants output reports sent on the ctrl endpoint
+                * when connected via Bluetooth.
+                */
+               hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
                ret = sixaxis_set_operational_bt(hdev);
                sc->worker_initialized = 1;
                INIT_WORK(&sc->state_worker, sixaxis_state_worker);
        } else if (sc->quirks & DUALSHOCK4_CONTROLLER) {
                if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) {
+                       /*
+                        * The DualShock 4 wants output reports sent on the ctrl
+                        * endpoint when connected via Bluetooth.
+                        */
+                       hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
                        ret = dualshock4_set_operational_bt(hdev);
                        if (ret < 0) {
                                hid_err(hdev, "failed to set the Dualshock 4 operational mode\n");
@@ -1670,6 +1680,10 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
                        goto err_stop;
        }
 
+       if (sc->quirks & SONY_FF_SUPPORT) {
+               ret = sony_init_ff(hdev);
+               if (ret < 0)
+                       goto err_stop;
        if (sc->quirks & SONY_BATTERY_SUPPORT) {
                ret = sony_battery_probe(sc);
                if (ret < 0)
@@ -1711,6 +1725,8 @@ static void sony_remove(struct hid_device *hdev)
        if (sc->quirks & SONY_LED_SUPPORT)
                sony_leds_remove(hdev);
 
+       if (sc->worker_initialized)
+               cancel_work_sync(&sc->state_worker);
        if (sc->quirks & SONY_BATTERY_SUPPORT) {
                hid_hw_close(hdev);
                sony_battery_remove(sc);
index ffa648c..9c2d7c2 100644 (file)
@@ -331,13 +331,13 @@ static void drop_ref(struct hidraw *hidraw, int exists_bit)
                        hid_hw_close(hidraw->hid);
                        wake_up_interruptible(&hidraw->wait);
                }
+               device_destroy(hidraw_class,
+                              MKDEV(hidraw_major, hidraw->minor));
        } else {
                --hidraw->open;
        }
        if (!hidraw->open) {
                if (!hidraw->exist) {
-                       device_destroy(hidraw_class,
-                                       MKDEV(hidraw_major, hidraw->minor));
                        hidraw_table[hidraw->minor] = NULL;
                        kfree(hidraw);
                } else {
index 2de2b8e..8c52a07 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/pm.h>
+#include <linux/pm_runtime.h>
 #include <linux/device.h>
 #include <linux/wait.h>
 #include <linux/err.h>
@@ -467,10 +468,18 @@ static void i2c_hid_init_reports(struct hid_device *hid)
                return;
        }
 
+       /*
+        * The device must be powered on while we fetch initial reports
+        * from it.
+        */
+       pm_runtime_get_sync(&client->dev);
+
        list_for_each_entry(report,
                &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
                i2c_hid_init_report(report, inbuf, ihid->bufsize);
 
+       pm_runtime_put(&client->dev);
+
        kfree(inbuf);
 }
 
@@ -709,8 +718,8 @@ static int i2c_hid_open(struct hid_device *hid)
 
        mutex_lock(&i2c_hid_open_mut);
        if (!hid->open++) {
-               ret = i2c_hid_set_power(client, I2C_HID_PWR_ON);
-               if (ret) {
+               ret = pm_runtime_get_sync(&client->dev);
+               if (ret < 0) {
                        hid->open--;
                        goto done;
                }
@@ -718,7 +727,7 @@ static int i2c_hid_open(struct hid_device *hid)
        }
 done:
        mutex_unlock(&i2c_hid_open_mut);
-       return ret;
+       return ret < 0 ? ret : 0;
 }
 
 static void i2c_hid_close(struct hid_device *hid)
@@ -735,7 +744,7 @@ static void i2c_hid_close(struct hid_device *hid)
                clear_bit(I2C_HID_STARTED, &ihid->flags);
 
                /* Save some power */
-               i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
+               pm_runtime_put(&client->dev);
        }
        mutex_unlock(&i2c_hid_open_mut);
 }
@@ -744,19 +753,18 @@ static int i2c_hid_power(struct hid_device *hid, int lvl)
 {
        struct i2c_client *client = hid->driver_data;
        struct i2c_hid *ihid = i2c_get_clientdata(client);
-       int ret = 0;
 
        i2c_hid_dbg(ihid, "%s lvl:%d\n", __func__, lvl);
 
        switch (lvl) {
        case PM_HINT_FULLON:
-               ret = i2c_hid_set_power(client, I2C_HID_PWR_ON);
+               pm_runtime_get_sync(&client->dev);
                break;
        case PM_HINT_NORMAL:
-               ret = i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
+               pm_runtime_put(&client->dev);
                break;
        }
-       return ret;
+       return 0;
 }
 
 static struct hid_ll_driver i2c_hid_ll_driver = {
@@ -994,13 +1002,17 @@ static int i2c_hid_probe(struct i2c_client *client,
        if (ret < 0)
                goto err;
 
+       pm_runtime_get_noresume(&client->dev);
+       pm_runtime_set_active(&client->dev);
+       pm_runtime_enable(&client->dev);
+
        ret = i2c_hid_fetch_hid_descriptor(ihid);
        if (ret < 0)
-               goto err;
+               goto err_pm;
 
        ret = i2c_hid_init_irq(client);
        if (ret < 0)
-               goto err;
+               goto err_pm;
 
        hid = hid_allocate_device();
        if (IS_ERR(hid)) {
@@ -1029,6 +1041,7 @@ static int i2c_hid_probe(struct i2c_client *client,
                goto err_mem_free;
        }
 
+       pm_runtime_put(&client->dev);
        return 0;
 
 err_mem_free:
@@ -1037,6 +1050,10 @@ err_mem_free:
 err_irq:
        free_irq(client->irq, ihid);
 
+err_pm:
+       pm_runtime_put_noidle(&client->dev);
+       pm_runtime_disable(&client->dev);
+
 err:
        i2c_hid_free_buffers(ihid);
        kfree(ihid);
@@ -1048,6 +1065,11 @@ static int i2c_hid_remove(struct i2c_client *client)
        struct i2c_hid *ihid = i2c_get_clientdata(client);
        struct hid_device *hid;
 
+       pm_runtime_get_sync(&client->dev);
+       pm_runtime_disable(&client->dev);
+       pm_runtime_set_suspended(&client->dev);
+       pm_runtime_put_noidle(&client->dev);
+
        hid = ihid->hid;
        hid_destroy_device(hid);
 
@@ -1093,7 +1115,31 @@ static int i2c_hid_resume(struct device *dev)
 }
 #endif
 
-static SIMPLE_DEV_PM_OPS(i2c_hid_pm, i2c_hid_suspend, i2c_hid_resume);
+#ifdef CONFIG_PM_RUNTIME
+static int i2c_hid_runtime_suspend(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+
+       i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
+       disable_irq(client->irq);
+       return 0;
+}
+
+static int i2c_hid_runtime_resume(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+
+       enable_irq(client->irq);
+       i2c_hid_set_power(client, I2C_HID_PWR_ON);
+       return 0;
+}
+#endif
+
+static const struct dev_pm_ops i2c_hid_pm = {
+       SET_SYSTEM_SLEEP_PM_OPS(i2c_hid_suspend, i2c_hid_resume)
+       SET_RUNTIME_PM_OPS(i2c_hid_runtime_suspend, i2c_hid_runtime_resume,
+                          NULL)
+};
 
 static const struct i2c_device_id i2c_hid_id_table[] = {
        { "hid", 0 },
index 175ec0a..dbd8387 100644 (file)
@@ -74,6 +74,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GX680R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS },
index 7dcf839..dbefbda 100644 (file)
@@ -38,29 +38,40 @@ static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig,
        if (state) {
                if (sensor_hub_device_open(st->hsdev))
                        return -EIO;
-               state_val =
-               HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM;
-               report_val =
-               HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM;
-
+               state_val = hid_sensor_get_usage_index(st->hsdev,
+                       st->power_state.report_id,
+                       st->power_state.index,
+                       HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM);
+               report_val = hid_sensor_get_usage_index(st->hsdev,
+                       st->report_state.report_id,
+                       st->report_state.index,
+                       HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM);
        } else {
                sensor_hub_device_close(st->hsdev);
-               state_val =
-               HID_USAGE_SENSOR_PROP_POWER_STATE_D4_POWER_OFF_ENUM;
-               report_val =
-               HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM;
+               state_val = hid_sensor_get_usage_index(st->hsdev,
+                       st->power_state.report_id,
+                       st->power_state.index,
+                       HID_USAGE_SENSOR_PROP_POWER_STATE_D4_POWER_OFF_ENUM);
+               report_val = hid_sensor_get_usage_index(st->hsdev,
+                       st->report_state.report_id,
+                       st->report_state.index,
+                       HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM);
        }
-
        st->data_ready = state;
-       state_val += st->power_state.logical_minimum;
-       report_val += st->report_state.logical_minimum;
-       sensor_hub_set_feature(st->hsdev, st->power_state.report_id,
+
+       if (state_val >= 0) {
+               state_val += st->power_state.logical_minimum;
+               sensor_hub_set_feature(st->hsdev, st->power_state.report_id,
                                        st->power_state.index,
                                        (s32)state_val);
+       }
 
-       sensor_hub_set_feature(st->hsdev, st->report_state.report_id,
+       if (report_val >= 0) {
+               report_val += st->report_state.logical_minimum;
+               sensor_hub_set_feature(st->hsdev, st->report_state.report_id,
                                        st->report_state.index,
                                        (s32)report_val);
+       }
 
        return 0;
 }
index b914ca3..b70cfd7 100644 (file)
@@ -51,13 +51,15 @@ struct hid_sensor_hub_attribute_info {
  * @hdev:              Stores the hid instance.
  * @vendor_id:         Vendor id of hub device.
  * @product_id:                Product id of hub device.
- * @ref_cnt:           Number of MFD clients have opened this device
+ * @start_collection_index: Starting index for a phy type collection
+ * @end_collection_index: Last index for a phy type collection
  */
 struct hid_sensor_hub_device {
        struct hid_device *hdev;
        u32 vendor_id;
        u32 product_id;
-       int ref_cnt;
+       int start_collection_index;
+       int end_collection_index;
 };
 
 /**
@@ -218,4 +220,7 @@ int hid_sensor_write_samp_freq_value(struct hid_sensor_common *st,
 int hid_sensor_read_samp_freq_value(struct hid_sensor_common *st,
                                        int *val1, int *val2);
 
+int hid_sensor_get_usage_index(struct hid_sensor_hub_device *hsdev,
+                               u32 report_id, int field_index, u32 usage_id);
+
 #endif
index beaf965..f860760 100644 (file)
 #define HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS               0x1000
 
 /* Power state enumerations */
-#define HID_USAGE_SENSOR_PROP_POWER_STATE_UNDEFINED_ENUM               0x00
-#define HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM           0x01
-#define HID_USAGE_SENSOR_PROP_POWER_STATE_D1_LOW_POWER_ENUM            0x02
-#define HID_USAGE_SENSOR_PROP_POWER_STATE_D2_STANDBY_WITH_WAKE_ENUM    0x03
-#define HID_USAGE_SENSOR_PROP_POWER_STATE_D3_SLEEP_WITH_WAKE_ENUM      0x04
-#define HID_USAGE_SENSOR_PROP_POWER_STATE_D4_POWER_OFF_ENUM            0x05
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_UNDEFINED_ENUM       0x200850
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM   0x200851
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_D1_LOW_POWER_ENUM    0x200852
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_D2_STANDBY_WITH_WAKE_ENUM 0x200853
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_D3_SLEEP_WITH_WAKE_ENUM 0x200854
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_D4_POWER_OFF_ENUM    0x200855
 
 /* Report State enumerations */
-#define HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM           0x00
-#define HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM          0x01
+#define HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM   0x200840
+#define HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM  0x200841
 
 #endif
index 01a90b8..720e3a1 100644 (file)
@@ -201,6 +201,7 @@ struct hid_item {
 #define HID_GD_VBRZ            0x00010045
 #define HID_GD_VNO             0x00010046
 #define HID_GD_FEATURE         0x00010047
+#define HID_GD_SYSTEM_CONTROL  0x00010080
 #define HID_GD_UP              0x00010090
 #define HID_GD_DOWN            0x00010091
 #define HID_GD_RIGHT           0x00010092
@@ -208,6 +209,8 @@ struct hid_item {
 
 #define HID_DC_BATTERYSTRENGTH 0x00060020
 
+#define HID_CP_CONSUMER_CONTROL        0x000c0001
+
 #define HID_DG_DIGITIZER       0x000d0001
 #define HID_DG_PEN             0x000d0002
 #define HID_DG_LIGHTPEN                0x000d0003
index 514ddb5..8181ea4 100644 (file)
@@ -415,6 +415,16 @@ static void hidp_del_timer(struct hidp_session *session)
                del_timer(&session->timer);
 }
 
+static void hidp_process_report(struct hidp_session *session,
+                               int type, const u8 *data, int len, int intr)
+{
+       if (len > HID_MAX_BUFFER_SIZE)
+               len = HID_MAX_BUFFER_SIZE;
+
+       memcpy(session->input_buf, data, len);
+       hid_input_report(session->hid, type, session->input_buf, len, intr);
+}
+
 static void hidp_process_handshake(struct hidp_session *session,
                                        unsigned char param)
 {
@@ -487,7 +497,8 @@ static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
                        hidp_input_report(session, skb);
 
                if (session->hid)
-                       hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0);
+                       hidp_process_report(session, HID_INPUT_REPORT,
+                                           skb->data, skb->len, 0);
                break;
 
        case HIDP_DATA_RTYPE_OTHER:
@@ -569,7 +580,8 @@ static void hidp_recv_intr_frame(struct hidp_session *session,
                        hidp_input_report(session, skb);
 
                if (session->hid) {
-                       hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 1);
+                       hidp_process_report(session, HID_INPUT_REPORT,
+                                           skb->data, skb->len, 1);
                        BT_DBG("report len %d", skb->len);
                }
        } else {
index ab52414..8798492 100644 (file)
@@ -24,6 +24,7 @@
 #define __HIDP_H
 
 #include <linux/types.h>
+#include <linux/hid.h>
 #include <linux/kref.h>
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/l2cap.h>
@@ -179,6 +180,9 @@ struct hidp_session {
 
        /* Used in hidp_output_raw_report() */
        int output_report_success; /* boolean */
+
+       /* temporary input buffer */
+       u8 input_buf[HID_MAX_BUFFER_SIZE];
 };
 
 /* HIDP init defines */