/* Open /sys/class/leds/<loc_code>:<led_type>/brightnes file */
static int
open_led_brightness_file(struct loc_code *loc, int mode)
{
	const char *indicator_desc;
	char filename[PATH_MAX];
	int len;
	int fd;
	int rc = -1;

	indicator_desc = get_indicator_desc(loc->index);
	if (!indicator_desc)
		return rc;

	len = snprintf(filename, PATH_MAX, "%s/%s:%s/%s",
		       OPAL_LED_SYSFS_PATH, loc->code,
		       indicator_desc, OPAL_LED_FILE);
	if (len >= PATH_MAX) {
		log_msg("%s : Path to LED brightness file is too big",
			__func__);
		return rc;
	}

	fd = open(filename, mode);
	if (fd == -1)
		log_msg("%s : Failed to open %s file", __func__, filename);

	return fd;
}
/**
 * set_rtas_indicator - Set rtas indicator
 *
 * Call the rtas_set_indicator or rtas_set_dynamic_indicator librtas calls,
 * depending on whether the index indicates that the indicator is dynamic.
 *
 * @indicator	identification or attention indicator
 * @loc		location code of rtas indicator
 * @new_value	value to update indicator to
 *
 * Returns :
 *	rtas call return code
 */
static int
set_rtas_indicator(int indicator, struct loc_code *loc, int new_value)
{
	int	rc;
	int	rtas_token;
	char	err_buf[RTAS_ERROR_BUF_SIZE];

	rtas_token = get_rtas_token(indicator);
	if (rtas_token == -1)
		return -3; /* No such sensor implemented */

	if (loc->index == DYNAMIC_INDICATOR)
		rc = rtas_set_dynamic_indicator(rtas_token,
						new_value, (void *)loc);
	else
		rc = rtas_set_indicator(rtas_token, loc->index, new_value);

	switch (rc) {
	case 0:	/*success  */
		break;
	case -1:
		log_msg("Hardware error while setting the indicator at %s",
			loc->code);
		break;
	case -2:
		log_msg("Busy while setting the indicator at %s. "
			"Try again later", loc->code);
		break;
	case -3:
		log_msg("The indicator at %s is not implemented", loc->code);
		break;
	default:
		librtas_error(rc, err_buf, RTAS_ERROR_BUF_SIZE);

		log_msg("Could not set %ssensor %s indicators,\n%s",
			(loc->index == DYNAMIC_INDICATOR) ? "dynamic " : "",
			get_indicator_desc(indicator), err_buf);
		break;
	}

	return rc;
}
/**
 * Get OPAL platform related indicator list
 *
 * @indicator	identification or attention/fault indicator
 * @loc		pointer to loc_code structure
 *
 * Returns :
 *	0 on success, !0 on failure
 */
static int
opal_get_indices(int indicator, struct loc_code **loc)
{
	const char *indicator_desc;
	int i;
	int rc = -1;
	int nleds;
	struct loc_code *list = *loc;
	struct dirent **dirlist;
	struct dirent *dirent;

	indicator_desc = get_indicator_desc(indicator);
	if (!indicator_desc)
		return rc;

	nleds = scandir(OPAL_LED_SYSFS_PATH, &dirlist, NULL, alphasort);
	if (nleds == -1) {
		log_msg("%s : Failed to read led sysfs dir : %s",
			__func__, OPAL_LED_SYSFS_PATH);
		return rc;
	}

	for (i = 0; i < nleds; i++) {
		dirent = dirlist[i];

		if (dirent->d_type != DT_DIR && dirent->d_type != DT_LNK) {
			free(dirlist[i]);
			continue;
		}

		if (strstr(dirent->d_name, indicator_desc))
			list = opal_parse_loc_code(indicator,
						   list, dirent->d_name);

		free(dirlist[i]);
	}

	*loc = list;
	free(dirlist);
	return 0;
}
/**
 * get_rtas_list - Gets rtas indicator list
 *
 * @indicator	identification or attention indicator
 * @loc		pointer to loc_code structure
 *
 * Returns :
 *	rtas call return value
 */
static int
get_rtas_indices(int indicator, struct loc_code **loc)
{
	int	rc;
	int	index = 1;
	int	next_index;
	int	rtas_token;
	char	workarea[BUF_SIZE];
	char	err_buf[RTAS_ERROR_BUF_SIZE];
	struct	loc_code *list = NULL;

	rtas_token = get_rtas_token(indicator);
	if (rtas_token == -1)
		return -3; /* Indicator type not supported */

	do {
		rc = rtas_get_indices(0, rtas_token, workarea, BUF_SIZE,
				      index, &next_index);
		switch (rc) {
		case 1:		/* more data available */
			index = next_index;
			/* fall through */
		case 0:		/* success */
			list = parse_rtas_workarea(list, workarea);
			if (!list)
				return -99; /* Out of heap memory */
			break;
		case -1:	/* hardware error */
			log_msg("Hardware error retrieving indicator indices");
			free_indicator_list(list);
			break;
		case RTAS_UNKNOWN_OP:
			/* Yes, this is a librtas return code but it should
			 * be treated the same as a -3 return code, both
			 * indicate that functionality is not supported
			 */
			librtas_error(rc, err_buf, RTAS_ERROR_BUF_SIZE);
			/* fall through */
		case -3:	/* indicator type not supported. */
			log_msg("The %s indicators are not supported on this "
				"system", get_indicator_desc(indicator));

			if (rc == RTAS_UNKNOWN_OP)
				log_msg(",\n%s", err_buf);

			free_indicator_list(list);
			break;
		case -4:	/* list changed; start over */
			free_indicator_list(list);
			list = NULL;
			index = 1;
			break;
		default:
			librtas_error(rc, err_buf, RTAS_ERROR_BUF_SIZE);
			log_msg("Could not retrieve data for %s "
				"indicators,\n%s",
				get_indicator_desc(indicator), err_buf);
			free_indicator_list(list);
			break;
		}

	} while ((rc == 1) || (rc == -4));

	*loc = list;
	return rc;
}