(root)/
strace-6.5/
src/
evdev_mpers.c
       1  /*
       2   * Copyright (c) 2015 Etienne Gemsa <etienne.gemsa@lse.epita.fr>
       3   * Copyright (c) 2015-2016 Dmitry V. Levin <ldv@strace.io>
       4   * Copyright (c) 2015-2021 The strace developers.
       5   * All rights reserved.
       6   *
       7   * SPDX-License-Identifier: LGPL-2.1-or-later
       8   */
       9  
      10  #include "defs.h"
      11  
      12  #include DEF_MPERS_TYPE(struct_ff_effect)
      13  
      14  #include <linux/ioctl.h>
      15  #include <linux/input.h>
      16  
      17  typedef struct ff_effect struct_ff_effect;
      18  
      19  #include MPERS_DEFS
      20  
      21  static void
      22  print_ff_envelope(const MPERS_PTR_ARG(struct ff_envelope *) const arg)
      23  {
      24  	const struct ff_envelope *const p = arg;
      25  	tprint_struct_begin();
      26  	PRINT_FIELD_U(*p, attack_length);
      27  	tprint_struct_next();
      28  	PRINT_FIELD_U(*p, attack_level);
      29  	tprint_struct_next();
      30  	PRINT_FIELD_U(*p, fade_length);
      31  	tprint_struct_next();
      32  	PRINT_FIELD_X(*p, fade_level);
      33  	tprint_struct_end();
      34  }
      35  
      36  #define DECL_print_ff(name_)	\
      37  	print_ff_ ## name_(const typeof_field(struct_ff_effect, name_) *const p)
      38  
      39  static void
      40  DECL_print_ff(trigger)
      41  {
      42  	tprint_struct_begin();
      43  	PRINT_FIELD_U(*p, button);
      44  	tprint_struct_next();
      45  	PRINT_FIELD_U(*p, interval);
      46  	tprint_struct_end();
      47  }
      48  
      49  static void
      50  DECL_print_ff(replay)
      51  {
      52  	tprint_struct_begin();
      53  	PRINT_FIELD_U(*p, length);
      54  	tprint_struct_next();
      55  	PRINT_FIELD_U(*p, delay);
      56  	tprint_struct_end();
      57  }
      58  
      59  #define PRINT_FIELD_FF_EFFECT(where_, field_)			\
      60  	do {							\
      61  		tprints_field_name(#field_);			\
      62  		print_ff_ ## field_(&((where_).field_));	\
      63  	} while (0)
      64  
      65  #define DECL_print_ff_effect(name_)	\
      66  	print_ff_ ## name_ ## _effect(const typeof_field(struct_ff_effect, u.name_) *const p)
      67  
      68  static void
      69  DECL_print_ff_effect(constant)
      70  {
      71  	tprint_struct_begin();
      72  	PRINT_FIELD_D(*p, level);
      73  	tprint_struct_next();
      74  	PRINT_FIELD_OBJ_PTR(*p, envelope, print_ff_envelope);
      75  	tprint_struct_end();
      76  }
      77  
      78  static void
      79  DECL_print_ff_effect(ramp)
      80  {
      81  	tprint_struct_begin();
      82  	PRINT_FIELD_D(*p, start_level);
      83  	tprint_struct_next();
      84  	PRINT_FIELD_D(*p, end_level);
      85  	tprint_struct_next();
      86  	PRINT_FIELD_OBJ_PTR(*p, envelope, print_ff_envelope);
      87  	tprint_struct_end();
      88  }
      89  
      90  static void
      91  DECL_print_ff_effect(periodic)
      92  {
      93  	tprint_struct_begin();
      94  	PRINT_FIELD_U(*p, waveform);
      95  	tprint_struct_next();
      96  	PRINT_FIELD_U(*p, period);
      97  	tprint_struct_next();
      98  	PRINT_FIELD_D(*p, magnitude);
      99  	tprint_struct_next();
     100  	PRINT_FIELD_D(*p, offset);
     101  	tprint_struct_next();
     102  	PRINT_FIELD_U(*p, phase);
     103  	tprint_struct_next();
     104  	PRINT_FIELD_OBJ_PTR(*p, envelope, print_ff_envelope);
     105  	tprint_struct_next();
     106  	PRINT_FIELD_U(*p, custom_len);
     107  	tprint_struct_next();
     108  	PRINT_FIELD_PTR(*p, custom_data);
     109  	tprint_struct_end();
     110  }
     111  
     112  static void
     113  DECL_print_ff_effect(rumble)
     114  {
     115  	tprint_struct_begin();
     116  	PRINT_FIELD_U(*p, strong_magnitude);
     117  	tprint_struct_next();
     118  	PRINT_FIELD_U(*p, weak_magnitude);
     119  	tprint_struct_end();
     120  }
     121  
     122  #define PRINT_FIELD_FF_TYPE_EFFECT(where_, field_)			\
     123  	do {								\
     124  		tprints_field_name(#field_);				\
     125  		print_ff_ ## field_ ## _effect(&((where_).field_));	\
     126  	} while (0)
     127  
     128  static int
     129  ff_effect_ioctl(struct tcb *const tcp, const kernel_ulong_t arg)
     130  {
     131  	struct_ff_effect ffe;
     132  
     133  	if (umove_or_printaddr(tcp, arg, &ffe))
     134  		return RVAL_IOCTL_DECODED;
     135  
     136  	tprint_struct_begin();
     137  	PRINT_FIELD_OBJ_VAL(ffe, type, print_evdev_ff_type);
     138  	tprint_struct_next();
     139  	PRINT_FIELD_D(ffe, id);
     140  	tprint_struct_next();
     141  	PRINT_FIELD_U(ffe, direction);
     142  	tprint_struct_next();
     143  
     144  	if (abbrev(tcp)) {
     145  		tprint_more_data_follows();
     146  		tprint_struct_end();
     147  		return RVAL_IOCTL_DECODED;
     148  	}
     149  
     150  	PRINT_FIELD_FF_EFFECT(ffe, trigger);
     151  	tprint_struct_next();
     152  	PRINT_FIELD_FF_EFFECT(ffe, replay);
     153  
     154  	switch (ffe.type) {
     155  	case FF_CONSTANT:
     156  		tprint_struct_next();
     157  		PRINT_FIELD_FF_TYPE_EFFECT(ffe.u, constant);
     158  		break;
     159  	case FF_RAMP:
     160  		tprint_struct_next();
     161  		PRINT_FIELD_FF_TYPE_EFFECT(ffe.u, ramp);
     162  		break;
     163  	case FF_PERIODIC:
     164  		tprint_struct_next();
     165  		PRINT_FIELD_FF_TYPE_EFFECT(ffe.u, periodic);
     166  		break;
     167  	case FF_RUMBLE:
     168  		tprint_struct_next();
     169  		PRINT_FIELD_FF_TYPE_EFFECT(ffe.u, rumble);
     170  		break;
     171  	default:
     172  		break;
     173  	}
     174  
     175  	tprint_struct_end();
     176  
     177  	return RVAL_IOCTL_DECODED;
     178  }
     179  
     180  MPERS_PRINTER_DECL(int, evdev_write_ioctl_mpers, struct tcb *const tcp,
     181  		   const unsigned int code, const kernel_ulong_t arg)
     182  {
     183  	switch (code) {
     184  	case EVIOCSFF:
     185  		return ff_effect_ioctl(tcp, arg);
     186  	default:
     187  		return RVAL_DECODED;
     188  	}
     189  }