touchpad: Clear touches being the pointer when doing 2 finger scrolling
[platform/upstream/libinput.git] / src / evdev-mt-touchpad.c
1 /*
2  * Copyright © 2014 Red Hat, Inc.
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and
5  * its documentation for any purpose is hereby granted without fee, provided
6  * that the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of the copyright holders not be used in
9  * advertising or publicity pertaining to distribution of the software
10  * without specific, written prior permission.  The copyright holders make
11  * no representations about the suitability of this software for any
12  * purpose.  It is provided "as is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  */
22
23 #include "config.h"
24
25 #include <assert.h>
26 #include <math.h>
27 #include <stdbool.h>
28
29 #include "evdev-mt-touchpad.h"
30
31 #define DEFAULT_CONSTANT_ACCEL_NUMERATOR 100
32 #define DEFAULT_MIN_ACCEL_FACTOR 0.20
33 #define DEFAULT_MAX_ACCEL_FACTOR 0.40
34 #define DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR 700.0
35
36 static inline int
37 tp_hysteresis(int in, int center, int margin)
38 {
39         int diff = in - center;
40         if (abs(diff) <= margin)
41                 return center;
42
43         if (diff > margin)
44                 return center + diff - margin;
45         else if (diff < -margin)
46                 return center + diff + margin;
47         return center + diff;
48 }
49
50 static double
51 tp_accel_profile(struct motion_filter *filter,
52                  void *data,
53                  double velocity,
54                  uint64_t time)
55 {
56         struct tp_dispatch *tp =
57                 (struct tp_dispatch *) data;
58
59         double accel_factor;
60
61         accel_factor = velocity * tp->accel.constant_factor;
62
63         if (accel_factor > tp->accel.max_factor)
64                 accel_factor = tp->accel.max_factor;
65         else if (accel_factor < tp->accel.min_factor)
66                 accel_factor = tp->accel.min_factor;
67
68         return accel_factor;
69 }
70
71 static inline struct tp_motion *
72 tp_motion_history_offset(struct tp_touch *t, int offset)
73 {
74         int offset_index =
75                 (t->history.index - offset + TOUCHPAD_HISTORY_LENGTH) %
76                 TOUCHPAD_HISTORY_LENGTH;
77
78         return &t->history.samples[offset_index];
79 }
80
81 static void
82 tp_filter_motion(struct tp_dispatch *tp,
83                  double *dx, double *dy, uint64_t time)
84 {
85         struct motion_params motion;
86
87         motion.dx = *dx;
88         motion.dy = *dy;
89
90         filter_dispatch(tp->filter, &motion, tp, time);
91
92         *dx = motion.dx;
93         *dy = motion.dy;
94 }
95
96 static inline void
97 tp_motion_history_push(struct tp_touch *t)
98 {
99         int motion_index = (t->history.index + 1) % TOUCHPAD_HISTORY_LENGTH;
100
101         if (t->history.count < TOUCHPAD_HISTORY_LENGTH)
102                 t->history.count++;
103
104         t->history.samples[motion_index].x = t->x;
105         t->history.samples[motion_index].y = t->y;
106         t->history.index = motion_index;
107 }
108
109 static inline void
110 tp_motion_hysteresis(struct tp_dispatch *tp,
111                      struct tp_touch *t)
112 {
113         int x = t->x,
114             y = t->y;
115
116         if (t->history.count == 0) {
117                 t->hysteresis.center_x = t->x;
118                 t->hysteresis.center_y = t->y;
119         } else {
120                 x = tp_hysteresis(x,
121                                   t->hysteresis.center_x,
122                                   tp->hysteresis.margin_x);
123                 y = tp_hysteresis(y,
124                                   t->hysteresis.center_y,
125                                   tp->hysteresis.margin_y);
126                 t->hysteresis.center_x = x;
127                 t->hysteresis.center_y = y;
128                 t->x = x;
129                 t->y = y;
130         }
131 }
132
133 static inline void
134 tp_motion_history_reset(struct tp_touch *t)
135 {
136         t->history.count = 0;
137 }
138
139 static inline struct tp_touch *
140 tp_current_touch(struct tp_dispatch *tp)
141 {
142         return &tp->touches[min(tp->slot, tp->ntouches)];
143 }
144
145 static inline struct tp_touch *
146 tp_get_touch(struct tp_dispatch *tp, unsigned int slot)
147 {
148         assert(slot < tp->ntouches);
149         return &tp->touches[slot];
150 }
151
152 static inline void
153 tp_begin_touch(struct tp_dispatch *tp, struct tp_touch *t)
154 {
155         if (t->state != TOUCH_UPDATE) {
156                 tp_motion_history_reset(t);
157                 t->dirty = true;
158                 t->state = TOUCH_BEGIN;
159                 t->pinned.is_pinned = false;
160                 tp->nfingers_down++;
161                 assert(tp->nfingers_down >= 1);
162                 tp->queued |= TOUCHPAD_EVENT_MOTION;
163         }
164 }
165
166 static inline void
167 tp_end_touch(struct tp_dispatch *tp, struct tp_touch *t)
168 {
169         if (t->state == TOUCH_NONE)
170                 return;
171
172         t->dirty = true;
173         t->is_pointer = false;
174         t->state = TOUCH_END;
175         t->pinned.is_pinned = false;
176         assert(tp->nfingers_down >= 1);
177         tp->nfingers_down--;
178         tp->queued |= TOUCHPAD_EVENT_MOTION;
179 }
180
181 static double
182 tp_estimate_delta(int x0, int x1, int x2, int x3)
183 {
184         return (x0 + x1 - x2 - x3) / 4;
185 }
186
187 void
188 tp_get_delta(struct tp_touch *t, double *dx, double *dy)
189 {
190         if (t->history.count < 4) {
191                 *dx = 0;
192                 *dy = 0;
193                 return;
194         }
195
196         *dx = tp_estimate_delta(tp_motion_history_offset(t, 0)->x,
197                                 tp_motion_history_offset(t, 1)->x,
198                                 tp_motion_history_offset(t, 2)->x,
199                                 tp_motion_history_offset(t, 3)->x);
200         *dy = tp_estimate_delta(tp_motion_history_offset(t, 0)->y,
201                                 tp_motion_history_offset(t, 1)->y,
202                                 tp_motion_history_offset(t, 2)->y,
203                                 tp_motion_history_offset(t, 3)->y);
204 }
205
206 static void
207 tp_process_absolute(struct tp_dispatch *tp,
208                     const struct input_event *e,
209                     uint64_t time)
210 {
211         struct tp_touch *t = tp_current_touch(tp);
212
213         switch(e->code) {
214         case ABS_MT_POSITION_X:
215                 t->x = e->value;
216                 t->millis = time;
217                 t->dirty = true;
218                 tp->queued |= TOUCHPAD_EVENT_MOTION;
219                 break;
220         case ABS_MT_POSITION_Y:
221                 t->y = e->value;
222                 t->millis = time;
223                 t->dirty = true;
224                 tp->queued |= TOUCHPAD_EVENT_MOTION;
225                 break;
226         case ABS_MT_SLOT:
227                 tp->slot = e->value;
228                 break;
229         case ABS_MT_TRACKING_ID:
230                 t->millis = time;
231                 if (e->value != -1)
232                         tp_begin_touch(tp, t);
233                 else
234                         tp_end_touch(tp, t);
235         }
236 }
237
238 static void
239 tp_process_absolute_st(struct tp_dispatch *tp,
240                        const struct input_event *e,
241                        uint64_t time)
242 {
243         struct tp_touch *t = tp_current_touch(tp);
244
245         switch(e->code) {
246         case ABS_X:
247                 t->x = e->value;
248                 t->millis = time;
249                 t->dirty = true;
250                 tp->queued |= TOUCHPAD_EVENT_MOTION;
251                 break;
252         case ABS_Y:
253                 t->y = e->value;
254                 t->millis = time;
255                 t->dirty = true;
256                 tp->queued |= TOUCHPAD_EVENT_MOTION;
257                 break;
258         }
259 }
260
261 static void
262 tp_process_fake_touch(struct tp_dispatch *tp,
263                       const struct input_event *e,
264                       uint64_t time)
265 {
266         struct tp_touch *t;
267         unsigned int fake_touches;
268         unsigned int nfake_touches;
269         unsigned int i;
270         unsigned int shift;
271
272         if (e->code != BTN_TOUCH &&
273             (e->code < BTN_TOOL_DOUBLETAP || e->code > BTN_TOOL_QUADTAP))
274                 return;
275
276         shift = e->code == BTN_TOUCH ? 0 : (e->code - BTN_TOOL_DOUBLETAP + 1);
277
278         if (e->value)
279                 tp->fake_touches |= 1 << shift;
280         else
281                 tp->fake_touches &= ~(0x1 << shift);
282
283         fake_touches = tp->fake_touches;
284         nfake_touches = 0;
285         while (fake_touches) {
286                 nfake_touches++;
287                 fake_touches >>= 1;
288         }
289
290         for (i = 0; i < tp->ntouches; i++) {
291                 t = tp_get_touch(tp, i);
292                 if (i >= nfake_touches) {
293                         if (t->state != TOUCH_NONE) {
294                                 tp_end_touch(tp, t);
295                                 t->millis = time;
296                         }
297                 } else if (t->state != TOUCH_UPDATE &&
298                            t->state != TOUCH_BEGIN) {
299                         t->state = TOUCH_NONE;
300                         tp_begin_touch(tp, t);
301                         t->millis = time;
302                         t->fake =true;
303                 }
304         }
305
306         assert(tp->nfingers_down == nfake_touches);
307 }
308
309 static void
310 tp_process_key(struct tp_dispatch *tp,
311                const struct input_event *e,
312                uint64_t time)
313 {
314         switch (e->code) {
315                 case BTN_LEFT:
316                 case BTN_MIDDLE:
317                 case BTN_RIGHT:
318                         tp_process_button(tp, e, time);
319                         break;
320                 case BTN_TOUCH:
321                 case BTN_TOOL_DOUBLETAP:
322                 case BTN_TOOL_TRIPLETAP:
323                 case BTN_TOOL_QUADTAP:
324                         if (!tp->has_mt)
325                                 tp_process_fake_touch(tp, e, time);
326                         break;
327         }
328 }
329
330 static void
331 tp_unpin_finger(struct tp_dispatch *tp, struct tp_touch *t)
332 {
333         unsigned int xdist, ydist;
334
335         if (!t->pinned.is_pinned)
336                 return;
337
338         xdist = abs(t->x - t->pinned.center_x);
339         ydist = abs(t->y - t->pinned.center_y);
340
341         if (xdist * xdist + ydist * ydist >=
342                         tp->buttons.motion_dist * tp->buttons.motion_dist) {
343                 t->pinned.is_pinned = false;
344                 tp_set_pointer(tp, t);
345         }
346 }
347
348 static void
349 tp_pin_fingers(struct tp_dispatch *tp)
350 {
351         struct tp_touch *t;
352
353         tp_for_each_touch(tp, t) {
354                 t->is_pointer = false;
355                 t->pinned.is_pinned = true;
356                 t->pinned.center_x = t->x;
357                 t->pinned.center_y = t->y;
358         }
359 }
360
361 static int
362 tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t)
363 {
364         return (t->state == TOUCH_BEGIN || t->state == TOUCH_UPDATE) &&
365                 !t->pinned.is_pinned && tp_button_touch_active(tp, t);
366 }
367
368 void
369 tp_set_pointer(struct tp_dispatch *tp, struct tp_touch *t)
370 {
371         struct tp_touch *tmp = NULL;
372
373         /* Only set the touch as pointer if we don't have one yet */
374         tp_for_each_touch(tp, tmp) {
375                 if (tmp->is_pointer)
376                         return;
377         }
378
379         if (tp_touch_active(tp, t))
380                 t->is_pointer = true;
381 }
382
383 static void
384 tp_process_state(struct tp_dispatch *tp, uint64_t time)
385 {
386         struct tp_touch *t;
387         struct tp_touch *first = tp_get_touch(tp, 0);
388
389         tp_for_each_touch(tp, t) {
390                 if (!tp->has_mt && t != first && first->fake) {
391                         t->x = first->x;
392                         t->y = first->y;
393                         if (!t->dirty)
394                                 t->dirty = first->dirty;
395                 } else if (!t->dirty)
396                         continue;
397
398                 tp_motion_hysteresis(tp, t);
399                 tp_motion_history_push(t);
400
401                 tp_unpin_finger(tp, t);
402         }
403
404         tp_button_handle_state(tp, time);
405
406         /*
407          * We have a physical button down event on a clickpad. To avoid
408          * spurious pointer moves by the clicking finger we pin all fingers.
409          * We unpin fingers when they move more then a certain threshold to
410          * to allow drag and drop.
411          */
412         if ((tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS) &&
413             tp->buttons.is_clickpad)
414                 tp_pin_fingers(tp);
415 }
416
417 static void
418 tp_post_process_state(struct tp_dispatch *tp, uint64_t time)
419 {
420         struct tp_touch *t;
421
422         tp_for_each_touch(tp, t) {
423                 if (!t->dirty)
424                         continue;
425
426                 if (t->state == TOUCH_END) {
427                         t->state = TOUCH_NONE;
428                         t->fake = false;
429                 } else if (t->state == TOUCH_BEGIN)
430                         t->state = TOUCH_UPDATE;
431
432                 t->dirty = false;
433         }
434
435         tp->buttons.old_state = tp->buttons.state;
436
437         tp->queued = TOUCHPAD_EVENT_NONE;
438 }
439
440 static void
441 tp_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
442 {
443         struct tp_touch *t;
444         int nchanged = 0;
445         double dx = 0, dy =0;
446         double tmpx, tmpy;
447
448         tp_for_each_touch(tp, t) {
449                 if (tp_touch_active(tp, t) && t->dirty) {
450                         nchanged++;
451                         tp_get_delta(t, &tmpx, &tmpy);
452
453                         dx += tmpx;
454                         dy += tmpy;
455                 }
456         }
457
458         if (nchanged == 0)
459                 return;
460
461         dx /= nchanged;
462         dy /= nchanged;
463
464         tp_filter_motion(tp, &dx, &dy, time);
465
466         if (tp->scroll.state == SCROLL_STATE_NONE) {
467                 /* Require at least one px scrolling to start */
468                 if (dx <= -1.0 || dx >= 1.0) {
469                         tp->scroll.state = SCROLL_STATE_SCROLLING;
470                         tp->scroll.direction |= (1 << LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL);
471                 }
472
473                 if (dy <= -1.0 || dy >= 1.0) {
474                         tp->scroll.state = SCROLL_STATE_SCROLLING;
475                         tp->scroll.direction |= (1 << LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL);
476                 }
477
478                 if (tp->scroll.state == SCROLL_STATE_NONE)
479                         return;
480         }
481
482         /* Stop spurious MOTION events at the end of scrolling */
483         tp_for_each_touch(tp, t)
484                 t->is_pointer = false;
485
486         if (dy != 0.0 &&
487             (tp->scroll.direction & (1 << LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL))) {
488                 pointer_notify_axis(&tp->device->base,
489                                     time,
490                                     LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL,
491                                     li_fixed_from_double(dy));
492         }
493
494         if (dx != 0.0 &&
495             (tp->scroll.direction & (1 << LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL))) {
496                 pointer_notify_axis(&tp->device->base,
497                                     time,
498                                     LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL,
499                                     li_fixed_from_double(dx));
500         }
501 }
502
503 static int
504 tp_post_scroll_events(struct tp_dispatch *tp, uint64_t time)
505 {
506         struct tp_touch *t;
507         int nfingers_down = 0;
508
509         /* Only count active touches for 2 finger scrolling */
510         tp_for_each_touch(tp, t) {
511                 if (tp_touch_active(tp, t))
512                         nfingers_down++;
513         }
514
515         if (nfingers_down != 2) {
516                 /* terminate scrolling with a zero scroll event to notify
517                  * caller that it really ended now */
518                 if (tp->scroll.state != SCROLL_STATE_NONE) {
519                         tp->scroll.state = SCROLL_STATE_NONE;
520                         tp->scroll.direction = 0;
521                         if (tp->scroll.direction & LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL)
522                                 pointer_notify_axis(&tp->device->base,
523                                                     time,
524                                                     LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL,
525                                                     0);
526                         if (tp->scroll.direction & LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL)
527                                 pointer_notify_axis(&tp->device->base,
528                                                     time,
529                                                     LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL,
530                                                     0);
531                 }
532         } else {
533                 tp_post_twofinger_scroll(tp, time);
534                 return 1;
535         }
536         return 0;
537 }
538
539 static void
540 tp_post_events(struct tp_dispatch *tp, uint64_t time)
541 {
542         struct tp_touch *t = tp_current_touch(tp);
543         double dx, dy;
544
545         if (tp_post_button_events(tp, time) != 0)
546                 return;
547
548         if (tp_tap_handle_state(tp, time) != 0)
549                 return;
550
551         if (tp_post_scroll_events(tp, time) != 0)
552                 return;
553
554         if (t->history.count >= TOUCHPAD_MIN_SAMPLES) {
555                 if (!t->is_pointer) {
556                         tp_for_each_touch(tp, t) {
557                                 if (t->is_pointer)
558                                         break;
559                         }
560                 }
561
562                 if (!t->is_pointer)
563                         return;
564
565                 tp_get_delta(t, &dx, &dy);
566                 tp_filter_motion(tp, &dx, &dy, time);
567
568                 if (dx != 0 || dy != 0)
569                         pointer_notify_motion(
570                                 &tp->device->base,
571                                 time,
572                                 li_fixed_from_double(dx),
573                                 li_fixed_from_double(dy));
574         }
575 }
576
577 static void
578 tp_process(struct evdev_dispatch *dispatch,
579            struct evdev_device *device,
580            struct input_event *e,
581            uint64_t time)
582 {
583         struct tp_dispatch *tp =
584                 (struct tp_dispatch *)dispatch;
585
586         switch (e->type) {
587         case EV_ABS:
588                 if (tp->has_mt)
589                         tp_process_absolute(tp, e, time);
590                 else
591                         tp_process_absolute_st(tp, e, time);
592                 break;
593         case EV_KEY:
594                 tp_process_key(tp, e, time);
595                 break;
596         case EV_SYN:
597                 tp_process_state(tp, time);
598                 tp_post_events(tp, time);
599                 tp_post_process_state(tp, time);
600                 break;
601         }
602 }
603
604 static void
605 tp_destroy(struct evdev_dispatch *dispatch)
606 {
607         struct tp_dispatch *tp =
608                 (struct tp_dispatch*)dispatch;
609
610         tp_destroy_tap(tp);
611         tp_destroy_buttons(tp);
612
613         if (tp->filter)
614                 tp->filter->interface->destroy(tp->filter);
615         free(tp->touches);
616         free(tp);
617 }
618
619 static struct evdev_dispatch_interface tp_interface = {
620         tp_process,
621         tp_destroy
622 };
623
624 static void
625 tp_init_touch(struct tp_dispatch *tp,
626               struct tp_touch *t)
627 {
628         t->button.state = BUTTON_STATE_NONE;
629 }
630
631 static int
632 tp_init_slots(struct tp_dispatch *tp,
633               struct evdev_device *device)
634 {
635         size_t i;
636         const struct input_absinfo *absinfo;
637
638         absinfo = libevdev_get_abs_info(device->evdev, ABS_MT_SLOT);
639         if (absinfo) {
640                 tp->ntouches = absinfo->maximum + 1;
641                 tp->slot = absinfo->value;
642                 tp->has_mt = true;
643         } else {
644                 struct map {
645                         unsigned int code;
646                         int ntouches;
647                 } max_touches[] = {
648                         { BTN_TOOL_QUINTTAP, 5 },
649                         { BTN_TOOL_QUADTAP, 4 },
650                         { BTN_TOOL_TRIPLETAP, 3 },
651                         { BTN_TOOL_DOUBLETAP, 2 },
652                 };
653                 struct map *m;
654
655                 tp->slot = 0;
656                 tp->has_mt = false;
657                 tp->ntouches = 1;
658
659                 ARRAY_FOR_EACH(max_touches, m) {
660                         if (libevdev_has_event_code(device->evdev,
661                                                     EV_KEY,
662                                                     m->code)) {
663                                 tp->ntouches = m->ntouches;
664                                 break;
665                         }
666                 }
667         }
668         tp->touches = calloc(tp->ntouches,
669                              sizeof(struct tp_touch));
670         if (!tp->touches)
671                 return -1;
672
673         for (i = 0; i < tp->ntouches; i++)
674                 tp_init_touch(tp, &tp->touches[i]);
675
676         return 0;
677 }
678
679 static int
680 tp_init_accel(struct tp_dispatch *touchpad, double diagonal)
681 {
682         struct motion_filter *accel;
683
684         touchpad->accel.constant_factor =
685                 DEFAULT_CONSTANT_ACCEL_NUMERATOR / diagonal;
686         touchpad->accel.min_factor = DEFAULT_MIN_ACCEL_FACTOR;
687         touchpad->accel.max_factor = DEFAULT_MAX_ACCEL_FACTOR;
688
689         accel = create_pointer_accelator_filter(tp_accel_profile);
690         if (accel == NULL)
691                 return -1;
692
693         touchpad->filter = accel;
694
695         return 0;
696 }
697
698 static int
699 tp_init_scroll(struct tp_dispatch *tp)
700 {
701         tp->scroll.direction = 0;
702         tp->scroll.state = SCROLL_STATE_NONE;
703
704         return 0;
705 }
706
707 static int
708 tp_init(struct tp_dispatch *tp,
709         struct evdev_device *device)
710 {
711         int width, height;
712         double diagonal;
713
714         tp->base.interface = &tp_interface;
715         tp->device = device;
716         tp->tap.timer_fd = -1;
717         tp->buttons.timer_fd = -1;
718
719         if (tp_init_slots(tp, device) != 0)
720                 return -1;
721
722         width = abs(device->abs.max_x - device->abs.min_x);
723         height = abs(device->abs.max_y - device->abs.min_y);
724         diagonal = sqrt(width*width + height*height);
725
726         tp->hysteresis.margin_x =
727                 diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
728         tp->hysteresis.margin_y =
729                 diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
730
731         if (tp_init_scroll(tp) != 0)
732                 return -1;
733
734         if (tp_init_accel(tp, diagonal) != 0)
735                 return -1;
736
737         if (tp_init_tap(tp) != 0)
738                 return -1;
739
740         if (tp_init_buttons(tp, device) != 0)
741                 return -1;
742
743         return 0;
744 }
745
746 struct evdev_dispatch *
747 evdev_mt_touchpad_create(struct evdev_device *device)
748 {
749         struct tp_dispatch *tp;
750
751         tp = zalloc(sizeof *tp);
752         if (!tp)
753                 return NULL;
754
755         if (tp_init(tp, device) != 0) {
756                 tp_destroy(&tp->base);
757                 return NULL;
758         }
759
760         return  &tp->base;
761 }