diff options
Diffstat (limited to 'tools/gpio/gpio-utils.c')
| -rw-r--r-- | tools/gpio/gpio-utils.c | 176 | 
1 files changed, 141 insertions, 35 deletions
diff --git a/tools/gpio/gpio-utils.c b/tools/gpio/gpio-utils.c index 16a5d9cb9da2..37187e056c8b 100644 --- a/tools/gpio/gpio-utils.c +++ b/tools/gpio/gpio-utils.c @@ -38,7 +38,7 @@   *			such as "gpiochip0"   * @lines:		An array desired lines, specified by offset   *			index for the associated GPIO device. - * @nline:		The number of lines to request. + * @num_lines:		The number of lines to request.   * @flag:		The new flag for requsted gpio. Reference   *			"linux/gpio.h" for the meaning of flag.   * @data:		Default value will be set to gpio when flag is @@ -56,7 +56,7 @@   *			On failure return the errno.   */  int gpiotools_request_linehandle(const char *device_name, unsigned int *lines, -				 unsigned int nlines, unsigned int flag, +				 unsigned int num_lines, unsigned int flag,  				 struct gpiohandle_data *data,  				 const char *consumer_label)  { @@ -78,12 +78,12 @@ int gpiotools_request_linehandle(const char *device_name, unsigned int *lines,  		goto exit_free_name;  	} -	for (i = 0; i < nlines; i++) +	for (i = 0; i < num_lines; i++)  		req.lineoffsets[i] = lines[i];  	req.flags = flag;  	strcpy(req.consumer_label, consumer_label); -	req.lines = nlines; +	req.lines = num_lines;  	if (flag & GPIOHANDLE_REQUEST_OUTPUT)  		memcpy(req.default_values, data, sizeof(req.default_values)); @@ -100,20 +100,87 @@ exit_free_name:  	free(chrdev_name);  	return ret < 0 ? ret : req.fd;  } + +/** + * gpiotools_request_line() - request gpio lines in a gpiochip + * @device_name:	The name of gpiochip without prefix "/dev/", + *			such as "gpiochip0" + * @lines:		An array desired lines, specified by offset + *			index for the associated GPIO device. + * @num_lines:		The number of lines to request. + * @config:		The new config for requested gpio. Reference + *			"linux/gpio.h" for config details. + * @consumer:		The name of consumer, such as "sysfs", + *			"powerkey". This is useful for other users to + *			know who is using. + * + * Request gpio lines through the ioctl provided by chardev. User + * could call gpiotools_set_values() and gpiotools_get_values() to + * read and write respectively through the returned fd. Call + * gpiotools_release_line() to release these lines after that. + * + * Return:		On success return the fd; + *			On failure return the errno. + */ +int gpiotools_request_line(const char *device_name, unsigned int *lines, +			   unsigned int num_lines, +			   struct gpio_v2_line_config *config, +			   const char *consumer) +{ +	struct gpio_v2_line_request req; +	char *chrdev_name; +	int fd; +	int i; +	int ret; + +	ret = asprintf(&chrdev_name, "/dev/%s", device_name); +	if (ret < 0) +		return -ENOMEM; + +	fd = open(chrdev_name, 0); +	if (fd == -1) { +		ret = -errno; +		fprintf(stderr, "Failed to open %s, %s\n", +			chrdev_name, strerror(errno)); +		goto exit_free_name; +	} + +	memset(&req, 0, sizeof(req)); +	for (i = 0; i < num_lines; i++) +		req.offsets[i] = lines[i]; + +	req.config = *config; +	strcpy(req.consumer, consumer); +	req.num_lines = num_lines; + +	ret = ioctl(fd, GPIO_V2_GET_LINE_IOCTL, &req); +	if (ret == -1) { +		ret = -errno; +		fprintf(stderr, "Failed to issue %s (%d), %s\n", +			"GPIO_GET_LINE_IOCTL", ret, strerror(errno)); +	} + +	if (close(fd) == -1) +		perror("Failed to close GPIO character device file"); +exit_free_name: +	free(chrdev_name); +	return ret < 0 ? ret : req.fd; +} +  /**   * gpiotools_set_values(): Set the value of gpio(s)   * @fd:			The fd returned by - *			gpiotools_request_linehandle(). - * @data:		The array of values want to set. + *			gpiotools_request_line(). + * @values:		The array of values want to set.   *   * Return:		On success return 0;   *			On failure return the errno.   */ -int gpiotools_set_values(const int fd, struct gpiohandle_data *data) +int gpiotools_set_values(const int fd, struct gpio_v2_line_values *values)  {  	int ret; -	ret = ioctl(fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, data); +	ret = ioctl(fd, GPIO_V2_LINE_SET_VALUES_IOCTL, values);  	if (ret == -1) {  		ret = -errno;  		fprintf(stderr, "Failed to issue %s (%d), %s\n", @@ -127,17 +194,17 @@ int gpiotools_set_values(const int fd, struct gpiohandle_data *data)  /**   * gpiotools_get_values(): Get the value of gpio(s)   * @fd:			The fd returned by - *			gpiotools_request_linehandle(). - * @data:		The array of values get from hardware. + *			gpiotools_request_line(). + * @values:		The array of values get from hardware.   *   * Return:		On success return 0;   *			On failure return the errno.   */ -int gpiotools_get_values(const int fd, struct gpiohandle_data *data) +int gpiotools_get_values(const int fd, struct gpio_v2_line_values *values)  {  	int ret; -	ret = ioctl(fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, data); +	ret = ioctl(fd, GPIO_V2_LINE_GET_VALUES_IOCTL, values);  	if (ret == -1) {  		ret = -errno;  		fprintf(stderr, "Failed to issue %s (%d), %s\n", @@ -170,6 +237,27 @@ int gpiotools_release_linehandle(const int fd)  }  /** + * gpiotools_release_line(): Release the line(s) of gpiochip + * @fd:			The fd returned by + *			gpiotools_request_line(). + * + * Return:		On success return 0; + *			On failure return the errno. + */ +int gpiotools_release_line(const int fd) +{ +	int ret; + +	ret = close(fd); +	if (ret == -1) { +		perror("Failed to close GPIO LINE device file"); +		ret = -errno; +	} + +	return ret; +} + +/**   * gpiotools_get(): Get value from specific line   * @device_name:	The name of gpiochip without prefix "/dev/",   *			such as "gpiochip0" @@ -180,11 +268,14 @@ int gpiotools_release_linehandle(const int fd)   */  int gpiotools_get(const char *device_name, unsigned int line)  { -	struct gpiohandle_data data; +	int ret; +	unsigned int value;  	unsigned int lines[] = {line}; -	gpiotools_gets(device_name, lines, 1, &data); -	return data.values[0]; +	ret = gpiotools_gets(device_name, lines, 1, &value); +	if (ret) +		return ret; +	return value;  } @@ -194,28 +285,36 @@ int gpiotools_get(const char *device_name, unsigned int line)   *			such as "gpiochip0".   * @lines:		An array desired lines, specified by offset   *			index for the associated GPIO device. - * @nline:		The number of lines to request. - * @data:		The array of values get from gpiochip. + * @num_lines:		The number of lines to request. + * @values:		The array of values get from gpiochip.   *   * Return:		On success return 0;   *			On failure return the errno.   */  int gpiotools_gets(const char *device_name, unsigned int *lines, -		   unsigned int nlines, struct gpiohandle_data *data) +		   unsigned int num_lines, unsigned int *values)  { -	int fd; +	int fd, i;  	int ret;  	int ret_close; +	struct gpio_v2_line_config config; +	struct gpio_v2_line_values lv; -	ret = gpiotools_request_linehandle(device_name, lines, nlines, -					   GPIOHANDLE_REQUEST_INPUT, data, -					   CONSUMER); +	memset(&config, 0, sizeof(config)); +	config.flags = GPIO_V2_LINE_FLAG_INPUT; +	ret = gpiotools_request_line(device_name, lines, num_lines, +				     &config, CONSUMER);  	if (ret < 0)  		return ret;  	fd = ret; -	ret = gpiotools_get_values(fd, data); -	ret_close = gpiotools_release_linehandle(fd); +	for (i = 0; i < num_lines; i++) +		gpiotools_set_bit(&lv.mask, i); +	ret = gpiotools_get_values(fd, &lv); +	if (!ret) +		for (i = 0; i < num_lines; i++) +			values[i] = gpiotools_test_bit(lv.bits, i); +	ret_close = gpiotools_release_line(fd);  	return ret < 0 ? ret : ret_close;  } @@ -232,11 +331,9 @@ int gpiotools_gets(const char *device_name, unsigned int *lines,  int gpiotools_set(const char *device_name, unsigned int line,  		  unsigned int value)  { -	struct gpiohandle_data data;  	unsigned int lines[] = {line}; -	data.values[0] = value; -	return gpiotools_sets(device_name, lines, 1, &data); +	return gpiotools_sets(device_name, lines, 1, &value);  }  /** @@ -245,23 +342,32 @@ int gpiotools_set(const char *device_name, unsigned int line,   *			such as "gpiochip0".   * @lines:		An array desired lines, specified by offset   *			index for the associated GPIO device. - * @nline:		The number of lines to request. - * @data:		The array of values set to gpiochip, must be + * @num_lines:		The number of lines to request. + * @value:		The array of values set to gpiochip, must be   *			0(low) or 1(high).   *   * Return:		On success return 0;   *			On failure return the errno.   */  int gpiotools_sets(const char *device_name, unsigned int *lines, -		   unsigned int nlines, struct gpiohandle_data *data) +		   unsigned int num_lines, unsigned int *values)  { -	int ret; +	int ret, i; +	struct gpio_v2_line_config config; -	ret = gpiotools_request_linehandle(device_name, lines, nlines, -					   GPIOHANDLE_REQUEST_OUTPUT, data, -					   CONSUMER); +	memset(&config, 0, sizeof(config)); +	config.flags = GPIO_V2_LINE_FLAG_OUTPUT; +	config.num_attrs = 1; +	config.attrs[0].attr.id = GPIO_V2_LINE_ATTR_ID_OUTPUT_VALUES; +	for (i = 0; i < num_lines; i++) { +		gpiotools_set_bit(&config.attrs[0].mask, i); +		gpiotools_assign_bit(&config.attrs[0].attr.values, +				     i, values[i]); +	} +	ret = gpiotools_request_line(device_name, lines, num_lines, +				     &config, CONSUMER);  	if (ret < 0)  		return ret; -	return gpiotools_release_linehandle(ret); +	return gpiotools_release_line(ret);  }  | 
