support a AUX code events generated from EV_ABS
authorJengHyun Kang <jhyuni.kang@samsung.com>
Tue, 25 Apr 2017 09:51:02 +0000 (18:51 +0900)
committerJihoon Kim <jihoon48.kim@samsung.com>
Tue, 4 Feb 2025 09:32:08 +0000 (18:32 +0900)
Change-Id: I144282f5ddc330eb77b73b3da5a36cedb6af069f

src/evdev-fallback.c
src/evdev-fallback.h
src/evdev.c
src/evdev.h
src/libinput-private.h
src/libinput.c
src/libinput.h
src/libinput.sym

index 38e3c92e058f9a1f15256bfe24c976c98c250335..d66305852ad8dfbdf16901ae7ad442471cc4a7fb 100644 (file)
@@ -165,6 +165,23 @@ fallback_rotate_relative(struct fallback_dispatch *dispatch,
        return rel;
 }
 
+static void
+fallback_flush_extra_aux_data(struct fallback_dispatch *dispatch,
+                                   struct evdev_device *device,
+                                   uint64_t time, int32_t type,
+                                   int32_t slot, int32_t seat_slot)
+{
+       struct libinput_device *base = &device->base;
+       struct mt_aux_data *aux_data;
+
+       list_for_each(aux_data, &dispatch->mt.aux_data_list[slot], link) {
+               if (aux_data->changed) {
+                       touch_notify_aux_data(base, time, slot, seat_slot, aux_data->code, aux_data->value);
+                       aux_data->changed = false;
+               }
+       }
+}
+
 static void
 fallback_flush_relative_motion(struct fallback_dispatch *dispatch,
                               struct evdev_device *device,
@@ -253,6 +270,8 @@ fallback_flush_mt_down(struct fallback_dispatch *dispatch,
        slot->hysteresis_center = point;
        evdev_transform_absolute(device, &point);
 
+       fallback_flush_extra_aux_data(dispatch, device, time,
+                               dispatch->pending_event, slot_idx, seat_slot);
        touch_notify_touch_down(base, time, slot_idx, seat_slot,
                                &point, &slot->area, slot->pressure);
 
@@ -284,6 +303,9 @@ fallback_flush_mt_motion(struct fallback_dispatch *dispatch,
                return false;
 
        evdev_transform_absolute(device, &point);
+
+       fallback_flush_extra_aux_data(dispatch, device, time,
+                                 dispatch->pending_event, slot_idx, seat_slot);
        touch_notify_touch_motion(base, time, slot_idx, seat_slot,
                                  &point, &slot->area, slot->pressure);
 
@@ -313,6 +335,8 @@ fallback_flush_mt_up(struct fallback_dispatch *dispatch,
 
        seat->slot_map &= ~bit(seat_slot);
 
+       fallback_flush_extra_aux_data(dispatch, device, time,
+                               dispatch->pending_event, slot_idx, seat_slot);
        touch_notify_touch_up(base, time, slot_idx, seat_slot);
 
        return true;
@@ -463,6 +487,32 @@ fallback_flush_st_cancel(struct fallback_dispatch *dispatch,
        return true;
 }
 
+static void
+fallback_process_touch_extra_aux_data(struct fallback_dispatch *dispatch,
+                   struct evdev_device *device,
+                   struct input_event *e)
+{
+       struct mt_aux_data *aux_data;
+       struct list *current_axis_list;
+
+       if (!dispatch->mt.aux_data_list) return false;
+
+       current_axis_list = &dispatch->mt.aux_data_list[dispatch->mt.slot];
+       if (!current_axis_list) return false;
+
+       if (list_empty(current_axis_list)) return false;
+
+       list_for_each(aux_data, current_axis_list, link) {
+               if (aux_data->code == e->code) {
+                       if (aux_data->value != e->value) {
+                               aux_data->changed = true;
+                               aux_data->value = e->value;
+                       }
+                       break;
+               }
+       }
+}
+
 static void
 fallback_process_touch_button(struct fallback_dispatch *dispatch,
                              struct evdev_device *device,
@@ -627,6 +677,7 @@ fallback_process_touch(struct fallback_dispatch *dispatch,
                        dispatch->pending_event = EVDEV_ABSOLUTE_MT;
                break;
        default:
+               fallback_process_touch_extra_aux_data(dispatch, device, e);
                break;
        }
 }
@@ -1465,6 +1516,42 @@ static struct evdev_dispatch_interface fallback_interface = {
        .get_switch_state = fallback_interface_get_switch_state,
 };
 
+static void
+fallback_device_interface_set_aux_data(struct evdev_dispatch *evdev_dispatch, uint32_t code)
+{
+       int i;
+       struct fallback_dispatch *dispatch;
+       struct mt_aux_data *aux_data;
+
+       dispatch = fallback_dispatch(evdev_dispatch);
+
+       if (!list_empty(&dispatch->mt.aux_data_list[0])) {
+               list_for_each(aux_data, &dispatch->mt.aux_data_list[0], link) {
+                       if (code == aux_data->code) return;
+               }
+       }
+
+       for (i = 0; i < (int)dispatch->mt.slots_len; i++) {
+               aux_data = calloc(1, sizeof(struct mt_aux_data));
+               if (!aux_data) goto failed;
+               aux_data->code = code;
+               list_insert(&dispatch->mt.aux_data_list[i], &aux_data->link);
+       }
+
+       return;
+failed:
+       for (i = i-1; i >= 0; i--) {
+               list_for_each_safe(aux_data, &dispatch->mt.aux_data_list[i], link) {
+                       list_remove(&aux_data->link);
+                       free(aux_data);
+               }
+       }
+}
+
+struct evdev_dispatch_device_interface fallback_device_interface = {
+       .set_aux_data = fallback_device_interface_set_aux_data
+};
+
 static void
 fallback_change_to_left_handed(struct evdev_device *device)
 {
@@ -1614,6 +1701,16 @@ fallback_dispatch_init_slots(struct fallback_dispatch *dispatch,
                                                        EV_ABS,
                                                        ABS_MT_TOOL_TYPE);
 
+       dispatch->mt.aux_data_list = calloc(num_slots, sizeof(struct list));
+       if (device->mt.aux_data_list) {
+               int i;
+               for (i = 0; i < num_slots; i++) {
+                       list_init(&device->mt.aux_data_list[i]);
+               }
+       }
+       else
+               return -1;
+
        if (device->abs.absinfo_x->fuzz || device->abs.absinfo_y->fuzz) {
                dispatch->mt.want_hysteresis = true;
                dispatch->mt.hysteresis_margin.x = device->abs.absinfo_x->fuzz/2;
@@ -1756,5 +1853,7 @@ fallback_dispatch_create(struct libinput_device *libinput_device)
        fallback_init_debounce(dispatch);
        fallback_init_arbitration(dispatch, device);
 
+       dispatch->base.device_interface = &fallback_device_interface;
+
        return &dispatch->base;
 }
index fd01c752e01f355531e1983ddfbb7bf267915fc7..6c453ca4220e65c60d8fae58a157672feadd3f76 100644 (file)
@@ -84,6 +84,13 @@ struct mt_slot {
        int32_t pressure;
 };
 
+struct mt_aux_data {
+       uint32_t code;
+       int32_t value;
+       bool changed;
+       struct list link;
+};
+
 struct fallback_dispatch {
        struct evdev_dispatch base;
        struct evdev_device *device;
@@ -108,6 +115,7 @@ struct fallback_dispatch {
                bool want_hysteresis;
                struct device_coords hysteresis_margin;
                bool has_palm;
+               struct list *aux_data_list;
        } mt;
 
        struct device_coords rel;
index 99ef7aa8299b4f67eef7deaa566024f96faf9040..9ccefd3043ca15d8dcd16b2d5a8c07e5a36ac325 100644 (file)
@@ -3204,3 +3204,24 @@ evdev_device_destroy(struct evdev_device *device)
        udev_device_unref(device->udev_device);
        free(device);
 }
+
+int
+evdev_device_has_aux_data(struct evdev_device *device, uint32_t code)
+{
+       const struct input_absinfo *absinfo_aux_data;
+       absinfo_aux_data = libevdev_get_abs_info(device->evdev, code);
+
+       return !!absinfo_aux_data;
+}
+
+void
+evdev_device_set_aux_data(struct evdev_device *device, uint32_t code)
+{
+       struct evdev_dispatch *dispatch = device->dispatch;
+       if (!dispatch) return;
+       if (!dispatch->device_interface) return;
+
+       if (dispatch->device_interface->set_auxdata) {
+               dispatch->device_interface->set_auxdata(dispatch, code);
+       }
+}
index 441d92ffcda60c8520a1ad42e35b437d0893940b..1da180e279a7cdc87c61c3a7e0fded8c66fabb4a 100644 (file)
@@ -355,6 +355,10 @@ struct evdev_dispatch_interface {
                                   bool left_handed_enabled);
 };
 
+struct evdev_dispatch_device_interface {
+       void (*set_aux_data) (struct evdev_dispatch *dispatch, uint32_t code);
+};
+
 enum evdev_dispatch_type {
        DISPATCH_FALLBACK,
        DISPATCH_TOUCHPAD,
@@ -371,6 +375,8 @@ struct evdev_dispatch {
                struct libinput_device_config_send_events config;
                enum libinput_config_send_events_mode current_mode;
        } sendevents;
+
+       struct evdev_dispatch_device_interface *device_interface;
 };
 
 static inline void
@@ -1062,4 +1068,10 @@ evdev_paired_keyboard_destroy(struct evdev_paired_keyboard *kbd)
        free(kbd);
 }
 
+int
+evdev_device_has_aux_data(struct evdev_device *device, uint32_t code);
+
+void
+evdev_device_set_aux_data(struct evdev_device *device, uint32_t code);
+
 #endif /* EVDEV_H */
index 4f9ed6a4eb2c0d37af1ff599b69fd50471cad320..451b3b6f6bdd94fb30c9f6dde711241237c602a0 100644 (file)
@@ -758,6 +758,14 @@ void
 touch_notify_frame(struct libinput_device *device,
                   uint64_t time);
 
+void
+touch_notify_aux_data(struct libinput_device *device,
+                         uint64_t time,
+                         int32_t slot,
+                         int32_t seat_slot,
+                         uint32_t code,
+                         int32_t value);
+
 void
 gesture_notify_swipe(struct libinput_device *device,
                     uint64_t time,
index 853d951a69edbfa74109efd343a6f310af1eaec3..d58e0de02ec1474b2e2155282ce5c32436064d65 100644 (file)
@@ -79,6 +79,10 @@ ASSERT_INT_SIZE(enum libinput_config_scroll_method);
 ASSERT_INT_SIZE(enum libinput_config_dwt_state);
 ASSERT_INT_SIZE(enum libinput_config_dwtp_state);
 
+#ifndef ABS_MT_PALM
+#define ABS_MT_PALM 0x3e
+#endif
+
 static inline const char *
 event_type_to_str(enum libinput_event_type type)
 {
@@ -264,6 +268,15 @@ struct libinput_event_switch {
        enum libinput_switch_state state;
 };
 
+struct libinput_event_touch_aux_data {
+       struct libinput_event base;
+       uint32_t time;
+       int32_t slot;
+       int32_t seat_slot;
+       uint32_t code;
+       int32_t value;
+};
+
 LIBINPUT_ATTRIBUTE_PRINTF(3, 0)
 static void
 libinput_default_log_func(struct libinput *libinput,
@@ -1955,6 +1968,135 @@ libinput_event_switch_get_time_usec(struct libinput_event_switch *event)
        return event->time;
 }
 
+LIBINPUT_EXPORT struct libinput_event_touch_aux_data *
+libinput_event_get_touch_aux_data(struct libinput_event *event)
+{
+       switch (event->type) {
+       case LIBINPUT_EVENT_NONE:
+               abort(); /* not used as actual event type */
+       case LIBINPUT_EVENT_DEVICE_ADDED:
+       case LIBINPUT_EVENT_DEVICE_REMOVED:
+       case LIBINPUT_EVENT_KEYBOARD_KEY:
+       case LIBINPUT_EVENT_POINTER_MOTION:
+       case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
+       case LIBINPUT_EVENT_POINTER_BUTTON:
+       case LIBINPUT_EVENT_POINTER_AXIS:
+       case LIBINPUT_EVENT_TOUCH_DOWN:
+       case LIBINPUT_EVENT_TOUCH_UP:
+       case LIBINPUT_EVENT_TOUCH_MOTION:
+       case LIBINPUT_EVENT_TOUCH_CANCEL:
+       case LIBINPUT_EVENT_TOUCH_FRAME:
+               break;
+       case LIBINPUT_EVENT_TOUCH_AUX_DATA:
+               return (struct libinput_event_touch_aux_data *) event;
+       }
+
+       return NULL;
+}
+
+LIBINPUT_EXPORT int
+libinput_event_touch_aux_data_get_code(struct libinput_event_touch_aux_data *event)
+{
+       require_event_type(libinput_event_get_context(&event->base),
+                          event->base.type,
+                          0,
+                          LIBINPUT_EVENT_TOUCH_AUX_DATA);
+
+       return event->code;
+}
+
+LIBINPUT_EXPORT int
+libinput_event_touch_aux_data_get_value(struct libinput_event_touch_aux_data *event)
+{
+       require_event_type(libinput_event_get_context(&event->base),
+                          event->base.type,
+                          0,
+                          LIBINPUT_EVENT_TOUCH_AUX_DATA);
+
+       return event->value;
+}
+
+LIBINPUT_EXPORT int
+libinput_event_touch_aux_data_get_slot(struct libinput_event_touch_aux_data *event)
+{
+       require_event_type(libinput_event_get_context(&event->base),
+                          event->base.type,
+                          0,
+                          LIBINPUT_EVENT_TOUCH_AUX_DATA);
+
+       return event->slot;
+}
+
+LIBINPUT_EXPORT int
+libinput_event_touch_aux_data_get_seat_slot(struct libinput_event_touch_aux_data *event)
+{
+       require_event_type(libinput_event_get_context(&event->base),
+                          event->base.type,
+                          0,
+                          LIBINPUT_EVENT_TOUCH_AUX_DATA);
+
+       return event->seat_slot;
+}
+
+LIBINPUT_EXPORT int
+libinput_event_touch_aux_data_get_time(struct libinput_event_touch_aux_data *event)
+{
+       require_event_type(libinput_event_get_context(&event->base),
+                          event->base.type,
+                          0,
+                          LIBINPUT_EVENT_TOUCH_AUX_DATA);
+
+       return event->time;
+}
+
+LIBINPUT_EXPORT unsigned int
+libinput_event_touch_aux_data_get_type(struct libinput_event_touch_aux_data *event)
+{
+       require_event_type(libinput_event_get_context(&event->base),
+                          event->base.type,
+                          0,
+                          LIBINPUT_EVENT_TOUCH_AUX_DATA);
+
+       if (event->code == ABS_MT_PALM) {
+               return LIBINPUT_TOUCH_AUX_DATA_TYPE_PALM;
+       }
+
+       return LIBINPUT_TOUCH_AUX_DATA_TYPE_UNKNOWN;
+}
+
+
+LIBINPUT_EXPORT int
+libinput_device_touch_has_aux_data(struct libinput_device *device, uint32_t aux_data)
+{
+       if (!evdev_device_has_capability((struct evdev_device *)device,
+                       LIBINPUT_DEVICE_CAP_TOUCH))
+               return 0;
+
+       return evdev_device_has_aux_data((struct evdev_device *)device, aux_data);
+}
+
+LIBINPUT_EXPORT int
+libinput_device_touch_set_aux_data(struct libinput_device *device, uint32_t aux_data)
+{
+       if (!evdev_device_has_capability((struct evdev_device *)device,
+                       LIBINPUT_DEVICE_CAP_TOUCH))
+               return 0;
+
+       evdev_device_set_aux_data((struct evdev_device *)device, aux_data);
+       return 1;
+}
+
+LIBINPUT_EXPORT unsigned int
+libinput_device_touch_aux_data_get_code(enum libinput_touch_aux_data_type type)
+{
+       switch (type) {
+       case LIBINPUT_TOUCH_AUX_DATA_TYPE_PALM:
+               return ABS_MT_PALM;
+       default:
+               return 0;
+       }
+}
+
 struct libinput_source *
 libinput_add_fd(struct libinput *libinput,
                int fd,
@@ -3380,6 +3522,39 @@ switch_notify_toggle(struct libinput_device *device,
 #endif
 }
 
+void
+touch_notify_aux_data(struct libinput_device *device,
+                     uint64_t time,
+                     int32_t slot,
+                     int32_t seat_slot,
+                     uint32_t code,
+                     int32_t value)
+{
+       struct libinput_event_touch_aux_data *touch_aux_data_event;
+
+       TRACE_INPUT_BEGIN(touch_notify_aux_data);
+
+       touch_aux_data_event = zalloc(sizeof *touch_aux_data_event);
+       if (!touch_aux_data_event) {
+               TRACE_INPUT_END();
+               return;
+       }
+
+       *touch_aux_data_event = (struct libinput_event_touch_aux_data) {
+               .time = time,
+               .slot = slot,
+               .seat_slot = seat_slot,
+               .code = code,
+               .value = value,
+       };
+
+       post_device_event(device, time,
+                         LIBINPUT_EVENT_TOUCH_AUX_DATA,
+                         &touch_aux_data_event->base);
+
+       TRACE_INPUT_END();
+}
+
 static void
 libinput_post_event(struct libinput *libinput,
                    struct libinput_event *event)
index d789e073424268f32f63bd2f49309cc5e7c7ffd6..e0ec4a76a0fff90a6b0989480789ea81007e8632 100644 (file)
@@ -144,6 +144,14 @@ struct libinput_event_pointer;
  */
 struct libinput_event_touch;
 
+/**
+ * @ingroup event_touch_aux_data
+ * @struct libinput_event_touch_aux_data
+ *
+ * Support extra touch axis
+ */
+struct libinput_event_touch_aux_data;
+
 /**
  * @ingroup event_tablet
  * @struct libinput_event_tablet_tool
@@ -289,6 +297,11 @@ enum libinput_pointer_axis_source {
        LIBINPUT_POINTER_AXIS_SOURCE_WHEEL_TILT,
 };
 
+enum libinput_touch_aux_data_type {
+       LIBINPUT_TOUCH_AUX_DATA_TYPE_UNKNOWN,
+       LIBINPUT_TOUCH_AUX_DATA_TYPE_PALM,
+};
+
 /**
  * @ingroup event_tablet_pad
  *
@@ -852,6 +865,9 @@ enum libinput_event_type {
         */
        LIBINPUT_EVENT_TOUCH_FRAME,
 
+       LIBINPUT_EVENT_TOUCH_LAST = LIBINPUT_EVENT_TOUCH_FRAME,
+       LIBINPUT_EVENT_TOUCH_AUX_DATA = LIBINPUT_EVENT_TOUCH_LAST + 1,
+
        /**
         * One or more axes have changed state on a device with the @ref
         * LIBINPUT_DEVICE_CAP_TABLET_TOOL capability. This event is only sent
@@ -1109,6 +1125,7 @@ libinput_event_get_keyboard_event(struct libinput_event *event);
 struct libinput_event_touch *
 libinput_event_get_touch_event(struct libinput_event *event);
 
+
 /**
  * @ingroup event
  *
@@ -3741,6 +3758,36 @@ libinput_event_switch_get_switch(struct libinput_event_switch *event);
 enum libinput_switch_state
 libinput_event_switch_get_switch_state(struct libinput_event_switch *event);
 
+struct libinput_event_touch_aux_data *
+libinput_event_get_touch_aux_data(struct libinput_event *event);
+
+int
+libinput_device_touch_has_aux_data(struct libinput_device *device, uint32_t axis);
+
+int
+libinput_device_touch_set_aux_data(struct libinput_device *device, uint32_t axis);
+
+unsigned int
+libinput_device_touch_aux_data_get_code(enum libinput_touch_aux_data_type type);
+
+int
+libinput_event_touch_aux_data_get_code(struct libinput_event_touch_aux_data *event);
+
+int
+libinput_event_touch_aux_data_get_value(struct libinput_event_touch_aux_data *event);
+
+int
+libinput_event_touch_aux_data_get_slot(struct libinput_event_touch_aux_data *event);
+
+int
+libinput_event_touch_aux_data_get_seat_slot(struct libinput_event_touch_aux_data *event);
+
+int
+libinput_event_touch_aux_data_get_time(struct libinput_event_touch_aux_data *event);
+
+unsigned int
+libinput_event_touch_aux_data_get_type(struct libinput_event_touch_aux_data *event);
+
 /**
  * @ingroup event_switch
  *
index de9d743409c6b3fc24095e6030d5a9a0d8337eda..a8266634493a002fee2a7aac0126c5ff0b247f0b 100644 (file)
@@ -190,6 +190,16 @@ LIBINPUT_1.1 {
        libinput_event_touch_has_minor;
        libinput_event_touch_has_orientation;
        libinput_event_touch_has_pressure;
+       libinput_event_get_touch_aux_data;
+       libinput_device_touch_has_aux_data;
+       libinput_device_touch_set_aux_data;
+       libinput_event_touch_aux_data_get_code;
+       libinput_event_touch_aux_data_get_value;
+       libinput_event_touch_aux_data_get_slot;
+       libinput_event_touch_aux_data_get_seat_slot;
+       libinput_event_touch_aux_data_get_time;
+       libinput_event_touch_aux_data_get_type;
+       libinput_device_touch_aux_data_get_code;
 } LIBINPUT_0.21.0;
 
 LIBINPUT_1.2 {