|
@@ -1248,6 +1248,176 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static void wacom_map_usage(struct wacom *wacom, struct hid_usage *usage,
|
|
|
+ struct hid_field *field, __u8 type, __u16 code, int fuzz)
|
|
|
+{
|
|
|
+ struct wacom_wac *wacom_wac = &wacom->wacom_wac;
|
|
|
+ struct input_dev *input = wacom_wac->input;
|
|
|
+ int fmin = field->logical_minimum;
|
|
|
+ int fmax = field->logical_maximum;
|
|
|
+
|
|
|
+ usage->type = type;
|
|
|
+ usage->code = code;
|
|
|
+
|
|
|
+ set_bit(type, input->evbit);
|
|
|
+
|
|
|
+ switch (type) {
|
|
|
+ case EV_ABS:
|
|
|
+ input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
|
|
|
+ input_abs_set_res(input, code,
|
|
|
+ hidinput_calc_abs_res(field, code));
|
|
|
+ break;
|
|
|
+ case EV_KEY:
|
|
|
+ input_set_capability(input, EV_KEY, code);
|
|
|
+ break;
|
|
|
+ case EV_MSC:
|
|
|
+ input_set_capability(input, EV_MSC, code);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
|
|
|
+ struct hid_field *field, struct hid_usage *usage)
|
|
|
+{
|
|
|
+ struct wacom *wacom = hid_get_drvdata(hdev);
|
|
|
+
|
|
|
+ switch (usage->hid) {
|
|
|
+ case HID_GD_X:
|
|
|
+ wacom_map_usage(wacom, usage, field, EV_ABS, ABS_X, 4);
|
|
|
+ break;
|
|
|
+ case HID_GD_Y:
|
|
|
+ wacom_map_usage(wacom, usage, field, EV_ABS, ABS_Y, 4);
|
|
|
+ break;
|
|
|
+ case HID_DG_TIPPRESSURE:
|
|
|
+ wacom_map_usage(wacom, usage, field, EV_ABS, ABS_PRESSURE, 0);
|
|
|
+ break;
|
|
|
+ case HID_DG_INRANGE:
|
|
|
+ wacom_map_usage(wacom, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
|
|
|
+ break;
|
|
|
+ case HID_DG_INVERT:
|
|
|
+ wacom_map_usage(wacom, usage, field, EV_KEY,
|
|
|
+ BTN_TOOL_RUBBER, 0);
|
|
|
+ break;
|
|
|
+ case HID_DG_ERASER:
|
|
|
+ case HID_DG_TIPSWITCH:
|
|
|
+ wacom_map_usage(wacom, usage, field, EV_KEY, BTN_TOUCH, 0);
|
|
|
+ break;
|
|
|
+ case HID_DG_BARRELSWITCH:
|
|
|
+ wacom_map_usage(wacom, usage, field, EV_KEY, BTN_STYLUS, 0);
|
|
|
+ break;
|
|
|
+ case HID_DG_BARRELSWITCH2:
|
|
|
+ wacom_map_usage(wacom, usage, field, EV_KEY, BTN_STYLUS2, 0);
|
|
|
+ break;
|
|
|
+ case HID_DG_TOOLSERIALNUMBER:
|
|
|
+ wacom_map_usage(wacom, usage, field, EV_MSC, MSC_SERIAL, 0);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
|
|
|
+ struct hid_usage *usage, __s32 value)
|
|
|
+{
|
|
|
+ struct wacom *wacom = hid_get_drvdata(hdev);
|
|
|
+ struct wacom_wac *wacom_wac = &wacom->wacom_wac;
|
|
|
+ struct input_dev *input = wacom_wac->input;
|
|
|
+
|
|
|
+ /* checking which Tool / tip switch to send */
|
|
|
+ switch (usage->hid) {
|
|
|
+ case HID_DG_INRANGE:
|
|
|
+ wacom_wac->hid_data.inrange_state = value;
|
|
|
+ return 0;
|
|
|
+ case HID_DG_INVERT:
|
|
|
+ wacom_wac->hid_data.invert_state = value;
|
|
|
+ return 0;
|
|
|
+ case HID_DG_ERASER:
|
|
|
+ case HID_DG_TIPSWITCH:
|
|
|
+ wacom_wac->hid_data.tipswitch |= value;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* send pen events only when touch is up or forced out */
|
|
|
+ if (!usage->type || wacom_wac->shared->touch_down)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ input_event(input, usage->type, usage->code, value);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static void wacom_wac_pen_report(struct hid_device *hdev,
|
|
|
+ struct hid_report *report)
|
|
|
+{
|
|
|
+ struct wacom *wacom = hid_get_drvdata(hdev);
|
|
|
+ struct wacom_wac *wacom_wac = &wacom->wacom_wac;
|
|
|
+ struct input_dev *input = wacom_wac->input;
|
|
|
+ bool prox = wacom_wac->hid_data.inrange_state;
|
|
|
+
|
|
|
+ if (!wacom_wac->shared->stylus_in_proximity) /* 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;
|
|
|
+
|
|
|
+ /* send pen events only when touch is up or forced out */
|
|
|
+ if (!wacom_wac->shared->touch_down) {
|
|
|
+ input_report_key(input, BTN_TOUCH,
|
|
|
+ wacom_wac->hid_data.tipswitch);
|
|
|
+ input_report_key(input, wacom_wac->tool[0], prox);
|
|
|
+
|
|
|
+ wacom_wac->hid_data.tipswitch = false;
|
|
|
+
|
|
|
+ input_sync(input);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#define WACOM_PEN_FIELD(f) (((f)->logical == HID_DG_STYLUS) || \
|
|
|
+ ((f)->physical == HID_DG_STYLUS))
|
|
|
+#define WACOM_FINGER_FIELD(f) (((f)->logical == HID_DG_FINGER) || \
|
|
|
+ ((f)->physical == HID_DG_FINGER))
|
|
|
+
|
|
|
+void wacom_wac_usage_mapping(struct hid_device *hdev,
|
|
|
+ struct hid_field *field, struct hid_usage *usage)
|
|
|
+{
|
|
|
+ struct wacom *wacom = hid_get_drvdata(hdev);
|
|
|
+ struct wacom_wac *wacom_wac = &wacom->wacom_wac;
|
|
|
+ struct input_dev *input = wacom_wac->input;
|
|
|
+
|
|
|
+ /* currently, only direct devices have proper hid report descriptors */
|
|
|
+ __set_bit(INPUT_PROP_DIRECT, input->propbit);
|
|
|
+
|
|
|
+ if (WACOM_PEN_FIELD(field))
|
|
|
+ return wacom_wac_pen_usage_mapping(hdev, field, usage);
|
|
|
+}
|
|
|
+
|
|
|
+int wacom_wac_event(struct hid_device *hdev, struct hid_field *field,
|
|
|
+ struct hid_usage *usage, __s32 value)
|
|
|
+{
|
|
|
+ struct wacom *wacom = hid_get_drvdata(hdev);
|
|
|
+
|
|
|
+ if (wacom->wacom_wac.features.type != HID_GENERIC)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (WACOM_PEN_FIELD(field))
|
|
|
+ return wacom_wac_pen_event(hdev, field, usage, value);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+void wacom_wac_report(struct hid_device *hdev, struct hid_report *report)
|
|
|
+{
|
|
|
+ struct wacom *wacom = hid_get_drvdata(hdev);
|
|
|
+ struct wacom_wac *wacom_wac = &wacom->wacom_wac;
|
|
|
+ struct hid_field *field = report->field[0];
|
|
|
+
|
|
|
+ if (wacom_wac->features.type != HID_GENERIC)
|
|
|
+ return;
|
|
|
+
|
|
|
+ if (WACOM_PEN_FIELD(field))
|
|
|
+ return wacom_wac_pen_report(hdev, report);
|
|
|
+}
|
|
|
+
|
|
|
static int wacom_bpt_touch(struct wacom_wac *wacom)
|
|
|
{
|
|
|
struct wacom_features *features = &wacom->features;
|
|
@@ -1746,6 +1916,10 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
|
|
|
|
|
|
input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
|
|
|
|
|
|
+ if (features->type == HID_GENERIC)
|
|
|
+ /* setup has already been done */
|
|
|
+ return 0;
|
|
|
+
|
|
|
__set_bit(BTN_TOUCH, input_dev->keybit);
|
|
|
__set_bit(ABS_MISC, input_dev->absbit);
|
|
|
|
|
@@ -2585,6 +2759,9 @@ static const struct wacom_features wacom_features_0x30C =
|
|
|
.oVid = USB_VENDOR_ID_WACOM, .oPid = 0x30A, .touch_max = 10,
|
|
|
.check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
|
|
|
|
|
|
+static const struct wacom_features wacom_features_HID_ANY_ID =
|
|
|
+ { "Wacom HID", .type = HID_GENERIC };
|
|
|
+
|
|
|
#define USB_DEVICE_WACOM(prod) \
|
|
|
HID_DEVICE(BUS_USB, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\
|
|
|
.driver_data = (kernel_ulong_t)&wacom_features_##prod
|
|
@@ -2729,6 +2906,8 @@ const struct hid_device_id wacom_ids[] = {
|
|
|
{ USB_DEVICE_WACOM(0x4004) },
|
|
|
{ USB_DEVICE_WACOM(0x5000) },
|
|
|
{ USB_DEVICE_WACOM(0x5002) },
|
|
|
+
|
|
|
+ { USB_DEVICE_WACOM(HID_ANY_ID) },
|
|
|
{ }
|
|
|
};
|
|
|
MODULE_DEVICE_TABLE(hid, wacom_ids);
|