(root)/
strace-6.5/
src/
gpio_ioctl.c
       1  /*
       2   * Copyright (c) 2020-2022 The strace developers.
       3   * All rights reserved.
       4   *
       5   * SPDX-License-Identifier: LGPL-2.1-or-later
       6   */
       7  
       8  #include "defs.h"
       9  
      10  #include <linux/gpio.h>
      11  
      12  static int
      13  print_gpiochip_info(struct tcb *const tcp, const kernel_ulong_t arg)
      14  {
      15  	struct gpiochip_info info;
      16  
      17  	if (entering(tcp))
      18  		return 0;
      19  
      20  	tprint_arg_next();
      21  	if (umove_or_printaddr(tcp, arg, &info))
      22  		return RVAL_IOCTL_DECODED;
      23  
      24  	tprint_struct_begin();
      25  	PRINT_FIELD_CSTRING(info, name);
      26  	tprint_struct_next();
      27  	PRINT_FIELD_CSTRING(info, label);
      28  	tprint_struct_next();
      29  	PRINT_FIELD_U(info, lines);
      30  	tprint_struct_end();
      31  
      32  	return RVAL_IOCTL_DECODED;
      33  }
      34  
      35  #include "xlat/gpio_line_flags.h"
      36  
      37  static int
      38  print_gpioline_info(struct tcb *const tcp, const kernel_ulong_t arg)
      39  {
      40  	struct gpioline_info info;
      41  
      42  	if (entering(tcp))
      43  		tprint_arg_next();
      44  	else if (syserror(tcp))
      45  		return RVAL_IOCTL_DECODED;
      46  	else
      47  		tprint_value_changed();
      48  
      49  	if (umove_or_printaddr(tcp, arg, &info))
      50  		return RVAL_IOCTL_DECODED;
      51  
      52  	if (entering(tcp)) {
      53  		tprint_struct_begin();
      54  		PRINT_FIELD_U(info, line_offset);
      55  		tprint_struct_end();
      56  		return 0;
      57  	}
      58  
      59  	/* exiting */
      60  	tprint_struct_begin();
      61  	PRINT_FIELD_FLAGS(info, flags, gpio_line_flags, "GPIOLINE_FLAG_???");
      62  	tprint_struct_next();
      63  	PRINT_FIELD_CSTRING(info, name);
      64  	tprint_struct_next();
      65  	PRINT_FIELD_CSTRING(info, consumer);
      66  	tprint_struct_end();
      67  
      68  	return RVAL_IOCTL_DECODED;
      69  }
      70  
      71  static int
      72  print_gpioline_info_unwatch(struct tcb *const tcp, const kernel_ulong_t arg)
      73  {
      74  	struct { uint32_t offset; } data;
      75  
      76  	tprint_arg_next();
      77  	if (!umove_or_printaddr(tcp, arg, &data)) {
      78  		tprint_struct_begin();
      79  		PRINT_FIELD_U(data, offset);
      80  		tprint_struct_end();
      81  	}
      82  
      83  	return RVAL_IOCTL_DECODED;
      84  }
      85  
      86  #include "xlat/gpio_handle_flags.h"
      87  
      88  static int
      89  print_gpiohandle_request(struct tcb *const tcp, const kernel_ulong_t arg)
      90  {
      91  	struct gpiohandle_request hr;
      92  
      93  	if (entering(tcp))
      94  		tprint_arg_next();
      95  	else if (syserror(tcp))
      96  		return RVAL_IOCTL_DECODED;
      97  	else
      98  		tprint_value_changed();
      99  
     100  	if (umove_or_printaddr(tcp, arg, &hr))
     101  		return RVAL_IOCTL_DECODED;
     102  
     103  	if (exiting(tcp)) {
     104  		tprint_struct_begin();
     105  		PRINT_FIELD_FD(hr, fd, tcp);
     106  		tprint_struct_end();
     107  		return RVAL_IOCTL_DECODED;
     108  	}
     109  
     110  	/* entering */
     111  	tprint_struct_begin();
     112  	PRINT_FIELD_U(hr, lines);
     113  	tprint_struct_next();
     114  	PRINT_FIELD_ARRAY_UPTO(hr, lineoffsets, hr.lines, tcp,
     115  			       print_uint_array_member);
     116  	tprint_struct_next();
     117  	PRINT_FIELD_FLAGS(hr, flags, gpio_handle_flags,
     118  			  "GPIOHANDLE_REQUEST_???");
     119  	tprint_struct_next();
     120  	PRINT_FIELD_ARRAY_UPTO(hr, default_values, hr.lines, tcp,
     121  			       print_uint_array_member);
     122  	tprint_struct_next();
     123  	PRINT_FIELD_CSTRING(hr, consumer_label);
     124  	tprint_struct_end();
     125  	return 0;
     126  }
     127  
     128  #include "xlat/gpio_event_flags.h"
     129  
     130  static int
     131  print_gpioevent_request(struct tcb *const tcp, const kernel_ulong_t arg)
     132  {
     133  	struct gpioevent_request er;
     134  
     135  	if (entering(tcp))
     136  		tprint_arg_next();
     137  	else if (syserror(tcp))
     138  		return RVAL_IOCTL_DECODED;
     139  	else
     140  		tprint_value_changed();
     141  
     142  	if (umove_or_printaddr(tcp, arg, &er))
     143  		return RVAL_IOCTL_DECODED;
     144  
     145  	if (exiting(tcp)) {
     146  		tprint_struct_begin();
     147  		PRINT_FIELD_FD(er, fd, tcp);
     148  		tprint_struct_end();
     149  		return RVAL_IOCTL_DECODED;
     150  	}
     151  
     152  	/* entering */
     153  	tprint_struct_begin();
     154  	PRINT_FIELD_U(er, lineoffset);
     155  	tprint_struct_next();
     156  	PRINT_FIELD_FLAGS(er, handleflags, gpio_handle_flags,
     157  			  "GPIOHANDLE_REQUEST_???");
     158  	tprint_struct_next();
     159  	PRINT_FIELD_FLAGS(er, eventflags, gpio_event_flags,
     160  			  "GPIOEVENT_REQUEST_???");
     161  	tprint_struct_next();
     162  	PRINT_FIELD_CSTRING(er, consumer_label);
     163  	tprint_struct_end();
     164  	return 0;
     165  }
     166  
     167  static void
     168  print_gpiohandle_data(struct tcb *const tcp, const struct gpiohandle_data *vals)
     169  {
     170  	tprint_struct_begin();
     171  	PRINT_FIELD_ARRAY(*vals, values, tcp, print_uint_array_member);
     172  	tprint_struct_end();
     173  }
     174  
     175  static int
     176  print_gpiohandle_get_values(struct tcb *const tcp, const kernel_ulong_t arg)
     177  {
     178  	struct gpiohandle_data vals;
     179  
     180  	if (entering(tcp))
     181  		return 0;
     182  
     183  	/* exiting */
     184  	tprint_arg_next();
     185  	if (!umove_or_printaddr(tcp, arg, &vals))
     186  		print_gpiohandle_data(tcp, &vals);
     187  
     188  	return RVAL_IOCTL_DECODED;
     189  }
     190  
     191  static int
     192  print_gpiohandle_set_values(struct tcb *const tcp, const kernel_ulong_t arg)
     193  {
     194  	struct gpiohandle_data vals;
     195  
     196  	tprint_arg_next();
     197  	if (!umove_or_printaddr(tcp, arg, &vals))
     198  		print_gpiohandle_data(tcp, &vals);
     199  
     200  	return RVAL_IOCTL_DECODED;
     201  }
     202  
     203  static int
     204  print_gpiohandle_set_config(struct tcb *const tcp, const kernel_ulong_t arg)
     205  {
     206  	struct gpiohandle_config hc;
     207  
     208  	tprint_arg_next();
     209  	if (umove_or_printaddr(tcp, arg, &hc))
     210  		return RVAL_IOCTL_DECODED;
     211  
     212  	tprint_struct_begin();
     213  	PRINT_FIELD_FLAGS(hc, flags, gpio_handle_flags, "GPIOHANDLE_REQUEST_???");
     214  	tprint_struct_next();
     215  	PRINT_FIELD_ARRAY(hc, default_values, tcp, print_uint_array_member);
     216  	tprint_struct_end();
     217  
     218  	return RVAL_IOCTL_DECODED;
     219  }
     220  
     221  #include "xlat/gpio_v2_line_flags.h"
     222  #include "xlat/gpio_v2_line_attr_ids.h"
     223  
     224  static void
     225  print_gpio_v2_line_attribute_raw(const struct gpio_v2_line_attribute *attr,
     226  				 bool as_field)
     227  {
     228  	if (as_field) {
     229  		tprints_field_name("attr");
     230  		tprint_struct_begin();
     231  	}
     232  	PRINT_FIELD_U(*attr, id);
     233  	if (attr->padding) {
     234  		tprint_struct_next();
     235  		PRINT_FIELD_X(*attr, padding);
     236  	}
     237  	tprint_struct_next();
     238  	tprints_field_name("data");
     239  	PRINT_VAL_X(attr->values);
     240  	if (as_field)
     241  		tprint_struct_end();
     242  }
     243  
     244  static void
     245  print_gpio_v2_line_attribute(const struct gpio_v2_line_attribute *attr,
     246  			     bool as_field)
     247  {
     248  	if (attr->padding) {
     249  		/* unexpected padding usage so decode fields raw */
     250  		print_gpio_v2_line_attribute_raw(attr, as_field);
     251  		return;
     252  	}
     253  	switch (attr->id) {
     254  	case GPIO_V2_LINE_ATTR_ID_FLAGS:
     255  		PRINT_FIELD_FLAGS(*attr, flags, gpio_v2_line_flags,
     256  				  "GPIO_V2_LINE_FLAG_???");
     257  		break;
     258  	case GPIO_V2_LINE_ATTR_ID_OUTPUT_VALUES:
     259  		PRINT_FIELD_X(*attr, values);
     260  		break;
     261  	case GPIO_V2_LINE_ATTR_ID_DEBOUNCE:
     262  		PRINT_FIELD_U(*attr, debounce_period_us);
     263  		break;
     264  	default:
     265  		/* unknown id so decode fields raw */
     266  		print_gpio_v2_line_attribute_raw(attr, as_field);
     267  		break;
     268  	}
     269  }
     270  
     271  static void
     272  print_gpio_v2_line_config_attribute(const struct gpio_v2_line_config_attribute *attr)
     273  {
     274  	tprint_struct_begin();
     275  	print_gpio_v2_line_attribute(&attr->attr, true);
     276  	tprint_struct_next();
     277  	PRINT_FIELD_X(*attr, mask);
     278  	tprint_struct_end();
     279  }
     280  
     281  static bool
     282  print_gpio_v2_line_attr_array_member(struct tcb *tcp, void *elem_buf,
     283  				     size_t elem_size, void *data)
     284  {
     285  	tprint_struct_begin();
     286  	print_gpio_v2_line_attribute(elem_buf, false);
     287  	tprint_struct_end();
     288  
     289  	return true;
     290  }
     291  
     292  static bool
     293  print_gpio_v2_line_config_attr_array_member(struct tcb *tcp, void *elem_buf,
     294  					    size_t elem_size, void *data)
     295  {
     296  	print_gpio_v2_line_config_attribute(elem_buf);
     297  
     298  	return true;
     299  }
     300  
     301  static void
     302  print_gpio_v2_line_config(struct tcb *const tcp,
     303  			  const struct gpio_v2_line_config *lc)
     304  {
     305  	tprint_struct_begin();
     306  	PRINT_FIELD_FLAGS(*lc, flags, gpio_v2_line_flags,
     307  			  "GPIO_V2_LINE_FLAG_???");
     308  	tprint_struct_next();
     309  	PRINT_FIELD_U(*lc, num_attrs);
     310  	if (!IS_ARRAY_ZERO(lc->padding)) {
     311  		tprint_struct_next();
     312  		PRINT_FIELD_X_ARRAY(*lc, padding);
     313  	}
     314  	if (lc->num_attrs) {
     315  		tprint_struct_next();
     316  		PRINT_FIELD_ARRAY_UPTO(*lc, attrs, lc->num_attrs, tcp,
     317  				       print_gpio_v2_line_config_attr_array_member);
     318  	}
     319  	tprint_struct_end();
     320  }
     321  
     322  static int
     323  print_gpio_v2_line_info(struct tcb *const tcp, const kernel_ulong_t arg)
     324  {
     325  	struct gpio_v2_line_info li;
     326  
     327  	if (entering(tcp))
     328  		tprint_arg_next();
     329  	else if (syserror(tcp))
     330  		return RVAL_IOCTL_DECODED;
     331  	else
     332  		tprint_value_changed();
     333  
     334  	if (umove_or_printaddr(tcp, arg, &li))
     335  		return RVAL_IOCTL_DECODED;
     336  
     337  	if (entering(tcp)) {
     338  		tprint_struct_begin();
     339  		PRINT_FIELD_U(li, offset);
     340  		tprint_struct_end();
     341  		return 0;
     342  	}
     343  
     344  	/* exiting */
     345  	tprint_struct_begin();
     346  	PRINT_FIELD_CSTRING(li, name);
     347  	tprint_struct_next();
     348  	PRINT_FIELD_CSTRING(li, consumer);
     349  	tprint_struct_next();
     350  	PRINT_FIELD_FLAGS(li, flags, gpio_v2_line_flags, "GPIO_V2_LINE_FLAG_???");
     351  	tprint_struct_next();
     352  	PRINT_FIELD_U(li, num_attrs);
     353  	if (li.num_attrs) {
     354  		tprint_struct_next();
     355  		PRINT_FIELD_ARRAY_UPTO(li, attrs, li.num_attrs, tcp,
     356  				       print_gpio_v2_line_attr_array_member);
     357  	}
     358  	if (!IS_ARRAY_ZERO(li.padding)) {
     359  		tprint_struct_next();
     360  		PRINT_FIELD_X_ARRAY(li, padding);
     361  	}
     362  	tprint_struct_end();
     363  
     364  	return RVAL_IOCTL_DECODED;
     365  }
     366  
     367  static int
     368  print_gpio_v2_line_request(struct tcb *const tcp, const kernel_ulong_t arg)
     369  {
     370  	struct gpio_v2_line_request lr;
     371  
     372  	if (entering(tcp))
     373  		tprint_arg_next();
     374  	else if (syserror(tcp))
     375  		return RVAL_IOCTL_DECODED;
     376  	else
     377  		tprint_value_changed();
     378  
     379  	if (umove_or_printaddr(tcp, arg, &lr))
     380  		return RVAL_IOCTL_DECODED;
     381  
     382  	if (exiting(tcp)) {
     383  		tprint_struct_begin();
     384  		PRINT_FIELD_FD(lr, fd, tcp);
     385  		tprint_struct_end();
     386  		return RVAL_IOCTL_DECODED;
     387  	}
     388  
     389  	/* entering */
     390  	tprint_struct_begin();
     391  	PRINT_FIELD_U(lr, num_lines);
     392  	tprint_struct_next();
     393  	PRINT_FIELD_ARRAY_UPTO(lr, offsets, lr.num_lines, tcp,
     394  			       print_uint_array_member);
     395  	tprint_struct_next();
     396  	PRINT_FIELD_CSTRING(lr, consumer);
     397  	tprint_struct_next();
     398  	PRINT_FIELD_OBJ_TCB_PTR(lr, config, tcp,
     399  				print_gpio_v2_line_config);
     400  	if (lr.event_buffer_size) {
     401  		tprint_struct_next();
     402  		PRINT_FIELD_U(lr, event_buffer_size);
     403  	}
     404  	if (!IS_ARRAY_ZERO(lr.padding)) {
     405  		tprint_struct_next();
     406  		PRINT_FIELD_X_ARRAY(lr, padding);
     407  	}
     408  	tprint_struct_end();
     409  	return 0;
     410  }
     411  
     412  static int
     413  print_gpio_v2_line_get_values(struct tcb *const tcp, const kernel_ulong_t arg)
     414  {
     415  	struct gpio_v2_line_values vals;
     416  
     417  	if (entering(tcp))
     418  		tprint_arg_next();
     419  	else if (syserror(tcp))
     420  		return RVAL_IOCTL_DECODED;
     421  	else
     422  		tprint_value_changed();
     423  
     424  	if (umove_or_printaddr(tcp, arg, &vals))
     425  		return RVAL_IOCTL_DECODED;
     426  
     427  	if (entering(tcp)) {
     428  		tprint_struct_begin();
     429  		PRINT_FIELD_X(vals, mask);
     430  		tprint_struct_end();
     431  		return 0;
     432  	}
     433  
     434  	/* exiting */
     435  	tprint_struct_begin();
     436  	PRINT_FIELD_X(vals, bits);
     437  	tprint_struct_end();
     438  
     439  	return RVAL_IOCTL_DECODED;
     440  }
     441  
     442  static int
     443  print_gpio_v2_line_set_values(struct tcb *const tcp, const kernel_ulong_t arg)
     444  {
     445  	struct gpio_v2_line_values vals;
     446  
     447  	tprint_arg_next();
     448  	if (!umove_or_printaddr(tcp, arg, &vals)) {
     449  		tprint_struct_begin();
     450  		PRINT_FIELD_X(vals, bits);
     451  		tprint_struct_next();
     452  		PRINT_FIELD_X(vals, mask);
     453  		tprint_struct_end();
     454  	}
     455  
     456  	return RVAL_IOCTL_DECODED;
     457  }
     458  
     459  static int
     460  print_gpio_v2_line_set_config(struct tcb *const tcp, const kernel_ulong_t arg)
     461  {
     462  	struct gpio_v2_line_config lc;
     463  
     464  	tprint_arg_next();
     465  	if (!umove_or_printaddr(tcp, arg, &lc))
     466  		print_gpio_v2_line_config(tcp, &lc);
     467  
     468  	return RVAL_IOCTL_DECODED;
     469  }
     470  
     471  int
     472  gpio_ioctl(struct tcb *const tcp, const unsigned int code,
     473  	   const kernel_ulong_t arg)
     474  {
     475  	switch (code) {
     476  	case GPIO_GET_CHIPINFO_IOCTL:
     477  		return print_gpiochip_info(tcp, arg);
     478  	case GPIO_GET_LINEINFO_UNWATCH_IOCTL:
     479  		return print_gpioline_info_unwatch(tcp, arg);
     480  	case GPIO_V2_GET_LINEINFO_IOCTL:
     481  	case GPIO_V2_GET_LINEINFO_WATCH_IOCTL:
     482  		return print_gpio_v2_line_info(tcp, arg);
     483  	case GPIO_V2_GET_LINE_IOCTL:
     484  		return print_gpio_v2_line_request(tcp, arg);
     485  	case GPIO_V2_LINE_SET_CONFIG_IOCTL:
     486  		return print_gpio_v2_line_set_config(tcp, arg);
     487  	case GPIO_V2_LINE_GET_VALUES_IOCTL:
     488  		return print_gpio_v2_line_get_values(tcp, arg);
     489  	case GPIO_V2_LINE_SET_VALUES_IOCTL:
     490  		return print_gpio_v2_line_set_values(tcp, arg);
     491  	case GPIO_GET_LINEINFO_IOCTL:
     492  	case GPIO_GET_LINEINFO_WATCH_IOCTL:
     493  		return print_gpioline_info(tcp, arg);
     494  	case GPIO_GET_LINEHANDLE_IOCTL:
     495  		return print_gpiohandle_request(tcp, arg);
     496  	case GPIO_GET_LINEEVENT_IOCTL:
     497  		return print_gpioevent_request(tcp, arg);
     498  	case GPIOHANDLE_GET_LINE_VALUES_IOCTL:
     499  		return print_gpiohandle_get_values(tcp, arg);
     500  	case GPIOHANDLE_SET_LINE_VALUES_IOCTL:
     501  		return print_gpiohandle_set_values(tcp, arg);
     502  	case GPIOHANDLE_SET_CONFIG_IOCTL:
     503  		return print_gpiohandle_set_config(tcp, arg);
     504  	}
     505  	return RVAL_DECODED;
     506  }