1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* 3 * ALSA sequencer Ports 4 * Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl> 5 */ 6 #ifndef __SND_SEQ_PORTS_H 7 #define __SND_SEQ_PORTS_H 8 9 #include <sound/seq_kernel.h> 10 #include "seq_lock.h" 11 12 /* list of 'exported' ports */ 13 14 /* Client ports that are not exported are still accessible, but are 15 anonymous ports. 16 17 If a port supports SUBSCRIPTION, that port can send events to all 18 subscribersto a special address, with address 19 (queue==SNDRV_SEQ_ADDRESS_SUBSCRIBERS). The message is then send to all 20 recipients that are registered in the subscription list. A typical 21 application for these SUBSCRIPTION events is handling of incoming MIDI 22 data. The port doesn't 'know' what other clients are interested in this 23 message. If for instance a MIDI recording application would like to receive 24 the events from that port, it will first have to subscribe with that port. 25 26 */ 27 28 struct snd_seq_subscribers { 29 struct snd_seq_port_subscribe info; /* additional info */ 30 struct list_head src_list; /* link of sources */ 31 struct list_head dest_list; /* link of destinations */ 32 atomic_t ref_count; 33 }; 34 35 struct snd_seq_port_subs_info { 36 struct list_head list_head; /* list of subscribed ports */ 37 unsigned int count; /* count of subscribers */ 38 unsigned int exclusive: 1; /* exclusive mode */ 39 struct rw_semaphore list_mutex; 40 rwlock_t list_lock; 41 int (*open)(void *private_data, struct snd_seq_port_subscribe *info); 42 int (*close)(void *private_data, struct snd_seq_port_subscribe *info); 43 }; 44 45 /* context for converting from legacy control event to UMP packet */ 46 struct snd_seq_ump_midi2_bank { 47 bool rpn_set; 48 bool nrpn_set; 49 bool bank_set; 50 unsigned char cc_rpn_msb, cc_rpn_lsb; 51 unsigned char cc_nrpn_msb, cc_nrpn_lsb; 52 unsigned char cc_data_msb, cc_data_lsb; 53 unsigned char cc_bank_msb, cc_bank_lsb; 54 }; 55 56 struct snd_seq_client_port { 57 58 struct snd_seq_addr addr; /* client/port number */ 59 struct module *owner; /* owner of this port */ 60 char name[64]; /* port name */ 61 struct list_head list; /* port list */ 62 snd_use_lock_t use_lock; 63 64 /* subscribers */ 65 struct snd_seq_port_subs_info c_src; /* read (sender) list */ 66 struct snd_seq_port_subs_info c_dest; /* write (dest) list */ 67 68 int (*event_input)(struct snd_seq_event *ev, int direct, void *private_data, 69 int atomic, int hop); 70 void (*private_free)(void *private_data); 71 void *private_data; 72 unsigned int closing : 1; 73 unsigned int timestamping: 1; 74 unsigned int time_real: 1; 75 int time_queue; 76 77 /* capability, inport, output, sync */ 78 unsigned int capability; /* port capability bits */ 79 unsigned int type; /* port type bits */ 80 81 /* supported channels */ 82 int midi_channels; 83 int midi_voices; 84 int synth_voices; 85 86 /* UMP direction and group */ 87 unsigned char direction; 88 unsigned char ump_group; 89 90 #if IS_ENABLED(CONFIG_SND_SEQ_UMP) 91 struct snd_seq_ump_midi2_bank midi2_bank[16]; /* per channel */ 92 #endif 93 }; 94 95 struct snd_seq_client; 96 97 /* return pointer to port structure and lock port */ 98 struct snd_seq_client_port *snd_seq_port_use_ptr(struct snd_seq_client *client, int num); 99 100 /* search for next port - port is locked if found */ 101 struct snd_seq_client_port *snd_seq_port_query_nearest(struct snd_seq_client *client, 102 struct snd_seq_port_info *pinfo); 103 104 /* unlock the port */ 105 #define snd_seq_port_unlock(port) snd_use_lock_free(&(port)->use_lock) 106 107 /* create a port, port number or a negative error code is returned */ 108 int snd_seq_create_port(struct snd_seq_client *client, int port_index, 109 struct snd_seq_client_port **port_ret); 110 111 /* delete a port */ 112 int snd_seq_delete_port(struct snd_seq_client *client, int port); 113 114 /* delete all ports */ 115 int snd_seq_delete_all_ports(struct snd_seq_client *client); 116 117 /* set port info fields */ 118 int snd_seq_set_port_info(struct snd_seq_client_port *port, 119 struct snd_seq_port_info *info); 120 121 /* get port info fields */ 122 int snd_seq_get_port_info(struct snd_seq_client_port *port, 123 struct snd_seq_port_info *info); 124 125 /* add subscriber to subscription list */ 126 int snd_seq_port_connect(struct snd_seq_client *caller, 127 struct snd_seq_client *s, struct snd_seq_client_port *sp, 128 struct snd_seq_client *d, struct snd_seq_client_port *dp, 129 struct snd_seq_port_subscribe *info); 130 131 /* remove subscriber from subscription list */ 132 int snd_seq_port_disconnect(struct snd_seq_client *caller, 133 struct snd_seq_client *s, struct snd_seq_client_port *sp, 134 struct snd_seq_client *d, struct snd_seq_client_port *dp, 135 struct snd_seq_port_subscribe *info); 136 137 /* subscribe port */ 138 int snd_seq_port_subscribe(struct snd_seq_client_port *port, 139 struct snd_seq_port_subscribe *info); 140 141 /* get matched subscriber */ 142 int snd_seq_port_get_subscription(struct snd_seq_port_subs_info *src_grp, 143 struct snd_seq_addr *dest_addr, 144 struct snd_seq_port_subscribe *subs); 145 146 #endif 147