sound/core/seq/seq_ports.c

Source file repositories/reference/linux-study-clean/sound/core/seq/seq_ports.c

File Facts

System
Linux kernel
Corpus path
sound/core/seq/seq_ports.c
Extension
.c
Size
19489 bytes
Lines
733
Domain
Driver Families
Bucket
sound/core
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (port->addr.port == num) {
			if (port->closing)
				break; /* deleting now */
			snd_use_lock_use(&port->use_lock);
			return port;
		}
	}
	return NULL;		/* not found */
}


/* search for the next port - port is locked if found */
struct snd_seq_client_port *snd_seq_port_query_nearest(struct snd_seq_client *client,
						       struct snd_seq_port_info *pinfo)
{
	int num;
	struct snd_seq_client_port *port, *found;
	bool check_inactive = (pinfo->capability & SNDRV_SEQ_PORT_CAP_INACTIVE);

	num = pinfo->addr.port;
	found = NULL;
	guard(read_lock)(&client->ports_lock);
	list_for_each_entry(port, &client->ports_list_head, list) {
		if ((port->capability & SNDRV_SEQ_PORT_CAP_INACTIVE) &&
		    !check_inactive)
			continue; /* skip inactive ports */
		if (port->addr.port < num)
			continue;
		if (port->addr.port == num) {
			found = port;
			break;
		}
		if (found == NULL || port->addr.port < found->addr.port)
			found = port;
	}
	if (found) {
		if (found->closing)
			found = NULL;
		else
			snd_use_lock_use(&found->use_lock);
	}
	return found;
}


/* initialize snd_seq_port_subs_info */
static void port_subs_info_init(struct snd_seq_port_subs_info *grp)
{
	INIT_LIST_HEAD(&grp->list_head);
	grp->count = 0;
	grp->exclusive = 0;
	rwlock_init(&grp->list_lock);
	init_rwsem(&grp->list_mutex);
	grp->open = NULL;
	grp->close = NULL;
}


/* create a port, 0 on success or a negative error code is returned
 * the caller needs to unref the port via snd_seq_port_unlock() appropriately
 */
int snd_seq_create_port(struct snd_seq_client *client,
			struct snd_seq_client_port **port_ret)
{
	struct snd_seq_client_port *new_port;
	
	*port_ret = NULL;

	/* sanity check */
	if (snd_BUG_ON(!client))
		return -EINVAL;

	if (client->num_ports >= SNDRV_SEQ_MAX_PORTS) {
		pr_warn("ALSA: seq: too many ports for client %d\n", client->number);
		return -EINVAL;
	}

	/* create a new port */
	new_port = kzalloc_obj(*new_port);
	if (!new_port)
		return -ENOMEM;	/* failure, out of memory */
	/* init port data */
	new_port->addr.client = client->number;
	new_port->addr.port = -1;
	new_port->owner = THIS_MODULE;
	snd_use_lock_init(&new_port->use_lock);
	port_subs_info_init(&new_port->c_src);
	port_subs_info_init(&new_port->c_dest);
	snd_use_lock_use(&new_port->use_lock);

Annotation

Implementation Notes