Commit ff166a9d authored by Takashi Iwai's avatar Takashi Iwai
Browse files

ALSA: seq: Add port direction to snd_seq_port_info



Add a new field "direction" to snd_seq_port_info for allowing a client
to tell the expected direction of the port access.  A port might still
allow subscriptions for read/write (e.g. for MIDI-CI) even if the
primary usage of the port is a single direction (either input or
output only).  This new "direction" field can help to indicate such
cases.

When the direction is unspecified at creating a port and the port has
either read or write capability, the corresponding direction bits are
set automatically as default.

Reviewed-by: default avatarJaroslav Kysela <perex@perex.cz>
Link: https://lore.kernel.org/r/20230523075358.9672-29-tiwai@suse.de


Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 177ccf81
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -455,6 +455,12 @@ struct snd_seq_remove_events {
#define SNDRV_SEQ_PORT_FLG_TIMESTAMP	(1<<1)
#define SNDRV_SEQ_PORT_FLG_TIME_REAL	(1<<2)

/* port direction */
#define SNDRV_SEQ_PORT_DIR_UNKNOWN	0
#define SNDRV_SEQ_PORT_DIR_INPUT	1
#define SNDRV_SEQ_PORT_DIR_OUTPUT	2
#define SNDRV_SEQ_PORT_DIR_BIDIRECTION	3

struct snd_seq_port_info {
	struct snd_seq_addr addr;	/* client/port numbers */
	char name[64];			/* port name */
@@ -471,7 +477,8 @@ struct snd_seq_port_info {
	void *kernel;			/* reserved for kernel use (must be NULL) */
	unsigned int flags;		/* misc. conditioning */
	unsigned char time_queue;	/* queue # for timestamping */
	char reserved[59];		/* for future use */
	unsigned char direction;	/* port usage direction (r/w/bidir) */
	char reserved[58];		/* for future use */
};


+14 −2
Original line number Diff line number Diff line
@@ -2440,6 +2440,17 @@ static void snd_seq_info_dump_subscribers(struct snd_info_buffer *buffer,

#define FLAG_PERM_DUPLEX(perm) ((perm) & SNDRV_SEQ_PORT_CAP_DUPLEX ? 'X' : '-')

static const char *port_direction_name(unsigned char dir)
{
	static const char *names[4] = {
		"-", "In", "Out", "In/Out"
	};

	if (dir > SNDRV_SEQ_PORT_DIR_BIDIRECTION)
		return "Invalid";
	return names[dir];
}

static void snd_seq_info_dump_ports(struct snd_info_buffer *buffer,
				    struct snd_seq_client *client)
{
@@ -2449,12 +2460,13 @@ static void snd_seq_info_dump_ports(struct snd_info_buffer *buffer,
	list_for_each_entry(p, &client->ports_list_head, list) {
		if (p->capability & SNDRV_SEQ_PORT_CAP_INACTIVE)
			continue;
		snd_iprintf(buffer, "  Port %3d : \"%s\" (%c%c%c%c)\n",
		snd_iprintf(buffer, "  Port %3d : \"%s\" (%c%c%c%c) [%s]\n",
			    p->addr.port, p->name,
			    FLAG_PERM_RD(p->capability),
			    FLAG_PERM_WR(p->capability),
			    FLAG_PERM_EX(p->capability),
			    FLAG_PERM_DUPLEX(p->capability));
			    FLAG_PERM_DUPLEX(p->capability),
			    port_direction_name(p->direction));
		snd_seq_info_dump_subscribers(buffer, &p->c_src, 1, "    Connecting To: ");
		snd_seq_info_dump_subscribers(buffer, &p->c_dest, 0, "    Connected From: ");
	}
+1 −0
Original line number Diff line number Diff line
@@ -127,6 +127,7 @@ create_port(int idx, int type)
	pinfo.capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE;
	if (duplex)
		pinfo.capability |= SNDRV_SEQ_PORT_CAP_DUPLEX;
	pinfo.direction = SNDRV_SEQ_PORT_DIR_BIDIRECTION;
	pinfo.type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC
		| SNDRV_SEQ_PORT_TYPE_SOFTWARE
		| SNDRV_SEQ_PORT_TYPE_PORT;
+4 −0
Original line number Diff line number Diff line
@@ -367,6 +367,10 @@ snd_seq_midisynth_probe(struct device *_dev)
		if ((port->capability & (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ)) == (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ) &&
		    info->flags & SNDRV_RAWMIDI_INFO_DUPLEX)
			port->capability |= SNDRV_SEQ_PORT_CAP_DUPLEX;
		if (port->capability & SNDRV_SEQ_PORT_CAP_READ)
			port->direction |= SNDRV_SEQ_PORT_DIR_INPUT;
		if (port->capability & SNDRV_SEQ_PORT_CAP_WRITE)
			port->direction |= SNDRV_SEQ_PORT_DIR_OUTPUT;
		port->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC
			| SNDRV_SEQ_PORT_TYPE_HARDWARE
			| SNDRV_SEQ_PORT_TYPE_PORT;
+13 −0
Original line number Diff line number Diff line
@@ -356,6 +356,16 @@ int snd_seq_set_port_info(struct snd_seq_client_port * port,
	port->time_real = (info->flags & SNDRV_SEQ_PORT_FLG_TIME_REAL) ? 1 : 0;
	port->time_queue = info->time_queue;

	/* direction */
	port->direction = info->direction;
	/* fill default port direction */
	if (!port->direction) {
		if (info->capability & SNDRV_SEQ_PORT_CAP_READ)
			port->direction |= SNDRV_SEQ_PORT_DIR_INPUT;
		if (info->capability & SNDRV_SEQ_PORT_CAP_WRITE)
			port->direction |= SNDRV_SEQ_PORT_DIR_OUTPUT;
	}

	return 0;
}

@@ -393,6 +403,9 @@ int snd_seq_get_port_info(struct snd_seq_client_port * port,
		info->time_queue = port->time_queue;
	}

	/* direction */
	info->direction = port->direction;

	return 0;
}

Loading