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 }