Blame hda-verb/hda-verb.c

Packit Service b98cfc
/*
Packit Service b98cfc
 * Accessing HD-audio verbs via hwdep interface
Packit Service b98cfc
 * Version 0.3
Packit Service b98cfc
 *
Packit Service b98cfc
 * Copyright (c) 2008 Takashi Iwai <tiwai@suse.de>
Packit Service b98cfc
 *
Packit Service b98cfc
 * Licensed under GPL v2 or later.
Packit Service b98cfc
 */
Packit Service b98cfc
Packit Service b98cfc
#include <stdio.h>
Packit Service b98cfc
#include <stdlib.h>
Packit Service b98cfc
#include <string.h>
Packit Service b98cfc
#include <ctype.h>
Packit Service b98cfc
#include <unistd.h>
Packit Service b98cfc
#include <sys/ioctl.h>
Packit Service b98cfc
#include <sys/types.h>
Packit Service b98cfc
#include <sys/fcntl.h>
Packit Service b98cfc
Packit Service b98cfc
#include <stdint.h>
Packit Service b98cfc
typedef uint8_t u8;
Packit Service b98cfc
typedef uint16_t u16;
Packit Service b98cfc
typedef uint32_t u32;
Packit Service b98cfc
typedef uint64_t u64;
Packit Service b98cfc
Packit Service b98cfc
#include "hda_hwdep.h"
Packit Service b98cfc
Packit Service b98cfc
#define AC_VERB_GET_STREAM_FORMAT		0x0a00
Packit Service b98cfc
#define AC_VERB_GET_AMP_GAIN_MUTE		0x0b00
Packit Service b98cfc
#define AC_VERB_GET_PROC_COEF			0x0c00
Packit Service b98cfc
#define AC_VERB_GET_COEF_INDEX			0x0d00
Packit Service b98cfc
#define AC_VERB_PARAMETERS			0x0f00
Packit Service b98cfc
#define AC_VERB_GET_CONNECT_SEL			0x0f01
Packit Service b98cfc
#define AC_VERB_GET_CONNECT_LIST		0x0f02
Packit Service b98cfc
#define AC_VERB_GET_PROC_STATE			0x0f03
Packit Service b98cfc
#define AC_VERB_GET_SDI_SELECT			0x0f04
Packit Service b98cfc
#define AC_VERB_GET_POWER_STATE			0x0f05
Packit Service b98cfc
#define AC_VERB_GET_CONV			0x0f06
Packit Service b98cfc
#define AC_VERB_GET_PIN_WIDGET_CONTROL		0x0f07
Packit Service b98cfc
#define AC_VERB_GET_UNSOLICITED_RESPONSE	0x0f08
Packit Service b98cfc
#define AC_VERB_GET_PIN_SENSE			0x0f09
Packit Service b98cfc
#define AC_VERB_GET_BEEP_CONTROL		0x0f0a
Packit Service b98cfc
#define AC_VERB_GET_EAPD_BTLENABLE		0x0f0c
Packit Service b98cfc
#define AC_VERB_GET_DIGI_CONVERT_1		0x0f0d
Packit Service b98cfc
#define AC_VERB_GET_DIGI_CONVERT_2		0x0f0e
Packit Service b98cfc
#define AC_VERB_GET_VOLUME_KNOB_CONTROL		0x0f0f
Packit Service b98cfc
#define AC_VERB_GET_GPIO_DATA			0x0f15
Packit Service b98cfc
#define AC_VERB_GET_GPIO_MASK			0x0f16
Packit Service b98cfc
#define AC_VERB_GET_GPIO_DIRECTION		0x0f17
Packit Service b98cfc
#define AC_VERB_GET_GPIO_WAKE_MASK		0x0f18
Packit Service b98cfc
#define AC_VERB_GET_GPIO_UNSOLICITED_RSP_MASK	0x0f19
Packit Service b98cfc
#define AC_VERB_GET_GPIO_STICKY_MASK		0x0f1a
Packit Service b98cfc
#define AC_VERB_GET_CONFIG_DEFAULT		0x0f1c
Packit Service b98cfc
#define AC_VERB_GET_SUBSYSTEM_ID		0x0f20
Packit Service b98cfc
Packit Service b98cfc
#define AC_VERB_SET_STREAM_FORMAT		0x200
Packit Service b98cfc
#define AC_VERB_SET_AMP_GAIN_MUTE		0x300
Packit Service b98cfc
#define AC_VERB_SET_PROC_COEF			0x400
Packit Service b98cfc
#define AC_VERB_SET_COEF_INDEX			0x500
Packit Service b98cfc
#define AC_VERB_SET_CONNECT_SEL			0x701
Packit Service b98cfc
#define AC_VERB_SET_PROC_STATE			0x703
Packit Service b98cfc
#define AC_VERB_SET_SDI_SELECT			0x704
Packit Service b98cfc
#define AC_VERB_SET_POWER_STATE			0x705
Packit Service b98cfc
#define AC_VERB_SET_CHANNEL_STREAMID		0x706
Packit Service b98cfc
#define AC_VERB_SET_PIN_WIDGET_CONTROL		0x707
Packit Service b98cfc
#define AC_VERB_SET_UNSOLICITED_ENABLE		0x708
Packit Service b98cfc
#define AC_VERB_SET_PIN_SENSE			0x709
Packit Service b98cfc
#define AC_VERB_SET_BEEP_CONTROL		0x70a
Packit Service b98cfc
#define AC_VERB_SET_EAPD_BTLENABLE		0x70c
Packit Service b98cfc
#define AC_VERB_SET_DIGI_CONVERT_1		0x70d
Packit Service b98cfc
#define AC_VERB_SET_DIGI_CONVERT_2		0x70e
Packit Service b98cfc
#define AC_VERB_SET_VOLUME_KNOB_CONTROL		0x70f
Packit Service b98cfc
#define AC_VERB_SET_GPIO_DATA			0x715
Packit Service b98cfc
#define AC_VERB_SET_GPIO_MASK			0x716
Packit Service b98cfc
#define AC_VERB_SET_GPIO_DIRECTION		0x717
Packit Service b98cfc
#define AC_VERB_SET_GPIO_WAKE_MASK		0x718
Packit Service b98cfc
#define AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK	0x719
Packit Service b98cfc
#define AC_VERB_SET_GPIO_STICKY_MASK		0x71a
Packit Service b98cfc
#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_0	0x71c
Packit Service b98cfc
#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_1	0x71d
Packit Service b98cfc
#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_2	0x71e
Packit Service b98cfc
#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_3	0x71f
Packit Service b98cfc
#define AC_VERB_SET_CODEC_RESET			0x7ff
Packit Service b98cfc
Packit Service b98cfc
#define AC_PAR_VENDOR_ID		0x00
Packit Service b98cfc
#define AC_PAR_SUBSYSTEM_ID		0x01
Packit Service b98cfc
#define AC_PAR_REV_ID			0x02
Packit Service b98cfc
#define AC_PAR_NODE_COUNT		0x04
Packit Service b98cfc
#define AC_PAR_FUNCTION_TYPE		0x05
Packit Service b98cfc
#define AC_PAR_AUDIO_FG_CAP		0x08
Packit Service b98cfc
#define AC_PAR_AUDIO_WIDGET_CAP		0x09
Packit Service b98cfc
#define AC_PAR_PCM			0x0a
Packit Service b98cfc
#define AC_PAR_STREAM			0x0b
Packit Service b98cfc
#define AC_PAR_PIN_CAP			0x0c
Packit Service b98cfc
#define AC_PAR_AMP_IN_CAP		0x0d
Packit Service b98cfc
#define AC_PAR_CONNLIST_LEN		0x0e
Packit Service b98cfc
#define AC_PAR_POWER_STATE		0x0f
Packit Service b98cfc
#define AC_PAR_PROC_CAP			0x10
Packit Service b98cfc
#define AC_PAR_GPIO_CAP			0x11
Packit Service b98cfc
#define AC_PAR_AMP_OUT_CAP		0x12
Packit Service b98cfc
#define AC_PAR_VOL_KNB_CAP		0x13
Packit Service b98cfc
Packit Service b98cfc
/*
Packit Service b98cfc
 */
Packit Service b98cfc
#define VERBSTR(x)	{ .val = AC_VERB_##x, .str = #x }
Packit Service b98cfc
#define PARMSTR(x)	{ .val = AC_PAR_##x, .str = #x }
Packit Service b98cfc
Packit Service b98cfc
struct strtbl {
Packit Service b98cfc
	int val;
Packit Service b98cfc
	const char *str;
Packit Service b98cfc
};
Packit Service b98cfc
Packit Service b98cfc
static struct strtbl hda_verbs[] = {
Packit Service b98cfc
	VERBSTR(GET_STREAM_FORMAT),
Packit Service b98cfc
	VERBSTR(GET_AMP_GAIN_MUTE),
Packit Service b98cfc
	VERBSTR(GET_PROC_COEF),
Packit Service b98cfc
	VERBSTR(GET_COEF_INDEX),
Packit Service b98cfc
	VERBSTR(PARAMETERS),
Packit Service b98cfc
	VERBSTR(GET_CONNECT_SEL),
Packit Service b98cfc
	VERBSTR(GET_CONNECT_LIST),
Packit Service b98cfc
	VERBSTR(GET_PROC_STATE),
Packit Service b98cfc
	VERBSTR(GET_SDI_SELECT),
Packit Service b98cfc
	VERBSTR(GET_POWER_STATE),
Packit Service b98cfc
	VERBSTR(GET_CONV),
Packit Service b98cfc
	VERBSTR(GET_PIN_WIDGET_CONTROL),
Packit Service b98cfc
	VERBSTR(GET_UNSOLICITED_RESPONSE),
Packit Service b98cfc
	VERBSTR(GET_PIN_SENSE),
Packit Service b98cfc
	VERBSTR(GET_BEEP_CONTROL),
Packit Service b98cfc
	VERBSTR(GET_EAPD_BTLENABLE),
Packit Service b98cfc
	VERBSTR(GET_DIGI_CONVERT_1),
Packit Service b98cfc
	VERBSTR(GET_DIGI_CONVERT_2),
Packit Service b98cfc
	VERBSTR(GET_VOLUME_KNOB_CONTROL),
Packit Service b98cfc
	VERBSTR(GET_GPIO_DATA),
Packit Service b98cfc
	VERBSTR(GET_GPIO_MASK),
Packit Service b98cfc
	VERBSTR(GET_GPIO_DIRECTION),
Packit Service b98cfc
	VERBSTR(GET_GPIO_WAKE_MASK),
Packit Service b98cfc
	VERBSTR(GET_GPIO_UNSOLICITED_RSP_MASK),
Packit Service b98cfc
	VERBSTR(GET_GPIO_STICKY_MASK),
Packit Service b98cfc
	VERBSTR(GET_CONFIG_DEFAULT),
Packit Service b98cfc
	VERBSTR(GET_SUBSYSTEM_ID),
Packit Service b98cfc
Packit Service b98cfc
	VERBSTR(SET_STREAM_FORMAT),
Packit Service b98cfc
	VERBSTR(SET_AMP_GAIN_MUTE),
Packit Service b98cfc
	VERBSTR(SET_PROC_COEF),
Packit Service b98cfc
	VERBSTR(SET_COEF_INDEX),
Packit Service b98cfc
	VERBSTR(SET_CONNECT_SEL),
Packit Service b98cfc
	VERBSTR(SET_PROC_STATE),
Packit Service b98cfc
	VERBSTR(SET_SDI_SELECT),
Packit Service b98cfc
	VERBSTR(SET_POWER_STATE),
Packit Service b98cfc
	VERBSTR(SET_CHANNEL_STREAMID),
Packit Service b98cfc
	VERBSTR(SET_PIN_WIDGET_CONTROL),
Packit Service b98cfc
	VERBSTR(SET_UNSOLICITED_ENABLE),
Packit Service b98cfc
	VERBSTR(SET_PIN_SENSE),
Packit Service b98cfc
	VERBSTR(SET_BEEP_CONTROL),
Packit Service b98cfc
	VERBSTR(SET_EAPD_BTLENABLE),
Packit Service b98cfc
	VERBSTR(SET_DIGI_CONVERT_1),
Packit Service b98cfc
	VERBSTR(SET_DIGI_CONVERT_2),
Packit Service b98cfc
	VERBSTR(SET_VOLUME_KNOB_CONTROL),
Packit Service b98cfc
	VERBSTR(SET_GPIO_DATA),
Packit Service b98cfc
	VERBSTR(SET_GPIO_MASK),
Packit Service b98cfc
	VERBSTR(SET_GPIO_DIRECTION),
Packit Service b98cfc
	VERBSTR(SET_GPIO_WAKE_MASK),
Packit Service b98cfc
	VERBSTR(SET_GPIO_UNSOLICITED_RSP_MASK),
Packit Service b98cfc
	VERBSTR(SET_GPIO_STICKY_MASK),
Packit Service b98cfc
	VERBSTR(SET_CONFIG_DEFAULT_BYTES_0),
Packit Service b98cfc
	VERBSTR(SET_CONFIG_DEFAULT_BYTES_1),
Packit Service b98cfc
	VERBSTR(SET_CONFIG_DEFAULT_BYTES_2),
Packit Service b98cfc
	VERBSTR(SET_CONFIG_DEFAULT_BYTES_3),
Packit Service b98cfc
	VERBSTR(SET_CODEC_RESET),
Packit Service b98cfc
	{ }, /* end */
Packit Service b98cfc
};
Packit Service b98cfc
Packit Service b98cfc
static struct strtbl hda_params[] = {
Packit Service b98cfc
	PARMSTR(VENDOR_ID),
Packit Service b98cfc
	PARMSTR(SUBSYSTEM_ID),
Packit Service b98cfc
	PARMSTR(REV_ID),
Packit Service b98cfc
	PARMSTR(NODE_COUNT),
Packit Service b98cfc
	PARMSTR(FUNCTION_TYPE),
Packit Service b98cfc
	PARMSTR(AUDIO_FG_CAP),
Packit Service b98cfc
	PARMSTR(AUDIO_WIDGET_CAP),
Packit Service b98cfc
	PARMSTR(PCM),
Packit Service b98cfc
	PARMSTR(STREAM),
Packit Service b98cfc
	PARMSTR(PIN_CAP),
Packit Service b98cfc
	PARMSTR(AMP_IN_CAP),
Packit Service b98cfc
	PARMSTR(CONNLIST_LEN),
Packit Service b98cfc
	PARMSTR(POWER_STATE),
Packit Service b98cfc
	PARMSTR(PROC_CAP),
Packit Service b98cfc
	PARMSTR(GPIO_CAP),
Packit Service b98cfc
	PARMSTR(AMP_OUT_CAP),
Packit Service b98cfc
	PARMSTR(VOL_KNB_CAP),
Packit Service b98cfc
	{ }, /* end */
Packit Service b98cfc
};
Packit Service b98cfc
Packit Service b98cfc
static void list_keys(struct strtbl *tbl, int one_per_line)
Packit Service b98cfc
{
Packit Service b98cfc
	int c = 0;
Packit Service b98cfc
	for (; tbl->str; tbl++) {
Packit Service b98cfc
		int len = strlen(tbl->str) + 2;
Packit Service b98cfc
		if (!one_per_line && c + len >= 80) {
Packit Service b98cfc
			fprintf(stderr, "\n");
Packit Service b98cfc
			c = 0;
Packit Service b98cfc
		}
Packit Service b98cfc
		if (one_per_line)
Packit Service b98cfc
			fprintf(stderr, "  %s\n", tbl->str);
Packit Service b98cfc
		else if (!c)
Packit Service b98cfc
			fprintf(stderr, "  %s", tbl->str);
Packit Service b98cfc
		else
Packit Service b98cfc
			fprintf(stderr, ", %s", tbl->str);
Packit Service b98cfc
		c += 2 + len;
Packit Service b98cfc
	}
Packit Service b98cfc
	if (!one_per_line)
Packit Service b98cfc
		fprintf(stderr, "\n");
Packit Service b98cfc
}
Packit Service b98cfc
Packit Service b98cfc
/* look up a value from the given string table */
Packit Service b98cfc
static int lookup_str(struct strtbl *tbl, const char *str)
Packit Service b98cfc
{
Packit Service b98cfc
	struct strtbl *p, *found;
Packit Service b98cfc
	int len = strlen(str);
Packit Service b98cfc
Packit Service b98cfc
	found = NULL;
Packit Service b98cfc
	for (p = tbl; p->str; p++) {
Packit Service b98cfc
		if (!strncmp(str, p->str, len)) {
Packit Service b98cfc
			if (found) {
Packit Service b98cfc
				fprintf(stderr, "No unique key '%s'\n", str);
Packit Service b98cfc
				return -1;
Packit Service b98cfc
			}
Packit Service b98cfc
			found = p;
Packit Service b98cfc
		}
Packit Service b98cfc
	}
Packit Service b98cfc
	if (!found) {
Packit Service b98cfc
		fprintf(stderr, "No key matching with '%s'\n", str);
Packit Service b98cfc
		return -1;
Packit Service b98cfc
	}
Packit Service b98cfc
	return found->val;
Packit Service b98cfc
}
Packit Service b98cfc
Packit Service b98cfc
/* convert a string to upper letters */
Packit Service b98cfc
static void strtoupper(char *str)
Packit Service b98cfc
{
Packit Service b98cfc
	for (; *str; str++)
Packit Service b98cfc
		*str = toupper(*str);
Packit Service b98cfc
}
Packit Service b98cfc
Packit Service b98cfc
static void usage(void)
Packit Service b98cfc
{
Packit Service b98cfc
	fprintf(stderr, "usage: hda-verb [option] hwdep-device nid verb param\n");
Packit Service b98cfc
	fprintf(stderr, "   -l      List known verbs and parameters\n");
Packit Service b98cfc
	fprintf(stderr, "   -L      List known verbs and parameters (one per line)\n");
Packit Service b98cfc
}
Packit Service b98cfc
Packit Service b98cfc
static void list_verbs(int one_per_line)
Packit Service b98cfc
{
Packit Service b98cfc
	fprintf(stderr, "known verbs:\n");
Packit Service b98cfc
	list_keys(hda_verbs, one_per_line);
Packit Service b98cfc
	fprintf(stderr, "known parameters:\n");
Packit Service b98cfc
	list_keys(hda_params, one_per_line);
Packit Service b98cfc
}
Packit Service b98cfc
Packit Service b98cfc
int main(int argc, char **argv)
Packit Service b98cfc
{
Packit Service b98cfc
	int version;
Packit Service b98cfc
	int fd;
Packit Service b98cfc
	int nid, verb, param;
Packit Service b98cfc
	int c;
Packit Service b98cfc
	struct hda_verb_ioctl val;
Packit Service b98cfc
	char **p;
Packit Service b98cfc
Packit Service b98cfc
	while ((c = getopt(argc, argv, "lL")) >= 0) {
Packit Service b98cfc
		switch (c) {
Packit Service b98cfc
		case 'l':
Packit Service b98cfc
			list_verbs(0);
Packit Service b98cfc
			return 0;
Packit Service b98cfc
		case 'L':
Packit Service b98cfc
			list_verbs(1);
Packit Service b98cfc
			return 0;
Packit Service b98cfc
		default:
Packit Service b98cfc
			usage();
Packit Service b98cfc
			return 1;
Packit Service b98cfc
		}
Packit Service b98cfc
	}
Packit Service b98cfc
Packit Service b98cfc
	if (argc - optind < 4) {
Packit Service b98cfc
		usage();
Packit Service b98cfc
		return 1;
Packit Service b98cfc
	}
Packit Service b98cfc
	p = argv + optind;
Packit Service b98cfc
	fd = open(*p, O_RDWR);
Packit Service b98cfc
	if (fd < 0) {
Packit Service b98cfc
		perror("open");
Packit Service b98cfc
		return 1;
Packit Service b98cfc
	}
Packit Service b98cfc
	version = 0;
Packit Service b98cfc
	if (ioctl(fd, HDA_IOCTL_PVERSION, &version) < 0) {
Packit Service b98cfc
		perror("ioctl(PVERSION)");
Packit Service b98cfc
		fprintf(stderr, "Looks like an invalid hwdep device...\n");
Packit Service b98cfc
		return 1;
Packit Service b98cfc
	}
Packit Service b98cfc
	if (version < HDA_HWDEP_VERSION) {
Packit Service b98cfc
		fprintf(stderr, "Invalid version number 0x%x\n", version);
Packit Service b98cfc
		fprintf(stderr, "Looks like an invalid hwdep device...\n");
Packit Service b98cfc
		return 1;
Packit Service b98cfc
	}
Packit Service b98cfc
Packit Service b98cfc
	p++;
Packit Service b98cfc
	nid = strtol(*p, NULL, 0);
Packit Service b98cfc
	if (nid < 0 || nid > 0xff) {
Packit Service b98cfc
		fprintf(stderr, "invalid nid %s\n", *p);
Packit Service b98cfc
		return 1;
Packit Service b98cfc
	}
Packit Service b98cfc
Packit Service b98cfc
	p++;
Packit Service b98cfc
	if (!isdigit(**p)) {
Packit Service b98cfc
		strtoupper(*p);
Packit Service b98cfc
		verb = lookup_str(hda_verbs, *p);
Packit Service b98cfc
		if (verb < 0)
Packit Service b98cfc
			return 1;
Packit Service b98cfc
	} else {
Packit Service b98cfc
		verb = strtol(*p, NULL, 0);
Packit Service b98cfc
		if (verb < 0 || verb > 0xfff) {
Packit Service b98cfc
			fprintf(stderr, "invalid verb %s\n", *p);
Packit Service b98cfc
			return 1;
Packit Service b98cfc
		}
Packit Service b98cfc
	}
Packit Service b98cfc
	p++;
Packit Service b98cfc
	if (!isdigit(**p)) {
Packit Service b98cfc
		strtoupper(*p);
Packit Service b98cfc
		param = lookup_str(hda_params, *p);
Packit Service b98cfc
		if (param < 0)
Packit Service b98cfc
			return 1;
Packit Service b98cfc
	} else {
Packit Service b98cfc
		param = strtol(*p, NULL, 0);
Packit Service b98cfc
		if (param < 0 || param > 0xffff) {
Packit Service b98cfc
			fprintf(stderr, "invalid param %s\n", *p);
Packit Service b98cfc
			return 1;
Packit Service b98cfc
		}
Packit Service b98cfc
	}
Packit Service b98cfc
	fprintf(stderr, "nid = 0x%x, verb = 0x%x, param = 0x%x\n",
Packit Service b98cfc
		nid, verb, param);
Packit Service b98cfc
Packit Service b98cfc
	val.verb = HDA_VERB(nid, verb, param);
Packit Service b98cfc
	if (ioctl(fd, HDA_IOCTL_VERB_WRITE, &val) < 0)
Packit Service b98cfc
		perror("ioctl");
Packit Service b98cfc
	printf("value = 0x%x\n", val.res);
Packit Service b98cfc
	close(fd);
Packit Service b98cfc
	return 0;
Packit Service b98cfc
}