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 bool is_midi1; /* keep MIDI 1.0 protocol */ 91 92 #if IS_ENABLED(CONFIG_SND_SEQ_UMP) 93 struct snd_seq_ump_midi2_bank midi2_bank[16]; /* per channel */ 94 #endif 95 }; 96 97 struct snd_seq_client; 98 99 /* return pointer to port structure and lock port */ 100 struct snd_seq_client_port *snd_seq_port_use_ptr(struct snd_seq_client *client, int num); 101 102 /* search for next port - port is locked if found */ 103 struct snd_seq_client_port *snd_seq_port_query_nearest(struct snd_seq_client *client, 104 struct snd_seq_port_info *pinfo); 105 106 /* unlock the port */ 107 #define snd_seq_port_unlock(port) snd_use_lock_free(&(port)->use_lock) 108 109 /* create a port, port number or a negative error code is returned */ 110 int snd_seq_create_port(struct snd_seq_client *client, int port_index, 111 struct snd_seq_client_port **port_ret); 112 113 /* delete a port */ 114 int snd_seq_delete_port(struct snd_seq_client *client, int port); 115 116 /* delete all ports */ 117 int snd_seq_delete_all_ports(struct snd_seq_client *client); 118 119 /* set port info fields */ 120 int snd_seq_set_port_info(struct snd_seq_client_port *port, 121 struct snd_seq_port_info *info); 122 123 /* get port info fields */ 124 int snd_seq_get_port_info(struct snd_seq_client_port *port, 125 struct snd_seq_port_info *info); 126 127 /* add subscriber to subscription list */ 128 int snd_seq_port_connect(struct snd_seq_client *caller, 129 struct snd_seq_client *s, struct snd_seq_client_port *sp, 130 struct snd_seq_client *d, struct snd_seq_client_port *dp, 131 struct snd_seq_port_subscribe *info); 132 133 /* remove subscriber from subscription list */ 134 int snd_seq_port_disconnect(struct snd_seq_client *caller, 135 struct snd_seq_client *s, struct snd_seq_client_port *sp, 136 struct snd_seq_client *d, struct snd_seq_client_port *dp, 137 struct snd_seq_port_subscribe *info); 138 139 /* subscribe port */ 140 int snd_seq_port_subscribe(struct snd_seq_client_port *port, 141 struct snd_seq_port_subscribe *info); 142 143 /* get matched subscriber */ 144 int snd_seq_port_get_subscription(struct snd_seq_port_subs_info *src_grp, 145 struct snd_seq_addr *dest_addr, 146 struct snd_seq_port_subscribe *subs); 147 148 #endif 149