1 /*
2 * Copyright © 2016 Red Hat, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 #include "config.h"
25 #include "evdev-tablet-pad.h"
26
27 #include <assert.h>
28 #include <stdbool.h>
29 #include <string.h>
30
31 #if HAVE_LIBWACOM
32 #include <libwacom/libwacom.h>
33 #endif
34
35 #define pad_set_status(pad_,s_) (pad_)->status |= (s_)
36 #define pad_unset_status(pad_,s_) (pad_)->status &= ~(s_)
37 #define pad_has_status(pad_,s_) (!!((pad_)->status & (s_)))
38
39 static void
pad_get_buttons_pressed(struct pad_dispatch * pad,struct button_state * buttons)40 pad_get_buttons_pressed(struct pad_dispatch *pad,
41 struct button_state *buttons)
42 {
43 struct button_state *state = &pad->button_state;
44 struct button_state *prev_state = &pad->prev_button_state;
45 unsigned int i;
46
47 for (i = 0; i < sizeof(buttons->bits); i++)
48 buttons->bits[i] = state->bits[i] & ~(prev_state->bits[i]);
49 }
50
51 static void
pad_get_buttons_released(struct pad_dispatch * pad,struct button_state * buttons)52 pad_get_buttons_released(struct pad_dispatch *pad,
53 struct button_state *buttons)
54 {
55 struct button_state *state = &pad->button_state;
56 struct button_state *prev_state = &pad->prev_button_state;
57 unsigned int i;
58
59 for (i = 0; i < sizeof(buttons->bits); i++)
60 buttons->bits[i] = prev_state->bits[i] & ~(state->bits[i]);
61 }
62
63 static inline bool
pad_button_is_down(const struct pad_dispatch * pad,uint32_t button)64 pad_button_is_down(const struct pad_dispatch *pad,
65 uint32_t button)
66 {
67 return bit_is_set(pad->button_state.bits, button);
68 }
69
70 static inline bool
pad_any_button_down(const struct pad_dispatch * pad)71 pad_any_button_down(const struct pad_dispatch *pad)
72 {
73 const struct button_state *state = &pad->button_state;
74 unsigned int i;
75
76 for (i = 0; i < sizeof(state->bits); i++)
77 if (state->bits[i] != 0)
78 return true;
79
80 return false;
81 }
82
83 static inline void
pad_button_set_down(struct pad_dispatch * pad,uint32_t button,bool is_down)84 pad_button_set_down(struct pad_dispatch *pad,
85 uint32_t button,
86 bool is_down)
87 {
88 struct button_state *state = &pad->button_state;
89
90 if (is_down) {
91 set_bit(state->bits, button);
92 pad_set_status(pad, PAD_BUTTONS_PRESSED);
93 } else {
94 clear_bit(state->bits, button);
95 pad_set_status(pad, PAD_BUTTONS_RELEASED);
96 }
97 }
98
99 static void
pad_process_absolute(struct pad_dispatch * pad,struct evdev_device * device,struct input_event * e,uint64_t time)100 pad_process_absolute(struct pad_dispatch *pad,
101 struct evdev_device *device,
102 struct input_event *e,
103 uint64_t time)
104 {
105 switch (e->code) {
106 case ABS_WHEEL:
107 pad->changed_axes |= PAD_AXIS_RING1;
108 pad_set_status(pad, PAD_AXES_UPDATED);
109 break;
110 case ABS_THROTTLE:
111 pad->changed_axes |= PAD_AXIS_RING2;
112 pad_set_status(pad, PAD_AXES_UPDATED);
113 break;
114 case ABS_RX:
115 pad->changed_axes |= PAD_AXIS_STRIP1;
116 pad_set_status(pad, PAD_AXES_UPDATED);
117 break;
118 case ABS_RY:
119 pad->changed_axes |= PAD_AXIS_STRIP2;
120 pad_set_status(pad, PAD_AXES_UPDATED);
121 break;
122 case ABS_MISC:
123 /* The wacom driver always sends a 0 axis event on finger
124 up, but we also get an ABS_MISC 15 on touch down and
125 ABS_MISC 0 on touch up, on top of the actual event. This
126 is kernel behavior for xf86-input-wacom backwards
127 compatibility after the 3.17 wacom HID move.
128
129 We use that event to tell when we truly went a full
130 rotation around the wheel vs. a finger release.
131
132 FIXME: On the Intuos5 and later the kernel merges all
133 states into that event, so if any finger is down on any
134 button, the wheel release won't trigger the ABS_MISC 0
135 but still send a 0 event. We can't currently detect this.
136 */
137 pad->have_abs_misc_terminator = true;
138 break;
139 default:
140 evdev_log_info(device,
141 "Unhandled EV_ABS event code %#x\n",
142 e->code);
143 break;
144 }
145 }
146
147 static inline double
normalize_ring(const struct input_absinfo * absinfo)148 normalize_ring(const struct input_absinfo *absinfo)
149 {
150 /* libinput has 0 as the ring's northernmost point in the device's
151 current logical rotation, increasing clockwise to 1. Wacom has
152 0 on the left-most wheel position.
153 */
154 double range = absinfo->maximum - absinfo->minimum + 1;
155 double value = (absinfo->value - absinfo->minimum) / range - 0.25;
156
157 if (value < 0.0)
158 value += 1.0;
159
160 return value;
161 }
162
163 static inline double
normalize_strip(const struct input_absinfo * absinfo)164 normalize_strip(const struct input_absinfo *absinfo)
165 {
166 /* strip axes don't use a proper value, they just shift the bit left
167 * for each position. 0 isn't a real value either, it's only sent on
168 * finger release */
169 double min = 0,
170 max = log2(absinfo->maximum);
171 double range = max - min;
172 double value = (log2(absinfo->value) - min) / range;
173
174 return value;
175 }
176
177 static inline double
pad_handle_ring(struct pad_dispatch * pad,struct evdev_device * device,unsigned int code)178 pad_handle_ring(struct pad_dispatch *pad,
179 struct evdev_device *device,
180 unsigned int code)
181 {
182 const struct input_absinfo *absinfo;
183 double degrees;
184
185 absinfo = libevdev_get_abs_info(device->evdev, code);
186 assert(absinfo);
187
188 degrees = normalize_ring(absinfo) * 360;
189
190 if (device->left_handed.enabled)
191 degrees = fmod(degrees + 180, 360);
192
193 return degrees;
194 }
195
196 static inline double
pad_handle_strip(struct pad_dispatch * pad,struct evdev_device * device,unsigned int code)197 pad_handle_strip(struct pad_dispatch *pad,
198 struct evdev_device *device,
199 unsigned int code)
200 {
201 const struct input_absinfo *absinfo;
202 double pos;
203
204 absinfo = libevdev_get_abs_info(device->evdev, code);
205 assert(absinfo);
206
207 if (absinfo->value == 0)
208 return 0.0;
209
210 pos = normalize_strip(absinfo);
211
212 if (device->left_handed.enabled)
213 pos = 1.0 - pos;
214
215 return pos;
216 }
217
218 static inline struct libinput_tablet_pad_mode_group *
pad_ring_get_mode_group(struct pad_dispatch * pad,unsigned int ring)219 pad_ring_get_mode_group(struct pad_dispatch *pad,
220 unsigned int ring)
221 {
222 struct libinput_tablet_pad_mode_group *group;
223
224 list_for_each(group, &pad->modes.mode_group_list, link) {
225 if (libinput_tablet_pad_mode_group_has_ring(group, ring))
226 return group;
227 }
228
229 assert(!"Unable to find ring mode group");
230
231 return NULL;
232 }
233
234 static inline struct libinput_tablet_pad_mode_group *
pad_strip_get_mode_group(struct pad_dispatch * pad,unsigned int strip)235 pad_strip_get_mode_group(struct pad_dispatch *pad,
236 unsigned int strip)
237 {
238 struct libinput_tablet_pad_mode_group *group;
239
240 list_for_each(group, &pad->modes.mode_group_list, link) {
241 if (libinput_tablet_pad_mode_group_has_strip(group, strip))
242 return group;
243 }
244
245 assert(!"Unable to find strip mode group");
246
247 return NULL;
248 }
249
250 static void
pad_check_notify_axes(struct pad_dispatch * pad,struct evdev_device * device,uint64_t time)251 pad_check_notify_axes(struct pad_dispatch *pad,
252 struct evdev_device *device,
253 uint64_t time)
254 {
255 struct libinput_device *base = &device->base;
256 struct libinput_tablet_pad_mode_group *group;
257 double value;
258 bool send_finger_up = false;
259
260 /* Suppress the reset to 0 on finger up. See the
261 comment in pad_process_absolute */
262 if (pad->have_abs_misc_terminator &&
263 libevdev_get_event_value(device->evdev, EV_ABS, ABS_MISC) == 0)
264 send_finger_up = true;
265
266 if (pad->changed_axes & PAD_AXIS_RING1) {
267 value = pad_handle_ring(pad, device, ABS_WHEEL);
268 if (send_finger_up)
269 value = -1.0;
270
271 group = pad_ring_get_mode_group(pad, 0);
272 tablet_pad_notify_ring(base,
273 time,
274 0,
275 value,
276 LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER,
277 group);
278 }
279
280 if (pad->changed_axes & PAD_AXIS_RING2) {
281 value = pad_handle_ring(pad, device, ABS_THROTTLE);
282 if (send_finger_up)
283 value = -1.0;
284
285 group = pad_ring_get_mode_group(pad, 1);
286 tablet_pad_notify_ring(base,
287 time,
288 1,
289 value,
290 LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER,
291 group);
292 }
293
294 if (pad->changed_axes & PAD_AXIS_STRIP1) {
295 value = pad_handle_strip(pad, device, ABS_RX);
296 if (send_finger_up)
297 value = -1.0;
298
299 group = pad_strip_get_mode_group(pad, 0);
300 tablet_pad_notify_strip(base,
301 time,
302 0,
303 value,
304 LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER,
305 group);
306 }
307
308 if (pad->changed_axes & PAD_AXIS_STRIP2) {
309 value = pad_handle_strip(pad, device, ABS_RY);
310 if (send_finger_up)
311 value = -1.0;
312
313 group = pad_strip_get_mode_group(pad, 1);
314 tablet_pad_notify_strip(base,
315 time,
316 1,
317 value,
318 LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER,
319 group);
320 }
321
322 pad->changed_axes = PAD_AXIS_NONE;
323 pad->have_abs_misc_terminator = false;
324 }
325
326 static void
pad_process_key(struct pad_dispatch * pad,struct evdev_device * device,struct input_event * e,uint64_t time)327 pad_process_key(struct pad_dispatch *pad,
328 struct evdev_device *device,
329 struct input_event *e,
330 uint64_t time)
331 {
332 uint32_t button = e->code;
333 uint32_t is_press = e->value != 0;
334
335 pad_button_set_down(pad, button, is_press);
336 }
337
338 static inline struct libinput_tablet_pad_mode_group *
pad_button_get_mode_group(struct pad_dispatch * pad,unsigned int button)339 pad_button_get_mode_group(struct pad_dispatch *pad,
340 unsigned int button)
341 {
342 struct libinput_tablet_pad_mode_group *group;
343
344 list_for_each(group, &pad->modes.mode_group_list, link) {
345 if (libinput_tablet_pad_mode_group_has_button(group, button))
346 return group;
347 }
348
349 assert(!"Unable to find button mode group\n");
350
351 return NULL;
352 }
353
354 static void
pad_notify_button_mask(struct pad_dispatch * pad,struct evdev_device * device,uint64_t time,const struct button_state * buttons,enum libinput_button_state state)355 pad_notify_button_mask(struct pad_dispatch *pad,
356 struct evdev_device *device,
357 uint64_t time,
358 const struct button_state *buttons,
359 enum libinput_button_state state)
360 {
361 struct libinput_device *base = &device->base;
362 struct libinput_tablet_pad_mode_group *group;
363 int32_t code;
364 unsigned int i;
365
366 for (i = 0; i < sizeof(buttons->bits); i++) {
367 unsigned char buttons_slice = buttons->bits[i];
368
369 code = i * 8;
370 while (buttons_slice) {
371 int enabled;
372 char map;
373
374 code++;
375 enabled = (buttons_slice & 1);
376 buttons_slice >>= 1;
377
378 if (!enabled)
379 continue;
380
381 map = pad->button_map[code - 1];
382 if (map != -1) {
383 group = pad_button_get_mode_group(pad, map);
384 pad_button_update_mode(group, map, state);
385 tablet_pad_notify_button(base, time, map, state, group);
386 }
387 }
388 }
389 }
390
391 static void
pad_notify_buttons(struct pad_dispatch * pad,struct evdev_device * device,uint64_t time,enum libinput_button_state state)392 pad_notify_buttons(struct pad_dispatch *pad,
393 struct evdev_device *device,
394 uint64_t time,
395 enum libinput_button_state state)
396 {
397 struct button_state buttons;
398
399 if (state == LIBINPUT_BUTTON_STATE_PRESSED)
400 pad_get_buttons_pressed(pad, &buttons);
401 else
402 pad_get_buttons_released(pad, &buttons);
403
404 pad_notify_button_mask(pad, device, time, &buttons, state);
405 }
406
407 static void
pad_change_to_left_handed(struct evdev_device * device)408 pad_change_to_left_handed(struct evdev_device *device)
409 {
410 struct pad_dispatch *pad = (struct pad_dispatch*)device->dispatch;
411
412 if (device->left_handed.enabled == device->left_handed.want_enabled)
413 return;
414
415 if (pad_any_button_down(pad))
416 return;
417
418 device->left_handed.enabled = device->left_handed.want_enabled;
419 }
420
421 static void
pad_flush(struct pad_dispatch * pad,struct evdev_device * device,uint64_t time)422 pad_flush(struct pad_dispatch *pad,
423 struct evdev_device *device,
424 uint64_t time)
425 {
426 if (pad_has_status(pad, PAD_AXES_UPDATED)) {
427 pad_check_notify_axes(pad, device, time);
428 pad_unset_status(pad, PAD_AXES_UPDATED);
429 }
430
431 if (pad_has_status(pad, PAD_BUTTONS_RELEASED)) {
432 pad_notify_buttons(pad,
433 device,
434 time,
435 LIBINPUT_BUTTON_STATE_RELEASED);
436 pad_unset_status(pad, PAD_BUTTONS_RELEASED);
437
438 pad_change_to_left_handed(device);
439 }
440
441 if (pad_has_status(pad, PAD_BUTTONS_PRESSED)) {
442 pad_notify_buttons(pad,
443 device,
444 time,
445 LIBINPUT_BUTTON_STATE_PRESSED);
446 pad_unset_status(pad, PAD_BUTTONS_PRESSED);
447 }
448
449 /* Update state */
450 memcpy(&pad->prev_button_state,
451 &pad->button_state,
452 sizeof(pad->button_state));
453 }
454
455 static void
pad_process(struct evdev_dispatch * dispatch,struct evdev_device * device,struct input_event * e,uint64_t time)456 pad_process(struct evdev_dispatch *dispatch,
457 struct evdev_device *device,
458 struct input_event *e,
459 uint64_t time)
460 {
461 struct pad_dispatch *pad = pad_dispatch(dispatch);
462
463 switch (e->type) {
464 case EV_ABS:
465 pad_process_absolute(pad, device, e, time);
466 break;
467 case EV_KEY:
468 pad_process_key(pad, device, e, time);
469 break;
470 case EV_SYN:
471 pad_flush(pad, device, time);
472 break;
473 case EV_MSC:
474 /* The EKR sends the serial as MSC_SERIAL, ignore this for
475 * now */
476 break;
477 default:
478 evdev_log_error(device,
479 "Unexpected event type %s (%#x)\n",
480 libevdev_event_type_get_name(e->type),
481 e->type);
482 break;
483 }
484 }
485
486 static void
pad_suspend(struct evdev_dispatch * dispatch,struct evdev_device * device)487 pad_suspend(struct evdev_dispatch *dispatch,
488 struct evdev_device *device)
489 {
490 struct pad_dispatch *pad = pad_dispatch(dispatch);
491 struct libinput *libinput = pad_libinput_context(pad);
492 unsigned int code;
493
494 for (code = KEY_ESC; code < KEY_CNT; code++) {
495 if (pad_button_is_down(pad, code))
496 pad_button_set_down(pad, code, false);
497 }
498
499 pad_flush(pad, device, libinput_now(libinput));
500 }
501
502 static void
pad_destroy(struct evdev_dispatch * dispatch)503 pad_destroy(struct evdev_dispatch *dispatch)
504 {
505 struct pad_dispatch *pad = pad_dispatch(dispatch);
506
507 pad_destroy_leds(pad);
508 free(pad);
509 }
510
511 static struct evdev_dispatch_interface pad_interface = {
512 .process = pad_process,
513 .suspend = pad_suspend,
514 .remove = NULL,
515 .destroy = pad_destroy,
516 .device_added = NULL,
517 .device_removed = NULL,
518 .device_suspended = NULL,
519 .device_resumed = NULL,
520 .post_added = NULL,
521 .toggle_touch = NULL,
522 .get_switch_state = NULL,
523 };
524
525 static bool
pad_init_buttons_from_libwacom(struct pad_dispatch * pad,struct evdev_device * device)526 pad_init_buttons_from_libwacom(struct pad_dispatch *pad,
527 struct evdev_device *device)
528 {
529 bool rc = false;
530 #if HAVE_LIBWACOM_GET_BUTTON_EVDEV_CODE
531 WacomDeviceDatabase *db = NULL;
532 WacomDevice *tablet = NULL;
533 int num_buttons;
534 int map = 0;
535
536 db = libwacom_database_new();
537 if (!db) {
538 evdev_log_info(device,
539 "Failed to initialize libwacom context.\n");
540 goto out;
541 }
542
543 tablet = libwacom_new_from_usbid(db,
544 evdev_device_get_id_vendor(device),
545 evdev_device_get_id_product(device),
546 NULL);
547 if (!tablet)
548 goto out;
549
550 num_buttons = libwacom_get_num_buttons(tablet);
551 for (int i = 0; i < num_buttons; i++) {
552 unsigned int code;
553
554 code = libwacom_get_button_evdev_code(tablet, 'A' + i);
555 if (code == 0)
556 continue;
557
558 pad->button_map[code] = map++;
559 }
560
561 pad->nbuttons = map;
562
563 rc = true;
564 out:
565 if (tablet)
566 libwacom_destroy(tablet);
567 if (db)
568 libwacom_database_destroy(db);
569 #endif
570 return rc;
571 }
572
573 static void
pad_init_buttons_from_kernel(struct pad_dispatch * pad,struct evdev_device * device)574 pad_init_buttons_from_kernel(struct pad_dispatch *pad,
575 struct evdev_device *device)
576 {
577 unsigned int code;
578 int map = 0;
579
580 /* we match wacom_report_numbered_buttons() from the kernel */
581 for (code = BTN_0; code < BTN_0 + 10; code++) {
582 if (libevdev_has_event_code(device->evdev, EV_KEY, code))
583 pad->button_map[code] = map++;
584 }
585
586 for (code = BTN_BASE; code < BTN_BASE + 2; code++) {
587 if (libevdev_has_event_code(device->evdev, EV_KEY, code))
588 pad->button_map[code] = map++;
589 }
590
591 for (code = BTN_A; code < BTN_A + 6; code++) {
592 if (libevdev_has_event_code(device->evdev, EV_KEY, code))
593 pad->button_map[code] = map++;
594 }
595
596 for (code = BTN_LEFT; code < BTN_LEFT + 7; code++) {
597 if (libevdev_has_event_code(device->evdev, EV_KEY, code))
598 pad->button_map[code] = map++;
599 }
600
601 pad->nbuttons = map;
602 }
603
604 static void
pad_init_buttons(struct pad_dispatch * pad,struct evdev_device * device)605 pad_init_buttons(struct pad_dispatch *pad,
606 struct evdev_device *device)
607 {
608 size_t i;
609
610 for (i = 0; i < ARRAY_LENGTH(pad->button_map); i++)
611 pad->button_map[i] = -1;
612
613 if (!pad_init_buttons_from_libwacom(pad, device))
614 pad_init_buttons_from_kernel(pad, device);
615
616 }
617
618 static void
pad_init_left_handed(struct evdev_device * device)619 pad_init_left_handed(struct evdev_device *device)
620 {
621 if (evdev_tablet_has_left_handed(device))
622 evdev_init_left_handed(device,
623 pad_change_to_left_handed);
624 }
625
626 static int
pad_init(struct pad_dispatch * pad,struct evdev_device * device)627 pad_init(struct pad_dispatch *pad, struct evdev_device *device)
628 {
629 pad->base.dispatch_type = DISPATCH_TABLET_PAD;
630 pad->base.interface = &pad_interface;
631 pad->device = device;
632 pad->status = PAD_NONE;
633 pad->changed_axes = PAD_AXIS_NONE;
634
635 pad_init_buttons(pad, device);
636 pad_init_left_handed(device);
637 if (pad_init_leds(pad, device) != 0)
638 return 1;
639
640 return 0;
641 }
642
643 static uint32_t
pad_sendevents_get_modes(struct libinput_device * device)644 pad_sendevents_get_modes(struct libinput_device *device)
645 {
646 return LIBINPUT_CONFIG_SEND_EVENTS_DISABLED;
647 }
648
649 static enum libinput_config_status
pad_sendevents_set_mode(struct libinput_device * device,enum libinput_config_send_events_mode mode)650 pad_sendevents_set_mode(struct libinput_device *device,
651 enum libinput_config_send_events_mode mode)
652 {
653 struct evdev_device *evdev = evdev_device(device);
654 struct pad_dispatch *pad = (struct pad_dispatch*)evdev->dispatch;
655
656 if (mode == pad->sendevents.current_mode)
657 return LIBINPUT_CONFIG_STATUS_SUCCESS;
658
659 switch(mode) {
660 case LIBINPUT_CONFIG_SEND_EVENTS_ENABLED:
661 break;
662 case LIBINPUT_CONFIG_SEND_EVENTS_DISABLED:
663 pad_suspend(evdev->dispatch, evdev);
664 break;
665 default:
666 return LIBINPUT_CONFIG_STATUS_UNSUPPORTED;
667 }
668
669 pad->sendevents.current_mode = mode;
670
671 return LIBINPUT_CONFIG_STATUS_SUCCESS;
672 }
673
674 static enum libinput_config_send_events_mode
pad_sendevents_get_mode(struct libinput_device * device)675 pad_sendevents_get_mode(struct libinput_device *device)
676 {
677 struct evdev_device *evdev = evdev_device(device);
678 struct pad_dispatch *dispatch = (struct pad_dispatch*)evdev->dispatch;
679
680 return dispatch->sendevents.current_mode;
681 }
682
683 static enum libinput_config_send_events_mode
pad_sendevents_get_default_mode(struct libinput_device * device)684 pad_sendevents_get_default_mode(struct libinput_device *device)
685 {
686 return LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
687 }
688
689 struct evdev_dispatch *
evdev_tablet_pad_create(struct evdev_device * device)690 evdev_tablet_pad_create(struct evdev_device *device)
691 {
692 struct pad_dispatch *pad;
693
694 pad = zalloc(sizeof *pad);
695
696 if (pad_init(pad, device) != 0) {
697 pad_destroy(&pad->base);
698 return NULL;
699 }
700
701 device->base.config.sendevents = &pad->sendevents.config;
702 pad->sendevents.current_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
703 pad->sendevents.config.get_modes = pad_sendevents_get_modes;
704 pad->sendevents.config.set_mode = pad_sendevents_set_mode;
705 pad->sendevents.config.get_mode = pad_sendevents_get_mode;
706 pad->sendevents.config.get_default_mode = pad_sendevents_get_default_mode;
707
708 return &pad->base;
709 }
710
711 int
evdev_device_tablet_pad_get_num_buttons(struct evdev_device * device)712 evdev_device_tablet_pad_get_num_buttons(struct evdev_device *device)
713 {
714 struct pad_dispatch *pad = (struct pad_dispatch*)device->dispatch;
715
716 if (!(device->seat_caps & EVDEV_DEVICE_TABLET_PAD))
717 return -1;
718
719 return pad->nbuttons;
720 }
721
722 int
evdev_device_tablet_pad_get_num_rings(struct evdev_device * device)723 evdev_device_tablet_pad_get_num_rings(struct evdev_device *device)
724 {
725 int nrings = 0;
726
727 if (!(device->seat_caps & EVDEV_DEVICE_TABLET_PAD))
728 return -1;
729
730 if (libevdev_has_event_code(device->evdev, EV_ABS, ABS_WHEEL)) {
731 nrings++;
732 if (libevdev_has_event_code(device->evdev,
733 EV_ABS,
734 ABS_THROTTLE))
735 nrings++;
736 }
737
738 return nrings;
739 }
740
741 int
evdev_device_tablet_pad_get_num_strips(struct evdev_device * device)742 evdev_device_tablet_pad_get_num_strips(struct evdev_device *device)
743 {
744 int nstrips = 0;
745
746 if (!(device->seat_caps & EVDEV_DEVICE_TABLET_PAD))
747 return -1;
748
749 if (libevdev_has_event_code(device->evdev, EV_ABS, ABS_RX)) {
750 nstrips++;
751 if (libevdev_has_event_code(device->evdev,
752 EV_ABS,
753 ABS_RY))
754 nstrips++;
755 }
756
757 return nstrips;
758 }
759