if (subpage == WACOM_HID_SP_DIGITIZER ||
                    subpage == WACOM_HID_SP_DIGITIZERINFO ||
+                   usage == WACOM_HID_WD_SENSE ||
                    usage == WACOM_HID_WD_DISTANCE) {
                        return usage;
                }
 {
        struct wacom *wacom = hid_get_drvdata(hdev);
        struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+       struct wacom_features *features = &wacom_wac->features;
        struct input_dev *input = wacom_wac->pen_input;
        unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
 
        case HID_DG_TOOLSERIALNUMBER:
                wacom_map_usage(input, usage, field, EV_MSC, MSC_SERIAL, 0);
                break;
+       case WACOM_HID_WD_SENSE:
+               features->quirks |= WACOM_QUIRK_SENSE;
+               wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
+               break;
        case WACOM_HID_WD_FINGERWHEEL:
                wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
                break;
 {
        struct wacom *wacom = hid_get_drvdata(hdev);
        struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+       struct wacom_features *features = &wacom_wac->features;
        struct input_dev *input = wacom_wac->pen_input;
        unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
 
                break;
        case HID_DG_INRANGE:
                wacom_wac->hid_data.inrange_state = value;
+               if (!(features->quirks & WACOM_QUIRK_SENSE))
+                       wacom_wac->hid_data.sense_state = value;
                return 0;
        case HID_DG_INVERT:
                wacom_wac->hid_data.invert_state = value;
        case HID_DG_TIPSWITCH:
                wacom_wac->hid_data.tipswitch |= value;
                return 0;
+       case WACOM_HID_WD_SENSE:
+               wacom_wac->hid_data.sense_state = value;
+               return 0;
        }
 
        /* send pen events only when touch is up or forced out
        if (!usage->type || delay_pen_events(wacom_wac))
                return 0;
 
+       /* send pen events only when the pen is in/entering/leaving proximity */
+       if (!wacom_wac->hid_data.inrange_state && !wacom_wac->tool[0])
+               return 0;
+
        input_event(input, usage->type, usage->code, value);
 
        return 0;
        struct wacom_wac *wacom_wac = &wacom->wacom_wac;
        struct input_dev *input = wacom_wac->pen_input;
        bool prox = wacom_wac->hid_data.inrange_state;
+       bool range = wacom_wac->hid_data.sense_state;
 
-       if (!wacom_wac->shared->stylus_in_proximity) /* first in prox */
+       if (!wacom_wac->tool[0] && prox) /* first in prox */
                /* Going into proximity select tool */
                wacom_wac->tool[0] = wacom_wac->hid_data.invert_state ?
                                                BTN_TOOL_RUBBER : BTN_TOOL_PEN;
 
        /* keep pen state for touch events */
-       wacom_wac->shared->stylus_in_proximity = prox;
+       wacom_wac->shared->stylus_in_proximity = range;
 
-       if (!delay_pen_events(wacom_wac)) {
+       if (!delay_pen_events(wacom_wac) && wacom_wac->tool[0]) {
                input_report_key(input, BTN_TOUCH,
                                wacom_wac->hid_data.tipswitch);
                input_report_key(input, wacom_wac->tool[0], prox);
 
                input_sync(input);
        }
+
+       if (!prox)
+               wacom_wac->tool[0] = 0;
 }
 
 static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
 
 
 /* device quirks */
 #define WACOM_QUIRK_BBTOUCH_LOWRES     0x0001
+#define WACOM_QUIRK_SENSE              0x0002
 #define WACOM_QUIRK_BATTERY            0x0008
 
 /* device types */
 #define WACOM_HID_SP_DIGITIZER          0x000d0000
 #define WACOM_HID_SP_DIGITIZERINFO      0x00100000
 #define WACOM_HID_WD_DIGITIZER          (WACOM_HID_UP_WACOMDIGITIZER | 0x01)
+#define WACOM_HID_WD_SENSE              (WACOM_HID_UP_WACOMDIGITIZER | 0x36)
 #define WACOM_HID_WD_DISTANCE           (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)
 #define WACOM_HID_WD_FINGERWHEEL        (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)
 #define WACOM_HID_WD_DATAMODE           (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
 struct hid_data {
        __s16 inputmode;        /* InputMode HID feature, -1 if non-existent */
        __s16 inputmode_index;  /* InputMode HID feature index in the report */
+       bool sense_state;
        bool inrange_state;
        bool invert_state;
        bool tipswitch;