]> Git Repo - linux.git/commitdiff
Merge branches 'for-3.15/multitouch', 'for-3.15/sony' and 'for-3.15/uhid' into for...
authorJiri Kosina <[email protected]>
Tue, 1 Apr 2014 17:06:50 +0000 (19:06 +0200)
committerJiri Kosina <[email protected]>
Tue, 1 Apr 2014 17:06:50 +0000 (19:06 +0200)
1  2  3  4 
drivers/hid/hid-ids.h
drivers/hid/hid-multitouch.c
drivers/hid/hid-sony.c
include/linux/hid.h

diff --combined drivers/hid/hid-ids.h
index af15a631bb24183b3553aa8712d1a683639cdd45,ca9b206a01c1c87bb3c8c686bfdb1363de3d4ff7,239f29c1c85c14f64fe5d51ff1a935b98377d06c,239f29c1c85c14f64fe5d51ff1a935b98377d06c..548c1a51959334e867b27c73ae20d682515c9149
    #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_DEVICE_ID_CYPRESS_MOUSE 0x0001
    #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 221d503f1c24fa7b1bbbc0c5871c3cbe742d1a5b,59742f49295cfe9f469be8eede5e4c5435b4cefb,f134d73beca16b72ddce5716d36e4d7ca949e61d,f134d73beca16b72ddce5716d36e4d7ca949e61d..35278e43c7a48d1999283c21f0f60cceccbc3b84
@@@@@ -68,6 -68,9 -68,6 -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 -84,6 -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 -100,11 -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 -128,16 -128,16 +132,17 @@@@@ static void mt_post_parse(struct mt_dev
    #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 -189,28 -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
                .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 -360,45 -360,45 +351,6 @@@@@ static void mt_store_field(struct hid_u
        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)
         * 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 -776,28 -776,28 +730,52 @@@@@ static int mt_input_mapping(struct hid_
                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;
  ++
-       return mt_touch_input_mapping(hdev, hi, field, usage, bit, max);
+ ++    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;
  ++
-       return mt_touch_input_mapped(hdev, hi, field, usage, bit, max);
+ ++    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,
        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)
        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 -907,13 -907,13 +882,49 @@@@@ static void mt_input_configured(struct 
        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 -973,9 -973,9 +984,9 @@@@@ static int mt_probe(struct hid_device *
        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 -1034,6 -1034,6 +1045,12 @@@@@ static void mt_remove(struct hid_devic
        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 */
                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) },
        { .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) },
                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,
                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,
                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,
                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,
                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,
                        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,
                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) },
    
diff --combined drivers/hid/hid-sony.c
index b3e82585309e51ec85297d4be4e797871a71f21a,e3e89b6a41c28d9b18702e8c53e21218cb292840,908de278921944dfae837284f582e117617c479d,4884bb567bf88ab0a71030c6eb9666c4fc88cbab..4d348c069981f21b51c12aabfea9f4fdaa342952
     * any later version.
     */
    
 -  /* NOTE: in order for the Sony PS3 BD Remote Control to be found by
 +  /*
 +   * NOTE: in order for the Sony PS3 BD Remote Control to be found by
     * a Bluetooth host, the key combination Start+Enter has to be kept pressed
     * for about 7 seconds with the Bluetooth Host Controller in discovering mode.
     *
    #include <linux/hid.h>
    #include <linux/module.h>
    #include <linux/slab.h>
 -  #include <linux/usb.h>
    #include <linux/leds.h>
 +  #include <linux/power_supply.h>
 +  #include <linux/spinlock.h>
 +  #include <linux/list.h>
 +  #include <linux/input/mt.h>
    
    #include "hid-ids.h"
    
    #define DUALSHOCK4_CONTROLLER_USB BIT(5)
    #define DUALSHOCK4_CONTROLLER_BT  BIT(6)
    
 -  #define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER_USB | BUZZ_CONTROLLER | DUALSHOCK4_CONTROLLER_USB)
 +  #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)
 +  #define DUALSHOCK4_CONTROLLER (DUALSHOCK4_CONTROLLER_USB |\
 +                              DUALSHOCK4_CONTROLLER_BT)
 +  #define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER | BUZZ_CONTROLLER |\
 +                              DUALSHOCK4_CONTROLLER)
 +  #define SONY_BATTERY_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER)
 +  #define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER)
    
    #define MAX_LEDS 4
    
@@@@@ -83,8 -73,7 -83,8 -83,8 +83,8 @@@@@ static const u8 sixaxis_rdesc_fixup2[] 
        0xb1, 0x02, 0xc0, 0xc0,
    };
    
 -  /* The default descriptor doesn't provide mapping for the accelerometers
 +  /*
 +   * The default descriptor doesn't provide mapping for the accelerometers
     * or orientation sensors.  This fixed descriptor maps the accelerometers
     * to usage values 0x40, 0x41 and 0x42 and maps the orientation sensors
     * to usage values 0x43, 0x44 and 0x45.
@@@@@ -343,217 -332,6 -343,217 -343,217 +343,217 @@@@@ static u8 dualshock4_usb_rdesc[] = 
        0xC0                /*  End Collection                      */
    };
    
 +  /*
 +   * The default behavior of the Dualshock 4 is to send reports using report
 +   * type 1 when running over Bluetooth. However, as soon as it receives a
 +   * report of type 17 to set the LEDs or rumble it starts returning it's state
 +   * in report 17 instead of 1.  Since report 17 is undefined in the default HID
 +   * descriptor the button and axis definitions must be moved to report 17 or
 +   * the HID layer won't process the received input once a report is sent.
 +   */
 +  static u8 dualshock4_bt_rdesc[] = {
 +      0x05, 0x01,         /*  Usage Page (Desktop),               */
 +      0x09, 0x05,         /*  Usage (Gamepad),                    */
 +      0xA1, 0x01,         /*  Collection (Application),           */
 +      0x85, 0x01,         /*      Report ID (1),                  */
 +      0x75, 0x08,         /*      Report Size (8),                */
 +      0x95, 0x0A,         /*      Report Count (9),               */
 +      0x81, 0x02,         /*      Input (Variable),               */
 +      0x06, 0x04, 0xFF,   /*      Usage Page (FF04h),             */
 +      0x85, 0x02,         /*      Report ID (2),                  */
 +      0x09, 0x24,         /*      Usage (24h),                    */
 +      0x95, 0x24,         /*      Report Count (36),              */
 +      0xB1, 0x02,         /*      Feature (Variable),             */
 +      0x85, 0xA3,         /*      Report ID (163),                */
 +      0x09, 0x25,         /*      Usage (25h),                    */
 +      0x95, 0x30,         /*      Report Count (48),              */
 +      0xB1, 0x02,         /*      Feature (Variable),             */
 +      0x85, 0x05,         /*      Report ID (5),                  */
 +      0x09, 0x26,         /*      Usage (26h),                    */
 +      0x95, 0x28,         /*      Report Count (40),              */
 +      0xB1, 0x02,         /*      Feature (Variable),             */
 +      0x85, 0x06,         /*      Report ID (6),                  */
 +      0x09, 0x27,         /*      Usage (27h),                    */
 +      0x95, 0x34,         /*      Report Count (52),              */
 +      0xB1, 0x02,         /*      Feature (Variable),             */
 +      0x85, 0x07,         /*      Report ID (7),                  */
 +      0x09, 0x28,         /*      Usage (28h),                    */
 +      0x95, 0x30,         /*      Report Count (48),              */
 +      0xB1, 0x02,         /*      Feature (Variable),             */
 +      0x85, 0x08,         /*      Report ID (8),                  */
 +      0x09, 0x29,         /*      Usage (29h),                    */
 +      0x95, 0x2F,         /*      Report Count (47),              */
 +      0xB1, 0x02,         /*      Feature (Variable),             */
 +      0x06, 0x03, 0xFF,   /*      Usage Page (FF03h),             */
 +      0x85, 0x03,         /*      Report ID (3),                  */
 +      0x09, 0x21,         /*      Usage (21h),                    */
 +      0x95, 0x26,         /*      Report Count (38),              */
 +      0xB1, 0x02,         /*      Feature (Variable),             */
 +      0x85, 0x04,         /*      Report ID (4),                  */
 +      0x09, 0x22,         /*      Usage (22h),                    */
 +      0x95, 0x2E,         /*      Report Count (46),              */
 +      0xB1, 0x02,         /*      Feature (Variable),             */
 +      0x85, 0xF0,         /*      Report ID (240),                */
 +      0x09, 0x47,         /*      Usage (47h),                    */
 +      0x95, 0x3F,         /*      Report Count (63),              */
 +      0xB1, 0x02,         /*      Feature (Variable),             */
 +      0x85, 0xF1,         /*      Report ID (241),                */
 +      0x09, 0x48,         /*      Usage (48h),                    */
 +      0x95, 0x3F,         /*      Report Count (63),              */
 +      0xB1, 0x02,         /*      Feature (Variable),             */
 +      0x85, 0xF2,         /*      Report ID (242),                */
 +      0x09, 0x49,         /*      Usage (49h),                    */
 +      0x95, 0x0F,         /*      Report Count (15),              */
 +      0xB1, 0x02,         /*      Feature (Variable),             */
 +      0x85, 0x11,         /*      Report ID (17),                 */
 +      0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
 +      0x09, 0x20,         /*      Usage (20h),                    */
 +      0x95, 0x02,         /*      Report Count (2),               */
 +      0x81, 0x02,         /*      Input (Variable),               */
 +      0x05, 0x01,         /*      Usage Page (Desktop),           */
 +      0x09, 0x30,         /*      Usage (X),                      */
 +      0x09, 0x31,         /*      Usage (Y),                      */
 +      0x09, 0x32,         /*      Usage (Z),                      */
 +      0x09, 0x35,         /*      Usage (Rz),                     */
 +      0x15, 0x00,         /*      Logical Minimum (0),            */
 +      0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
 +      0x75, 0x08,         /*      Report Size (8),                */
 +      0x95, 0x04,         /*      Report Count (4),               */
 +      0x81, 0x02,         /*      Input (Variable),               */
 +      0x09, 0x39,         /*      Usage (Hat Switch),             */
 +      0x15, 0x00,         /*      Logical Minimum (0),            */
 +      0x25, 0x07,         /*      Logical Maximum (7),            */
 +      0x75, 0x04,         /*      Report Size (4),                */
 +      0x95, 0x01,         /*      Report Count (1),               */
 +      0x81, 0x42,         /*      Input (Variable, Null State),   */
 +      0x05, 0x09,         /*      Usage Page (Button),            */
 +      0x19, 0x01,         /*      Usage Minimum (01h),            */
 +      0x29, 0x0E,         /*      Usage Maximum (0Eh),            */
 +      0x15, 0x00,         /*      Logical Minimum (0),            */
 +      0x25, 0x01,         /*      Logical Maximum (1),            */
 +      0x75, 0x01,         /*      Report Size (1),                */
 +      0x95, 0x0E,         /*      Report Count (14),              */
 +      0x81, 0x02,         /*      Input (Variable),               */
 +      0x75, 0x06,         /*      Report Size (6),                */
 +      0x95, 0x01,         /*      Report Count (1),               */
 +      0x81, 0x01,         /*      Input (Constant),               */
 +      0x05, 0x01,         /*      Usage Page (Desktop),           */
 +      0x09, 0x33,         /*      Usage (Rx),                     */
 +      0x09, 0x34,         /*      Usage (Ry),                     */
 +      0x15, 0x00,         /*      Logical Minimum (0),            */
 +      0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
 +      0x75, 0x08,         /*      Report Size (8),                */
 +      0x95, 0x02,         /*      Report Count (2),               */
 +      0x81, 0x02,         /*      Input (Variable),               */
 +      0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
 +      0x09, 0x20,         /*      Usage (20h),                    */
 +      0x95, 0x03,         /*      Report Count (3),               */
 +      0x81, 0x02,         /*      Input (Variable),               */
 +      0x05, 0x01,         /*      Usage Page (Desktop),           */
 +      0x19, 0x40,         /*      Usage Minimum (40h),            */
 +      0x29, 0x42,         /*      Usage Maximum (42h),            */
 +      0x16, 0x00, 0x80,   /*      Logical Minimum (-32768),       */
 +      0x26, 0x00, 0x7F,   /*      Logical Maximum (32767),        */
 +      0x75, 0x10,         /*      Report Size (16),               */
 +      0x95, 0x03,         /*      Report Count (3),               */
 +      0x81, 0x02,         /*      Input (Variable),               */
 +      0x19, 0x43,         /*      Usage Minimum (43h),            */
 +      0x29, 0x45,         /*      Usage Maximum (45h),            */
 +      0x16, 0xFF, 0xBF,   /*      Logical Minimum (-16385),       */
 +      0x26, 0x00, 0x40,   /*      Logical Maximum (16384),        */
 +      0x95, 0x03,         /*      Report Count (3),               */
 +      0x81, 0x02,         /*      Input (Variable),               */
 +      0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
 +      0x09, 0x20,         /*      Usage (20h),                    */
 +      0x15, 0x00,         /*      Logical Minimum (0),            */
 +      0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
 +      0x75, 0x08,         /*      Report Size (8),                */
 +      0x95, 0x31,         /*      Report Count (51),              */
 +      0x81, 0x02,         /*      Input (Variable),               */
 +      0x09, 0x21,         /*      Usage (21h),                    */
 +      0x75, 0x08,         /*      Report Size (8),                */
 +      0x95, 0x4D,         /*      Report Count (77),              */
 +      0x91, 0x02,         /*      Output (Variable),              */
 +      0x85, 0x12,         /*      Report ID (18),                 */
 +      0x09, 0x22,         /*      Usage (22h),                    */
 +      0x95, 0x8D,         /*      Report Count (141),             */
 +      0x81, 0x02,         /*      Input (Variable),               */
 +      0x09, 0x23,         /*      Usage (23h),                    */
 +      0x91, 0x02,         /*      Output (Variable),              */
 +      0x85, 0x13,         /*      Report ID (19),                 */
 +      0x09, 0x24,         /*      Usage (24h),                    */
 +      0x95, 0xCD,         /*      Report Count (205),             */
 +      0x81, 0x02,         /*      Input (Variable),               */
 +      0x09, 0x25,         /*      Usage (25h),                    */
 +      0x91, 0x02,         /*      Output (Variable),              */
 +      0x85, 0x14,         /*      Report ID (20),                 */
 +      0x09, 0x26,         /*      Usage (26h),                    */
 +      0x96, 0x0D, 0x01,   /*      Report Count (269),             */
 +      0x81, 0x02,         /*      Input (Variable),               */
 +      0x09, 0x27,         /*      Usage (27h),                    */
 +      0x91, 0x02,         /*      Output (Variable),              */
 +      0x85, 0x15,         /*      Report ID (21),                 */
 +      0x09, 0x28,         /*      Usage (28h),                    */
 +      0x96, 0x4D, 0x01,   /*      Report Count (333),             */
 +      0x81, 0x02,         /*      Input (Variable),               */
 +      0x09, 0x29,         /*      Usage (29h),                    */
 +      0x91, 0x02,         /*      Output (Variable),              */
 +      0x85, 0x16,         /*      Report ID (22),                 */
 +      0x09, 0x2A,         /*      Usage (2Ah),                    */
 +      0x96, 0x8D, 0x01,   /*      Report Count (397),             */
 +      0x81, 0x02,         /*      Input (Variable),               */
 +      0x09, 0x2B,         /*      Usage (2Bh),                    */
 +      0x91, 0x02,         /*      Output (Variable),              */
 +      0x85, 0x17,         /*      Report ID (23),                 */
 +      0x09, 0x2C,         /*      Usage (2Ch),                    */
 +      0x96, 0xCD, 0x01,   /*      Report Count (461),             */
 +      0x81, 0x02,         /*      Input (Variable),               */
 +      0x09, 0x2D,         /*      Usage (2Dh),                    */
 +      0x91, 0x02,         /*      Output (Variable),              */
 +      0x85, 0x18,         /*      Report ID (24),                 */
 +      0x09, 0x2E,         /*      Usage (2Eh),                    */
 +      0x96, 0x0D, 0x02,   /*      Report Count (525),             */
 +      0x81, 0x02,         /*      Input (Variable),               */
 +      0x09, 0x2F,         /*      Usage (2Fh),                    */
 +      0x91, 0x02,         /*      Output (Variable),              */
 +      0x85, 0x19,         /*      Report ID (25),                 */
 +      0x09, 0x30,         /*      Usage (30h),                    */
 +      0x96, 0x22, 0x02,   /*      Report Count (546),             */
 +      0x81, 0x02,         /*      Input (Variable),               */
 +      0x09, 0x31,         /*      Usage (31h),                    */
 +      0x91, 0x02,         /*      Output (Variable),              */
 +      0x06, 0x80, 0xFF,   /*      Usage Page (FF80h),             */
 +      0x85, 0x82,         /*      Report ID (130),                */
 +      0x09, 0x22,         /*      Usage (22h),                    */
 +      0x95, 0x3F,         /*      Report Count (63),              */
 +      0xB1, 0x02,         /*      Feature (Variable),             */
 +      0x85, 0x83,         /*      Report ID (131),                */
 +      0x09, 0x23,         /*      Usage (23h),                    */
 +      0xB1, 0x02,         /*      Feature (Variable),             */
 +      0x85, 0x84,         /*      Report ID (132),                */
 +      0x09, 0x24,         /*      Usage (24h),                    */
 +      0xB1, 0x02,         /*      Feature (Variable),             */
 +      0x85, 0x90,         /*      Report ID (144),                */
 +      0x09, 0x30,         /*      Usage (30h),                    */
 +      0xB1, 0x02,         /*      Feature (Variable),             */
 +      0x85, 0x91,         /*      Report ID (145),                */
 +      0x09, 0x31,         /*      Usage (31h),                    */
 +      0xB1, 0x02,         /*      Feature (Variable),             */
 +      0x85, 0x92,         /*      Report ID (146),                */
 +      0x09, 0x32,         /*      Usage (32h),                    */
 +      0xB1, 0x02,         /*      Feature (Variable),             */
 +      0x85, 0x93,         /*      Report ID (147),                */
 +      0x09, 0x33,         /*      Usage (33h),                    */
 +      0xB1, 0x02,         /*      Feature (Variable),             */
 +      0x85, 0xA0,         /*      Report ID (160),                */
 +      0x09, 0x40,         /*      Usage (40h),                    */
 +      0xB1, 0x02,         /*      Feature (Variable),             */
 +      0x85, 0xA4,         /*      Report ID (164),                */
 +      0x09, 0x44,         /*      Usage (44h),                    */
 +      0xB1, 0x02,         /*      Feature (Variable),             */
 +      0xC0                /*  End Collection                      */
 +  };
 +  
    static __u8 ps3remote_rdesc[] = {
        0x05, 0x01,          /* GUsagePage Generic Desktop */
        0x09, 0x05,          /* LUsage 0x05 [Game Pad] */
@@@@@ -671,8 -449,7 -671,8 -671,8 +671,8 @@@@@ static const unsigned int ps3remote_key
    };
    
    static const unsigned int buzz_keymap[] = {
 -      /* The controller has 4 remote buzzers, each with one LED and 5
 +      /*
 +       * The controller has 4 remote buzzers, each with one LED and 5
         * buttons.
         * 
         * We use the mapping chosen by the controller, which is:
        [20] = BTN_TRIGGER_HAPPY20,
    };
    
 +  static enum power_supply_property sony_battery_props[] = {
 +      POWER_SUPPLY_PROP_PRESENT,
 +      POWER_SUPPLY_PROP_CAPACITY,
 +      POWER_SUPPLY_PROP_SCOPE,
 +      POWER_SUPPLY_PROP_STATUS,
 +  };
 +  
 +  static spinlock_t sony_dev_list_lock;
 +  static LIST_HEAD(sony_device_list);
 +  
    struct sony_sc {
 +      spinlock_t lock;
 +      struct list_head list_node;
        struct hid_device *hdev;
        struct led_classdev *leds[MAX_LEDS];
 -      struct hid_report *output_report;
        unsigned long quirks;
        struct work_struct state_worker;
 +      struct power_supply battery;
    
    #ifdef CONFIG_SONY_FF
        __u8 left;
        __u8 right;
    #endif
    
 +      __u8 mac_address[6];
 +      __u8 worker_initialized;
 +      __u8 cable_state;
 +      __u8 battery_charging;
 +      __u8 battery_capacity;
        __u8 led_state[MAX_LEDS];
        __u8 led_count;
    };
@@@@@ -816,10 -576,6 -816,10 -816,10 +816,10 @@@@@ static __u8 *sony_report_fixup(struct h
                hid_info(hdev, "Using modified Dualshock 4 report descriptor with gyroscope axes\n");
                rdesc = dualshock4_usb_rdesc;
                *rsize = sizeof(dualshock4_usb_rdesc);
 +      } else if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) && *rsize == 357) {
 +              hid_info(hdev, "Using modified Dualshock 4 Bluetooth report descriptor\n");
 +              rdesc = dualshock4_bt_rdesc;
 +              *rsize = sizeof(dualshock4_bt_rdesc);
        }
    
        /* The HID descriptor exposed over BT has a trailing zero byte */
        return rdesc;
    }
    
-  -    cable_state = !((rd[31] >> 4) & 0x01);
 +  static void sixaxis_parse_report(struct sony_sc *sc, __u8 *rd, int size)
 +  {
 +      static const __u8 sixaxis_battery_capacity[] = { 0, 1, 25, 50, 75, 100 };
 +      unsigned long flags;
 +      __u8 cable_state, battery_capacity, battery_charging;
 +  
 +      /*
 +       * The sixaxis is charging if the battery value is 0xee
 +       * and it is fully charged if the value is 0xef.
 +       * It does not report the actual level while charging so it
 +       * is set to 100% while charging is in progress.
 +       */
 +      if (rd[30] >= 0xee) {
 +              battery_capacity = 100;
 +              battery_charging = !(rd[30] & 0x01);
 +      } else {
 +              __u8 index = rd[30] <= 5 ? rd[30] : 5;
 +              battery_capacity = sixaxis_battery_capacity[index];
 +              battery_charging = 0;
 +      }
++ +    cable_state = !(rd[31] & 0x04);
 +  
 +      spin_lock_irqsave(&sc->lock, flags);
 +      sc->cable_state = cable_state;
 +      sc->battery_capacity = battery_capacity;
 +      sc->battery_charging = battery_charging;
 +      spin_unlock_irqrestore(&sc->lock, flags);
 +  }
 +  
 +  static void dualshock4_parse_report(struct sony_sc *sc, __u8 *rd, int size)
 +  {
 +      struct hid_input *hidinput = list_entry(sc->hdev->inputs.next,
 +                                              struct hid_input, list);
 +      struct input_dev *input_dev = hidinput->input;
 +      unsigned long flags;
 +      int n, offset;
 +      __u8 cable_state, battery_capacity, battery_charging;
 +  
 +      /*
 +       * Battery and touchpad data starts at byte 30 in the USB report and
 +       * 32 in Bluetooth report.
 +       */
 +      offset = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 30 : 32;
 +  
 +      /*
 +       * The lower 4 bits of byte 30 contain the battery level
 +       * and the 5th bit contains the USB cable state.
 +       */
 +      cable_state = (rd[offset] >> 4) & 0x01;
 +      battery_capacity = rd[offset] & 0x0F;
 +  
 +      /*
 +       * When a USB power source is connected the battery level ranges from
 +       * 0 to 10, and when running on battery power it ranges from 0 to 9.
 +       * A battery level above 10 when plugged in means charge completed.
 +       */
 +      if (!cable_state || battery_capacity > 10)
 +              battery_charging = 0;
 +      else
 +              battery_charging = 1;
 +  
 +      if (!cable_state)
 +              battery_capacity++;
 +      if (battery_capacity > 10)
 +              battery_capacity = 10;
 +  
 +      battery_capacity *= 10;
 +  
 +      spin_lock_irqsave(&sc->lock, flags);
 +      sc->cable_state = cable_state;
 +      sc->battery_capacity = battery_capacity;
 +      sc->battery_charging = battery_charging;
 +      spin_unlock_irqrestore(&sc->lock, flags);
 +  
 +      offset += 5;
 +  
 +      /*
 +       * The Dualshock 4 multi-touch trackpad data starts at offset 35 on USB
 +       * and 37 on Bluetooth.
 +       * The first 7 bits of the first byte is a counter and bit 8 is a touch
 +       * indicator that is 0 when pressed and 1 when not pressed.
 +       * The next 3 bytes are two 12 bit touch coordinates, X and Y.
 +       * The data for the second touch is in the same format and immediatly
 +       * follows the data for the first.
 +       */
 +      for (n = 0; n < 2; n++) {
 +              __u16 x, y;
 +  
 +              x = rd[offset+1] | ((rd[offset+2] & 0xF) << 8);
 +              y = ((rd[offset+2] & 0xF0) >> 4) | (rd[offset+3] << 4);
 +  
 +              input_mt_slot(input_dev, n);
 +              input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
 +                                      !(rd[offset] >> 7));
 +              input_report_abs(input_dev, ABS_MT_POSITION_X, x);
 +              input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
 +  
 +              offset += 4;
 +      }
 +  }
 +  
    static int sony_raw_event(struct hid_device *hdev, struct hid_report *report,
                __u8 *rd, int size)
    {
        struct sony_sc *sc = hid_get_drvdata(hdev);
    
 -      /* Sixaxis HID report has acclerometers/gyro with MSByte first, this
 +      /*
 +       * Sixaxis HID report has acclerometers/gyro with MSByte first, this
         * has to be BYTE_SWAPPED before passing up to joystick interface
         */
 -      if ((sc->quirks & (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)) &&
 -                      rd[0] == 0x01 && size == 49) {
 +      if ((sc->quirks & SIXAXIS_CONTROLLER) && rd[0] == 0x01 && size == 49) {
                swap(rd[41], rd[42]);
                swap(rd[43], rd[44]);
                swap(rd[45], rd[46]);
                swap(rd[47], rd[48]);
 +  
 +              sixaxis_parse_report(sc, rd, size);
 +      } else if (((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && rd[0] == 0x01 &&
 +                      size == 64) || ((sc->quirks & DUALSHOCK4_CONTROLLER_BT)
 +                      && rd[0] == 0x11 && size == 78)) {
 +              dualshock4_parse_report(sc, rd, size);
        }
    
        return 0;
@@@@@ -1005,6 -654,45 -1005,6 -1005,6 +1005,6 @@@@@ static int sony_mapping(struct hid_devi
        return 0;
    }
    
 -  /*
 -   * The Sony Sixaxis does not handle HID Output Reports on the Interrupt EP
 -   * like it should according to usbhid/hid-core.c::usbhid_output_raw_report()
 -   * so we need to override that forcing HID Output Reports on the Control EP.
 -   *
 -   * There is also another issue about HID Output Reports via USB, the Sixaxis
 -   * does not want the report_id as part of the data packet, so we have to
 -   * discard buf[0] when sending the actual control message, even for numbered
 -   * reports, humpf!
 -   */
 -  static int sixaxis_usb_output_raw_report(struct hid_device *hid, __u8 *buf,
 -              size_t count, unsigned char report_type)
 -  {
 -      struct usb_interface *intf = to_usb_interface(hid->dev.parent);
 -      struct usb_device *dev = interface_to_usbdev(intf);
 -      struct usb_host_interface *interface = intf->cur_altsetting;
 -      int report_id = buf[0];
 -      int ret;
 -  
 -      if (report_type == HID_OUTPUT_REPORT) {
 -              /* Don't send the Report ID */
 -              buf++;
 -              count--;
 -      }
 -  
 -      ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 -              HID_REQ_SET_REPORT,
 -              USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
 -              ((report_type + 1) << 8) | report_id,
 -              interface->desc.bInterfaceNumber, buf, count,
 -              USB_CTRL_SET_TIMEOUT);
 -  
 -      /* Count also the Report ID, in case of an Output report. */
 -      if (ret > 0 && report_type == HID_OUTPUT_REPORT)
 -              ret++;
 -  
 -      return ret;
 -  }
 -  
    /*
     * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
     * to "operational".  Without this, the ps3 controller will not report any
@@@@@ -1036,18 -724,6 -1036,18 -1036,18 +1036,18 @@@@@ static int sixaxis_set_operational_bt(s
                                  HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
    }
    
 +  /*
 +   * Requesting feature report 0x02 in Bluetooth mode changes the state of the
 +   * controller so that it sends full input reports of type 0x11.
 +   */
 +  static int dualshock4_set_operational_bt(struct hid_device *hdev)
 +  {
 +      __u8 buf[37] = { 0 };
 +  
 +      return hid_hw_raw_request(hdev, 0x02, buf, sizeof(buf),
 +                              HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
 +  }
 +  
    static void buzz_set_leds(struct hid_device *hdev, const __u8 *leds)
    {
        struct list_head *report_list =
@@@@@ -1075,7 -751,8 -1075,7 -1075,7 +1075,7 @@@@@ static void sony_set_leds(struct hid_de
    
        if (drv_data->quirks & BUZZ_CONTROLLER && count == 4) {
                buzz_set_leds(hdev, leds);
 -      } else if ((drv_data->quirks & SIXAXIS_CONTROLLER_USB) ||
 -                 (drv_data->quirks & DUALSHOCK4_CONTROLLER_USB)) {
 +      } else {
                for (n = 0; n < count; n++)
                        drv_data->led_state[n] = leds[n];
                schedule_work(&drv_data->state_worker);
@@@@@ -1115,6 -792,7 -1115,6 -1115,6 +1115,6 @@@@@ static enum led_brightness sony_led_get
        struct sony_sc *drv_data;
    
        int n;
 -      int on = 0;
    
        drv_data = hid_get_drvdata(hdev);
        if (!drv_data) {
        }
    
        for (n = 0; n < drv_data->led_count; n++) {
 -              if (led == drv_data->leds[n]) {
 -                      on = !!(drv_data->led_state[n]);
 -                      break;
 -              }
 +              if (led == drv_data->leds[n])
 +                      return drv_data->led_state[n];
        }
    
 -      return on ? LED_FULL : LED_OFF;
 +      return LED_OFF;
    }
    
    static void sony_leds_remove(struct hid_device *hdev)
@@@@@ -1177,7 -857,7 -1177,7 -1177,7 +1177,7 @@@@@ static int sony_leds_init(struct hid_de
                /* Validate expected report characteristics. */
                if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7))
                        return -ENODEV;
 -      } else if (drv_data->quirks & DUALSHOCK4_CONTROLLER_USB) {
 +      } else if (drv_data->quirks & DUALSHOCK4_CONTROLLER) {
                drv_data->led_count = 3;
                max_brightness = 255;
                use_colors = 1;
                name_fmt = "%s::sony%d";
        }
    
 -      /* Clear LEDs as we have no way of reading their initial state. This is
 +      /*
 +       * Clear LEDs as we have no way of reading their initial state. This is
         * only relevant if the driver is loaded after somebody actively set the
 -       * LEDs to on */
 +       * LEDs to on
 +       */
        sony_set_leds(hdev, initial_values, drv_data->led_count);
    
        name_sz = strlen(dev_name(&hdev->dev)) + name_len + 1;
@@@@@ -1265,45 -943,28 -1265,45 -1265,45 +1265,45 @@@@@ static void sixaxis_state_worker(struc
        buf[10] |= sc->led_state[2] << 3;
        buf[10] |= sc->led_state[3] << 4;
    
 -      hid_output_raw_report(sc->hdev, buf, sizeof(buf), HID_OUTPUT_REPORT);
 +      hid_hw_raw_request(sc->hdev, 0x01, buf, sizeof(buf), HID_OUTPUT_REPORT,
 +                      HID_REQ_SET_REPORT);
    }
    
    static void dualshock4_state_worker(struct work_struct *work)
    {
        struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
        struct hid_device *hdev = sc->hdev;
 -      struct hid_report *report = sc->output_report;
 -      __s32 *value = report->field[0]->value;
 +      int offset;
    
 -      value[0] = 0x03;
 +      __u8 buf[78] = { 0 };
 +  
 +      if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
 +              buf[0] = 0x05;
 +              buf[1] = 0x03;
 +              offset = 4;
 +      } else {
 +              buf[0] = 0x11;
 +              buf[1] = 0xB0;
 +              buf[3] = 0x0F;
 +              offset = 6;
 +      }
    
    #ifdef CONFIG_SONY_FF
 -      value[3] = sc->right;
 -      value[4] = sc->left;
 +      buf[offset++] = sc->right;
 +      buf[offset++] = sc->left;
 +  #else
 +      offset += 2;
    #endif
    
 -      value[5] = sc->led_state[0];
 -      value[6] = sc->led_state[1];
 -      value[7] = sc->led_state[2];
 +      buf[offset++] = sc->led_state[0];
 +      buf[offset++] = sc->led_state[1];
 +      buf[offset++] = sc->led_state[2];
    
 -      hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
 +      if (sc->quirks & DUALSHOCK4_CONTROLLER_USB)
 +              hid_hw_output_report(hdev, buf, 32);
 +      else
 +              hid_hw_raw_request(hdev, 0x11, buf, 78,
 +                              HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
    }
    
    #ifdef CONFIG_SONY_FF
@@@@@ -1333,252 -994,51 -1333,252 -1333,252 +1333,252 @@@@@ static int sony_init_ff(struct hid_devi
        return input_ff_create_memless(input_dev, NULL, sony_play_effect);
    }
    
 -  static void sony_destroy_ff(struct hid_device *hdev)
 +  #else
 +  static int sony_init_ff(struct hid_device *hdev)
    {
 -      struct sony_sc *sc = hid_get_drvdata(hdev);
 +      return 0;
 +  }
 +  
 +  #endif
 +  
 +  static int sony_battery_get_property(struct power_supply *psy,
 +                                   enum power_supply_property psp,
 +                                   union power_supply_propval *val)
 +  {
 +      struct sony_sc *sc = container_of(psy, struct sony_sc, battery);
 +      unsigned long flags;
 +      int ret = 0;
 +      u8 battery_charging, battery_capacity, cable_state;
 +  
 +      spin_lock_irqsave(&sc->lock, flags);
 +      battery_charging = sc->battery_charging;
 +      battery_capacity = sc->battery_capacity;
 +      cable_state = sc->cable_state;
 +      spin_unlock_irqrestore(&sc->lock, flags);
 +  
 +      switch (psp) {
 +      case POWER_SUPPLY_PROP_PRESENT:
 +              val->intval = 1;
 +              break;
 +      case POWER_SUPPLY_PROP_SCOPE:
 +              val->intval = POWER_SUPPLY_SCOPE_DEVICE;
 +              break;
 +      case POWER_SUPPLY_PROP_CAPACITY:
 +              val->intval = battery_capacity;
 +              break;
 +      case POWER_SUPPLY_PROP_STATUS:
 +              if (battery_charging)
 +                      val->intval = POWER_SUPPLY_STATUS_CHARGING;
 +              else
 +                      if (battery_capacity == 100 && cable_state)
 +                              val->intval = POWER_SUPPLY_STATUS_FULL;
 +                      else
 +                              val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
 +              break;
 +      default:
 +              ret = -EINVAL;
 +              break;
 +      }
 +      return ret;
 +  }
 +  
 +  static int sony_battery_probe(struct sony_sc *sc)
 +  {
 +      static atomic_t power_id_seq = ATOMIC_INIT(0);
 +      unsigned long power_id;
 +      struct hid_device *hdev = sc->hdev;
 +      int ret;
 +  
 +      /*
 +       * Set the default battery level to 100% to avoid low battery warnings
 +       * if the battery is polled before the first device report is received.
 +       */
 +      sc->battery_capacity = 100;
 +  
 +      power_id = (unsigned long)atomic_inc_return(&power_id_seq);
 +  
 +      sc->battery.properties = sony_battery_props;
 +      sc->battery.num_properties = ARRAY_SIZE(sony_battery_props);
 +      sc->battery.get_property = sony_battery_get_property;
 +      sc->battery.type = POWER_SUPPLY_TYPE_BATTERY;
 +      sc->battery.use_for_apm = 0;
 +      sc->battery.name = kasprintf(GFP_KERNEL, "sony_controller_battery_%lu",
 +                                   power_id);
 +      if (!sc->battery.name)
 +              return -ENOMEM;
 +  
 +      ret = power_supply_register(&hdev->dev, &sc->battery);
 +      if (ret) {
 +              hid_err(hdev, "Unable to register battery device\n");
 +              goto err_free;
 +      }
 +  
 +      power_supply_powers(&sc->battery, &hdev->dev);
 +      return 0;
    
 -      cancel_work_sync(&sc->state_worker);
 +  err_free:
 +      kfree(sc->battery.name);
 +      sc->battery.name = NULL;
 +      return ret;
    }
    
 -  #else
 -  static int sony_init_ff(struct hid_device *hdev)
 +  static void sony_battery_remove(struct sony_sc *sc)
 +  {
 +      if (!sc->battery.name)
 +              return;
 +  
 +      power_supply_unregister(&sc->battery);
 +      kfree(sc->battery.name);
 +      sc->battery.name = NULL;
 +  }
 +  
 +  static int sony_register_touchpad(struct sony_sc *sc, int touch_count,
 +                                      int w, int h)
    {
 +      struct hid_input *hidinput = list_entry(sc->hdev->inputs.next,
 +                                              struct hid_input, list);
 +      struct input_dev *input_dev = hidinput->input;
 +      int ret;
 +  
 +      ret = input_mt_init_slots(input_dev, touch_count, 0);
 +      if (ret < 0) {
 +              hid_err(sc->hdev, "Unable to initialize multi-touch slots\n");
 +              return ret;
 +      }
 +  
 +      input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, w, 0, 0);
 +      input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, h, 0, 0);
 +  
        return 0;
    }
    
 -  static void sony_destroy_ff(struct hid_device *hdev)
 +  /*
 +   * If a controller is plugged in via USB while already connected via Bluetooth
 +   * it will show up as two devices. A global list of connected controllers and
 +   * their MAC addresses is maintained to ensure that a device is only connected
 +   * once.
 +   */
 +  static int sony_check_add_dev_list(struct sony_sc *sc)
    {
 +      struct sony_sc *entry;
 +      unsigned long flags;
 +      int ret;
 +  
 +      spin_lock_irqsave(&sony_dev_list_lock, flags);
 +  
 +      list_for_each_entry(entry, &sony_device_list, list_node) {
 +              ret = memcmp(sc->mac_address, entry->mac_address,
 +                              sizeof(sc->mac_address));
 +              if (!ret) {
 +                      ret = -EEXIST;
 +                      hid_info(sc->hdev, "controller with MAC address %pMR already connected\n",
 +                              sc->mac_address);
 +                      goto unlock;
 +              }
 +      }
 +  
 +      ret = 0;
 +      list_add(&(sc->list_node), &sony_device_list);
 +  
 +  unlock:
 +      spin_unlock_irqrestore(&sony_dev_list_lock, flags);
 +      return ret;
    }
 -  #endif
    
 -  static int sony_set_output_report(struct sony_sc *sc, int req_id, int req_size)
 +  static void sony_remove_dev_list(struct sony_sc *sc)
    {
 -      struct list_head *head, *list;
 -      struct hid_report *report;
 -      struct hid_device *hdev = sc->hdev;
 +      unsigned long flags;
    
 -      list = &hdev->report_enum[HID_OUTPUT_REPORT].report_list;
 +      if (sc->list_node.next) {
 +              spin_lock_irqsave(&sony_dev_list_lock, flags);
 +              list_del(&(sc->list_node));
 +              spin_unlock_irqrestore(&sony_dev_list_lock, flags);
 +      }
 +  }
 +  
 +  static int sony_get_bt_devaddr(struct sony_sc *sc)
 +  {
 +      int ret;
    
 -      list_for_each(head, list) {
 -              report = list_entry(head, struct hid_report, list);
 +      /* HIDP stores the device MAC address as a string in the uniq field. */
 +      ret = strlen(sc->hdev->uniq);
 +      if (ret != 17)
 +              return -EINVAL;
    
 -              if (report->id == req_id) {
 -                      if (report->size < req_size) {
 -                              hid_err(hdev, "Output report 0x%02x (%i bits) is smaller than requested size (%i bits)\n",
 -                                      req_id, report->size, req_size);
 -                              return -EINVAL;
 -                      }
 -                      sc->output_report = report;
 +      ret = sscanf(sc->hdev->uniq,
 +              "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
 +              &sc->mac_address[5], &sc->mac_address[4], &sc->mac_address[3],
 +              &sc->mac_address[2], &sc->mac_address[1], &sc->mac_address[0]);
 +  
 +      if (ret != 6)
 +              return -EINVAL;
 +  
 +      return 0;
 +  }
 +  
 +  static int sony_check_add(struct sony_sc *sc)
 +  {
 +      int n, ret;
 +  
 +      if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) ||
 +          (sc->quirks & SIXAXIS_CONTROLLER_BT)) {
 +              /*
 +               * sony_get_bt_devaddr() attempts to parse the Bluetooth MAC
 +               * address from the uniq string where HIDP stores it.
 +               * As uniq cannot be guaranteed to be a MAC address in all cases
 +               * a failure of this function should not prevent the connection.
 +               */
 +              if (sony_get_bt_devaddr(sc) < 0) {
 +                      hid_warn(sc->hdev, "UNIQ does not contain a MAC address; duplicate check skipped\n");
                        return 0;
                }
 -      }
 +      } else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
 +              __u8 buf[7];
 +  
 +              /*
 +               * The MAC address of a DS4 controller connected via USB can be
 +               * retrieved with feature report 0x81. The address begins at
 +               * offset 1.
 +               */
 +              ret = hid_hw_raw_request(sc->hdev, 0x81, buf, sizeof(buf),
 +                              HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
 +  
 +              if (ret != 7) {
 +                      hid_err(sc->hdev, "failed to retrieve feature report 0x81 with the DualShock 4 MAC address\n");
 +                      return ret < 0 ? ret : -EINVAL;
 +              }
    
 -      hid_err(hdev, "Unable to locate output report 0x%02x\n", req_id);
 +              memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address));
 +      } else if (sc->quirks & SIXAXIS_CONTROLLER_USB) {
 +              __u8 buf[18];
 +  
 +              /*
 +               * The MAC address of a Sixaxis controller connected via USB can
 +               * be retrieved with feature report 0xf2. The address begins at
 +               * offset 4.
 +               */
 +              ret = hid_hw_raw_request(sc->hdev, 0xf2, buf, sizeof(buf),
 +                              HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
 +  
 +              if (ret != 18) {
 +                      hid_err(sc->hdev, "failed to retrieve feature report 0xf2 with the Sixaxis MAC address\n");
 +                      return ret < 0 ? ret : -EINVAL;
 +              }
    
 -      return -EINVAL;
 +              /*
 +               * The Sixaxis device MAC in the report is big-endian and must
 +               * be byte-swapped.
 +               */
 +              for (n = 0; n < 6; n++)
 +                      sc->mac_address[5-n] = buf[4+n];
 +      } else {
 +              return 0;
 +      }
 +  
 +      return sony_check_add_dev_list(sc);
    }
    
 +  
    static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
    {
        int ret;
        }
    
        if (sc->quirks & SIXAXIS_CONTROLLER_USB) {
 -              hdev->hid_output_raw_report = sixaxis_usb_output_raw_report;
 +              /*
 +               * The Sony Sixaxis does not handle HID Output Reports on the
 +               * Interrupt EP like it could, so we need to force HID Output
 +               * Reports to use HID_REQ_SET_REPORT on the Control EP.
 +               *
 +               * There is also another issue about HID Output Reports via USB,
 +               * the Sixaxis does not want the report_id as part of the data
 +               * packet, so we have to discard buf[0] when sending the actual
 +               * control message, even for numbered reports, humpf!
 +               */
 +              hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
 +              hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID;
                ret = sixaxis_set_operational_usb(hdev);
 +              sc->worker_initialized = 1;
                INIT_WORK(&sc->state_worker, sixaxis_state_worker);
 -      }
 -      else if (sc->quirks & SIXAXIS_CONTROLLER_BT)
 +      } 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);
 -      else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
 -              /* Report 5 (31 bytes) is used to send data to the controller via USB */
 -              ret = sony_set_output_report(sc, 0x05, 248);
 +              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");
 +                              goto err_stop;
 +                      }
 +              }
 +              /*
 +               * The Dualshock 4 touchpad supports 2 touches and has a
 +               * resolution of 1920x940.
 +               */
 +              ret = sony_register_touchpad(sc, 2, 1920, 940);
                if (ret < 0)
                        goto err_stop;
    
 +              sc->worker_initialized = 1;
                INIT_WORK(&sc->state_worker, dualshock4_state_worker);
        } else {
                ret = 0;
        }
    
 +      if (ret < 0)
 +              goto err_stop;
 +  
 +      ret = sony_check_add(sc);
        if (ret < 0)
                goto err_stop;
    
                        goto err_stop;
        }
    
 -      ret = sony_init_ff(hdev);
 -      if (ret < 0)
 -              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)
 +                      goto err_stop;
 +  
 +              /* Open the device to receive reports with battery info */
 +              ret = hid_hw_open(hdev);
 +              if (ret < 0) {
 +                      hid_err(hdev, "hw open failed\n");
 +                      goto err_stop;
 +              }
 +      }
 +  
 +      if (sc->quirks & SONY_FF_SUPPORT) {
 +              ret = sony_init_ff(hdev);
 +              if (ret < 0)
 +                      goto err_close;
 +      }
    
        return 0;
 +  err_close:
 +      hid_hw_close(hdev);
    err_stop:
        if (sc->quirks & SONY_LED_SUPPORT)
                sony_leds_remove(hdev);
 +      if (sc->quirks & SONY_BATTERY_SUPPORT)
 +              sony_battery_remove(sc);
 +      if (sc->worker_initialized)
 +              cancel_work_sync(&sc->state_worker);
 +      sony_remove_dev_list(sc);
        hid_hw_stop(hdev);
        return ret;
    }
@@@@@ -1715,17 -1121,7 -1721,15 -1711,15 +1725,17 @@@@@ static void sony_remove(struct hid_devi
        if (sc->quirks & SONY_LED_SUPPORT)
                sony_leds_remove(hdev);
    
 -      sony_destroy_ff(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);
 +      }
 +  
 +      if (sc->worker_initialized)
 +              cancel_work_sync(&sc->state_worker);
 +  
 +      sony_remove_dev_list(sc);
    
        hid_hw_stop(hdev);
    }
diff --combined include/linux/hid.h
index 01a90b8d53bb10391eeabb2b1c41df8d6b73b1b4,e224516cc565be991280c40b842cf28ff24c4aa4,01a90b8d53bb10391eeabb2b1c41df8d6b73b1b4,01a90b8d53bb10391eeabb2b1c41df8d6b73b1b4..720e3a10608cec94c02c94a6a1053789a567bae5
@@@@@ -201,6 -201,7 -201,6 -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
    
    #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
    #define HID_QUIRK_NO_EMPTY_INPUT            0x00000100
    #define HID_QUIRK_NO_INIT_INPUT_REPORTS             0x00000200
    #define HID_QUIRK_SKIP_OUTPUT_REPORTS               0x00010000
 +  #define HID_QUIRK_SKIP_OUTPUT_REPORT_ID             0x00020000
 +  #define HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP      0x00040000
    #define HID_QUIRK_FULLSPEED_INTERVAL                0x10000000
    #define HID_QUIRK_NO_INIT_REPORTS           0x20000000
    #define HID_QUIRK_NO_IGNORE                 0x40000000
@@@@@ -510,6 -511,9 -510,6 -510,6 +513,6 @@@@@ struct hid_device {                                                      /* device rep
                                  struct hid_usage *, __s32);
        void (*hiddev_report_event) (struct hid_device *, struct hid_report *);
    
 -      /* handler for raw output data, used by hidraw */
 -      int (*hid_output_raw_report) (struct hid_device *, __u8 *, size_t, unsigned char);
 -  
        /* debugging support via debugfs */
        unsigned short debug;
        struct dentry *debug_dir;
@@@@@ -1016,6 -1020,22 -1016,6 -1016,6 +1019,6 @@@@@ static inline int hid_hw_output_report(
        return -ENOSYS;
    }
    
 -  /**
 -   * hid_output_raw_report - send an output or a feature report to the device
 -   *
 -   * @hdev: hid device
 -   * @buf: raw data to transfer
 -   * @len: length of buf
 -   * @report_type: HID_FEATURE_REPORT or HID_OUTPUT_REPORT
 -   *
 -   * @return: count of data transfered, negative if error
 -   */
 -  static inline int hid_output_raw_report(struct hid_device *hdev, __u8 *buf,
 -                                      size_t len, unsigned char report_type)
 -  {
 -      return hdev->hid_output_raw_report(hdev, buf, len, report_type);
 -  }
 -  
    /**
     * hid_hw_idle - send idle request to device
     *
This page took 0.135887 seconds and 4 git commands to generate.