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.
- 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.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
sound/core.hlinux/slab.hlinux/module.hseq_system.hseq_ports.hseq_clientmgr.h
Detected Declarations
function Copyrightfunction port_subs_info_initfunction snd_seq_port_unlockfunction snd_seq_insert_portfunction get_subscriberfunction clear_subscriber_listfunction list_for_each_safefunction port_deletefunction snd_seq_delete_portfunction scoped_guardfunction list_for_each_entryfunction snd_seq_delete_all_portsfunction snd_seq_set_port_infofunction snd_seq_get_port_infofunction functionsfunction unsubscribe_portfunction addr_matchfunction match_subs_infofunction check_and_subscribe_portfunction list_for_eachfunction __delete_and_unsubscribe_portfunction delete_and_unsubscribe_portfunction snd_seq_port_connectfunction snd_seq_port_disconnectfunction list_for_each_entryfunction snd_seq_port_get_subscriptionfunction snd_seq_midisynth_register_portfunction snd_seq_event_port_detachexport snd_seq_event_port_attachexport snd_seq_event_port_detach
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
- Immediate include surface: `sound/core.h`, `linux/slab.h`, `linux/module.h`, `seq_system.h`, `seq_ports.h`, `seq_clientmgr.h`.
- Detected declarations: `function Copyright`, `function port_subs_info_init`, `function snd_seq_port_unlock`, `function snd_seq_insert_port`, `function get_subscriber`, `function clear_subscriber_list`, `function list_for_each_safe`, `function port_delete`, `function snd_seq_delete_port`, `function scoped_guard`.
- Atlas domain: Driver Families / sound/core.
- Implementation status: integration implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.